118334Speter/* Compiler driver program that can handle many languages. 290277Sobrien Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3161660Skan 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, 4161660Skan Inc. 518334Speter 690277SobrienThis file is part of GCC. 718334Speter 890277SobrienGCC is free software; you can redistribute it and/or modify it under 990277Sobrienthe terms of the GNU General Public License as published by the Free 1090277SobrienSoftware Foundation; either version 2, or (at your option) any later 1190277Sobrienversion. 1218334Speter 1390277SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490277SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590277SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690277Sobrienfor more details. 1718334Speter 1818334SpeterYou should have received a copy of the GNU General Public License 1990277Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169704SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169704Skan02110-1301, USA. 2218334Speter 2318334SpeterThis paragraph is here to try to keep Sun CC from dying. 2418334SpeterThe number of chars here seems crucial!!!! */ 2518334Speter 2651232Sbde/* $FreeBSD$ */ 2751232Sbde 2818334Speter/* This program is the user interface to the C compiler and possibly to 2918334Speterother compilers. It is used because compilation is a complicated procedure 3018334Speterwhich involves running several programs and passing temporary files between 3118334Speterthem, forwarding the users switches to those programs selectively, 3218334Speterand deleting the temporary files at the end. 3318334Speter 3418334SpeterCC recognizes how to compile each input file by suffixes in the file names. 3518334SpeterOnce it knows which kind of compilation to perform, the procedure for 3618334Spetercompilation is specified by a string called a "spec". */ 3790277Sobrien 3890277Sobrien/* A Short Introduction to Adding a Command-Line Option. 3990277Sobrien 4090277Sobrien Before adding a command-line option, consider if it is really 4190277Sobrien necessary. Each additional command-line option adds complexity and 4290277Sobrien is difficult to remove in subsequent versions. 4390277Sobrien 4490277Sobrien In the following, consider adding the command-line argument 4590277Sobrien `--bar'. 4690277Sobrien 4790277Sobrien 1. Each command-line option is specified in the specs file. The 4890277Sobrien notation is described below in the comment entitled "The Specs 4990277Sobrien Language". Read it. 5090277Sobrien 5190277Sobrien 2. In this file, add an entry to "option_map" equating the long 5290277Sobrien `--' argument version and any shorter, single letter version. Read 5390277Sobrien the comments in the declaration of "struct option_map" for an 5490277Sobrien explanation. Do not omit the first `-'. 5590277Sobrien 5690277Sobrien 3. Look in the "specs" file to determine which program or option 5790277Sobrien list should be given the argument, e.g., "cc1_options". Add the 5890277Sobrien appropriate syntax for the shorter option version to the 5990277Sobrien corresponding "const char *" entry in this file. Omit the first 6090277Sobrien `-' from the option. For example, use `-bar', rather than `--bar'. 6190277Sobrien 6290277Sobrien 4. If the argument takes an argument, e.g., `--baz argument1', 6390277Sobrien modify either DEFAULT_SWITCH_TAKES_ARG or 64169704Skan DEFAULT_WORD_SWITCH_TAKES_ARG in gcc.h. Omit the first `-' 6590277Sobrien from `--baz'. 6690277Sobrien 6790277Sobrien 5. Document the option in this file's display_help(). If the 6890277Sobrien option is passed to a subprogram, modify its corresponding 6990277Sobrien function, e.g., cppinit.c:print_help() or toplev.c:display_help(), 7090277Sobrien instead. 7190277Sobrien 7290277Sobrien 6. Compile and test. Make sure that your new specs file is being 7390277Sobrien read. For example, use a debugger to investigate the value of 7490277Sobrien "specs_file" in main(). */ 7590277Sobrien 7650599Sobrien#include "config.h" 7750599Sobrien#include "system.h" 78132733Skan#include "coretypes.h" 79132733Skan#include "multilib.h" /* before tm.h */ 80132733Skan#include "tm.h" 8150599Sobrien#include <signal.h> 8290277Sobrien#if ! defined( SIGCHLD ) && defined( SIGCLD ) 8390277Sobrien# define SIGCHLD SIGCLD 8490277Sobrien#endif 85169704Skan#include "xregex.h" 8650599Sobrien#include "obstack.h" 8752520Sobrien#include "intl.h" 8852520Sobrien#include "prefix.h" 8990277Sobrien#include "gcc.h" 9090277Sobrien#include "flags.h" 91169704Skan#include "opts.h" 9218334Speter 9390277Sobrien/* By default there is no special suffix for target executables. */ 9490277Sobrien/* FIXME: when autoconf is fixed, remove the host check - dj */ 9590277Sobrien#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX) 9690277Sobrien#define HAVE_TARGET_EXECUTABLE_SUFFIX 9718334Speter#endif 9818334Speter 9990277Sobrien/* By default there is no special suffix for host executables. */ 10090277Sobrien#ifdef HOST_EXECUTABLE_SUFFIX 10190277Sobrien#define HAVE_HOST_EXECUTABLE_SUFFIX 10218334Speter#else 10390277Sobrien#define HOST_EXECUTABLE_SUFFIX "" 10418334Speter#endif 10518334Speter 10690277Sobrien/* By default, the suffix for target object files is ".o". */ 10790277Sobrien#ifdef TARGET_OBJECT_SUFFIX 10890277Sobrien#define HAVE_TARGET_OBJECT_SUFFIX 10990277Sobrien#else 11090277Sobrien#define TARGET_OBJECT_SUFFIX ".o" 11118334Speter#endif 11218334Speter 11390277Sobrienstatic const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; 11452520Sobrien 11590277Sobrien/* Most every one is fine with LIBRARY_PATH. For some, it conflicts. */ 11690277Sobrien#ifndef LIBRARY_PATH_ENV 11790277Sobrien#define LIBRARY_PATH_ENV "LIBRARY_PATH" 11890277Sobrien#endif 11990277Sobrien 12050599Sobrien#ifndef HAVE_KILL 12150599Sobrien#define kill(p,s) raise(s) 12218334Speter#endif 12318334Speter 12418334Speter/* If a stage of compilation returns an exit status >= 1, 12518334Speter compilation of that file ceases. */ 12618334Speter 12718334Speter#define MIN_FATAL_STATUS 1 12818334Speter 12990277Sobrien/* Flag set by cppspec.c to 1. */ 13090277Sobrienint is_cpp_driver; 13190277Sobrien 13290277Sobrien/* Flag saying to pass the greatest exit code returned by a sub-process 13390277Sobrien to the calling program. */ 13490277Sobrienstatic int pass_exit_codes; 13590277Sobrien 13690277Sobrien/* Definition of string containing the arguments given to configure. */ 13790277Sobrien#include "configargs.h" 13890277Sobrien 13918334Speter/* Flag saying to print the directories gcc will search through looking for 14018334Speter programs, libraries, etc. */ 14118334Speter 14218334Speterstatic int print_search_dirs; 14318334Speter 14418334Speter/* Flag saying to print the full filename of this file 14518334Speter as found through our usual search mechanism. */ 14618334Speter 14752520Sobrienstatic const char *print_file_name = NULL; 14818334Speter 14950599Sobrien/* As print_file_name, but search for executable file. */ 15018334Speter 15152520Sobrienstatic const char *print_prog_name = NULL; 15218334Speter 15318334Speter/* Flag saying to print the relative path we'd use to 15418334Speter find libgcc.a given the current compiler flags. */ 15518334Speter 15618334Speterstatic int print_multi_directory; 15718334Speter 158104763Skan/* Flag saying to print the relative path we'd use to 159104763Skan find OS libraries given the current compiler flags. */ 160104763Skan 161104763Skanstatic int print_multi_os_directory; 162104763Skan 16318334Speter/* Flag saying to print the list of subdirectories and 16418334Speter compiler flags used to select them in a standard form. */ 16518334Speter 16618334Speterstatic int print_multi_lib; 16718334Speter 16850599Sobrien/* Flag saying to print the command line options understood by gcc and its 16950599Sobrien sub-processes. */ 17050599Sobrien 17150599Sobrienstatic int print_help_list; 17250599Sobrien 17318334Speter/* Flag indicating whether we should print the command and arguments */ 17418334Speter 17518334Speterstatic int verbose_flag; 17618334Speter 17790277Sobrien/* Flag indicating whether we should ONLY print the command and 17890277Sobrien arguments (like verbose_flag) without executing the command. 17990277Sobrien Displayed arguments are quoted so that the generated command 18090277Sobrien line is suitable for execution. This is intended for use in 18190277Sobrien shell scripts to capture the driver-generated command line. */ 18290277Sobrienstatic int verbose_only_flag; 18390277Sobrien 18490277Sobrien/* Flag indicating to print target specific command line options. */ 18590277Sobrien 18690277Sobrienstatic int target_help_flag; 18790277Sobrien 18890277Sobrien/* Flag indicating whether we should report subprocess execution times 18990277Sobrien (if this is supported by the system - see pexecute.c). */ 19090277Sobrien 19190277Sobrienstatic int report_times; 19290277Sobrien 193132733Skan/* Nonzero means place this string before uses of /, so that include 194132733Skan and library files can be found in an alternate location. */ 195132733Skan 196132733Skan#ifdef TARGET_SYSTEM_ROOT 197132733Skanstatic const char *target_system_root = TARGET_SYSTEM_ROOT; 198132733Skan#else 199132733Skanstatic const char *target_system_root = 0; 200132733Skan#endif 201132733Skan 202132733Skan/* Nonzero means pass the updated target_system_root to the compiler. */ 203132733Skan 204132733Skanstatic int target_system_root_changed; 205132733Skan 206132733Skan/* Nonzero means append this string to target_system_root. */ 207132733Skan 208132733Skanstatic const char *target_sysroot_suffix = 0; 209132733Skan 210132733Skan/* Nonzero means append this string to target_system_root for headers. */ 211132733Skan 212132733Skanstatic const char *target_sysroot_hdrs_suffix = 0; 213132733Skan 21418334Speter/* Nonzero means write "temp" files in source directory 21518334Speter and use the source file's name in them, and don't delete them. */ 21618334Speter 21718334Speterstatic int save_temps_flag; 21818334Speter 219169704Skan/* Nonzero means pass multiple source files to the compiler at one time. */ 220169704Skan 221169704Skanstatic int combine_flag = 0; 222169704Skan 223132733Skan/* Nonzero means use pipes to communicate between subprocesses. 224132733Skan Overridden by either of the above two flags. */ 225132733Skan 226132733Skanstatic int use_pipes; 227132733Skan 22818334Speter/* The compiler version. */ 22918334Speter 23090277Sobrienstatic const char *compiler_version; 23118334Speter 23218334Speter/* The target version specified with -V */ 23318334Speter 234117413Skanstatic const char *const spec_version = DEFAULT_TARGET_VERSION; 23518334Speter 23618334Speter/* The target machine specified with -b. */ 23718334Speter 23852520Sobrienstatic const char *spec_machine = DEFAULT_TARGET_MACHINE; 23918334Speter 24018334Speter/* Nonzero if cross-compiling. 24118334Speter When -b is used, the value comes from the `specs' file. */ 24218334Speter 243259563Spfg#ifdef CROSS_DIRECTORY_STRUCTURE 24490277Sobrienstatic const char *cross_compile = "1"; 24518334Speter#else 24690277Sobrienstatic const char *cross_compile = "0"; 24718334Speter#endif 24818334Speter 24990277Sobrien#ifdef MODIFY_TARGET_NAME 25090277Sobrien 25190277Sobrien/* Information on how to alter the target name based on a command-line 25290277Sobrien switch. The only case we support now is simply appending or deleting a 25390277Sobrien string to or from the end of the first part of the configuration name. */ 25490277Sobrien 25590277Sobrienstatic const struct modify_target 25690277Sobrien{ 25790277Sobrien const char *const sw; 25890277Sobrien const enum add_del {ADD, DELETE} add_del; 25990277Sobrien const char *const str; 26090277Sobrien} 26190277Sobrienmodify_target[] = MODIFY_TARGET_NAME; 26290277Sobrien#endif 263117413Skan 26418334Speter/* The number of errors that have occurred; the link phase will not be 265117413Skan run if this is nonzero. */ 26618334Speterstatic int error_count = 0; 26718334Speter 26890277Sobrien/* Greatest exit code of sub-processes that has been encountered up to 26990277Sobrien now. */ 27090277Sobrienstatic int greatest_status = 1; 27190277Sobrien 27218334Speter/* This is the obstack which we use to allocate many strings. */ 27318334Speter 27418334Speterstatic struct obstack obstack; 27518334Speter 27618334Speter/* This is the obstack to build an environment variable to pass to 27718334Speter collect2 that describes all of the relevant switches of what to 27818334Speter pass the compiler in building the list of pointers to constructors 27918334Speter and destructors. */ 28018334Speter 28118334Speterstatic struct obstack collect_obstack; 28218334Speter 28318334Speter/* Forward declaration for prototypes. */ 28418334Speterstruct path_prefix; 285169704Skanstruct prefix_list; 28618334Speter 287132733Skanstatic void init_spec (void); 288132733Skanstatic void store_arg (const char *, int, int); 289132733Skanstatic char *load_specs (const char *); 290132733Skanstatic void read_specs (const char *, int); 291132733Skanstatic void set_spec (const char *, const char *); 292132733Skanstatic struct compiler *lookup_compiler (const char *, size_t, const char *); 293169704Skanstatic char *build_search_list (const struct path_prefix *, const char *, 294169704Skan bool, bool); 295169704Skanstatic void putenv_from_prefixes (const struct path_prefix *, const char *, 296169704Skan bool); 297132733Skanstatic int access_check (const char *, int); 298169704Skanstatic char *find_a_file (const struct path_prefix *, const char *, int, bool); 299132733Skanstatic void add_prefix (struct path_prefix *, const char *, const char *, 300169704Skan int, int, int); 301132733Skanstatic void add_sysrooted_prefix (struct path_prefix *, const char *, 302169704Skan const char *, int, int, int); 303132733Skanstatic void translate_options (int *, const char *const **); 304132733Skanstatic char *skip_whitespace (char *); 305132733Skanstatic void delete_if_ordinary (const char *); 306132733Skanstatic void delete_temp_files (void); 307132733Skanstatic void delete_failure_queue (void); 308132733Skanstatic void clear_failure_queue (void); 309132733Skanstatic int check_live_switch (int, int); 310132733Skanstatic const char *handle_braces (const char *); 311132733Skanstatic inline bool input_suffix_matches (const char *, const char *); 312132733Skanstatic inline bool switch_matches (const char *, const char *, int); 313132733Skanstatic inline void mark_matching_switches (const char *, const char *, int); 314132733Skanstatic inline void process_marked_switches (void); 315132733Skanstatic const char *process_brace_body (const char *, const char *, const char *, int, int); 316132733Skanstatic const struct spec_function *lookup_spec_function (const char *); 317132733Skanstatic const char *eval_spec_function (const char *, const char *); 318132733Skanstatic const char *handle_spec_function (const char *); 319132733Skanstatic char *save_string (const char *, int); 320132733Skanstatic void set_collect_gcc_options (void); 321132733Skanstatic int do_spec_1 (const char *, int, const char *); 322132733Skanstatic int do_spec_2 (const char *); 323132733Skanstatic void do_option_spec (const char *, const char *); 324132733Skanstatic void do_self_spec (const char *); 325132733Skanstatic const char *find_file (const char *); 326169704Skanstatic int is_directory (const char *, bool); 327132733Skanstatic const char *validate_switches (const char *); 328132733Skanstatic void validate_all_switches (void); 329132733Skanstatic inline void validate_switches_from_spec (const char *); 330132733Skanstatic void give_switch (int, int); 331132733Skanstatic int used_arg (const char *, int); 332132733Skanstatic int default_arg (const char *, int); 333132733Skanstatic void set_multilib_dir (void); 334132733Skanstatic void print_multilib_info (void); 335132733Skanstatic void perror_with_name (const char *); 336169704Skanstatic void fatal_ice (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN; 337132733Skanstatic void notice (const char *, ...) ATTRIBUTE_PRINTF_1; 338132733Skanstatic void display_help (void); 339132733Skanstatic void add_preprocessor_option (const char *, int); 340132733Skanstatic void add_assembler_option (const char *, int); 341132733Skanstatic void add_linker_option (const char *, int); 342132733Skanstatic void process_command (int, const char **); 343132733Skanstatic int execute (void); 344132733Skanstatic void alloc_args (void); 345132733Skanstatic void clear_args (void); 346132733Skanstatic void fatal_error (int); 347169704Skan#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC) 348132733Skanstatic void init_gcc_specs (struct obstack *, const char *, const char *, 349132733Skan const char *); 35090277Sobrien#endif 35190277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 352132733Skanstatic const char *convert_filename (const char *, int, int); 35390277Sobrien#endif 354117413Skan 355132733Skanstatic const char *if_exists_spec_function (int, const char **); 356132733Skanstatic const char *if_exists_else_spec_function (int, const char **); 357169704Skanstatic const char *replace_outfile_spec_function (int, const char **); 358169704Skanstatic const char *version_compare_spec_function (int, const char **); 359169704Skanstatic const char *include_spec_function (int, const char **); 36090277Sobrien 36190277Sobrien/* The Specs Language 36218334Speter 36390277SobrienSpecs are strings containing lines, each of which (if not blank) 36418334Speteris made up of a program name, and arguments separated by spaces. 36518334SpeterThe program name must be exact and start from root, since no path 36618334Speteris searched and it is unreliable to depend on the current working directory. 36718334SpeterRedirection of input or output is not supported; the subprograms must 36818334Speteraccept filenames saying what files to read and write. 36918334Speter 37018334SpeterIn addition, the specs can contain %-sequences to substitute variable text 37118334Speteror for conditional text. Here is a table of all defined %-sequences. 37218334SpeterNote that spaces are not generated automatically around the results of 37318334Speterexpanding these sequences; therefore, you can concatenate them together 37418334Speteror with constant text in a single argument. 37518334Speter 37618334Speter %% substitute one % into the program name or argument. 37718334Speter %i substitute the name of the input file being processed. 37818334Speter %b substitute the basename of the input file being processed. 37918334Speter This is the substring up to (and not including) the last period 38018334Speter and not including the directory. 38190277Sobrien %B same as %b, but include the file suffix (text after the last period). 38250599Sobrien %gSUFFIX 38350599Sobrien substitute a file name that has suffix SUFFIX and is chosen 38450599Sobrien once per compilation, and mark the argument a la %d. To reduce 38550599Sobrien exposure to denial-of-service attacks, the file name is now 38650599Sobrien chosen in a way that is hard to predict even when previously 38750599Sobrien chosen file names are known. For example, `%g.s ... %g.o ... %g.s' 38850599Sobrien might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'. SUFFIX matches 389169704Skan the regexp "[.0-9A-Za-z]*%O"; "%O" is treated exactly as if it 39090277Sobrien had been pre-processed. Previously, %g was simply substituted 39190277Sobrien with a file name chosen once per compilation, without regard 39290277Sobrien to any appended suffix (which was therefore treated just like 39390277Sobrien ordinary text), making such attacks more likely to succeed. 394132733Skan %|SUFFIX 395132733Skan like %g, but if -pipe is in effect, expands simply to "-". 396132733Skan %mSUFFIX 397132733Skan like %g, but if -pipe is in effect, expands to nothing. (We have both 398132733Skan %| and %m to accommodate differences between system assemblers; see 399132733Skan the AS_NEEDS_DASH_FOR_PIPED_INPUT target macro.) 40050599Sobrien %uSUFFIX 40150599Sobrien like %g, but generates a new temporary file name even if %uSUFFIX 40250599Sobrien was already seen. 40350599Sobrien %USUFFIX 40450599Sobrien substitutes the last file name generated with %uSUFFIX, generating a 40550599Sobrien new one if there is no such last file name. In the absence of any 40650599Sobrien %uSUFFIX, this is just like %gSUFFIX, except they don't share 40750599Sobrien the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s' 40850599Sobrien would involve the generation of two distinct file names, one 40950599Sobrien for each `%g.s' and another for each `%U.s'. Previously, %U was 41050599Sobrien simply substituted with a file name chosen for the previous %u, 41150599Sobrien without regard to any appended suffix. 41290277Sobrien %jSUFFIX 41390277Sobrien substitutes the name of the HOST_BIT_BUCKET, if any, and if it is 41490277Sobrien writable, and if save-temps is off; otherwise, substitute the name 41590277Sobrien of a temporary file, just like %u. This temporary file is not 41690277Sobrien meant for communication between processes, but rather as a junk 41790277Sobrien disposal mechanism. 41890277Sobrien %.SUFFIX 41990277Sobrien substitutes .SUFFIX for the suffixes of a matched switch's args when 42090277Sobrien it is subsequently output with %*. SUFFIX is terminated by the next 42190277Sobrien space or %. 42218334Speter %d marks the argument containing or following the %d as a 42318334Speter temporary file name, so that that file will be deleted if CC exits 42418334Speter successfully. Unlike %g, this contributes no text to the argument. 42518334Speter %w marks the argument containing or following the %w as the 42618334Speter "output file" of this compilation. This puts the argument 42718334Speter into the sequence of arguments that %o will substitute later. 428132733Skan %V indicates that this compilation produces no "output file". 42918334Speter %W{...} 43018334Speter like %{...} but mark last argument supplied within 43118334Speter as a file to be deleted on failure. 43218334Speter %o substitutes the names of all the output files, with spaces 43318334Speter automatically placed around them. You should write spaces 43418334Speter around the %o as well or the results are undefined. 43518334Speter %o is for use in the specs for running the linker. 43618334Speter Input files whose names have no recognized suffix are not compiled 43718334Speter at all, but they are included among the output files, so they will 43818334Speter be linked. 43950599Sobrien %O substitutes the suffix for object files. Note that this is 44090277Sobrien handled specially when it immediately follows %g, %u, or %U 44190277Sobrien (with or without a suffix argument) because of the need for 44290277Sobrien those to form complete file names. The handling is such that 44390277Sobrien %O is treated exactly as if it had already been substituted, 44490277Sobrien except that %g, %u, and %U do not currently support additional 44590277Sobrien SUFFIX characters following %O as they would following, for 44690277Sobrien example, `.o'. 447132733Skan %I Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot 448169704Skan (made from TARGET_SYSTEM_ROOT), -isystem (made from COMPILER_PATH 449169704Skan and -B options) and -imultilib as necessary. 45018334Speter %s current argument is the name of a library or startup file of some sort. 45118334Speter Search for that file in a standard list of directories 45218334Speter and substitute the full name found. 45318334Speter %eSTR Print STR as an error message. STR is terminated by a newline. 45418334Speter Use this when inconsistent options are detected. 455117413Skan %nSTR Print STR as a notice. STR is terminated by a newline. 45618334Speter %x{OPTION} Accumulate an option for %X. 45718334Speter %X Output the accumulated linker options specified by compilations. 45818334Speter %Y Output the accumulated assembler options specified by compilations. 45918334Speter %Z Output the accumulated preprocessor options specified by compilations. 46018334Speter %a process ASM_SPEC as a spec. 46118334Speter This allows config.h to specify part of the spec for running as. 46218334Speter %A process ASM_FINAL_SPEC as a spec. A capital A is actually 46318334Speter used here. This can be used to run a post-processor after the 46450599Sobrien assembler has done its job. 46518334Speter %D Dump out a -L option for each directory in startfile_prefixes. 46618334Speter If multilib_dir is set, extra entries are generated with it affixed. 46718334Speter %l process LINK_SPEC as a spec. 46818334Speter %L process LIB_SPEC as a spec. 46918334Speter %G process LIBGCC_SPEC as a spec. 470169704Skan %R Output the concatenation of target_system_root and 471169704Skan target_sysroot_suffix. 47218334Speter %S process STARTFILE_SPEC as a spec. A capital S is actually used here. 47318334Speter %E process ENDFILE_SPEC as a spec. A capital E is actually used here. 47490277Sobrien %C process CPP_SPEC as a spec. 47518334Speter %1 process CC1_SPEC as a spec. 47618334Speter %2 process CC1PLUS_SPEC as a spec. 47718334Speter %* substitute the variable part of a matched option. (See below.) 47818334Speter Note that each comma in the substituted string is replaced by 47918334Speter a single space. 480132733Skan %<S remove all occurrences of -S from the command line. 481132733Skan Note - this command is position dependent. % commands in the 482132733Skan spec string before this one will see -S, % commands in the 483132733Skan spec string after this one will not. 484132733Skan %<S* remove all occurrences of all switches beginning with -S from the 485132733Skan command line. 486117413Skan %:function(args) 487117413Skan Call the named function FUNCTION, passing it ARGS. ARGS is 488117413Skan first processed as a nested spec string, then split into an 489117413Skan argument vector in the usual fashion. The function returns 490117413Skan a string which is processed as if it had appeared literally 491117413Skan as part of the current spec. 49218334Speter %{S} substitutes the -S switch, if that switch was given to CC. 49318334Speter If that switch was not specified, this substitutes nothing. 49418334Speter Here S is a metasyntactic variable. 49518334Speter %{S*} substitutes all the switches specified to CC whose names start 49690277Sobrien with -S. This is used for -o, -I, etc; switches that take 49718334Speter arguments. CC considers `-o foo' as being one switch whose 49818334Speter name starts with `o'. %{o*} would substitute this text, 49918334Speter including the space; thus, two arguments would be generated. 50090277Sobrien %{S*&T*} likewise, but preserve order of S and T options (the order 501132733Skan of S and T in the spec is not significant). Can be any number 502132733Skan of ampersand-separated variables; for each the wild card is 503132733Skan optional. Useful for CPP as %{D*&U*&A*}. 504132733Skan 505132733Skan %{S:X} substitutes X, if the -S switch was given to CC. 506132733Skan %{!S:X} substitutes X, if the -S switch was NOT given to CC. 507132733Skan %{S*:X} substitutes X if one or more switches whose names start 508132733Skan with -S was given to CC. Normally X is substituted only 509132733Skan once, no matter how many such switches appeared. However, 510132733Skan if %* appears somewhere in X, then X will be substituted 511132733Skan once for each matching switch, with the %* replaced by the 512132733Skan part of that switch that matched the '*'. 513132733Skan %{.S:X} substitutes X, if processing a file with suffix S. 514132733Skan %{!.S:X} substitutes X, if NOT processing a file with suffix S. 515132733Skan 516132733Skan %{S|T:X} substitutes X if either -S or -T was given to CC. This may be 517132733Skan combined with !, ., and * as above binding stronger than the OR. 518132733Skan If %* appears in X, all of the alternatives must be starred, and 519132733Skan only the first matching alternative is substituted. 520132733Skan %{S:X; if S was given to CC, substitutes X; 521132733Skan T:Y; else if T was given to CC, substitutes Y; 522132733Skan :D} else substitutes D. There can be as many clauses as you need. 523132733Skan This may be combined with ., !, |, and * as above. 524132733Skan 52518334Speter %(Spec) processes a specification defined in a specs file as *Spec: 52618334Speter %[Spec] as above, but put __ around -D arguments 52718334Speter 528132733SkanThe conditional text X in a %{S:X} or similar construct may contain 52918334Speterother nested % constructs or spaces, or even newlines. They are 530132733Skanprocessed as usual, as described above. Trailing white space in X is 531132733Skanignored. White space may also appear anywhere on the left side of the 532132733Skancolon in these constructs, except between . or * and the corresponding 533132733Skanword. 53418334Speter 53518334SpeterThe -O, -f, -m, and -W switches are handled specifically in these 53618334Speterconstructs. If another value of -O or the negated form of a -f, -m, or 53718334Speter-W switch is found later in the command line, the earlier switch 53818334Spetervalue is ignored, except with {S*} where S is just one letter; this 53918334Speterpasses all matching options. 54018334Speter 54150599SobrienThe character | at the beginning of the predicate text is used to indicate 54250599Sobrienthat a command should be piped to the following command, but only if -pipe 54350599Sobrienis specified. 54418334Speter 54518334SpeterNote that it is built into CC which switches take arguments and which 54618334Speterdo not. You might think it would be useful to generalize this to 54718334Speterallow each compiler's spec to say which switches take arguments. But 54818334Speterthis cannot be done in a consistent fashion. CC cannot even decide 54918334Speterwhich input files have been specified without knowing which switches 55018334Spetertake arguments, and it must know which input files to compile in order 55118334Speterto tell which compilers to run. 55218334Speter 55318334SpeterCC also knows implicitly that arguments starting in `-l' are to be 55418334Spetertreated as compiler output files, and passed to the linker in their 55518334Speterproper position among the other output files. */ 55618334Speter 55796285Sobrien/* Define the macros used for specs %a, %l, %L, %S, %C, %1. */ 55818334Speter 55918334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler 56018334Speter or extra switch-translations. */ 56118334Speter#ifndef ASM_SPEC 56218334Speter#define ASM_SPEC "" 56318334Speter#endif 56418334Speter 56518334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after 56618334Speter the assembler has run. */ 56718334Speter#ifndef ASM_FINAL_SPEC 56818334Speter#define ASM_FINAL_SPEC "" 56918334Speter#endif 57018334Speter 57118334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor 57218334Speter or extra switch-translations. */ 57318334Speter#ifndef CPP_SPEC 57418334Speter#define CPP_SPEC "" 57518334Speter#endif 57618334Speter 57718334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus 57818334Speter or extra switch-translations. */ 57918334Speter#ifndef CC1_SPEC 58018334Speter#define CC1_SPEC "" 58118334Speter#endif 58218334Speter 58318334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus 58418334Speter or extra switch-translations. */ 58518334Speter#ifndef CC1PLUS_SPEC 58618334Speter#define CC1PLUS_SPEC "" 58718334Speter#endif 58818334Speter 58918334Speter/* config.h can define LINK_SPEC to provide extra args to the linker 59018334Speter or extra switch-translations. */ 59118334Speter#ifndef LINK_SPEC 59218334Speter#define LINK_SPEC "" 59318334Speter#endif 59418334Speter 59518334Speter/* config.h can define LIB_SPEC to override the default libraries. */ 59618334Speter#ifndef LIB_SPEC 59718334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}" 59818334Speter#endif 59918334Speter 600169704Skan/* mudflap specs */ 601169704Skan#ifndef MFWRAP_SPEC 602169704Skan/* XXX: valid only for GNU ld */ 603169704Skan/* XXX: should exactly match hooks provided by libmudflap.a */ 604169704Skan#define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \ 605169704Skan --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\ 606169704Skan --wrap=mmap --wrap=munmap --wrap=alloca\ 607169704Skan} %{fmudflapth: --wrap=pthread_create\ 608169704Skan}} %{fmudflap|fmudflapth: --wrap=main}" 609169704Skan#endif 610169704Skan#ifndef MFLIB_SPEC 611169704Skan#define MFLIB_SPEC "%{fmudflap|fmudflapth: -export-dynamic}" 612169704Skan#endif 613169704Skan 61418334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is 61518334Speter included. */ 61618334Speter#ifndef LIBGCC_SPEC 617169704Skan#if defined(REAL_LIBGCC_SPEC) 618169704Skan#define LIBGCC_SPEC REAL_LIBGCC_SPEC 619169704Skan#elif defined(LINK_LIBGCC_SPECIAL_1) 62018334Speter/* Have gcc do the search for libgcc.a. */ 62150599Sobrien#define LIBGCC_SPEC "libgcc.a%s" 62218334Speter#else 62350599Sobrien#define LIBGCC_SPEC "-lgcc" 62418334Speter#endif 62518334Speter#endif 62618334Speter 62718334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files. */ 62818334Speter#ifndef STARTFILE_SPEC 62918334Speter#define STARTFILE_SPEC \ 63018334Speter "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}" 63118334Speter#endif 63218334Speter 63350599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options 63450599Sobrien require spaces between the option and the argument. */ 63518334Speter#ifndef SWITCHES_NEED_SPACES 63618334Speter#define SWITCHES_NEED_SPACES "" 63718334Speter#endif 63818334Speter 63918334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files. */ 64018334Speter#ifndef ENDFILE_SPEC 64118334Speter#define ENDFILE_SPEC "" 64218334Speter#endif 64318334Speter 64450599Sobrien#ifndef LINKER_NAME 64550599Sobrien#define LINKER_NAME "collect2" 64618334Speter#endif 64718334Speter 64890277Sobrien/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g' 64990277Sobrien to the assembler. */ 65090277Sobrien#ifndef ASM_DEBUG_SPEC 65190277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \ 65290277Sobrien && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) 65390277Sobrien# define ASM_DEBUG_SPEC \ 65490277Sobrien (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \ 65590277Sobrien ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" \ 65690277Sobrien : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}") 65790277Sobrien# else 65890277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) 65990277Sobrien# define ASM_DEBUG_SPEC "%{g*:--gstabs}" 66090277Sobrien# endif 66190277Sobrien# if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) 66290277Sobrien# define ASM_DEBUG_SPEC "%{g*:--gdwarf2}" 66390277Sobrien# endif 66490277Sobrien# endif 66590277Sobrien#endif 66690277Sobrien#ifndef ASM_DEBUG_SPEC 66790277Sobrien# define ASM_DEBUG_SPEC "" 66890277Sobrien#endif 66918334Speter 67090277Sobrien/* Here is the spec for running the linker, after compiling all files. */ 67190277Sobrien 67296285Sobrien/* This is overridable by the target in case they need to specify the 67396285Sobrien -lgcc and -lc order specially, yet not require them to override all 67496285Sobrien of LINK_COMMAND_SPEC. */ 67596285Sobrien#ifndef LINK_GCC_C_SEQUENCE_SPEC 67696285Sobrien#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G" 67796285Sobrien#endif 67896285Sobrien 679169704Skan#ifndef LINK_SSP_SPEC 680169704Skan#ifdef TARGET_LIBC_PROVIDES_SSP 681169704Skan#define LINK_SSP_SPEC "%{fstack-protector:}" 682169704Skan#else 683286713Spfg#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-strong|fstack-protector-all:-lssp_nonshared -lssp}" 684169704Skan#endif 685169704Skan#endif 686169704Skan 687132733Skan#ifndef LINK_PIE_SPEC 688132733Skan#ifdef HAVE_LD_PIE 689132733Skan#define LINK_PIE_SPEC "%{pie:-pie} " 690132733Skan#else 691132733Skan#define LINK_PIE_SPEC "%{pie:} " 692132733Skan#endif 693132733Skan#endif 694132733Skan 69590277Sobrien/* -u* was put back because both BSD and SysV seem to support it. */ 69690277Sobrien/* %{static:} simply prevents an error message if the target machine 69790277Sobrien doesn't handle -static. */ 69890277Sobrien/* We want %{T*} after %{L*} and %D so that it can be used to specify linker 69990277Sobrien scripts which exist in user specified directories, or in standard 70090277Sobrien directories. */ 70190277Sobrien#ifndef LINK_COMMAND_SPEC 702169704Skan#ifndef FREEBSD_NATIVE 70390277Sobrien#define LINK_COMMAND_SPEC "\ 70490277Sobrien%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ 705132733Skan %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\ 706132733Skan %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ 707169704Skan %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\ 708169704Skan %{fopenmp:%:include(libgomp.spec)%(link_gomp)} %(mflib)\ 709169704Skan %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\ 710169704Skan %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\ 71190277Sobrien %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}" 712169704Skan#else 713169704Skan#define LINK_COMMAND_SPEC "\ 714169704Skan%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ 715169704Skan %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\ 716169704Skan %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ 717169704Skan %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\ 718169704Skan %{fopenmp: -lgomp} %(mflib)\ 719169704Skan %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\ 720169704Skan %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\ 721169704Skan %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}" 72290277Sobrien#endif 723169704Skan#endif 72490277Sobrien 72590277Sobrien#ifndef LINK_LIBGCC_SPEC 726169704Skan/* Generate -L options for startfile prefix list. */ 727169704Skan# define LINK_LIBGCC_SPEC "%D" 72890277Sobrien#endif 72990277Sobrien 730117413Skan#ifndef STARTFILE_PREFIX_SPEC 731117413Skan# define STARTFILE_PREFIX_SPEC "" 732117413Skan#endif 733117413Skan 734169704Skan#ifndef SYSROOT_SPEC 735169704Skan# define SYSROOT_SPEC "--sysroot=%R" 736169704Skan#endif 737169704Skan 738132733Skan#ifndef SYSROOT_SUFFIX_SPEC 739132733Skan# define SYSROOT_SUFFIX_SPEC "" 740132733Skan#endif 741132733Skan 742132733Skan#ifndef SYSROOT_HEADERS_SUFFIX_SPEC 743132733Skan# define SYSROOT_HEADERS_SUFFIX_SPEC "" 744132733Skan#endif 745132733Skan 746117413Skanstatic const char *asm_debug; 74790277Sobrienstatic const char *cpp_spec = CPP_SPEC; 74890277Sobrienstatic const char *cc1_spec = CC1_SPEC; 74990277Sobrienstatic const char *cc1plus_spec = CC1PLUS_SPEC; 75096285Sobrienstatic const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC; 751169704Skanstatic const char *link_ssp_spec = LINK_SSP_SPEC; 75290277Sobrienstatic const char *asm_spec = ASM_SPEC; 75390277Sobrienstatic const char *asm_final_spec = ASM_FINAL_SPEC; 75490277Sobrienstatic const char *link_spec = LINK_SPEC; 75590277Sobrienstatic const char *lib_spec = LIB_SPEC; 756169704Skanstatic const char *mfwrap_spec = MFWRAP_SPEC; 757169704Skanstatic const char *mflib_spec = MFLIB_SPEC; 758169704Skanstatic const char *link_gomp_spec = ""; 75990277Sobrienstatic const char *libgcc_spec = LIBGCC_SPEC; 76090277Sobrienstatic const char *endfile_spec = ENDFILE_SPEC; 76190277Sobrienstatic const char *startfile_spec = STARTFILE_SPEC; 76290277Sobrienstatic const char *switches_need_spaces = SWITCHES_NEED_SPACES; 76390277Sobrienstatic const char *linker_name_spec = LINKER_NAME; 76490277Sobrienstatic const char *link_command_spec = LINK_COMMAND_SPEC; 76590277Sobrienstatic const char *link_libgcc_spec = LINK_LIBGCC_SPEC; 766117413Skanstatic const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC; 767169704Skanstatic const char *sysroot_spec = SYSROOT_SPEC; 768132733Skanstatic const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC; 769132733Skanstatic const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC; 77090277Sobrien 77190277Sobrien/* Standard options to cpp, cc1, and as, to reduce duplication in specs. 77290277Sobrien There should be no need to override these in target dependent files, 77390277Sobrien but we need to copy them to the specs file so that newer versions 77490277Sobrien of the GCC driver can correctly drive older tool chains with the 77590277Sobrien appropriate -B options. */ 77690277Sobrien 777117413Skan/* When cpplib handles traditional preprocessing, get rid of this, and 778117413Skan call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so 779117413Skan that we default the front end language better. */ 78090277Sobrienstatic const char *trad_capable_cpp = 781117413Skan"cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}"; 78290277Sobrien 783107594Sobrien/* We don't wrap .d files in %W{} since a missing .d file, and 784107594Sobrien therefore no dependency entry, confuses make into thinking a .o 785107594Sobrien file that happens to exist is up-to-date. */ 78690277Sobrienstatic const char *cpp_unique_options = 787132733Skan"%{C|CC:%{!E:%eGCC does not support -C or -CC without -E}}\ 788169704Skan %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I\ 789107594Sobrien %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\ 790107594Sobrien %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\ 791107594Sobrien %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\ 79296285Sobrien %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\ 793146908Skan %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\ 794169704Skan %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\ 795169704Skan %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\ 79696285Sobrien %{E|M|MM:%W{o*}}"; 79790277Sobrien 79890277Sobrien/* This contains cpp options which are common with cc1_options and are passed 799117413Skan only when preprocessing only to avoid duplication. We pass the cc1 spec 800117413Skan options to the preprocessor so that it the cc1 spec may manipulate 801117413Skan options used to set target flags. Those special target flags settings may 802117413Skan in turn cause preprocessor symbols to be defined specially. */ 80390277Sobrienstatic const char *cpp_options = 804146908Skan"%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\ 805146908Skan %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\ 806169704Skan %{undef} %{save-temps:-fpch-preprocess}"; 80790277Sobrien 808117413Skan/* This contains cpp options which are not passed when the preprocessor 809117413Skan output will be used by another program. */ 810117413Skanstatic const char *cpp_debug_options = "%{d*}"; 811117413Skan 81290277Sobrien/* NB: This is shared amongst all front-ends. */ 81390277Sobrienstatic const char *cc1_options = 81490277Sobrien"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 81590277Sobrien %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\ 816132733Skan %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\ 817146908Skan %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\ 818117413Skan %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\ 81990277Sobrien %{Qn:-fno-ident} %{--help:--help}\ 82090277Sobrien %{--target-help:--target-help}\ 82190277Sobrien %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\ 822169704Skan %{fsyntax-only:-o %j} %{-param*}\ 823169704Skan %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\ 824169704Skan %{coverage:-fprofile-arcs -ftest-coverage}"; 82590277Sobrien 82690277Sobrienstatic const char *asm_options = 82790277Sobrien"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}"; 82890277Sobrien 82990277Sobrienstatic const char *invoke_as = 830132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT 831132733Skan"%{!S:-o %|.s |\n as %(asm_options) %|.s %A }"; 832132733Skan#else 833132733Skan"%{!S:-o %|.s |\n as %(asm_options) %m.s %A }"; 834132733Skan#endif 83590277Sobrien 83650599Sobrien/* Some compilers have limits on line lengths, and the multilib_select 83750599Sobrien and/or multilib_matches strings can be very long, so we build them at 83850599Sobrien run time. */ 83950599Sobrienstatic struct obstack multilib_obstack; 84090277Sobrienstatic const char *multilib_select; 84190277Sobrienstatic const char *multilib_matches; 84290277Sobrienstatic const char *multilib_defaults; 84390277Sobrienstatic const char *multilib_exclusions; 84450599Sobrien 84550599Sobrien/* Check whether a particular argument is a default argument. */ 84650599Sobrien 84750599Sobrien#ifndef MULTILIB_DEFAULTS 84850599Sobrien#define MULTILIB_DEFAULTS { "" } 84950599Sobrien#endif 85050599Sobrien 85190277Sobrienstatic const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS; 85250599Sobrien 853117413Skan#ifndef DRIVER_SELF_SPECS 854117413Skan#define DRIVER_SELF_SPECS "" 855117413Skan#endif 856117413Skan 857169704Skan/* Adding -fopenmp should imply pthreads. This is particularly important 858169704Skan for targets that use different start files and suchlike. */ 859169704Skan#ifndef GOMP_SELF_SPECS 860169704Skan#define GOMP_SELF_SPECS "%{fopenmp: -pthread}" 861169704Skan#endif 862117413Skan 863169704Skanstatic const char *const driver_self_specs[] = { 864169704Skan DRIVER_SELF_SPECS, GOMP_SELF_SPECS 865169704Skan}; 866169704Skan 867132733Skan#ifndef OPTION_DEFAULT_SPECS 868132733Skan#define OPTION_DEFAULT_SPECS { "", "" } 869132733Skan#endif 870132733Skan 871132733Skanstruct default_spec 872132733Skan{ 873132733Skan const char *name; 874132733Skan const char *spec; 875132733Skan}; 876132733Skan 877132733Skanstatic const struct default_spec 878132733Skan option_default_specs[] = { OPTION_DEFAULT_SPECS }; 879132733Skan 88090277Sobrienstruct user_specs 88190277Sobrien{ 88250599Sobrien struct user_specs *next; 88352520Sobrien const char *filename; 88450599Sobrien}; 88550599Sobrien 88650599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail; 88750599Sobrien 88850599Sobrien#ifndef SWITCH_TAKES_ARG 88950599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR) 89018334Speter#endif 89118334Speter 89218334Speter#ifndef WORD_SWITCH_TAKES_ARG 89318334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR) 89418334Speter#endif 89518334Speter 89690277Sobrien#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX 89750599Sobrien/* This defines which switches stop a full compilation. */ 89850599Sobrien#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \ 89950599Sobrien ((CHAR) == 'c' || (CHAR) == 'S') 90050599Sobrien 90150599Sobrien#ifndef SWITCH_CURTAILS_COMPILATION 90250599Sobrien#define SWITCH_CURTAILS_COMPILATION(CHAR) \ 90350599Sobrien DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) 90450599Sobrien#endif 90550599Sobrien#endif 90650599Sobrien 90718334Speter/* Record the mapping from file suffixes for compilation specs. */ 90818334Speter 90918334Speterstruct compiler 91018334Speter{ 91152520Sobrien const char *suffix; /* Use this compiler for input files 91218334Speter whose names end in this suffix. */ 91318334Speter 91490277Sobrien const char *spec; /* To use this compiler, run this spec. */ 91590277Sobrien 91690277Sobrien const char *cpp_spec; /* If non-NULL, substitute this spec 91790277Sobrien for `%C', rather than the usual 91890277Sobrien cpp_spec. */ 919169704Skan const int combinable; /* If nonzero, compiler can deal with 920169704Skan multiple source files at once (IMA). */ 921169704Skan const int needs_preprocessing; /* If nonzero, source files need to 922169704Skan be run through a preprocessor. */ 92318334Speter}; 92418334Speter 92518334Speter/* Pointer to a vector of `struct compiler' that gives the spec for 92618334Speter compiling a file, based on its suffix. 92718334Speter A file that does not end in any of these suffixes will be passed 92818334Speter unchanged to the loader and nothing else will be done to it. 92918334Speter 93018334Speter An entry containing two 0s is used to terminate the vector. 93118334Speter 93218334Speter If multiple entries match a file, the last matching one is used. */ 93318334Speter 93418334Speterstatic struct compiler *compilers; 93518334Speter 93618334Speter/* Number of entries in `compilers', not counting the null terminator. */ 93718334Speter 93818334Speterstatic int n_compilers; 93918334Speter 94018334Speter/* The default list of file name suffixes and their compilation specs. */ 94118334Speter 94290277Sobrienstatic const struct compiler default_compilers[] = 94318334Speter{ 94450599Sobrien /* Add lists of suffixes of known languages here. If those languages 94550599Sobrien were not present when we built the driver, we will hit these copies 94650599Sobrien and be given a more meaningful error than "file not used since 94750599Sobrien linking is not done". */ 948169704Skan {".m", "#Objective-C", 0, 0, 0}, {".mi", "#Objective-C", 0, 0, 0}, 949169704Skan {".mm", "#Objective-C++", 0, 0, 0}, {".M", "#Objective-C++", 0, 0, 0}, 950169704Skan {".mii", "#Objective-C++", 0, 0, 0}, 951169704Skan {".cc", "#C++", 0, 0, 0}, {".cxx", "#C++", 0, 0, 0}, 952169704Skan {".cpp", "#C++", 0, 0, 0}, {".cp", "#C++", 0, 0, 0}, 953169704Skan {".c++", "#C++", 0, 0, 0}, {".C", "#C++", 0, 0, 0}, 954169704Skan {".CPP", "#C++", 0, 0, 0}, {".ii", "#C++", 0, 0, 0}, 955169704Skan {".ads", "#Ada", 0, 0, 0}, {".adb", "#Ada", 0, 0, 0}, 956169704Skan {".f", "#Fortran", 0, 0, 0}, {".for", "#Fortran", 0, 0, 0}, 957169704Skan {".fpp", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0}, 958169704Skan {".FOR", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0}, 959169704Skan {".f90", "#Fortran", 0, 0, 0}, {".f95", "#Fortran", 0, 0, 0}, 960169704Skan {".F90", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0}, 961169704Skan {".r", "#Ratfor", 0, 0, 0}, 962169704Skan {".p", "#Pascal", 0, 0, 0}, {".pas", "#Pascal", 0, 0, 0}, 963169704Skan {".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0}, 964169704Skan {".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0}, 96550599Sobrien /* Next come the entries for C. */ 966169704Skan {".c", "@c", 0, 1, 1}, 96718334Speter {"@c", 96890277Sobrien /* cc1 has an integrated ISO C preprocessor. We should invoke the 969117413Skan external preprocessor if -save-temps is given. */ 970117413Skan "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\ 97190277Sobrien %{!E:%{!M:%{!MM:\ 972117413Skan %{traditional|ftraditional:\ 973117413Skan%eGNU C no longer supports -traditional without -E}\ 974169704Skan %{!combine:\ 975117413Skan %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ 976132733Skan %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\ 977132733Skan cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \ 978132733Skan %(cc1_options)}\ 979117413Skan %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\ 980117413Skan cc1 %(cpp_unique_options) %(cc1_options)}}}\ 981169704Skan %{!fsyntax-only:%(invoke_as)}} \ 982169704Skan %{combine:\ 983169704Skan %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ 984169704Skan %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i}}\ 985169704Skan %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\ 986169704Skan cc1 %(cpp_unique_options) %(cc1_options)}}\ 987169704Skan %{!fsyntax-only:%(invoke_as)}}}}}}", 0, 1, 1}, 98818334Speter {"-", 989146908Skan "%{!E:%e-E or -x required when input is from standard input}\ 990169704Skan %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0, 0, 0}, 991169704Skan {".h", "@c-header", 0, 0, 0}, 99218334Speter {"@c-header", 993132733Skan /* cc1 has an integrated ISO C preprocessor. We should invoke the 994132733Skan external preprocessor if -save-temps is given. */ 995132733Skan "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\ 996132733Skan %{!E:%{!M:%{!MM:\ 997132733Skan %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ 998132733Skan %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\ 999132733Skan cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \ 1000132733Skan %(cc1_options)\ 1001132733Skan -o %g.s %{!o*:--output-pch=%i.gch}\ 1002132733Skan %W{o*:--output-pch=%*}%V}\ 1003132733Skan %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\ 1004132733Skan cc1 %(cpp_unique_options) %(cc1_options)\ 1005132733Skan -o %g.s %{!o*:--output-pch=%i.gch}\ 1006169704Skan %W{o*:--output-pch=%*}%V}}}}}}", 0, 0, 0}, 1007169704Skan {".i", "@cpp-output", 0, 1, 0}, 100818334Speter {"@cpp-output", 1009169704Skan "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 1, 0}, 1010169704Skan {".s", "@assembler", 0, 1, 0}, 101118334Speter {"@assembler", 1012169704Skan "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 1, 0}, 1013169704Skan {".S", "@assembler-with-cpp", 0, 1, 0}, 101418334Speter {"@assembler-with-cpp", 1015132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT 101690277Sobrien "%(trad_capable_cpp) -lang-asm %(cpp_options)\ 1017117413Skan %{E|M|MM:%(cpp_debug_options)}\ 1018132733Skan %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\ 1019132733Skan as %(asm_debug) %(asm_options) %|.s %A }}}}" 1020132733Skan#else 1021132733Skan "%(trad_capable_cpp) -lang-asm %(cpp_options)\ 1022132733Skan %{E|M|MM:%(cpp_debug_options)}\ 1023132733Skan %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\ 1024132733Skan as %(asm_debug) %(asm_options) %m.s %A }}}}" 1025132733Skan#endif 1026169704Skan , 0, 1, 0}, 1027132733Skan 102818334Speter#include "specs.h" 1029132733Skan /* Mark end of table. */ 1030169704Skan {0, 0, 0, 0, 0} 103118334Speter}; 103218334Speter 103318334Speter/* Number of elements in default_compilers, not counting the terminator. */ 103418334Speter 1035117413Skanstatic const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1; 103618334Speter 103718334Speter/* A vector of options to give to the linker. 103818334Speter These options are accumulated by %x, 103918334Speter and substituted into the linker command with %X. */ 104018334Speterstatic int n_linker_options; 104118334Speterstatic char **linker_options; 104218334Speter 104318334Speter/* A vector of options to give to the assembler. 104418334Speter These options are accumulated by -Wa, 104518334Speter and substituted into the assembler command with %Y. */ 104618334Speterstatic int n_assembler_options; 104718334Speterstatic char **assembler_options; 104818334Speter 104918334Speter/* A vector of options to give to the preprocessor. 105018334Speter These options are accumulated by -Wp, 105118334Speter and substituted into the preprocessor command with %Z. */ 105218334Speterstatic int n_preprocessor_options; 105318334Speterstatic char **preprocessor_options; 105418334Speter 105518334Speter/* Define how to map long options into short ones. */ 105618334Speter 105718334Speter/* This structure describes one mapping. */ 105818334Speterstruct option_map 105918334Speter{ 106018334Speter /* The long option's name. */ 106190277Sobrien const char *const name; 106218334Speter /* The equivalent short option. */ 106390277Sobrien const char *const equivalent; 106418334Speter /* Argument info. A string of flag chars; NULL equals no options. 106518334Speter a => argument required. 106618334Speter o => argument optional. 106718334Speter j => join argument to equivalent, making one word. 106818334Speter * => require other text after NAME as an argument. */ 106990277Sobrien const char *const arg_info; 107018334Speter}; 107118334Speter 107218334Speter/* This is the table of mappings. Mappings are tried sequentially 107318334Speter for each option encountered; the first one that matches, wins. */ 107418334Speter 107590277Sobrienstatic const struct option_map option_map[] = 107618334Speter { 107718334Speter {"--all-warnings", "-Wall", 0}, 107818334Speter {"--ansi", "-ansi", 0}, 107918334Speter {"--assemble", "-S", 0}, 108018334Speter {"--assert", "-A", "a"}, 108152520Sobrien {"--classpath", "-fclasspath=", "aj"}, 108296285Sobrien {"--bootclasspath", "-fbootclasspath=", "aj"}, 108396285Sobrien {"--CLASSPATH", "-fclasspath=", "aj"}, 1084169704Skan {"--combine", "-combine", 0}, 108518334Speter {"--comments", "-C", 0}, 1086117413Skan {"--comments-in-macros", "-CC", 0}, 108718334Speter {"--compile", "-c", 0}, 108818334Speter {"--debug", "-g", "oj"}, 108950599Sobrien {"--define-macro", "-D", "aj"}, 109018334Speter {"--dependencies", "-M", 0}, 109118334Speter {"--dump", "-d", "a"}, 109218334Speter {"--dumpbase", "-dumpbase", "a"}, 1093169704Skan {"--encoding", "-fencoding=", "aj"}, 109418334Speter {"--entry", "-e", 0}, 109518334Speter {"--extra-warnings", "-W", 0}, 1096169704Skan {"--extdirs", "-fextdirs=", "aj"}, 109718334Speter {"--for-assembler", "-Wa", "a"}, 109818334Speter {"--for-linker", "-Xlinker", "a"}, 109918334Speter {"--force-link", "-u", "a"}, 1100169704Skan {"--coverage", "-coverage", 0}, 110118334Speter {"--imacros", "-imacros", "a"}, 110218334Speter {"--include", "-include", "a"}, 110318334Speter {"--include-barrier", "-I-", 0}, 110450599Sobrien {"--include-directory", "-I", "aj"}, 110518334Speter {"--include-directory-after", "-idirafter", "a"}, 110618334Speter {"--include-prefix", "-iprefix", "a"}, 110718334Speter {"--include-with-prefix", "-iwithprefix", "a"}, 110818334Speter {"--include-with-prefix-before", "-iwithprefixbefore", "a"}, 110918334Speter {"--include-with-prefix-after", "-iwithprefix", "a"}, 111018334Speter {"--language", "-x", "a"}, 111118334Speter {"--library-directory", "-L", "a"}, 111218334Speter {"--machine", "-m", "aj"}, 111318334Speter {"--machine-", "-m", "*j"}, 111496285Sobrien {"--no-integrated-cpp", "-no-integrated-cpp", 0}, 111518334Speter {"--no-line-commands", "-P", 0}, 111618334Speter {"--no-precompiled-includes", "-noprecomp", 0}, 111718334Speter {"--no-standard-includes", "-nostdinc", 0}, 111818334Speter {"--no-standard-libraries", "-nostdlib", 0}, 111918334Speter {"--no-warnings", "-w", 0}, 112018334Speter {"--optimize", "-O", "oj"}, 112118334Speter {"--output", "-o", "a"}, 112252520Sobrien {"--output-class-directory", "-foutput-class-dir=", "ja"}, 112390277Sobrien {"--param", "--param", "a"}, 1124169704Skan {"--pass-exit-codes", "-pass-exit-codes", 0}, 112518334Speter {"--pedantic", "-pedantic", 0}, 112618334Speter {"--pedantic-errors", "-pedantic-errors", 0}, 1127132733Skan {"--pie", "-pie", 0}, 112818334Speter {"--pipe", "-pipe", 0}, 112918334Speter {"--prefix", "-B", "a"}, 113018334Speter {"--preprocess", "-E", 0}, 113118334Speter {"--print-search-dirs", "-print-search-dirs", 0}, 113218334Speter {"--print-file-name", "-print-file-name=", "aj"}, 113318334Speter {"--print-libgcc-file-name", "-print-libgcc-file-name", 0}, 113418334Speter {"--print-missing-file-dependencies", "-MG", 0}, 113518334Speter {"--print-multi-lib", "-print-multi-lib", 0}, 113618334Speter {"--print-multi-directory", "-print-multi-directory", 0}, 1137104763Skan {"--print-multi-os-directory", "-print-multi-os-directory", 0}, 113818334Speter {"--print-prog-name", "-print-prog-name=", "aj"}, 113918334Speter {"--profile", "-p", 0}, 114018334Speter {"--profile-blocks", "-a", 0}, 114118334Speter {"--quiet", "-q", 0}, 114296285Sobrien {"--resource", "-fcompile-resource=", "aj"}, 114318334Speter {"--save-temps", "-save-temps", 0}, 114418334Speter {"--shared", "-shared", 0}, 114518334Speter {"--silent", "-q", 0}, 114650599Sobrien {"--specs", "-specs=", "aj"}, 114718334Speter {"--static", "-static", 0}, 114852520Sobrien {"--std", "-std=", "aj"}, 114918334Speter {"--symbolic", "-symbolic", 0}, 1150169704Skan {"--sysroot", "--sysroot=", "aj"}, 115190277Sobrien {"--time", "-time", 0}, 115218334Speter {"--trace-includes", "-H", 0}, 115318334Speter {"--traditional", "-traditional", 0}, 115418334Speter {"--traditional-cpp", "-traditional-cpp", 0}, 115518334Speter {"--trigraphs", "-trigraphs", 0}, 115650599Sobrien {"--undefine-macro", "-U", "aj"}, 115718334Speter {"--user-dependencies", "-MM", 0}, 115818334Speter {"--verbose", "-v", 0}, 115918334Speter {"--warn-", "-W", "*j"}, 116018334Speter {"--write-dependencies", "-MD", 0}, 116118334Speter {"--write-user-dependencies", "-MMD", 0}, 116218334Speter {"--", "-f", "*j"} 116318334Speter }; 116418334Speter 116590277Sobrien 116690277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE 116790277Sobrienstatic const struct { 116890277Sobrien const char *const option_found; 116990277Sobrien const char *const replacements; 117090277Sobrien} target_option_translations[] = 117190277Sobrien{ 117290277Sobrien TARGET_OPTION_TRANSLATE_TABLE, 117390277Sobrien { 0, 0 } 117490277Sobrien}; 117590277Sobrien#endif 117690277Sobrien 117718334Speter/* Translate the options described by *ARGCP and *ARGVP. 117818334Speter Make a new vector and store it back in *ARGVP, 117918334Speter and store its length in *ARGVC. */ 118018334Speter 118118334Speterstatic void 1182132733Skantranslate_options (int *argcp, const char *const **argvp) 118318334Speter{ 118452520Sobrien int i; 118518334Speter int argc = *argcp; 118690277Sobrien const char *const *argv = *argvp; 118790277Sobrien int newvsize = (argc + 2) * 2 * sizeof (const char *); 1188132733Skan const char **newv = xmalloc (newvsize); 118918334Speter int newindex = 0; 119018334Speter 119118334Speter i = 0; 119218334Speter newv[newindex++] = argv[i++]; 119318334Speter 119418334Speter while (i < argc) 119518334Speter { 119690277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE 119790277Sobrien int tott_idx; 119890277Sobrien 119990277Sobrien for (tott_idx = 0; 120090277Sobrien target_option_translations[tott_idx].option_found; 120190277Sobrien tott_idx++) 120290277Sobrien { 120390277Sobrien if (strcmp (target_option_translations[tott_idx].option_found, 120490277Sobrien argv[i]) == 0) 120590277Sobrien { 120690277Sobrien int spaces = 1; 120790277Sobrien const char *sp; 120890277Sobrien char *np; 120990277Sobrien 121090277Sobrien for (sp = target_option_translations[tott_idx].replacements; 121190277Sobrien *sp; sp++) 121290277Sobrien { 121390277Sobrien if (*sp == ' ') 121490277Sobrien spaces ++; 121590277Sobrien } 121690277Sobrien 121790277Sobrien newvsize += spaces * sizeof (const char *); 1218132733Skan newv = xrealloc (newv, newvsize); 121990277Sobrien 122090277Sobrien sp = target_option_translations[tott_idx].replacements; 122190277Sobrien np = xstrdup (sp); 122290277Sobrien 122390277Sobrien while (1) 122490277Sobrien { 122590277Sobrien while (*np == ' ') 122690277Sobrien np++; 122790277Sobrien if (*np == 0) 122890277Sobrien break; 122990277Sobrien newv[newindex++] = np; 123090277Sobrien while (*np != ' ' && *np) 123190277Sobrien np++; 123290277Sobrien if (*np == 0) 123390277Sobrien break; 123490277Sobrien *np++ = 0; 123590277Sobrien } 123690277Sobrien 123790277Sobrien i ++; 123890277Sobrien break; 123990277Sobrien } 124090277Sobrien } 124190277Sobrien if (target_option_translations[tott_idx].option_found) 124290277Sobrien continue; 124390277Sobrien#endif 124490277Sobrien 124518334Speter /* Translate -- options. */ 124618334Speter if (argv[i][0] == '-' && argv[i][1] == '-') 124718334Speter { 124852520Sobrien size_t j; 124918334Speter /* Find a mapping that applies to this option. */ 125090277Sobrien for (j = 0; j < ARRAY_SIZE (option_map); j++) 125118334Speter { 125250599Sobrien size_t optlen = strlen (option_map[j].name); 125350599Sobrien size_t arglen = strlen (argv[i]); 125450599Sobrien size_t complen = arglen > optlen ? optlen : arglen; 125552520Sobrien const char *arginfo = option_map[j].arg_info; 125618334Speter 125718334Speter if (arginfo == 0) 125818334Speter arginfo = ""; 125918334Speter 126018334Speter if (!strncmp (argv[i], option_map[j].name, complen)) 126118334Speter { 126252520Sobrien const char *arg = 0; 126318334Speter 126418334Speter if (arglen < optlen) 126518334Speter { 126652520Sobrien size_t k; 126790277Sobrien for (k = j + 1; k < ARRAY_SIZE (option_map); k++) 126818334Speter if (strlen (option_map[k].name) >= arglen 126918334Speter && !strncmp (argv[i], option_map[k].name, arglen)) 127018334Speter { 127190277Sobrien error ("ambiguous abbreviation %s", argv[i]); 127218334Speter break; 127318334Speter } 127418334Speter 127590277Sobrien if (k != ARRAY_SIZE (option_map)) 127618334Speter break; 127718334Speter } 127818334Speter 127918334Speter if (arglen > optlen) 128018334Speter { 128118334Speter /* If the option has an argument, accept that. */ 128218334Speter if (argv[i][optlen] == '=') 128318334Speter arg = argv[i] + optlen + 1; 128418334Speter 128518334Speter /* If this mapping requires extra text at end of name, 128618334Speter accept that as "argument". */ 128790277Sobrien else if (strchr (arginfo, '*') != 0) 128818334Speter arg = argv[i] + optlen; 128918334Speter 129018334Speter /* Otherwise, extra text at end means mismatch. 129118334Speter Try other mappings. */ 129218334Speter else 129318334Speter continue; 129418334Speter } 129518334Speter 129690277Sobrien else if (strchr (arginfo, '*') != 0) 129718334Speter { 1298169704Skan error ("incomplete '%s' option", option_map[j].name); 129918334Speter break; 130018334Speter } 130118334Speter 130218334Speter /* Handle arguments. */ 130390277Sobrien if (strchr (arginfo, 'a') != 0) 130418334Speter { 130518334Speter if (arg == 0) 130618334Speter { 130718334Speter if (i + 1 == argc) 130818334Speter { 1309169704Skan error ("missing argument to '%s' option", 131018334Speter option_map[j].name); 131118334Speter break; 131218334Speter } 131318334Speter 131418334Speter arg = argv[++i]; 131518334Speter } 131618334Speter } 131790277Sobrien else if (strchr (arginfo, '*') != 0) 131818334Speter ; 131990277Sobrien else if (strchr (arginfo, 'o') == 0) 132018334Speter { 132118334Speter if (arg != 0) 1322169704Skan error ("extraneous argument to '%s' option", 132318334Speter option_map[j].name); 132418334Speter arg = 0; 132518334Speter } 132618334Speter 132718334Speter /* Store the translation as one argv elt or as two. */ 132890277Sobrien if (arg != 0 && strchr (arginfo, 'j') != 0) 132950599Sobrien newv[newindex++] = concat (option_map[j].equivalent, arg, 133090277Sobrien NULL); 133118334Speter else if (arg != 0) 133218334Speter { 133318334Speter newv[newindex++] = option_map[j].equivalent; 133418334Speter newv[newindex++] = arg; 133518334Speter } 133618334Speter else 133718334Speter newv[newindex++] = option_map[j].equivalent; 133818334Speter 133918334Speter break; 134018334Speter } 134118334Speter } 134218334Speter i++; 134318334Speter } 134418334Speter 134518334Speter /* Handle old-fashioned options--just copy them through, 134618334Speter with their arguments. */ 134718334Speter else if (argv[i][0] == '-') 134818334Speter { 134952520Sobrien const char *p = argv[i] + 1; 135018334Speter int c = *p; 135118334Speter int nskip = 1; 135218334Speter 135318334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 135418334Speter nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0); 135518334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 135618334Speter nskip += WORD_SWITCH_TAKES_ARG (p); 1357117413Skan else if ((c == 'B' || c == 'b' || c == 'x') 135818334Speter && p[1] == 0) 135918334Speter nskip += 1; 136018334Speter else if (! strcmp (p, "Xlinker")) 136118334Speter nskip += 1; 1362132733Skan else if (! strcmp (p, "Xpreprocessor")) 1363132733Skan nskip += 1; 1364132733Skan else if (! strcmp (p, "Xassembler")) 1365132733Skan nskip += 1; 136618334Speter 136718334Speter /* Watch out for an option at the end of the command line that 136818334Speter is missing arguments, and avoid skipping past the end of the 136918334Speter command line. */ 137018334Speter if (nskip + i > argc) 137118334Speter nskip = argc - i; 137218334Speter 137318334Speter while (nskip > 0) 137418334Speter { 137518334Speter newv[newindex++] = argv[i++]; 137618334Speter nskip--; 137718334Speter } 137818334Speter } 137918334Speter else 138018334Speter /* Ordinary operands, or +e options. */ 138118334Speter newv[newindex++] = argv[i++]; 138218334Speter } 138318334Speter 138418334Speter newv[newindex] = 0; 138518334Speter 138618334Speter *argvp = newv; 138718334Speter *argcp = newindex; 138818334Speter} 138918334Speter 139018334Speterstatic char * 1391132733Skanskip_whitespace (char *p) 139218334Speter{ 139318334Speter while (1) 139418334Speter { 139518334Speter /* A fully-blank line is a delimiter in the SPEC file and shouldn't 139618334Speter be considered whitespace. */ 139718334Speter if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n') 139818334Speter return p + 1; 139918334Speter else if (*p == '\n' || *p == ' ' || *p == '\t') 140018334Speter p++; 140118334Speter else if (*p == '#') 140218334Speter { 140390277Sobrien while (*p != '\n') 140490277Sobrien p++; 140518334Speter p++; 140618334Speter } 140718334Speter else 140818334Speter break; 140918334Speter } 141018334Speter 141118334Speter return p; 141218334Speter} 141390277Sobrien/* Structures to keep track of prefixes to try when looking for files. */ 141490277Sobrien 141590277Sobrienstruct prefix_list 141690277Sobrien{ 141790277Sobrien const char *prefix; /* String to prepend to the path. */ 141890277Sobrien struct prefix_list *next; /* Next in linked list. */ 141990277Sobrien int require_machine_suffix; /* Don't use without machine_suffix. */ 142090277Sobrien /* 2 means try both machine_suffix and just_machine_suffix. */ 1421104763Skan int priority; /* Sort key - priority within list. */ 1422104763Skan int os_multilib; /* 1 if OS multilib scheme should be used, 1423104763Skan 0 for GCC multilib scheme. */ 142490277Sobrien}; 142590277Sobrien 142690277Sobrienstruct path_prefix 142790277Sobrien{ 142890277Sobrien struct prefix_list *plist; /* List of prefixes to try */ 142990277Sobrien int max_len; /* Max length of a prefix in PLIST */ 143090277Sobrien const char *name; /* Name of this list (used in config stuff) */ 143190277Sobrien}; 143290277Sobrien 143390277Sobrien/* List of prefixes to try when looking for executables. */ 143490277Sobrien 143590277Sobrienstatic struct path_prefix exec_prefixes = { 0, 0, "exec" }; 143690277Sobrien 143790277Sobrien/* List of prefixes to try when looking for startup (crt0) files. */ 143890277Sobrien 143990277Sobrienstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" }; 144090277Sobrien 144190277Sobrien/* List of prefixes to try when looking for include files. */ 144290277Sobrien 144390277Sobrienstatic struct path_prefix include_prefixes = { 0, 0, "include" }; 144490277Sobrien 144590277Sobrien/* Suffix to attach to directories searched for commands. 144690277Sobrien This looks like `MACHINE/VERSION/'. */ 144790277Sobrien 144890277Sobrienstatic const char *machine_suffix = 0; 144990277Sobrien 145090277Sobrien/* Suffix to attach to directories searched for commands. 145190277Sobrien This is just `MACHINE/'. */ 145290277Sobrien 145390277Sobrienstatic const char *just_machine_suffix = 0; 145490277Sobrien 145590277Sobrien/* Adjusted value of GCC_EXEC_PREFIX envvar. */ 145690277Sobrien 145790277Sobrienstatic const char *gcc_exec_prefix; 145890277Sobrien 1459132733Skan/* Adjusted value of standard_libexec_prefix. */ 1460132733Skan 1461132733Skanstatic const char *gcc_libexec_prefix; 1462132733Skan 146390277Sobrien/* Default prefixes to attach to command names. */ 146490277Sobrien 1465169704Skan#ifndef STANDARD_STARTFILE_PREFIX_1 1466169704Skan#define STANDARD_STARTFILE_PREFIX_1 "/lib/" 1467169704Skan#endif 1468169704Skan#ifndef STANDARD_STARTFILE_PREFIX_2 1469169704Skan#define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/" 1470169704Skan#endif 1471169704Skan 1472259563Spfg#ifdef CROSS_DIRECTORY_STRUCTURE /* Don't use these prefixes for a cross compiler. */ 147390277Sobrien#undef MD_EXEC_PREFIX 147490277Sobrien#undef MD_STARTFILE_PREFIX 147590277Sobrien#undef MD_STARTFILE_PREFIX_1 147690277Sobrien#endif 147790277Sobrien 147890277Sobrien/* If no prefixes defined, use the null string, which will disable them. */ 147990277Sobrien#ifndef MD_EXEC_PREFIX 148090277Sobrien#define MD_EXEC_PREFIX "" 148190277Sobrien#endif 148290277Sobrien#ifndef MD_STARTFILE_PREFIX 148390277Sobrien#define MD_STARTFILE_PREFIX "" 148490277Sobrien#endif 148590277Sobrien#ifndef MD_STARTFILE_PREFIX_1 148690277Sobrien#define MD_STARTFILE_PREFIX_1 "" 148790277Sobrien#endif 148890277Sobrien 148990277Sobrienstatic const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX; 1490132733Skanstatic const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/"; 1491132733Skanstatic const char *const standard_exec_prefix_2 = "/usr/lib/gcc/"; 149290277Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX; 149390277Sobrien 149490277Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX; 149590277Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1; 149690277Sobrienstatic const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; 1497169704Skanstatic const char *const standard_startfile_prefix_1 1498169704Skan = STANDARD_STARTFILE_PREFIX_1; 1499169704Skanstatic const char *const standard_startfile_prefix_2 1500169704Skan = STANDARD_STARTFILE_PREFIX_2; 150190277Sobrien 150290277Sobrienstatic const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX; 150390277Sobrienstatic const char *tooldir_prefix; 150490277Sobrien 150596736Sru#ifndef FREEBSD_NATIVE 150690277Sobrienstatic const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX; 150796736Sru#endif /* not FREEBSD_NATIVE */ 150890277Sobrien 1509132733Skanstatic const char *standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX; 1510132733Skan 151190277Sobrien/* Subdirectory to use for locating libraries. Set by 151290277Sobrien set_multilib_dir based on the compilation options. */ 151390277Sobrien 151490277Sobrienstatic const char *multilib_dir; 1515104763Skan 1516104763Skan/* Subdirectory to use for locating libraries in OS conventions. Set by 1517104763Skan set_multilib_dir based on the compilation options. */ 1518104763Skan 1519104763Skanstatic const char *multilib_os_dir; 152018334Speter 152150599Sobrien/* Structure to keep track of the specs that have been defined so far. 152250599Sobrien These are accessed using %(specname) or %[specname] in a compiler 152350599Sobrien or link spec. */ 152418334Speter 152518334Speterstruct spec_list 152618334Speter{ 152750599Sobrien /* The following 2 fields must be first */ 152850599Sobrien /* to allow EXTRA_SPECS to be initialized */ 152990277Sobrien const char *name; /* name of the spec. */ 153090277Sobrien const char *ptr; /* available ptr if no static pointer */ 153150599Sobrien 153250599Sobrien /* The following fields are not initialized */ 153350599Sobrien /* by EXTRA_SPECS */ 153490277Sobrien const char **ptr_spec; /* pointer to the spec itself. */ 153550599Sobrien struct spec_list *next; /* Next spec in linked list. */ 153650599Sobrien int name_len; /* length of the name */ 153750599Sobrien int alloc_p; /* whether string was allocated */ 153818334Speter}; 153918334Speter 154050599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \ 154190277Sobrien{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 } 154218334Speter 154390277Sobrien/* List of statically defined specs. */ 154490277Sobrienstatic struct spec_list static_specs[] = 154590277Sobrien{ 154650599Sobrien INIT_STATIC_SPEC ("asm", &asm_spec), 154790277Sobrien INIT_STATIC_SPEC ("asm_debug", &asm_debug), 154850599Sobrien INIT_STATIC_SPEC ("asm_final", &asm_final_spec), 154990277Sobrien INIT_STATIC_SPEC ("asm_options", &asm_options), 155090277Sobrien INIT_STATIC_SPEC ("invoke_as", &invoke_as), 155150599Sobrien INIT_STATIC_SPEC ("cpp", &cpp_spec), 155290277Sobrien INIT_STATIC_SPEC ("cpp_options", &cpp_options), 1553117413Skan INIT_STATIC_SPEC ("cpp_debug_options", &cpp_debug_options), 155490277Sobrien INIT_STATIC_SPEC ("cpp_unique_options", &cpp_unique_options), 155590277Sobrien INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp), 155650599Sobrien INIT_STATIC_SPEC ("cc1", &cc1_spec), 155790277Sobrien INIT_STATIC_SPEC ("cc1_options", &cc1_options), 155850599Sobrien INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec), 155996285Sobrien INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec), 1560169704Skan INIT_STATIC_SPEC ("link_ssp", &link_ssp_spec), 156150599Sobrien INIT_STATIC_SPEC ("endfile", &endfile_spec), 156250599Sobrien INIT_STATIC_SPEC ("link", &link_spec), 156350599Sobrien INIT_STATIC_SPEC ("lib", &lib_spec), 1564169704Skan INIT_STATIC_SPEC ("mfwrap", &mfwrap_spec), 1565169704Skan INIT_STATIC_SPEC ("mflib", &mflib_spec), 1566169704Skan INIT_STATIC_SPEC ("link_gomp", &link_gomp_spec), 156750599Sobrien INIT_STATIC_SPEC ("libgcc", &libgcc_spec), 156850599Sobrien INIT_STATIC_SPEC ("startfile", &startfile_spec), 156950599Sobrien INIT_STATIC_SPEC ("switches_need_spaces", &switches_need_spaces), 157050599Sobrien INIT_STATIC_SPEC ("cross_compile", &cross_compile), 157150599Sobrien INIT_STATIC_SPEC ("version", &compiler_version), 157250599Sobrien INIT_STATIC_SPEC ("multilib", &multilib_select), 157350599Sobrien INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults), 157450599Sobrien INIT_STATIC_SPEC ("multilib_extra", &multilib_extra), 157550599Sobrien INIT_STATIC_SPEC ("multilib_matches", &multilib_matches), 157690277Sobrien INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions), 1577104763Skan INIT_STATIC_SPEC ("multilib_options", &multilib_options), 157850599Sobrien INIT_STATIC_SPEC ("linker", &linker_name_spec), 157990277Sobrien INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec), 158090277Sobrien INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix), 158190277Sobrien INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix), 158290277Sobrien INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1), 1583117413Skan INIT_STATIC_SPEC ("startfile_prefix_spec", &startfile_prefix_spec), 1584169704Skan INIT_STATIC_SPEC ("sysroot_spec", &sysroot_spec), 1585132733Skan INIT_STATIC_SPEC ("sysroot_suffix_spec", &sysroot_suffix_spec), 1586132733Skan INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec", &sysroot_hdrs_suffix_spec), 158750599Sobrien}; 158850599Sobrien 158950599Sobrien#ifdef EXTRA_SPECS /* additional specs needed */ 159052520Sobrien/* Structure to keep track of just the first two args of a spec_list. 159190277Sobrien That is all that the EXTRA_SPECS macro gives us. */ 159252520Sobrienstruct spec_list_1 159352520Sobrien{ 159490277Sobrien const char *const name; 159590277Sobrien const char *const ptr; 159652520Sobrien}; 159752520Sobrien 159890277Sobrienstatic const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS }; 159990277Sobrienstatic struct spec_list *extra_specs = (struct spec_list *) 0; 160050599Sobrien#endif 160150599Sobrien 160250599Sobrien/* List of dynamically allocates specs that have been defined so far. */ 160350599Sobrien 160490277Sobrienstatic struct spec_list *specs = (struct spec_list *) 0; 160590277Sobrien 1606117413Skan/* List of static spec functions. */ 1607117413Skan 1608117413Skanstatic const struct spec_function static_spec_functions[] = 1609117413Skan{ 1610117413Skan { "if-exists", if_exists_spec_function }, 1611117413Skan { "if-exists-else", if_exists_else_spec_function }, 1612169704Skan { "replace-outfile", replace_outfile_spec_function }, 1613169704Skan { "version-compare", version_compare_spec_function }, 1614169704Skan { "include", include_spec_function }, 1615169704Skan#ifdef EXTRA_SPEC_FUNCTIONS 1616169704Skan EXTRA_SPEC_FUNCTIONS 1617169704Skan#endif 1618117413Skan { 0, 0 } 1619117413Skan}; 1620117413Skan 1621117413Skanstatic int processing_spec_function; 1622117413Skan 162390277Sobrien/* Add appropriate libgcc specs to OBSTACK, taking into account 162490277Sobrien various permutations of -shared-libgcc, -shared, and such. */ 162550599Sobrien 1626169704Skan#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC) 1627169704Skan 1628169704Skan#ifndef USE_LD_AS_NEEDED 1629169704Skan#define USE_LD_AS_NEEDED 0 1630169704Skan#endif 1631169704Skan 163290277Sobrienstatic void 1633132733Skaninit_gcc_specs (struct obstack *obstack, const char *shared_name, 1634132733Skan const char *static_name, const char *eh_name) 163590277Sobrien{ 163696285Sobrien char *buf; 163790277Sobrien 1638170077Skan buf = concat ("%{pg:", static_name, " ", eh_name, "} %{!pg:", 1639170077Skan "%{static|static-libgcc|pg:", static_name, " ", eh_name, "}" 1640169704Skan "%{!static:%{!static-libgcc:" 1641169704Skan#if USE_LD_AS_NEEDED 1642169704Skan "%{!shared-libgcc:", 1643169704Skan static_name, " --as-needed ", shared_name, " --no-as-needed" 1644169704Skan "}" 1645169704Skan "%{shared-libgcc:", 1646169704Skan shared_name, "%{!shared: ", static_name, "}" 1647169704Skan "}" 1648132733Skan#else 1649169704Skan "%{!shared:" 1650169704Skan "%{!shared-libgcc:", static_name, " ", eh_name, "}" 1651169704Skan "%{shared-libgcc:", shared_name, " ", static_name, "}" 1652169704Skan "}" 165390277Sobrien#ifdef LINK_EH_SPEC 1654169704Skan "%{shared:" 1655169704Skan "%{shared-libgcc:", shared_name, "}" 1656169704Skan "%{!shared-libgcc:", static_name, "}" 1657169704Skan "}" 165890277Sobrien#else 1659169704Skan "%{shared:", shared_name, "}" 166090277Sobrien#endif 1661132733Skan#endif 1662170077Skan "}}}", NULL); 166396285Sobrien 166496285Sobrien obstack_grow (obstack, buf, strlen (buf)); 166596285Sobrien free (buf); 166690277Sobrien} 166790277Sobrien#endif /* ENABLE_SHARED_LIBGCC */ 166890277Sobrien 166950599Sobrien/* Initialize the specs lookup routines. */ 167050599Sobrien 167150599Sobrienstatic void 1672132733Skaninit_spec (void) 167350599Sobrien{ 167490277Sobrien struct spec_list *next = (struct spec_list *) 0; 167590277Sobrien struct spec_list *sl = (struct spec_list *) 0; 167650599Sobrien int i; 167750599Sobrien 167850599Sobrien if (specs) 167990277Sobrien return; /* Already initialized. */ 168050599Sobrien 168150599Sobrien if (verbose_flag) 168290277Sobrien notice ("Using built-in specs.\n"); 168350599Sobrien 168450599Sobrien#ifdef EXTRA_SPECS 1685132733Skan extra_specs = xcalloc (sizeof (struct spec_list), 1686132733Skan ARRAY_SIZE (extra_specs_1)); 168790277Sobrien 168890277Sobrien for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--) 168950599Sobrien { 169050599Sobrien sl = &extra_specs[i]; 169152520Sobrien sl->name = extra_specs_1[i].name; 169252520Sobrien sl->ptr = extra_specs_1[i].ptr; 169350599Sobrien sl->next = next; 169450599Sobrien sl->name_len = strlen (sl->name); 169550599Sobrien sl->ptr_spec = &sl->ptr; 169650599Sobrien next = sl; 169750599Sobrien } 169850599Sobrien#endif 169950599Sobrien 1700117413Skan /* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes 1701117413Skan on ?: in file-scope variable initializations. */ 1702117413Skan asm_debug = ASM_DEBUG_SPEC; 1703117413Skan 170490277Sobrien for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) 170550599Sobrien { 170650599Sobrien sl = &static_specs[i]; 170750599Sobrien sl->next = next; 170850599Sobrien next = sl; 170950599Sobrien } 171050599Sobrien 1711169704Skan#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC) 171290277Sobrien /* ??? If neither -shared-libgcc nor --static-libgcc was 171390277Sobrien seen, then we should be making an educated guess. Some proposed 171490277Sobrien heuristics for ELF include: 171590277Sobrien 171690277Sobrien (1) If "-Wl,--export-dynamic", then it's a fair bet that the 171790277Sobrien program will be doing dynamic loading, which will likely 171890277Sobrien need the shared libgcc. 171990277Sobrien 172090277Sobrien (2) If "-ldl", then it's also a fair bet that we're doing 172190277Sobrien dynamic loading. 172290277Sobrien 172390277Sobrien (3) For each ET_DYN we're linking against (either through -lfoo 172490277Sobrien or /some/path/foo.so), check to see whether it or one of 172590277Sobrien its dependencies depends on a shared libgcc. 172690277Sobrien 172790277Sobrien (4) If "-shared" 172890277Sobrien 172990277Sobrien If the runtime is fixed to look for program headers instead 173090277Sobrien of calling __register_frame_info at all, for each object, 173190277Sobrien use the shared libgcc if any EH symbol referenced. 173290277Sobrien 173390277Sobrien If crtstuff is fixed to not invoke __register_frame_info 173490277Sobrien automatically, for each object, use the shared libgcc if 173590277Sobrien any non-empty unwind section found. 173690277Sobrien 173790277Sobrien Doing any of this probably requires invoking an external program to 173890277Sobrien do the actual object file scanning. */ 173990277Sobrien { 174090277Sobrien const char *p = libgcc_spec; 174190277Sobrien int in_sep = 1; 1742117413Skan 174390277Sobrien /* Transform the extant libgcc_spec into one that uses the shared libgcc 174490277Sobrien when given the proper command line arguments. */ 174590277Sobrien while (*p) 174690277Sobrien { 1747117413Skan if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0) 174890277Sobrien { 174990277Sobrien init_gcc_specs (&obstack, 175090277Sobrien "-lgcc_s" 1751146908Skan#ifdef USE_LIBUNWIND_EXCEPTIONS 1752146908Skan " -lunwind" 1753146908Skan#endif 1754132733Skan , 1755169704Skan#ifdef FREEBSD_NATIVE 1756169704Skan LIBGCC_STATIC_LIB_SPEC, 1757169704Skan LIBGCC_EH_STATIC_LIB_SPEC 1758169704Skan#else 1759132733Skan "-lgcc", 1760132733Skan "-lgcc_eh" 1761169704Skan#endif 1762122197Skan#ifdef USE_LIBUNWIND_EXCEPTIONS 1763146908Skan# ifdef HAVE_LD_STATIC_DYNAMIC 1764146908Skan " %{!static:-Bstatic} -lunwind %{!static:-Bdynamic}" 1765146908Skan# else 1766122197Skan " -lunwind" 1767146908Skan# endif 1768122197Skan#endif 1769132733Skan ); 1770132733Skan 177190277Sobrien p += 5; 177290277Sobrien in_sep = 0; 177390277Sobrien } 177490277Sobrien else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0) 177590277Sobrien { 177690277Sobrien /* Ug. We don't know shared library extensions. Hope that 177790277Sobrien systems that use this form don't do shared libraries. */ 177890277Sobrien init_gcc_specs (&obstack, 1779169704Skan "-lgcc_s", 178090277Sobrien "libgcc.a%s", 1781132733Skan "libgcc_eh.a%s" 1782132733Skan#ifdef USE_LIBUNWIND_EXCEPTIONS 1783132733Skan " -lunwind" 1784132733Skan#endif 1785132733Skan ); 178690277Sobrien p += 10; 178790277Sobrien in_sep = 0; 178890277Sobrien } 178990277Sobrien else 179090277Sobrien { 179190277Sobrien obstack_1grow (&obstack, *p); 179290277Sobrien in_sep = (*p == ' '); 179390277Sobrien p += 1; 179490277Sobrien } 179590277Sobrien } 179690277Sobrien 179790277Sobrien obstack_1grow (&obstack, '\0'); 1798169704Skan libgcc_spec = XOBFINISH (&obstack, const char *); 179990277Sobrien } 180090277Sobrien#endif 180190277Sobrien#ifdef USE_AS_TRADITIONAL_FORMAT 180290277Sobrien /* Prepend "--traditional-format" to whatever asm_spec we had before. */ 180390277Sobrien { 180490277Sobrien static const char tf[] = "--traditional-format "; 180590277Sobrien obstack_grow (&obstack, tf, sizeof(tf) - 1); 180690277Sobrien obstack_grow0 (&obstack, asm_spec, strlen (asm_spec)); 1807169704Skan asm_spec = XOBFINISH (&obstack, const char *); 180890277Sobrien } 180990277Sobrien#endif 181090277Sobrien#ifdef LINK_EH_SPEC 181190277Sobrien /* Prepend LINK_EH_SPEC to whatever link_spec we had before. */ 181290277Sobrien obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1); 181390277Sobrien obstack_grow0 (&obstack, link_spec, strlen (link_spec)); 1814169704Skan link_spec = XOBFINISH (&obstack, const char *); 181590277Sobrien#endif 181690277Sobrien 181750599Sobrien specs = sl; 181850599Sobrien} 181950599Sobrien 182018334Speter/* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is 182118334Speter removed; If the spec starts with a + then SPEC is added to the end of the 182250599Sobrien current spec. */ 182318334Speter 182418334Speterstatic void 1825132733Skanset_spec (const char *name, const char *spec) 182618334Speter{ 182718334Speter struct spec_list *sl; 182890277Sobrien const char *old_spec; 182950599Sobrien int name_len = strlen (name); 183050599Sobrien int i; 183118334Speter 183290277Sobrien /* If this is the first call, initialize the statically allocated specs. */ 183350599Sobrien if (!specs) 183450599Sobrien { 183590277Sobrien struct spec_list *next = (struct spec_list *) 0; 183690277Sobrien for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) 183750599Sobrien { 183850599Sobrien sl = &static_specs[i]; 183950599Sobrien sl->next = next; 184050599Sobrien next = sl; 184150599Sobrien } 184250599Sobrien specs = sl; 184350599Sobrien } 184450599Sobrien 184590277Sobrien /* See if the spec already exists. */ 184618334Speter for (sl = specs; sl; sl = sl->next) 184750599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, name)) 184818334Speter break; 184918334Speter 185018334Speter if (!sl) 185118334Speter { 185290277Sobrien /* Not found - make it. */ 1853169704Skan sl = XNEW (struct spec_list); 185490277Sobrien sl->name = xstrdup (name); 185550599Sobrien sl->name_len = name_len; 185650599Sobrien sl->ptr_spec = &sl->ptr; 185750599Sobrien sl->alloc_p = 0; 185850599Sobrien *(sl->ptr_spec) = ""; 185918334Speter sl->next = specs; 186018334Speter specs = sl; 186118334Speter } 186218334Speter 186350599Sobrien old_spec = *(sl->ptr_spec); 186452520Sobrien *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1])) 186590277Sobrien ? concat (old_spec, spec + 1, NULL) 186690277Sobrien : xstrdup (spec)); 186718334Speter 186850599Sobrien#ifdef DEBUG_SPECS 186950599Sobrien if (verbose_flag) 187052520Sobrien notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec)); 187150599Sobrien#endif 187250599Sobrien 187390277Sobrien /* Free the old spec. */ 187450599Sobrien if (old_spec && sl->alloc_p) 1875132733Skan free ((void *) old_spec); 187650599Sobrien 187750599Sobrien sl->alloc_p = 1; 187818334Speter} 187918334Speter 188018334Speter/* Accumulate a command (program name and args), and run it. */ 188118334Speter 188218334Speter/* Vector of pointers to arguments in the current line of specifications. */ 188318334Speter 188490277Sobrienstatic const char **argbuf; 188518334Speter 188618334Speter/* Number of elements allocated in argbuf. */ 188718334Speter 188818334Speterstatic int argbuf_length; 188918334Speter 189018334Speter/* Number of elements in argbuf currently in use (containing args). */ 189118334Speter 189218334Speterstatic int argbuf_index; 189318334Speter 1894169704Skan/* Position in the argbuf array containing the name of the output file 1895169704Skan (the value associated with the "-o" flag). */ 1896169704Skan 1897169704Skanstatic int have_o_argbuf_index = 0; 1898169704Skan 1899169704Skan/* Were the options -c or -S passed. */ 1900169704Skanstatic int have_c = 0; 1901169704Skan 1902169704Skan/* Was the option -o passed. */ 1903169704Skanstatic int have_o = 0; 1904169704Skan 190590277Sobrien/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated 190690277Sobrien temp file. If the HOST_BIT_BUCKET is used for %j, no entry is made for 190790277Sobrien it here. */ 190850599Sobrien 190918334Speterstatic struct temp_name { 191052520Sobrien const char *suffix; /* suffix associated with the code. */ 191118334Speter int length; /* strlen (suffix). */ 191218334Speter int unique; /* Indicates whether %g or %u/%U was used. */ 191352520Sobrien const char *filename; /* associated filename. */ 191418334Speter int filename_length; /* strlen (filename). */ 191518334Speter struct temp_name *next; 191618334Speter} *temp_names; 191718334Speter 191818334Speter/* Number of commands executed so far. */ 191918334Speter 192018334Speterstatic int execution_count; 192118334Speter 192218334Speter/* Number of commands that exited with a signal. */ 192318334Speter 192418334Speterstatic int signal_count; 192518334Speter 192618334Speter/* Name with which this program was invoked. */ 192718334Speter 192852520Sobrienstatic const char *programname; 192918334Speter 1930117413Skan/* Allocate the argument vector. */ 1931117413Skan 1932117413Skanstatic void 1933132733Skanalloc_args (void) 1934117413Skan{ 1935117413Skan argbuf_length = 10; 1936169704Skan argbuf = XNEWVEC (const char *, argbuf_length); 1937117413Skan} 1938117413Skan 193918334Speter/* Clear out the vector of arguments (after a command is executed). */ 194018334Speter 194118334Speterstatic void 1942132733Skanclear_args (void) 194318334Speter{ 194418334Speter argbuf_index = 0; 194518334Speter} 194618334Speter 194718334Speter/* Add one argument to the vector at the end. 194818334Speter This is done when a space is seen or at the end of the line. 194918334Speter If DELETE_ALWAYS is nonzero, the arg is a filename 195018334Speter and the file should be deleted eventually. 195118334Speter If DELETE_FAILURE is nonzero, the arg is a filename 195218334Speter and the file should be deleted if this compilation fails. */ 195318334Speter 195418334Speterstatic void 1955132733Skanstore_arg (const char *arg, int delete_always, int delete_failure) 195618334Speter{ 195718334Speter if (argbuf_index + 1 == argbuf_length) 1958132733Skan argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *)); 195918334Speter 196018334Speter argbuf[argbuf_index++] = arg; 196118334Speter argbuf[argbuf_index] = 0; 196218334Speter 1963169704Skan if (strcmp (arg, "-o") == 0) 1964169704Skan have_o_argbuf_index = argbuf_index; 196518334Speter if (delete_always || delete_failure) 196618334Speter record_temp_file (arg, delete_always, delete_failure); 196718334Speter} 196818334Speter 196990277Sobrien/* Load specs from a file name named FILENAME, replacing occurrences of 197090277Sobrien various different types of line-endings, \r\n, \n\r and just \r, with 197190277Sobrien a single \n. */ 197250599Sobrien 197390277Sobrienstatic char * 1974132733Skanload_specs (const char *filename) 197550599Sobrien{ 197650599Sobrien int desc; 197750599Sobrien int readlen; 197850599Sobrien struct stat statbuf; 197950599Sobrien char *buffer; 198090277Sobrien char *buffer_p; 198190277Sobrien char *specs; 198290277Sobrien char *specs_p; 198350599Sobrien 198450599Sobrien if (verbose_flag) 198552520Sobrien notice ("Reading specs from %s\n", filename); 198650599Sobrien 198750599Sobrien /* Open and stat the file. */ 198850599Sobrien desc = open (filename, O_RDONLY, 0); 198950599Sobrien if (desc < 0) 199050599Sobrien pfatal_with_name (filename); 199150599Sobrien if (stat (filename, &statbuf) < 0) 199250599Sobrien pfatal_with_name (filename); 199350599Sobrien 199450599Sobrien /* Read contents of file into BUFFER. */ 1995169704Skan buffer = XNEWVEC (char, statbuf.st_size + 1); 199650599Sobrien readlen = read (desc, buffer, (unsigned) statbuf.st_size); 199750599Sobrien if (readlen < 0) 199850599Sobrien pfatal_with_name (filename); 199950599Sobrien buffer[readlen] = 0; 200050599Sobrien close (desc); 200150599Sobrien 2002169704Skan specs = XNEWVEC (char, readlen + 1); 200390277Sobrien specs_p = specs; 200490277Sobrien for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++) 200590277Sobrien { 200690277Sobrien int skip = 0; 200790277Sobrien char c = *buffer_p; 200890277Sobrien if (c == '\r') 200990277Sobrien { 201090277Sobrien if (buffer_p > buffer && *(buffer_p - 1) == '\n') /* \n\r */ 201190277Sobrien skip = 1; 201290277Sobrien else if (*(buffer_p + 1) == '\n') /* \r\n */ 201390277Sobrien skip = 1; 201490277Sobrien else /* \r */ 201590277Sobrien c = '\n'; 201690277Sobrien } 201790277Sobrien if (! skip) 201890277Sobrien *specs_p++ = c; 201990277Sobrien } 202090277Sobrien *specs_p = '\0'; 202190277Sobrien 202290277Sobrien free (buffer); 202390277Sobrien return (specs); 202490277Sobrien} 202590277Sobrien 202690277Sobrien/* Read compilation specs from a file named FILENAME, 202790277Sobrien replacing the default ones. 202890277Sobrien 202990277Sobrien A suffix which starts with `*' is a definition for 203090277Sobrien one of the machine-specific sub-specs. The "suffix" should be 203196285Sobrien *asm, *cc1, *cpp, *link, *startfile, etc. 203290277Sobrien The corresponding spec is stored in asm_spec, etc., 203390277Sobrien rather than in the `compilers' vector. 203490277Sobrien 203590277Sobrien Anything invalid in the file is a fatal error. */ 203690277Sobrien 203790277Sobrienstatic void 2038132733Skanread_specs (const char *filename, int main_p) 203990277Sobrien{ 204090277Sobrien char *buffer; 204190277Sobrien char *p; 204290277Sobrien 204390277Sobrien buffer = load_specs (filename); 204490277Sobrien 204550599Sobrien /* Scan BUFFER for specs, putting them in the vector. */ 204650599Sobrien p = buffer; 204750599Sobrien while (1) 204850599Sobrien { 204950599Sobrien char *suffix; 205050599Sobrien char *spec; 205150599Sobrien char *in, *out, *p1, *p2, *p3; 205250599Sobrien 205350599Sobrien /* Advance P in BUFFER to the next nonblank nocomment line. */ 205450599Sobrien p = skip_whitespace (p); 205550599Sobrien if (*p == 0) 205650599Sobrien break; 205750599Sobrien 205850599Sobrien /* Is this a special command that starts with '%'? */ 205950599Sobrien /* Don't allow this for the main specs file, since it would 206050599Sobrien encourage people to overwrite it. */ 206150599Sobrien if (*p == '%' && !main_p) 206250599Sobrien { 206350599Sobrien p1 = p; 206450599Sobrien while (*p && *p != '\n') 206550599Sobrien p++; 206650599Sobrien 206790277Sobrien /* Skip '\n'. */ 206890277Sobrien p++; 206950599Sobrien 207090277Sobrien if (!strncmp (p1, "%include", sizeof ("%include") - 1) 207150599Sobrien && (p1[sizeof "%include" - 1] == ' ' 207250599Sobrien || p1[sizeof "%include" - 1] == '\t')) 207350599Sobrien { 207450599Sobrien char *new_filename; 207550599Sobrien 207650599Sobrien p1 += sizeof ("%include"); 207750599Sobrien while (*p1 == ' ' || *p1 == '\t') 207850599Sobrien p1++; 207950599Sobrien 208050599Sobrien if (*p1++ != '<' || p[-2] != '>') 208152520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 208252520Sobrien (long) (p1 - buffer + 1)); 208350599Sobrien 208450599Sobrien p[-2] = '\0'; 2085169704Skan new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true); 208650599Sobrien read_specs (new_filename ? new_filename : p1, FALSE); 208750599Sobrien continue; 208850599Sobrien } 208950599Sobrien else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1) 209050599Sobrien && (p1[sizeof "%include_noerr" - 1] == ' ' 209150599Sobrien || p1[sizeof "%include_noerr" - 1] == '\t')) 209250599Sobrien { 209350599Sobrien char *new_filename; 209450599Sobrien 209550599Sobrien p1 += sizeof "%include_noerr"; 209690277Sobrien while (*p1 == ' ' || *p1 == '\t') 209790277Sobrien p1++; 209850599Sobrien 209950599Sobrien if (*p1++ != '<' || p[-2] != '>') 210052520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 210152520Sobrien (long) (p1 - buffer + 1)); 210250599Sobrien 210350599Sobrien p[-2] = '\0'; 2104169704Skan new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true); 210550599Sobrien if (new_filename) 210650599Sobrien read_specs (new_filename, FALSE); 210750599Sobrien else if (verbose_flag) 210890277Sobrien notice ("could not find specs file %s\n", p1); 210950599Sobrien continue; 211050599Sobrien } 211150599Sobrien else if (!strncmp (p1, "%rename", sizeof "%rename" - 1) 211250599Sobrien && (p1[sizeof "%rename" - 1] == ' ' 211350599Sobrien || p1[sizeof "%rename" - 1] == '\t')) 211450599Sobrien { 211550599Sobrien int name_len; 211650599Sobrien struct spec_list *sl; 2117117413Skan struct spec_list *newsl; 211850599Sobrien 2119117413Skan /* Get original name. */ 212050599Sobrien p1 += sizeof "%rename"; 212150599Sobrien while (*p1 == ' ' || *p1 == '\t') 212250599Sobrien p1++; 212350599Sobrien 212490277Sobrien if (! ISALPHA ((unsigned char) *p1)) 212552520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 212652520Sobrien (long) (p1 - buffer)); 212750599Sobrien 212850599Sobrien p2 = p1; 212990277Sobrien while (*p2 && !ISSPACE ((unsigned char) *p2)) 213050599Sobrien p2++; 213150599Sobrien 213250599Sobrien if (*p2 != ' ' && *p2 != '\t') 213352520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 213452520Sobrien (long) (p2 - buffer)); 213550599Sobrien 213650599Sobrien name_len = p2 - p1; 213750599Sobrien *p2++ = '\0'; 213850599Sobrien while (*p2 == ' ' || *p2 == '\t') 213950599Sobrien p2++; 214050599Sobrien 214190277Sobrien if (! ISALPHA ((unsigned char) *p2)) 214252520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 214352520Sobrien (long) (p2 - buffer)); 214450599Sobrien 214590277Sobrien /* Get new spec name. */ 214650599Sobrien p3 = p2; 214790277Sobrien while (*p3 && !ISSPACE ((unsigned char) *p3)) 214850599Sobrien p3++; 214950599Sobrien 215090277Sobrien if (p3 != p - 1) 215152520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 215252520Sobrien (long) (p3 - buffer)); 215350599Sobrien *p3 = '\0'; 215450599Sobrien 215550599Sobrien for (sl = specs; sl; sl = sl->next) 215650599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, p1)) 215750599Sobrien break; 215850599Sobrien 215950599Sobrien if (!sl) 216050599Sobrien fatal ("specs %s spec was not found to be renamed", p1); 216150599Sobrien 216250599Sobrien if (strcmp (p1, p2) == 0) 216350599Sobrien continue; 216450599Sobrien 2165117413Skan for (newsl = specs; newsl; newsl = newsl->next) 2166117413Skan if (strcmp (newsl->name, p2) == 0) 2167117413Skan fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'", 2168117413Skan filename, p1, p2); 2169117413Skan 217050599Sobrien if (verbose_flag) 217150599Sobrien { 217252520Sobrien notice ("rename spec %s to %s\n", p1, p2); 217350599Sobrien#ifdef DEBUG_SPECS 217452520Sobrien notice ("spec is '%s'\n\n", *(sl->ptr_spec)); 217550599Sobrien#endif 217650599Sobrien } 217750599Sobrien 217850599Sobrien set_spec (p2, *(sl->ptr_spec)); 217950599Sobrien if (sl->alloc_p) 2180132733Skan free ((void *) *(sl->ptr_spec)); 218150599Sobrien 218250599Sobrien *(sl->ptr_spec) = ""; 218350599Sobrien sl->alloc_p = 0; 218450599Sobrien continue; 218550599Sobrien } 218650599Sobrien else 218752520Sobrien fatal ("specs unknown %% command after %ld characters", 218852520Sobrien (long) (p1 - buffer)); 218950599Sobrien } 219050599Sobrien 219150599Sobrien /* Find the colon that should end the suffix. */ 219250599Sobrien p1 = p; 219350599Sobrien while (*p1 && *p1 != ':' && *p1 != '\n') 219450599Sobrien p1++; 219550599Sobrien 219650599Sobrien /* The colon shouldn't be missing. */ 219750599Sobrien if (*p1 != ':') 219852520Sobrien fatal ("specs file malformed after %ld characters", 219952520Sobrien (long) (p1 - buffer)); 220050599Sobrien 220150599Sobrien /* Skip back over trailing whitespace. */ 220250599Sobrien p2 = p1; 220350599Sobrien while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) 220450599Sobrien p2--; 220550599Sobrien 220650599Sobrien /* Copy the suffix to a string. */ 220750599Sobrien suffix = save_string (p, p2 - p); 220850599Sobrien /* Find the next line. */ 220950599Sobrien p = skip_whitespace (p1 + 1); 221050599Sobrien if (p[1] == 0) 221152520Sobrien fatal ("specs file malformed after %ld characters", 221252520Sobrien (long) (p - buffer)); 221350599Sobrien 221450599Sobrien p1 = p; 221550599Sobrien /* Find next blank line or end of string. */ 221650599Sobrien while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0'))) 221750599Sobrien p1++; 221850599Sobrien 221950599Sobrien /* Specs end at the blank line and do not include the newline. */ 222050599Sobrien spec = save_string (p, p1 - p); 222150599Sobrien p = p1; 222250599Sobrien 222350599Sobrien /* Delete backslash-newline sequences from the spec. */ 222450599Sobrien in = spec; 222550599Sobrien out = spec; 222650599Sobrien while (*in != 0) 222750599Sobrien { 222850599Sobrien if (in[0] == '\\' && in[1] == '\n') 222950599Sobrien in += 2; 223050599Sobrien else if (in[0] == '#') 223150599Sobrien while (*in && *in != '\n') 223250599Sobrien in++; 223350599Sobrien 223450599Sobrien else 223550599Sobrien *out++ = *in++; 223650599Sobrien } 223750599Sobrien *out = 0; 223850599Sobrien 223950599Sobrien if (suffix[0] == '*') 224050599Sobrien { 224150599Sobrien if (! strcmp (suffix, "*link_command")) 224250599Sobrien link_command_spec = spec; 224350599Sobrien else 224450599Sobrien set_spec (suffix + 1, spec); 224550599Sobrien } 224650599Sobrien else 224750599Sobrien { 224850599Sobrien /* Add this pair to the vector. */ 224950599Sobrien compilers 2250132733Skan = xrealloc (compilers, 2251132733Skan (n_compilers + 2) * sizeof (struct compiler)); 225250599Sobrien 225350599Sobrien compilers[n_compilers].suffix = suffix; 225490277Sobrien compilers[n_compilers].spec = spec; 225550599Sobrien n_compilers++; 225690277Sobrien memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]); 225750599Sobrien } 225850599Sobrien 225950599Sobrien if (*suffix == 0) 226050599Sobrien link_command_spec = spec; 226150599Sobrien } 226250599Sobrien 226350599Sobrien if (link_command_spec == 0) 226450599Sobrien fatal ("spec file has no spec for linking"); 226550599Sobrien} 226650599Sobrien 226718334Speter/* Record the names of temporary files we tell compilers to write, 226818334Speter and delete them at the end of the run. */ 226918334Speter 227018334Speter/* This is the common prefix we use to make temp file names. 227118334Speter It is chosen once for each run of this program. 227290277Sobrien It is substituted into a spec by %g or %j. 227318334Speter Thus, all temp file names contain this prefix. 227418334Speter In practice, all temp file names start with this prefix. 227518334Speter 227618334Speter This prefix comes from the envvar TMPDIR if it is defined; 227718334Speter otherwise, from the P_tmpdir macro if that is defined; 227850599Sobrien otherwise, in /usr/tmp or /tmp; 227950599Sobrien or finally the current directory if all else fails. */ 228018334Speter 228152520Sobrienstatic const char *temp_filename; 228218334Speter 228318334Speter/* Length of the prefix. */ 228418334Speter 228518334Speterstatic int temp_filename_length; 228618334Speter 228718334Speter/* Define the list of temporary files to delete. */ 228818334Speter 228918334Speterstruct temp_file 229018334Speter{ 229152520Sobrien const char *name; 229218334Speter struct temp_file *next; 229318334Speter}; 229418334Speter 229518334Speter/* Queue of files to delete on success or failure of compilation. */ 229618334Speterstatic struct temp_file *always_delete_queue; 229718334Speter/* Queue of files to delete on failure of compilation. */ 229818334Speterstatic struct temp_file *failure_delete_queue; 229918334Speter 230018334Speter/* Record FILENAME as a file to be deleted automatically. 230118334Speter ALWAYS_DELETE nonzero means delete it if all compilation succeeds; 230218334Speter otherwise delete it in any case. 230318334Speter FAIL_DELETE nonzero means delete it if a compilation step fails; 230418334Speter otherwise delete it in any case. */ 230518334Speter 230690277Sobrienvoid 2307132733Skanrecord_temp_file (const char *filename, int always_delete, int fail_delete) 230818334Speter{ 230990277Sobrien char *const name = xstrdup (filename); 231018334Speter 231118334Speter if (always_delete) 231218334Speter { 231390277Sobrien struct temp_file *temp; 231418334Speter for (temp = always_delete_queue; temp; temp = temp->next) 231518334Speter if (! strcmp (name, temp->name)) 231618334Speter goto already1; 231750599Sobrien 2318169704Skan temp = XNEW (struct temp_file); 231918334Speter temp->next = always_delete_queue; 232018334Speter temp->name = name; 232118334Speter always_delete_queue = temp; 232250599Sobrien 232318334Speter already1:; 232418334Speter } 232518334Speter 232618334Speter if (fail_delete) 232718334Speter { 232890277Sobrien struct temp_file *temp; 232918334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 233018334Speter if (! strcmp (name, temp->name)) 233118334Speter goto already2; 233250599Sobrien 2333169704Skan temp = XNEW (struct temp_file); 233418334Speter temp->next = failure_delete_queue; 233518334Speter temp->name = name; 233618334Speter failure_delete_queue = temp; 233750599Sobrien 233818334Speter already2:; 233918334Speter } 234018334Speter} 234118334Speter 234218334Speter/* Delete all the temporary files whose names we previously recorded. */ 234318334Speter 2344169704Skan#ifndef DELETE_IF_ORDINARY 2345169704Skan#define DELETE_IF_ORDINARY(NAME,ST,VERBOSE_FLAG) \ 2346169704Skando \ 2347169704Skan { \ 2348169704Skan if (stat (NAME, &ST) >= 0 && S_ISREG (ST.st_mode)) \ 2349169704Skan if (unlink (NAME) < 0) \ 2350169704Skan if (VERBOSE_FLAG) \ 2351169704Skan perror_with_name (NAME); \ 2352169704Skan } while (0) 2353169704Skan#endif 2354169704Skan 235518334Speterstatic void 2356132733Skandelete_if_ordinary (const char *name) 235718334Speter{ 235818334Speter struct stat st; 235918334Speter#ifdef DEBUG 236018334Speter int i, c; 236118334Speter 236218334Speter printf ("Delete %s? (y or n) ", name); 236318334Speter fflush (stdout); 236418334Speter i = getchar (); 236518334Speter if (i != '\n') 236650599Sobrien while ((c = getchar ()) != '\n' && c != EOF) 236750599Sobrien ; 236850599Sobrien 236918334Speter if (i == 'y' || i == 'Y') 237018334Speter#endif /* DEBUG */ 2371169704Skan DELETE_IF_ORDINARY (name, st, verbose_flag); 237218334Speter} 237318334Speter 237418334Speterstatic void 2375132733Skandelete_temp_files (void) 237618334Speter{ 237790277Sobrien struct temp_file *temp; 237818334Speter 237918334Speter for (temp = always_delete_queue; temp; temp = temp->next) 238018334Speter delete_if_ordinary (temp->name); 238118334Speter always_delete_queue = 0; 238218334Speter} 238318334Speter 238418334Speter/* Delete all the files to be deleted on error. */ 238518334Speter 238618334Speterstatic void 2387132733Skandelete_failure_queue (void) 238818334Speter{ 238990277Sobrien struct temp_file *temp; 239018334Speter 239118334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 239218334Speter delete_if_ordinary (temp->name); 239318334Speter} 239418334Speter 239518334Speterstatic void 2396132733Skanclear_failure_queue (void) 239718334Speter{ 239818334Speter failure_delete_queue = 0; 239918334Speter} 240018334Speter 2401169704Skan/* Call CALLBACK for each path in PATHS, breaking out early if CALLBACK 2402169704Skan returns non-NULL. 2403169704Skan If DO_MULTI is true iterate over the paths twice, first with multilib 2404169704Skan suffix then without, otherwise iterate over the paths once without 2405169704Skan adding a multilib suffix. When DO_MULTI is true, some attempt is made 2406169704Skan to avoid visiting the same path twice, but we could do better. For 2407169704Skan instance, /usr/lib/../lib is considered different from /usr/lib. 2408169704Skan At least EXTRA_SPACE chars past the end of the path passed to 2409169704Skan CALLBACK are available for use by the callback. 2410169704Skan CALLBACK_INFO allows extra parameters to be passed to CALLBACK. 241118334Speter 2412169704Skan Returns the value returned by CALLBACK. */ 2413169704Skan 2414169704Skanstatic void * 2415169704Skanfor_each_path (const struct path_prefix *paths, 2416169704Skan bool do_multi, 2417169704Skan size_t extra_space, 2418169704Skan void *(*callback) (char *, void *), 2419169704Skan void *callback_info) 242018334Speter{ 2421169704Skan struct prefix_list *pl; 2422169704Skan const char *multi_dir = NULL; 2423169704Skan const char *multi_os_dir = NULL; 2424169704Skan const char *multi_suffix; 2425169704Skan const char *just_multi_suffix; 2426169704Skan char *path = NULL; 2427169704Skan void *ret = NULL; 2428169704Skan bool skip_multi_dir = false; 2429169704Skan bool skip_multi_os_dir = false; 243018334Speter 2431169704Skan multi_suffix = machine_suffix; 2432169704Skan just_multi_suffix = just_machine_suffix; 2433169704Skan if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0) 2434169704Skan { 2435169704Skan multi_dir = concat (multilib_dir, dir_separator_str, NULL); 2436169704Skan multi_suffix = concat (multi_suffix, multi_dir, NULL); 2437169704Skan just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL); 2438169704Skan } 2439169704Skan if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0) 2440169704Skan multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL); 244118334Speter 2442169704Skan while (1) 244318334Speter { 2444169704Skan size_t multi_dir_len = 0; 2445169704Skan size_t multi_os_dir_len = 0; 2446169704Skan size_t suffix_len; 2447169704Skan size_t just_suffix_len; 2448169704Skan size_t len; 244918334Speter 2450169704Skan if (multi_dir) 2451169704Skan multi_dir_len = strlen (multi_dir); 2452169704Skan if (multi_os_dir) 2453169704Skan multi_os_dir_len = strlen (multi_os_dir); 2454169704Skan suffix_len = strlen (multi_suffix); 2455169704Skan just_suffix_len = strlen (just_multi_suffix); 2456169704Skan 2457169704Skan if (path == NULL) 245818334Speter { 2459169704Skan len = paths->max_len + extra_space + 1; 2460169704Skan if (suffix_len > multi_os_dir_len) 2461169704Skan len += suffix_len; 2462169704Skan else 2463169704Skan len += multi_os_dir_len; 2464169704Skan path = XNEWVEC (char, len); 246518334Speter } 246618334Speter 2467169704Skan for (pl = paths->plist; pl != 0; pl = pl->next) 246818334Speter { 2469169704Skan len = strlen (pl->prefix); 2470169704Skan memcpy (path, pl->prefix, len); 247190277Sobrien 2472169704Skan /* Look first in MACHINE/VERSION subdirectory. */ 2473169704Skan if (!skip_multi_dir) 2474169704Skan { 2475169704Skan memcpy (path + len, multi_suffix, suffix_len + 1); 2476169704Skan ret = callback (path, callback_info); 2477169704Skan if (ret) 2478169704Skan break; 2479169704Skan } 2480169704Skan 2481169704Skan /* Some paths are tried with just the machine (ie. target) 2482169704Skan subdir. This is used for finding as, ld, etc. */ 2483169704Skan if (!skip_multi_dir 2484169704Skan && pl->require_machine_suffix == 2) 2485169704Skan { 2486169704Skan memcpy (path + len, just_multi_suffix, just_suffix_len + 1); 2487169704Skan ret = callback (path, callback_info); 2488169704Skan if (ret) 2489169704Skan break; 2490169704Skan } 2491169704Skan 2492169704Skan /* Now try the base path. */ 2493169704Skan if (!pl->require_machine_suffix 2494169704Skan && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir)) 2495169704Skan { 2496169704Skan const char *this_multi; 2497169704Skan size_t this_multi_len; 2498169704Skan 2499169704Skan if (pl->os_multilib) 2500169704Skan { 2501169704Skan this_multi = multi_os_dir; 2502169704Skan this_multi_len = multi_os_dir_len; 2503169704Skan } 2504169704Skan else 2505169704Skan { 2506169704Skan this_multi = multi_dir; 2507169704Skan this_multi_len = multi_dir_len; 2508169704Skan } 2509169704Skan 2510169704Skan if (this_multi_len) 2511169704Skan memcpy (path + len, this_multi, this_multi_len + 1); 2512169704Skan else 2513169704Skan path[len] = '\0'; 2514169704Skan 2515169704Skan ret = callback (path, callback_info); 2516169704Skan if (ret) 2517169704Skan break; 2518169704Skan } 251918334Speter } 2520169704Skan if (pl) 2521169704Skan break; 252218334Speter 2523169704Skan if (multi_dir == NULL && multi_os_dir == NULL) 2524169704Skan break; 2525169704Skan 2526169704Skan /* Run through the paths again, this time without multilibs. 2527169704Skan Don't repeat any we have already seen. */ 2528169704Skan if (multi_dir) 252918334Speter { 2530169704Skan free ((char *) multi_dir); 2531169704Skan multi_dir = NULL; 2532169704Skan free ((char *) multi_suffix); 2533169704Skan multi_suffix = machine_suffix; 2534169704Skan free ((char *) just_multi_suffix); 2535169704Skan just_multi_suffix = just_machine_suffix; 253618334Speter } 2537169704Skan else 2538169704Skan skip_multi_dir = true; 2539169704Skan if (multi_os_dir) 2540169704Skan { 2541169704Skan free ((char *) multi_os_dir); 2542169704Skan multi_os_dir = NULL; 2543169704Skan } 2544169704Skan else 2545169704Skan skip_multi_os_dir = true; 254618334Speter } 254750599Sobrien 2548169704Skan if (multi_dir) 2549169704Skan { 2550169704Skan free ((char *) multi_dir); 2551169704Skan free ((char *) multi_suffix); 2552169704Skan free ((char *) just_multi_suffix); 2553169704Skan } 2554169704Skan if (multi_os_dir) 2555169704Skan free ((char *) multi_os_dir); 2556169704Skan if (ret != path) 2557169704Skan free (path); 2558169704Skan return ret; 2559169704Skan} 2560169704Skan 2561169704Skan/* Callback for build_search_list. Adds path to obstack being built. */ 2562169704Skan 2563169704Skanstruct add_to_obstack_info { 2564169704Skan struct obstack *ob; 2565169704Skan bool check_dir; 2566169704Skan bool first_time; 2567169704Skan}; 2568169704Skan 2569169704Skanstatic void * 2570169704Skanadd_to_obstack (char *path, void *data) 2571169704Skan{ 2572169704Skan struct add_to_obstack_info *info = data; 2573169704Skan 2574169704Skan if (info->check_dir && !is_directory (path, false)) 2575169704Skan return NULL; 2576169704Skan 2577169704Skan if (!info->first_time) 2578169704Skan obstack_1grow (info->ob, PATH_SEPARATOR); 2579169704Skan 2580169704Skan obstack_grow (info->ob, path, strlen (path)); 2581169704Skan 2582169704Skan info->first_time = false; 2583169704Skan return NULL; 2584169704Skan} 2585169704Skan 2586169704Skan/* Build a list of search directories from PATHS. 2587169704Skan PREFIX is a string to prepend to the list. 2588169704Skan If CHECK_DIR_P is true we ensure the directory exists. 2589169704Skan If DO_MULTI is true, multilib paths are output first, then 2590169704Skan non-multilib paths. 2591169704Skan This is used mostly by putenv_from_prefixes so we use `collect_obstack'. 2592169704Skan It is also used by the --print-search-dirs flag. */ 2593169704Skan 2594169704Skanstatic char * 2595169704Skanbuild_search_list (const struct path_prefix *paths, const char *prefix, 2596169704Skan bool check_dir, bool do_multi) 2597169704Skan{ 2598169704Skan struct add_to_obstack_info info; 2599169704Skan 2600169704Skan info.ob = &collect_obstack; 2601169704Skan info.check_dir = check_dir; 2602169704Skan info.first_time = true; 2603169704Skan 2604169704Skan obstack_grow (&collect_obstack, prefix, strlen (prefix)); 2605169704Skan obstack_1grow (&collect_obstack, '='); 2606169704Skan 2607169704Skan for_each_path (paths, do_multi, 0, add_to_obstack, &info); 2608169704Skan 260918334Speter obstack_1grow (&collect_obstack, '\0'); 2610169704Skan return XOBFINISH (&collect_obstack, char *); 261118334Speter} 261218334Speter 261350599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 261450599Sobrien for collect. */ 261518334Speter 261618334Speterstatic void 2617169704Skanputenv_from_prefixes (const struct path_prefix *paths, const char *env_var, 2618169704Skan bool do_multi) 261918334Speter{ 2620169704Skan putenv (build_search_list (paths, env_var, true, do_multi)); 262118334Speter} 262218334Speter 262390277Sobrien/* Check whether NAME can be accessed in MODE. This is like access, 262490277Sobrien except that it never considers directories to be executable. */ 262590277Sobrien 262690277Sobrienstatic int 2627132733Skanaccess_check (const char *name, int mode) 262890277Sobrien{ 262990277Sobrien if (mode == X_OK) 263090277Sobrien { 263190277Sobrien struct stat st; 263290277Sobrien 263390277Sobrien if (stat (name, &st) < 0 263490277Sobrien || S_ISDIR (st.st_mode)) 263590277Sobrien return -1; 263690277Sobrien } 263790277Sobrien 263890277Sobrien return access (name, mode); 263990277Sobrien} 264090277Sobrien 2641169704Skan/* Callback for find_a_file. Appends the file name to the directory 2642169704Skan path. If the resulting file exists in the right mode, return the 2643169704Skan full pathname to the file. */ 2644169704Skan 2645169704Skanstruct file_at_path_info { 2646169704Skan const char *name; 2647169704Skan const char *suffix; 2648169704Skan int name_len; 2649169704Skan int suffix_len; 2650169704Skan int mode; 2651169704Skan}; 2652169704Skan 2653169704Skanstatic void * 2654169704Skanfile_at_path (char *path, void *data) 2655169704Skan{ 2656169704Skan struct file_at_path_info *info = data; 2657169704Skan size_t len = strlen (path); 2658169704Skan 2659169704Skan memcpy (path + len, info->name, info->name_len); 2660169704Skan len += info->name_len; 2661169704Skan 2662169704Skan /* Some systems have a suffix for executable files. 2663169704Skan So try appending that first. */ 2664169704Skan if (info->suffix_len) 2665169704Skan { 2666169704Skan memcpy (path + len, info->suffix, info->suffix_len + 1); 2667169704Skan if (access_check (path, info->mode) == 0) 2668169704Skan return path; 2669169704Skan } 2670169704Skan 2671169704Skan path[len] = '\0'; 2672169704Skan if (access_check (path, info->mode) == 0) 2673169704Skan return path; 2674169704Skan 2675169704Skan return NULL; 2676169704Skan} 2677169704Skan 267818334Speter/* Search for NAME using the prefix list PREFIXES. MODE is passed to 2679169704Skan access to check permissions. If DO_MULTI is true, search multilib 2680169704Skan paths then non-multilib paths, otherwise do not search multilib paths. 268150599Sobrien Return 0 if not found, otherwise return its name, allocated with malloc. */ 268218334Speter 268318334Speterstatic char * 2684169704Skanfind_a_file (const struct path_prefix *pprefix, const char *name, int mode, 2685169704Skan bool do_multi) 268618334Speter{ 2687169704Skan struct file_at_path_info info; 268818334Speter 268952520Sobrien#ifdef DEFAULT_ASSEMBLER 269090277Sobrien if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) 269190277Sobrien return xstrdup (DEFAULT_ASSEMBLER); 269252520Sobrien#endif 269352520Sobrien 269452520Sobrien#ifdef DEFAULT_LINKER 269590277Sobrien if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) 269690277Sobrien return xstrdup (DEFAULT_LINKER); 269752520Sobrien#endif 269852520Sobrien 2699231336Skientzle#ifdef FREEBSD_NATIVE 2700231336Skientzle if (! strcmp(name, "include")) 2701231336Skientzle { 2702231336Skientzle#ifdef CROSS_INCLUDE_DIR 2703231336Skientzle return xstrdup(CROSS_INCLUDE_DIR); 2704231336Skientzle#else 2705231336Skientzle return xstrdup(STANDARD_INCLUDE_DIR); 2706231336Skientzle#endif 2707231336Skientzle } 2708231336Skientzle#endif 2709231336Skientzle 271018334Speter /* Determine the filename to execute (special case for absolute paths). */ 271118334Speter 2712132733Skan if (IS_ABSOLUTE_PATH (name)) 271318334Speter { 271452520Sobrien if (access (name, mode) == 0) 2715169704Skan return xstrdup (name); 2716169704Skan 2717169704Skan return NULL; 271818334Speter } 2719104763Skan 2720169704Skan info.name = name; 2721169704Skan info.suffix = (mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : ""; 2722169704Skan info.name_len = strlen (info.name); 2723169704Skan info.suffix_len = strlen (info.suffix); 2724169704Skan info.mode = mode; 272518334Speter 2726169704Skan return for_each_path (pprefix, do_multi, info.name_len + info.suffix_len, 2727169704Skan file_at_path, &info); 272818334Speter} 272918334Speter 273090277Sobrien/* Ranking of prefixes in the sort list. -B prefixes are put before 273190277Sobrien all others. */ 273218334Speter 273390277Sobrienenum path_prefix_priority 273490277Sobrien{ 273590277Sobrien PREFIX_PRIORITY_B_OPT, 273690277Sobrien PREFIX_PRIORITY_LAST 273790277Sobrien}; 273890277Sobrien 2739132733Skan/* Add an entry for PREFIX in PLIST. The PLIST is kept in ascending 274090277Sobrien order according to PRIORITY. Within each PRIORITY, new entries are 274190277Sobrien appended. 274290277Sobrien 274318334Speter If WARN is nonzero, we will warn if no file is found 274418334Speter through this prefix. WARN should point to an int 274518334Speter which will be set to 1 if this entry is used. 274618334Speter 274750599Sobrien COMPONENT is the value to be passed to update_path. 274850599Sobrien 274918334Speter REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without 275018334Speter the complete value of machine_suffix. 275118334Speter 2 means try both machine_suffix and just_machine_suffix. */ 275218334Speter 275318334Speterstatic void 2754132733Skanadd_prefix (struct path_prefix *pprefix, const char *prefix, 2755132733Skan const char *component, /* enum prefix_priority */ int priority, 2756169704Skan int require_machine_suffix, int os_multilib) 275718334Speter{ 275818334Speter struct prefix_list *pl, **prev; 275918334Speter int len; 276018334Speter 276190277Sobrien for (prev = &pprefix->plist; 276290277Sobrien (*prev) != NULL && (*prev)->priority <= priority; 276390277Sobrien prev = &(*prev)->next) 276490277Sobrien ; 276518334Speter 2766132733Skan /* Keep track of the longest prefix. */ 276718334Speter 276850599Sobrien prefix = update_path (prefix, component); 276918334Speter len = strlen (prefix); 277018334Speter if (len > pprefix->max_len) 277118334Speter pprefix->max_len = len; 277218334Speter 2773169704Skan pl = XNEW (struct prefix_list); 277490277Sobrien pl->prefix = prefix; 277518334Speter pl->require_machine_suffix = require_machine_suffix; 277690277Sobrien pl->priority = priority; 2777104763Skan pl->os_multilib = os_multilib; 277818334Speter 2779132733Skan /* Insert after PREV. */ 278090277Sobrien pl->next = (*prev); 278190277Sobrien (*prev) = pl; 278218334Speter} 2783132733Skan 2784132733Skan/* Same as add_prefix, but prepending target_system_root to prefix. */ 2785132733Skanstatic void 2786132733Skanadd_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix, 2787132733Skan const char *component, 2788132733Skan /* enum prefix_priority */ int priority, 2789169704Skan int require_machine_suffix, int os_multilib) 2790132733Skan{ 2791132733Skan if (!IS_ABSOLUTE_PATH (prefix)) 2792169704Skan fatal ("system path '%s' is not absolute", prefix); 2793132733Skan 2794132733Skan if (target_system_root) 2795132733Skan { 2796132733Skan if (target_sysroot_suffix) 2797132733Skan prefix = concat (target_sysroot_suffix, prefix, NULL); 2798132733Skan prefix = concat (target_system_root, prefix, NULL); 2799132733Skan 2800132733Skan /* We have to override this because GCC's notion of sysroot 2801132733Skan moves along with GCC. */ 2802132733Skan component = "GCC"; 2803132733Skan } 2804132733Skan 2805132733Skan add_prefix (pprefix, prefix, component, priority, 2806169704Skan require_machine_suffix, os_multilib); 2807132733Skan} 280818334Speter 280918334Speter/* Execute the command specified by the arguments on the current line of spec. 281018334Speter When using pipes, this includes several piped-together commands 281118334Speter with `|' between them. 281218334Speter 281318334Speter Return 0 if successful, -1 if failed. */ 281418334Speter 281518334Speterstatic int 2816132733Skanexecute (void) 281718334Speter{ 281818334Speter int i; 281918334Speter int n_commands; /* # of command. */ 282018334Speter char *string; 2821169704Skan struct pex_obj *pex; 282218334Speter struct command 282390277Sobrien { 282490277Sobrien const char *prog; /* program name. */ 282590277Sobrien const char **argv; /* vector of args. */ 282690277Sobrien }; 282718334Speter 282818334Speter struct command *commands; /* each command buffer with above info. */ 282918334Speter 2830169704Skan gcc_assert (!processing_spec_function); 2831117413Skan 283218334Speter /* Count # of piped commands. */ 283318334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 283418334Speter if (strcmp (argbuf[i], "|") == 0) 283518334Speter n_commands++; 283618334Speter 283718334Speter /* Get storage for each command. */ 2838132733Skan commands = alloca (n_commands * sizeof (struct command)); 283918334Speter 284018334Speter /* Split argbuf into its separate piped processes, 284118334Speter and record info about each one. 284218334Speter Also search for the programs that are to be run. */ 284318334Speter 284418334Speter commands[0].prog = argbuf[0]; /* first command. */ 284518334Speter commands[0].argv = &argbuf[0]; 2846169704Skan string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false); 284750599Sobrien 284818334Speter if (string) 284918334Speter commands[0].argv[0] = string; 285018334Speter 285118334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 285218334Speter if (strcmp (argbuf[i], "|") == 0) 285318334Speter { /* each command. */ 285452520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS) 285590277Sobrien fatal ("-pipe not supported"); 285618334Speter#endif 285718334Speter argbuf[i] = 0; /* termination of command args. */ 285818334Speter commands[n_commands].prog = argbuf[i + 1]; 285918334Speter commands[n_commands].argv = &argbuf[i + 1]; 2860104763Skan string = find_a_file (&exec_prefixes, commands[n_commands].prog, 2861169704Skan X_OK, false); 286218334Speter if (string) 286318334Speter commands[n_commands].argv[0] = string; 286418334Speter n_commands++; 286518334Speter } 286618334Speter 286718334Speter argbuf[argbuf_index] = 0; 286818334Speter 286918334Speter /* If -v, print what we are about to do, and maybe query. */ 287018334Speter 287118334Speter if (verbose_flag) 287218334Speter { 287350599Sobrien /* For help listings, put a blank line between sub-processes. */ 287450599Sobrien if (print_help_list) 287550599Sobrien fputc ('\n', stderr); 287690277Sobrien 287718334Speter /* Print each piped command as a separate line. */ 287890277Sobrien for (i = 0; i < n_commands; i++) 287918334Speter { 288090277Sobrien const char *const *j; 288118334Speter 2882117413Skan if (verbose_only_flag) 2883117413Skan { 288490277Sobrien for (j = commands[i].argv; *j; j++) 288590277Sobrien { 288690277Sobrien const char *p; 288790277Sobrien fprintf (stderr, " \""); 288890277Sobrien for (p = *j; *p; ++p) 288990277Sobrien { 289090277Sobrien if (*p == '"' || *p == '\\' || *p == '$') 289190277Sobrien fputc ('\\', stderr); 289290277Sobrien fputc (*p, stderr); 289390277Sobrien } 289490277Sobrien fputc ('"', stderr); 289590277Sobrien } 2896117413Skan } 2897117413Skan else 289890277Sobrien for (j = commands[i].argv; *j; j++) 289990277Sobrien fprintf (stderr, " %s", *j); 290018334Speter 290118334Speter /* Print a pipe symbol after all but the last command. */ 290218334Speter if (i + 1 != n_commands) 290318334Speter fprintf (stderr, " |"); 290418334Speter fprintf (stderr, "\n"); 290518334Speter } 290618334Speter fflush (stderr); 290790277Sobrien if (verbose_only_flag != 0) 2908132733Skan { 2909132733Skan /* verbose_only_flag should act as if the spec was 2910132733Skan executed, so increment execution_count before 2911132733Skan returning. This prevents spurious warnings about 2912132733Skan unused linker input files, etc. */ 2913132733Skan execution_count++; 2914132733Skan return 0; 2915132733Skan } 291618334Speter#ifdef DEBUG 291752520Sobrien notice ("\nGo ahead? (y or n) "); 291818334Speter fflush (stderr); 291918334Speter i = getchar (); 292018334Speter if (i != '\n') 292150599Sobrien while (getchar () != '\n') 292250599Sobrien ; 292350599Sobrien 292418334Speter if (i != 'y' && i != 'Y') 292518334Speter return 0; 292618334Speter#endif /* DEBUG */ 292718334Speter } 292818334Speter 2929117413Skan#ifdef ENABLE_VALGRIND_CHECKING 2930132733Skan /* Run the each command through valgrind. To simplify prepending the 2931117413Skan path to valgrind and the option "-q" (for quiet operation unless 2932117413Skan something triggers), we allocate a separate argv array. */ 2933117413Skan 2934117413Skan for (i = 0; i < n_commands; i++) 2935117413Skan { 2936117413Skan const char **argv; 2937117413Skan int argc; 2938117413Skan int j; 2939117413Skan 2940117413Skan for (argc = 0; commands[i].argv[argc] != NULL; argc++) 2941117413Skan ; 2942117413Skan 2943117413Skan argv = alloca ((argc + 3) * sizeof (char *)); 2944117413Skan 2945117413Skan argv[0] = VALGRIND_PATH; 2946117413Skan argv[1] = "-q"; 2947117413Skan for (j = 2; j < argc + 2; j++) 2948117413Skan argv[j] = commands[i].argv[j - 2]; 2949117413Skan argv[j] = NULL; 2950117413Skan 2951117413Skan commands[i].argv = argv; 2952117413Skan commands[i].prog = argv[0]; 2953117413Skan } 2954117413Skan#endif 2955117413Skan 295618334Speter /* Run each piped subprocess. */ 295718334Speter 2958169704Skan pex = pex_init (PEX_USE_PIPES | (report_times ? PEX_RECORD_TIMES : 0), 2959169704Skan programname, temp_filename); 2960169704Skan if (pex == NULL) 2961169704Skan pfatal_with_name (_("pex_init failed")); 2962169704Skan 296318334Speter for (i = 0; i < n_commands; i++) 296418334Speter { 2965169704Skan const char *errmsg; 2966169704Skan int err; 296790277Sobrien const char *string = commands[i].argv[0]; 296818334Speter 2969169704Skan errmsg = pex_run (pex, 2970169704Skan ((i + 1 == n_commands ? PEX_LAST : 0) 2971169704Skan | (string == commands[i].prog ? PEX_SEARCH : 0)), 2972169704Skan string, (char * const *) commands[i].argv, 2973169704Skan NULL, NULL, &err); 2974169704Skan if (errmsg != NULL) 2975169704Skan { 2976169704Skan if (err == 0) 2977260011Spfg fatal ("%s", errmsg); 2978169704Skan else 2979169704Skan { 2980169704Skan errno = err; 2981169704Skan pfatal_with_name (errmsg); 2982169704Skan } 2983169704Skan } 298418334Speter 298518334Speter if (string != commands[i].prog) 2986132733Skan free ((void *) string); 298718334Speter } 298818334Speter 298918334Speter execution_count++; 299018334Speter 2991169704Skan /* Wait for all the subprocesses to finish. */ 299218334Speter 299318334Speter { 2994169704Skan int *statuses; 2995169704Skan struct pex_time *times = NULL; 299618334Speter int ret_code = 0; 299718334Speter 2998169704Skan statuses = alloca (n_commands * sizeof (int)); 2999169704Skan if (!pex_get_status (pex, n_commands, statuses)) 3000169704Skan pfatal_with_name (_("failed to get exit status")); 3001169704Skan 3002169704Skan if (report_times) 300318334Speter { 3004169704Skan times = alloca (n_commands * sizeof (struct pex_time)); 3005169704Skan if (!pex_get_times (pex, n_commands, times)) 3006169704Skan pfatal_with_name (_("failed to get process times")); 3007169704Skan } 300818334Speter 3009169704Skan pex_free (pex); 301018334Speter 3011169704Skan for (i = 0; i < n_commands; ++i) 3012169704Skan { 3013169704Skan int status = statuses[i]; 3014169704Skan 3015169704Skan if (WIFSIGNALED (status)) 301690277Sobrien { 301790277Sobrien#ifdef SIGPIPE 3018169704Skan /* SIGPIPE is a special case. It happens in -pipe mode 3019169704Skan when the compiler dies before the preprocessor is done, 3020169704Skan or the assembler dies before the compiler is done. 3021169704Skan There's generally been an error already, and this is 3022169704Skan just fallout. So don't generate another error unless 3023169704Skan we would otherwise have succeeded. */ 3024169704Skan if (WTERMSIG (status) == SIGPIPE 3025169704Skan && (signal_count || greatest_status >= MIN_FATAL_STATUS)) 3026169704Skan { 3027169704Skan signal_count++; 3028169704Skan ret_code = -1; 3029169704Skan } 3030169704Skan else 303190277Sobrien#endif 3032169704Skan fatal_ice ("\ 303390277SobrienInternal error: %s (program %s)\n\ 303490277SobrienPlease submit a full bug report.\n\ 303590277SobrienSee %s for instructions.", 3036169704Skan strsignal (WTERMSIG (status)), commands[i].prog, 3037169704Skan bug_report_url); 3038169704Skan } 3039169704Skan else if (WIFEXITED (status) 3040169704Skan && WEXITSTATUS (status) >= MIN_FATAL_STATUS) 3041169704Skan { 3042169704Skan if (WEXITSTATUS (status) > greatest_status) 3043169704Skan greatest_status = WEXITSTATUS (status); 3044169704Skan ret_code = -1; 3045169704Skan } 3046169704Skan 3047169704Skan if (report_times) 3048169704Skan { 3049169704Skan struct pex_time *pt = ×[i]; 3050169704Skan double ut, st; 3051169704Skan 3052169704Skan ut = ((double) pt->user_seconds 3053169704Skan + (double) pt->user_microseconds / 1.0e6); 3054169704Skan st = ((double) pt->system_seconds 3055169704Skan + (double) pt->system_microseconds / 1.0e6); 3056169704Skan 3057169704Skan if (ut + st != 0) 3058169704Skan notice ("# %s %.2f %.2f\n", commands[i].prog, ut, st); 3059169704Skan } 306018334Speter } 3061169704Skan 306218334Speter return ret_code; 306318334Speter } 306418334Speter} 306518334Speter 306618334Speter/* Find all the switches given to us 306718334Speter and make a vector describing them. 306818334Speter The elements of the vector are strings, one per switch given. 306918334Speter If a switch uses following arguments, then the `part1' field 307018334Speter is the switch itself and the `args' field 307118334Speter is a null-terminated vector containing the following arguments. 307290277Sobrien The `live_cond' field is: 307390277Sobrien 0 when initialized 307490277Sobrien 1 if the switch is true in a conditional spec, 307590277Sobrien -1 if false (overridden by a later switch) 3076132733Skan -2 if this switch should be ignored (used in %<S) 307752520Sobrien The `validated' field is nonzero if any spec has looked at this switch; 307818334Speter if it remains zero at the end of the run, it must be meaningless. */ 307918334Speter 308090277Sobrien#define SWITCH_OK 0 308190277Sobrien#define SWITCH_FALSE -1 308290277Sobrien#define SWITCH_IGNORE -2 308390277Sobrien#define SWITCH_LIVE 1 308490277Sobrien 308518334Speterstruct switchstr 308618334Speter{ 308752520Sobrien const char *part1; 308890277Sobrien const char **args; 308918334Speter int live_cond; 309090277Sobrien unsigned char validated; 309190277Sobrien unsigned char ordering; 309218334Speter}; 309318334Speter 309418334Speterstatic struct switchstr *switches; 309518334Speter 309618334Speterstatic int n_switches; 309718334Speter 3098169704Skan/* Language is one of three things: 3099169704Skan 3100169704Skan 1) The name of a real programming language. 3101169704Skan 2) NULL, indicating that no one has figured out 3102169704Skan what it is yet. 3103169704Skan 3) '*', indicating that the file should be passed 3104169704Skan to the linker. */ 310518334Speterstruct infile 310618334Speter{ 310752520Sobrien const char *name; 310852520Sobrien const char *language; 3109169704Skan struct compiler *incompiler; 3110169704Skan bool compiled; 3111169704Skan bool preprocessed; 311218334Speter}; 311318334Speter 311418334Speter/* Also a vector of input files specified. */ 311518334Speter 311618334Speterstatic struct infile *infiles; 311718334Speter 311890277Sobrienint n_infiles; 311918334Speter 3120132733Skan/* True if multiple input files are being compiled to a single 3121132733Skan assembly file. */ 3122132733Skan 3123132733Skanstatic bool combine_inputs; 3124132733Skan 312552520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that 312650599Sobrien we can tell if there were any user supplied any files or libraries. */ 312750599Sobrien 312850599Sobrienstatic int added_libraries; 312950599Sobrien 313018334Speter/* And a vector of corresponding output files is made up later. */ 313118334Speter 313290277Sobrienconst char **outfiles; 313350599Sobrien 313490277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 313550599Sobrien 313650599Sobrien/* Convert NAME to a new name if it is the standard suffix. DO_EXE 313790277Sobrien is true if we should look for an executable suffix. DO_OBJ 313890277Sobrien is true if we should look for an object suffix. */ 313950599Sobrien 314090277Sobrienstatic const char * 3141132733Skanconvert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED, 3142132733Skan int do_obj ATTRIBUTE_UNUSED) 314350599Sobrien{ 314490277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 314550599Sobrien int i; 314690277Sobrien#endif 314752520Sobrien int len; 314850599Sobrien 314952520Sobrien if (name == NULL) 315052520Sobrien return NULL; 315190277Sobrien 315252520Sobrien len = strlen (name); 315352520Sobrien 315490277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX 315590277Sobrien /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj". */ 315690277Sobrien if (do_obj && len > 2 315750599Sobrien && name[len - 2] == '.' 315850599Sobrien && name[len - 1] == 'o') 315950599Sobrien { 316050599Sobrien obstack_grow (&obstack, name, len - 2); 316190277Sobrien obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); 3162169704Skan name = XOBFINISH (&obstack, const char *); 316350599Sobrien } 316450599Sobrien#endif 316550599Sobrien 316690277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 316750599Sobrien /* If there is no filetype, make it the executable suffix (which includes 316850599Sobrien the "."). But don't get confused if we have just "-o". */ 316990277Sobrien if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-')) 317050599Sobrien return name; 317150599Sobrien 317250599Sobrien for (i = len - 1; i >= 0; i--) 317352520Sobrien if (IS_DIR_SEPARATOR (name[i])) 317450599Sobrien break; 317550599Sobrien 317650599Sobrien for (i++; i < len; i++) 317750599Sobrien if (name[i] == '.') 317850599Sobrien return name; 317950599Sobrien 318050599Sobrien obstack_grow (&obstack, name, len); 318190277Sobrien obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX, 318290277Sobrien strlen (TARGET_EXECUTABLE_SUFFIX)); 3183169704Skan name = XOBFINISH (&obstack, const char *); 318450599Sobrien#endif 318550599Sobrien 318650599Sobrien return name; 318750599Sobrien} 318850599Sobrien#endif 318950599Sobrien 319050599Sobrien/* Display the command line switches accepted by gcc. */ 319150599Sobrienstatic void 3192132733Skandisplay_help (void) 319350599Sobrien{ 319490277Sobrien printf (_("Usage: %s [options] file...\n"), programname); 319590277Sobrien fputs (_("Options:\n"), stdout); 319650599Sobrien 319790277Sobrien fputs (_(" -pass-exit-codes Exit with highest error code from a phase\n"), stdout); 319890277Sobrien fputs (_(" --help Display this information\n"), stdout); 319990277Sobrien fputs (_(" --target-help Display target specific command line options\n"), stdout); 320050599Sobrien if (! verbose_flag) 320190277Sobrien fputs (_(" (Use '-v --help' to display command line options of sub-processes)\n"), stdout); 320290277Sobrien fputs (_(" -dumpspecs Display all of the built in spec strings\n"), stdout); 320390277Sobrien fputs (_(" -dumpversion Display the version of the compiler\n"), stdout); 320490277Sobrien fputs (_(" -dumpmachine Display the compiler's target processor\n"), stdout); 320590277Sobrien fputs (_(" -print-search-dirs Display the directories in the compiler's search path\n"), stdout); 320690277Sobrien fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library\n"), stdout); 320790277Sobrien fputs (_(" -print-file-name=<lib> Display the full path to library <lib>\n"), stdout); 320890277Sobrien fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>\n"), stdout); 320990277Sobrien fputs (_(" -print-multi-directory Display the root directory for versions of libgcc\n"), stdout); 321090277Sobrien fputs (_("\ 321190277Sobrien -print-multi-lib Display the mapping between command line options and\n\ 321290277Sobrien multiple library search directories\n"), stdout); 3213104763Skan fputs (_(" -print-multi-os-directory Display the relative path to OS libraries\n"), stdout); 321490277Sobrien fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler\n"), stdout); 321590277Sobrien fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout); 321690277Sobrien fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker\n"), stdout); 3217132733Skan fputs (_(" -Xassembler <arg> Pass <arg> on to the assembler\n"), stdout); 3218132733Skan fputs (_(" -Xpreprocessor <arg> Pass <arg> on to the preprocessor\n"), stdout); 321990277Sobrien fputs (_(" -Xlinker <arg> Pass <arg> on to the linker\n"), stdout); 3220169704Skan fputs (_(" -combine Pass multiple source files to compiler at once\n"), stdout); 322190277Sobrien fputs (_(" -save-temps Do not delete intermediate files\n"), stdout); 322290277Sobrien fputs (_(" -pipe Use pipes rather than intermediate files\n"), stdout); 322390277Sobrien fputs (_(" -time Time the execution of each subprocess\n"), stdout); 322490277Sobrien fputs (_(" -specs=<file> Override built-in specs with the contents of <file>\n"), stdout); 322590277Sobrien fputs (_(" -std=<standard> Assume that the input sources are for <standard>\n"), stdout); 3226169704Skan fputs (_("\ 3227169704Skan --sysroot=<directory> Use <directory> as the root directory for headers\n\ 3228169704Skan and libraries\n"), stdout); 322990277Sobrien fputs (_(" -B <directory> Add <directory> to the compiler's search paths\n"), stdout); 323090277Sobrien fputs (_(" -b <machine> Run gcc for target <machine>, if installed\n"), stdout); 323190277Sobrien fputs (_(" -V <version> Run gcc version number <version>, if installed\n"), stdout); 323290277Sobrien fputs (_(" -v Display the programs invoked by the compiler\n"), stdout); 323390277Sobrien fputs (_(" -### Like -v but options quoted and commands not executed\n"), stdout); 323490277Sobrien fputs (_(" -E Preprocess only; do not compile, assemble or link\n"), stdout); 323590277Sobrien fputs (_(" -S Compile only; do not assemble or link\n"), stdout); 323690277Sobrien fputs (_(" -c Compile and assemble, but do not link\n"), stdout); 323790277Sobrien fputs (_(" -o <file> Place the output into <file>\n"), stdout); 323890277Sobrien fputs (_("\ 323990277Sobrien -x <language> Specify the language of the following input files\n\ 3240117413Skan Permissible languages include: c c++ assembler none\n\ 324190277Sobrien 'none' means revert to the default behavior of\n\ 324290277Sobrien guessing the language based on the file's extension\n\ 324390277Sobrien"), stdout); 324450599Sobrien 324590277Sobrien printf (_("\ 324690277Sobrien\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\ 324790277Sobrien passed on to the various sub-processes invoked by %s. In order to pass\n\ 324890277Sobrien other options on to these processes the -W<letter> options must be used.\n\ 324990277Sobrien"), programname); 325050599Sobrien 325150599Sobrien /* The rest of the options are displayed by invocations of the various 325250599Sobrien sub-processes. */ 325350599Sobrien} 325450599Sobrien 325590277Sobrienstatic void 3256132733Skanadd_preprocessor_option (const char *option, int len) 325790277Sobrien{ 325852520Sobrien n_preprocessor_options++; 325990277Sobrien 326052520Sobrien if (! preprocessor_options) 3261169704Skan preprocessor_options = XNEWVEC (char *, n_preprocessor_options); 326252520Sobrien else 3263132733Skan preprocessor_options = xrealloc (preprocessor_options, 3264132733Skan n_preprocessor_options * sizeof (char *)); 326590277Sobrien 326652520Sobrien preprocessor_options [n_preprocessor_options - 1] = 326752520Sobrien save_string (option, len); 326850599Sobrien} 326990277Sobrien 327090277Sobrienstatic void 3271132733Skanadd_assembler_option (const char *option, int len) 327252520Sobrien{ 327352520Sobrien n_assembler_options++; 327452520Sobrien 327552520Sobrien if (! assembler_options) 3276169704Skan assembler_options = XNEWVEC (char *, n_assembler_options); 327752520Sobrien else 3278132733Skan assembler_options = xrealloc (assembler_options, 3279132733Skan n_assembler_options * sizeof (char *)); 328052520Sobrien 328152520Sobrien assembler_options [n_assembler_options - 1] = save_string (option, len); 328250599Sobrien} 328390277Sobrien 328490277Sobrienstatic void 3285132733Skanadd_linker_option (const char *option, int len) 328652520Sobrien{ 328752520Sobrien n_linker_options++; 328852520Sobrien 328952520Sobrien if (! linker_options) 3290169704Skan linker_options = XNEWVEC (char *, n_linker_options); 329152520Sobrien else 3292132733Skan linker_options = xrealloc (linker_options, 3293132733Skan n_linker_options * sizeof (char *)); 329452520Sobrien 329552520Sobrien linker_options [n_linker_options - 1] = save_string (option, len); 329650599Sobrien} 329750599Sobrien 329818334Speter/* Create the vector `switches' and its contents. 329918334Speter Store its length in `n_switches'. */ 330018334Speter 330118334Speterstatic void 3302132733Skanprocess_command (int argc, const char **argv) 330318334Speter{ 330490277Sobrien int i; 330552520Sobrien const char *temp; 330652520Sobrien char *temp1; 330790277Sobrien const char *spec_lang = 0; 330818334Speter int last_language_n_infiles; 330950599Sobrien int lang_n_infiles = 0; 331090277Sobrien#ifdef MODIFY_TARGET_NAME 331190277Sobrien int is_modify_target_name; 3312169704Skan unsigned int j; 331390277Sobrien#endif 331418334Speter 3315117413Skan GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX"); 331618334Speter 331718334Speter n_switches = 0; 331818334Speter n_infiles = 0; 331950599Sobrien added_libraries = 0; 332018334Speter 332118334Speter /* Figure compiler version from version string. */ 332218334Speter 332390277Sobrien compiler_version = temp1 = xstrdup (version_string); 332490277Sobrien 332552520Sobrien for (; *temp1; ++temp1) 332618334Speter { 332752520Sobrien if (*temp1 == ' ') 332818334Speter { 332952520Sobrien *temp1 = '\0'; 333018334Speter break; 333118334Speter } 333218334Speter } 333318334Speter 3334117413Skan /* If there is a -V or -b option (or both), process it now, before 3335169704Skan trying to interpret the rest of the command line. 3336169704Skan Use heuristic that all configuration names must have at least 3337169704Skan one dash '-'. This allows us to pass options starting with -b. */ 3338117413Skan if (argc > 1 && argv[1][0] == '-' 3339169704Skan && (argv[1][1] == 'V' || 3340169704Skan ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-'))))) 3341117413Skan { 3342117413Skan const char *new_version = DEFAULT_TARGET_VERSION; 3343117413Skan const char *new_machine = DEFAULT_TARGET_MACHINE; 3344117413Skan const char *progname = argv[0]; 3345117413Skan char **new_argv; 3346117413Skan char *new_argv0; 3347117413Skan int baselen; 3348132733Skan 3349117413Skan while (argc > 1 && argv[1][0] == '-' 3350169704Skan && (argv[1][1] == 'V' || 3351169704Skan ((argv[1][1] == 'b') && ( NULL != strchr(argv[1] + 2,'-'))))) 3352117413Skan { 3353117413Skan char opt = argv[1][1]; 3354117413Skan const char *arg; 3355117413Skan if (argv[1][2] != '\0') 3356117413Skan { 3357117413Skan arg = argv[1] + 2; 3358117413Skan argc -= 1; 3359117413Skan argv += 1; 3360117413Skan } 3361117413Skan else if (argc > 2) 3362117413Skan { 3363117413Skan arg = argv[2]; 3364117413Skan argc -= 2; 3365117413Skan argv += 2; 3366117413Skan } 3367117413Skan else 3368169704Skan fatal ("'-%c' option must have argument", opt); 3369117413Skan if (opt == 'V') 3370117413Skan new_version = arg; 3371117413Skan else 3372117413Skan new_machine = arg; 3373117413Skan } 3374117413Skan 3375117413Skan for (baselen = strlen (progname); baselen > 0; baselen--) 3376117413Skan if (IS_DIR_SEPARATOR (progname[baselen-1])) 3377117413Skan break; 3378132733Skan new_argv0 = xmemdup (progname, baselen, 3379117413Skan baselen + concat_length (new_version, new_machine, 3380117413Skan "-gcc-", NULL) + 1); 3381117413Skan strcpy (new_argv0 + baselen, new_machine); 3382117413Skan strcat (new_argv0, "-gcc-"); 3383117413Skan strcat (new_argv0, new_version); 3384117413Skan 3385117413Skan new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]), 3386117413Skan (argc + 1) * sizeof (argv[0])); 3387117413Skan new_argv[0] = new_argv0; 3388117413Skan 3389117413Skan execvp (new_argv0, new_argv); 3390169704Skan fatal ("couldn't run '%s': %s", new_argv0, xstrerror (errno)); 3391117413Skan } 3392117413Skan 339390277Sobrien /* Set up the default search paths. If there is no GCC_EXEC_PREFIX, 339490277Sobrien see if we can create it from the pathname specified in argv[0]. */ 339518334Speter 3396132733Skan gcc_libexec_prefix = standard_libexec_prefix; 339796736Sru#ifndef FREEBSD_NATIVE 339890277Sobrien#ifndef VMS 339990277Sobrien /* FIXME: make_relative_prefix doesn't yet work for VMS. */ 340090277Sobrien if (!gcc_exec_prefix) 340190277Sobrien { 340290277Sobrien gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix, 340390277Sobrien standard_exec_prefix); 3404169704Skan gcc_libexec_prefix = make_relative_prefix (argv[0], 3405132733Skan standard_bindir_prefix, 3406132733Skan standard_libexec_prefix); 340790277Sobrien if (gcc_exec_prefix) 340890277Sobrien putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL)); 340990277Sobrien } 3410132733Skan else 3411169704Skan { 3412169704Skan /* make_relative_prefix requires a program name, but 3413169704Skan GCC_EXEC_PREFIX is typically a directory name with a trailing 3414169704Skan / (which is ignored by make_relative_prefix), so append a 3415169704Skan program name. */ 3416169704Skan char *tmp_prefix = concat (gcc_exec_prefix, "gcc", NULL); 3417169704Skan gcc_libexec_prefix = make_relative_prefix (tmp_prefix, 3418169704Skan standard_exec_prefix, 3419169704Skan standard_libexec_prefix); 3420169704Skan free (tmp_prefix); 3421169704Skan } 3422132733Skan#else 342390277Sobrien#endif 342496736Sru#endif /* not FREEBSD_NATIVE */ 342590277Sobrien 342618334Speter if (gcc_exec_prefix) 342718334Speter { 342850599Sobrien int len = strlen (gcc_exec_prefix); 342990277Sobrien 3430132733Skan if (len > (int) sizeof ("/lib/gcc/") - 1 343152520Sobrien && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1]))) 343250599Sobrien { 3433132733Skan temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1; 343452520Sobrien if (IS_DIR_SEPARATOR (*temp) 343590277Sobrien && strncmp (temp + 1, "lib", 3) == 0 343652520Sobrien && IS_DIR_SEPARATOR (temp[4]) 3437132733Skan && strncmp (temp + 5, "gcc", 3) == 0) 3438132733Skan len -= sizeof ("/lib/gcc/") - 1; 343950599Sobrien } 344050599Sobrien 344150599Sobrien set_std_prefix (gcc_exec_prefix, len); 3442132733Skan add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC", 3443169704Skan PREFIX_PRIORITY_LAST, 0, 0); 344490277Sobrien add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 3445169704Skan PREFIX_PRIORITY_LAST, 0, 0); 344618334Speter } 344718334Speter 344818334Speter /* COMPILER_PATH and LIBRARY_PATH have values 344918334Speter that are lists of directory names with colons. */ 345018334Speter 3451117413Skan GET_ENVIRONMENT (temp, "COMPILER_PATH"); 345218334Speter if (temp) 345318334Speter { 345452520Sobrien const char *startp, *endp; 3455132733Skan char *nstore = alloca (strlen (temp) + 3); 345618334Speter 345718334Speter startp = endp = temp; 345818334Speter while (1) 345918334Speter { 346018334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 346118334Speter { 346290277Sobrien strncpy (nstore, startp, endp - startp); 346318334Speter if (endp == startp) 346490277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 346552520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 346618334Speter { 346790277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 346890277Sobrien nstore[endp - startp + 1] = 0; 346918334Speter } 347018334Speter else 347190277Sobrien nstore[endp - startp] = 0; 347290277Sobrien add_prefix (&exec_prefixes, nstore, 0, 3473169704Skan PREFIX_PRIORITY_LAST, 0, 0); 3474169704Skan add_prefix (&include_prefixes, nstore, 0, 3475169704Skan PREFIX_PRIORITY_LAST, 0, 0); 347618334Speter if (*endp == 0) 347718334Speter break; 347818334Speter endp = startp = endp + 1; 347918334Speter } 348018334Speter else 348118334Speter endp++; 348218334Speter } 348318334Speter } 348418334Speter 3485117413Skan GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV); 348691651Sobrien if (temp && *cross_compile == '0') 348718334Speter { 348852520Sobrien const char *startp, *endp; 3489132733Skan char *nstore = alloca (strlen (temp) + 3); 349018334Speter 349118334Speter startp = endp = temp; 349218334Speter while (1) 349318334Speter { 349418334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 349518334Speter { 349690277Sobrien strncpy (nstore, startp, endp - startp); 349718334Speter if (endp == startp) 349890277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 349952520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 350018334Speter { 350190277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 350290277Sobrien nstore[endp - startp + 1] = 0; 350318334Speter } 350418334Speter else 350590277Sobrien nstore[endp - startp] = 0; 350690277Sobrien add_prefix (&startfile_prefixes, nstore, NULL, 3507169704Skan PREFIX_PRIORITY_LAST, 0, 1); 350818334Speter if (*endp == 0) 350918334Speter break; 351018334Speter endp = startp = endp + 1; 351118334Speter } 351218334Speter else 351318334Speter endp++; 351418334Speter } 351518334Speter } 351618334Speter 351718334Speter /* Use LPATH like LIBRARY_PATH (for the CMU build program). */ 3518117413Skan GET_ENVIRONMENT (temp, "LPATH"); 351950599Sobrien if (temp && *cross_compile == '0') 352018334Speter { 352152520Sobrien const char *startp, *endp; 3522132733Skan char *nstore = alloca (strlen (temp) + 3); 352318334Speter 352418334Speter startp = endp = temp; 352518334Speter while (1) 352618334Speter { 352718334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 352818334Speter { 352990277Sobrien strncpy (nstore, startp, endp - startp); 353018334Speter if (endp == startp) 353190277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 353252520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 353318334Speter { 353490277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 353590277Sobrien nstore[endp - startp + 1] = 0; 353618334Speter } 353718334Speter else 353890277Sobrien nstore[endp - startp] = 0; 353990277Sobrien add_prefix (&startfile_prefixes, nstore, NULL, 3540169704Skan PREFIX_PRIORITY_LAST, 0, 1); 354118334Speter if (*endp == 0) 354218334Speter break; 354318334Speter endp = startp = endp + 1; 354418334Speter } 354518334Speter else 354618334Speter endp++; 354718334Speter } 354818334Speter } 354918334Speter 355077389Sobrien /* Options specified as if they appeared on the command line. */ 355177389Sobrien temp = getenv ("GCC_OPTIONS"); 355277389Sobrien if ((temp) && (strlen (temp) > 0)) 355377389Sobrien { 355477389Sobrien int len; 355577389Sobrien int optc = 1; 355677389Sobrien int new_argc; 3557110024Sobrien const char **new_argv; 355877389Sobrien char *envopts; 355977389Sobrien 356077389Sobrien while (isspace (*temp)) 356177389Sobrien temp++; 356277389Sobrien len = strlen (temp); 356377389Sobrien envopts = (char *) xmalloc (len + 1); 356477389Sobrien strcpy (envopts, temp); 356577389Sobrien 356677389Sobrien for (i = 0; i < (len - 1); i++) 356777389Sobrien if ((isspace (envopts[i])) && ! (isspace (envopts[i+1]))) 356877389Sobrien optc++; 356977389Sobrien 3570110024Sobrien new_argv = (const char **) alloca ((optc + argc) * sizeof(char *)); 357177389Sobrien 357277389Sobrien for (i = 0, new_argc = 1; new_argc <= optc; new_argc++) 357377389Sobrien { 357477389Sobrien while (isspace (envopts[i])) 357577389Sobrien i++; 357677389Sobrien new_argv[new_argc] = envopts + i; 357777389Sobrien while (!isspace (envopts[i]) && (envopts[i] != '\0')) 357877389Sobrien i++; 357977389Sobrien envopts[i++] = '\0'; 358077389Sobrien } 358177389Sobrien for (i = 1; i < argc; i++) 358277389Sobrien new_argv[new_argc++] = argv[i]; 358377389Sobrien 358477389Sobrien argv = new_argv; 358577389Sobrien argc = new_argc; 358677389Sobrien } 358777389Sobrien 358818334Speter /* Convert new-style -- options to old-style. */ 3589132733Skan translate_options (&argc, (const char *const **) &argv); 359018334Speter 359150599Sobrien /* Do language-specific adjustment/addition of flags. */ 3592132733Skan lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries); 359350599Sobrien 359418334Speter /* Scan argv twice. Here, the first time, just count how many switches 359518334Speter there will be in their vector, and how many input files in theirs. 359618334Speter Here we also parse the switches that cc itself uses (e.g. -v). */ 359718334Speter 359818334Speter for (i = 1; i < argc; i++) 359918334Speter { 360018334Speter if (! strcmp (argv[i], "-dumpspecs")) 360118334Speter { 360250599Sobrien struct spec_list *sl; 360350599Sobrien init_spec (); 360450599Sobrien for (sl = specs; sl; sl = sl->next) 360550599Sobrien printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec)); 360690277Sobrien if (link_command_spec) 360790277Sobrien printf ("*link_command:\n%s\n\n", link_command_spec); 360818334Speter exit (0); 360918334Speter } 361018334Speter else if (! strcmp (argv[i], "-dumpversion")) 361118334Speter { 361250599Sobrien printf ("%s\n", spec_version); 361318334Speter exit (0); 361418334Speter } 361518334Speter else if (! strcmp (argv[i], "-dumpmachine")) 361618334Speter { 361718334Speter printf ("%s\n", spec_machine); 361890277Sobrien exit (0); 361918334Speter } 362090277Sobrien else if (strcmp (argv[i], "-fversion") == 0) 362190277Sobrien { 362290277Sobrien /* translate_options () has turned --version into -fversion. */ 362390277Sobrien printf (_("%s (GCC) %s\n"), programname, version_string); 3624169704Skan printf ("Copyright %s 2007 Free Software Foundation, Inc.\n", 3625132733Skan _("(C)")); 362690277Sobrien fputs (_("This is free software; see the source for copying conditions. There is NO\n\ 362790277Sobrienwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"), 362890277Sobrien stdout); 362990277Sobrien exit (0); 363090277Sobrien } 363150599Sobrien else if (strcmp (argv[i], "-fhelp") == 0) 363250599Sobrien { 363350599Sobrien /* translate_options () has turned --help into -fhelp. */ 363450599Sobrien print_help_list = 1; 363550599Sobrien 363650599Sobrien /* We will be passing a dummy file on to the sub-processes. */ 363750599Sobrien n_infiles++; 363850599Sobrien n_switches++; 363990277Sobrien 364090277Sobrien /* CPP driver cannot obtain switch from cc1_options. */ 364190277Sobrien if (is_cpp_driver) 364290277Sobrien add_preprocessor_option ("--help", 6); 364350599Sobrien add_assembler_option ("--help", 6); 364450599Sobrien add_linker_option ("--help", 6); 364550599Sobrien } 364690277Sobrien else if (strcmp (argv[i], "-ftarget-help") == 0) 3647117413Skan { 3648117413Skan /* translate_options() has turned --target-help into -ftarget-help. */ 3649117413Skan target_help_flag = 1; 365090277Sobrien 3651117413Skan /* We will be passing a dummy file on to the sub-processes. */ 3652117413Skan n_infiles++; 3653117413Skan n_switches++; 365490277Sobrien 365590277Sobrien /* CPP driver cannot obtain switch from cc1_options. */ 365690277Sobrien if (is_cpp_driver) 365790277Sobrien add_preprocessor_option ("--target-help", 13); 3658117413Skan add_assembler_option ("--target-help", 13); 3659117413Skan add_linker_option ("--target-help", 13); 3660117413Skan } 366190277Sobrien else if (! strcmp (argv[i], "-pass-exit-codes")) 366290277Sobrien { 366390277Sobrien pass_exit_codes = 1; 366490277Sobrien n_switches++; 366590277Sobrien } 366618334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 366718334Speter print_search_dirs = 1; 366818334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 366918334Speter print_file_name = "libgcc.a"; 367018334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 367118334Speter print_file_name = argv[i] + 17; 367218334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 367318334Speter print_prog_name = argv[i] + 17; 367418334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 367518334Speter print_multi_lib = 1; 367618334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 367718334Speter print_multi_directory = 1; 3678104763Skan else if (! strcmp (argv[i], "-print-multi-os-directory")) 3679104763Skan print_multi_os_directory = 1; 368018334Speter else if (! strncmp (argv[i], "-Wa,", 4)) 368118334Speter { 368218334Speter int prev, j; 368318334Speter /* Pass the rest of this option to the assembler. */ 368418334Speter 368518334Speter /* Split the argument at commas. */ 368618334Speter prev = 4; 368718334Speter for (j = 4; argv[i][j]; j++) 368818334Speter if (argv[i][j] == ',') 368918334Speter { 369050599Sobrien add_assembler_option (argv[i] + prev, j - prev); 369118334Speter prev = j + 1; 369218334Speter } 369390277Sobrien 369418334Speter /* Record the part after the last comma. */ 369550599Sobrien add_assembler_option (argv[i] + prev, j - prev); 369618334Speter } 369718334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 369818334Speter { 369918334Speter int prev, j; 370018334Speter /* Pass the rest of this option to the preprocessor. */ 370118334Speter 370218334Speter /* Split the argument at commas. */ 370318334Speter prev = 4; 370418334Speter for (j = 4; argv[i][j]; j++) 370518334Speter if (argv[i][j] == ',') 370618334Speter { 370750599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 370818334Speter prev = j + 1; 370918334Speter } 371090277Sobrien 371118334Speter /* Record the part after the last comma. */ 371250599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 371318334Speter } 371418334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 371518334Speter /* The +e options to the C++ front-end. */ 371618334Speter n_switches++; 371718334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 371818334Speter { 371918334Speter int j; 372018334Speter /* Split the argument at commas. */ 372118334Speter for (j = 3; argv[i][j]; j++) 372218334Speter n_infiles += (argv[i][j] == ','); 372318334Speter } 372418334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 372518334Speter { 372618334Speter if (i + 1 == argc) 3727169704Skan fatal ("argument to '-Xlinker' is missing"); 372818334Speter 372918334Speter n_infiles++; 373018334Speter i++; 373118334Speter } 3732132733Skan else if (strcmp (argv[i], "-Xpreprocessor") == 0) 3733132733Skan { 3734132733Skan if (i + 1 == argc) 3735169704Skan fatal ("argument to '-Xpreprocessor' is missing"); 3736132733Skan 3737132733Skan add_preprocessor_option (argv[i+1], strlen (argv[i+1])); 3738132733Skan } 3739132733Skan else if (strcmp (argv[i], "-Xassembler") == 0) 3740132733Skan { 3741132733Skan if (i + 1 == argc) 3742169704Skan fatal ("argument to '-Xassembler' is missing"); 3743132733Skan 3744132733Skan add_assembler_option (argv[i+1], strlen (argv[i+1])); 3745132733Skan } 374677389Sobrien else if (strcmp (argv[i], "-l") == 0) 374777389Sobrien { 374877389Sobrien if (i + 1 == argc) 3749169704Skan fatal ("argument to '-l' is missing"); 375077389Sobrien 375177389Sobrien n_infiles++; 375277389Sobrien i++; 375377389Sobrien } 375418334Speter else if (strncmp (argv[i], "-l", 2) == 0) 375518334Speter n_infiles++; 375650599Sobrien else if (strcmp (argv[i], "-save-temps") == 0) 375750599Sobrien { 375850599Sobrien save_temps_flag = 1; 375950599Sobrien n_switches++; 376050599Sobrien } 3761169704Skan else if (strcmp (argv[i], "-combine") == 0) 3762169704Skan { 3763169704Skan combine_flag = 1; 3764169704Skan n_switches++; 3765169704Skan } 376650599Sobrien else if (strcmp (argv[i], "-specs") == 0) 376750599Sobrien { 3768169704Skan struct user_specs *user = XNEW (struct user_specs); 376950599Sobrien if (++i >= argc) 3770169704Skan fatal ("argument to '-specs' is missing"); 377150599Sobrien 377290277Sobrien user->next = (struct user_specs *) 0; 377350599Sobrien user->filename = argv[i]; 377450599Sobrien if (user_specs_tail) 377550599Sobrien user_specs_tail->next = user; 377650599Sobrien else 377750599Sobrien user_specs_head = user; 377850599Sobrien user_specs_tail = user; 377950599Sobrien } 378050599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 378150599Sobrien { 3782169704Skan struct user_specs *user = XNEW (struct user_specs); 378350599Sobrien if (strlen (argv[i]) == 7) 3784169704Skan fatal ("argument to '-specs=' is missing"); 378550599Sobrien 378690277Sobrien user->next = (struct user_specs *) 0; 378790277Sobrien user->filename = argv[i] + 7; 378850599Sobrien if (user_specs_tail) 378950599Sobrien user_specs_tail->next = user; 379050599Sobrien else 379150599Sobrien user_specs_head = user; 379250599Sobrien user_specs_tail = user; 379350599Sobrien } 379490277Sobrien else if (strcmp (argv[i], "-time") == 0) 379590277Sobrien report_times = 1; 3796132733Skan else if (strcmp (argv[i], "-pipe") == 0) 3797132733Skan { 3798132733Skan /* -pipe has to go into the switches array as well as 3799132733Skan setting a flag. */ 3800132733Skan use_pipes = 1; 3801132733Skan n_switches++; 3802132733Skan } 380390277Sobrien else if (strcmp (argv[i], "-###") == 0) 380490277Sobrien { 380590277Sobrien /* This is similar to -v except that there is no execution 380690277Sobrien of the commands and the echoed arguments are quoted. It 380790277Sobrien is intended for use in shell scripts to capture the 380890277Sobrien driver-generated command line. */ 380990277Sobrien verbose_only_flag++; 381090277Sobrien verbose_flag++; 381190277Sobrien } 381218334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 381318334Speter { 381490277Sobrien const char *p = &argv[i][1]; 381590277Sobrien int c = *p; 381618334Speter 381718334Speter switch (c) 381818334Speter { 381918334Speter case 'b': 3820169704Skan if (NULL == strchr(argv[i] + 2, '-')) 3821169704Skan goto normal_switch; 3822169704Skan 3823169704Skan /* Fall through. */ 3824117413Skan case 'V': 3825169704Skan fatal ("'-%c' must come at the start of the command line", c); 382618334Speter break; 382718334Speter 382818334Speter case 'B': 382918334Speter { 383090277Sobrien const char *value; 383190277Sobrien int len; 383290277Sobrien 383318334Speter if (p[1] == 0 && i + 1 == argc) 3834169704Skan fatal ("argument to '-B' is missing"); 383518334Speter if (p[1] == 0) 383618334Speter value = argv[++i]; 383718334Speter else 383818334Speter value = p + 1; 383918334Speter 384090277Sobrien len = strlen (value); 384190277Sobrien 384290277Sobrien /* Catch the case where the user has forgotten to append a 384390277Sobrien directory separator to the path. Note, they may be using 384490277Sobrien -B to add an executable name prefix, eg "i386-elf-", in 384590277Sobrien order to distinguish between multiple installations of 384690277Sobrien GCC in the same directory. Hence we must check to see 384790277Sobrien if appending a directory separator actually makes a 384890277Sobrien valid directory name. */ 384990277Sobrien if (! IS_DIR_SEPARATOR (value [len - 1]) 3850169704Skan && is_directory (value, false)) 385190277Sobrien { 3852169704Skan char *tmp = XNEWVEC (char, len + 2); 385390277Sobrien strcpy (tmp, value); 385490277Sobrien tmp[len] = DIR_SEPARATOR; 385590277Sobrien tmp[++ len] = 0; 385690277Sobrien value = tmp; 385790277Sobrien } 3858117413Skan 385990277Sobrien /* As a kludge, if the arg is "[foo/]stageN/", just 386090277Sobrien add "[foo/]include" to the include prefix. */ 386190277Sobrien if ((len == 7 386290277Sobrien || (len > 7 386390277Sobrien && (IS_DIR_SEPARATOR (value[len - 8])))) 386490277Sobrien && strncmp (value + len - 7, "stage", 5) == 0 386590277Sobrien && ISDIGIT (value[len - 2]) 386690277Sobrien && (IS_DIR_SEPARATOR (value[len - 1]))) 386790277Sobrien { 386890277Sobrien if (len == 7) 3869169704Skan add_prefix (&include_prefixes, "./", NULL, 3870169704Skan PREFIX_PRIORITY_B_OPT, 0, 0); 387190277Sobrien else 387290277Sobrien { 3873169704Skan char *string = xmalloc (len - 6); 3874169704Skan memcpy (string, value, len - 7); 3875169704Skan string[len - 7] = 0; 3876169704Skan add_prefix (&include_prefixes, string, NULL, 3877169704Skan PREFIX_PRIORITY_B_OPT, 0, 0); 387890277Sobrien } 387990277Sobrien } 388090277Sobrien 388190277Sobrien add_prefix (&exec_prefixes, value, NULL, 3882169704Skan PREFIX_PRIORITY_B_OPT, 0, 0); 388390277Sobrien add_prefix (&startfile_prefixes, value, NULL, 3884169704Skan PREFIX_PRIORITY_B_OPT, 0, 0); 3885169704Skan add_prefix (&include_prefixes, value, NULL, 3886169704Skan PREFIX_PRIORITY_B_OPT, 0, 0); 388790277Sobrien n_switches++; 388818334Speter } 388918334Speter break; 389018334Speter 389118334Speter case 'v': /* Print our subcommands and print versions. */ 389218334Speter n_switches++; 389318334Speter /* If they do anything other than exactly `-v', don't set 389418334Speter verbose_flag; rather, continue on to give the error. */ 389518334Speter if (p[1] != 0) 389618334Speter break; 389718334Speter verbose_flag++; 389818334Speter break; 389918334Speter 390050599Sobrien case 'S': 390150599Sobrien case 'c': 390250599Sobrien if (p[1] == 0) 390318334Speter { 390450599Sobrien have_c = 1; 390518334Speter n_switches++; 390618334Speter break; 390718334Speter } 390850599Sobrien goto normal_switch; 390950599Sobrien 391050599Sobrien case 'o': 391150599Sobrien have_o = 1; 391290277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 391350599Sobrien if (! have_c) 391450599Sobrien { 391550599Sobrien int skip; 391690277Sobrien 391750599Sobrien /* Forward scan, just in case -S or -c is specified 391850599Sobrien after -o. */ 391950599Sobrien int j = i + 1; 392050599Sobrien if (p[1] == 0) 392150599Sobrien ++j; 392250599Sobrien while (j < argc) 392350599Sobrien { 392450599Sobrien if (argv[j][0] == '-') 392550599Sobrien { 392650599Sobrien if (SWITCH_CURTAILS_COMPILATION (argv[j][1]) 392750599Sobrien && argv[j][2] == 0) 392850599Sobrien { 392950599Sobrien have_c = 1; 393050599Sobrien break; 393150599Sobrien } 393290277Sobrien else if ((skip = SWITCH_TAKES_ARG (argv[j][1]))) 393350599Sobrien j += skip - (argv[j][2] != 0); 393490277Sobrien else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1))) 393550599Sobrien j += skip; 393650599Sobrien } 393750599Sobrien j++; 393850599Sobrien } 393950599Sobrien } 394050599Sobrien#endif 394190277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX) 394250599Sobrien if (p[1] == 0) 394390277Sobrien argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0); 394450599Sobrien else 394590277Sobrien argv[i] = convert_filename (argv[i], ! have_c, 0); 394650599Sobrien#endif 394750599Sobrien goto normal_switch; 394850599Sobrien 394918334Speter default: 395050599Sobrien normal_switch: 395190277Sobrien 395290277Sobrien#ifdef MODIFY_TARGET_NAME 395390277Sobrien is_modify_target_name = 0; 395490277Sobrien 3955117413Skan for (j = 0; j < ARRAY_SIZE (modify_target); j++) 395690277Sobrien if (! strcmp (argv[i], modify_target[j].sw)) 395790277Sobrien { 3958132733Skan char *new_name = xmalloc (strlen (modify_target[j].str) 3959132733Skan + strlen (spec_machine)); 396090277Sobrien const char *p, *r; 396190277Sobrien char *q; 396290277Sobrien int made_addition = 0; 396390277Sobrien 396490277Sobrien is_modify_target_name = 1; 396590277Sobrien for (p = spec_machine, q = new_name; *p != 0; ) 396690277Sobrien { 396790277Sobrien if (modify_target[j].add_del == DELETE 396890277Sobrien && (! strncmp (q, modify_target[j].str, 396990277Sobrien strlen (modify_target[j].str)))) 397090277Sobrien p += strlen (modify_target[j].str); 397190277Sobrien else if (modify_target[j].add_del == ADD 397290277Sobrien && ! made_addition && *p == '-') 397390277Sobrien { 397490277Sobrien for (r = modify_target[j].str; *r != 0; ) 397590277Sobrien *q++ = *r++; 397690277Sobrien made_addition = 1; 397790277Sobrien } 397890277Sobrien 397990277Sobrien *q++ = *p++; 398090277Sobrien } 398190277Sobrien 398290277Sobrien spec_machine = new_name; 398390277Sobrien } 398490277Sobrien 398590277Sobrien if (is_modify_target_name) 398690277Sobrien break; 3987117413Skan#endif 398890277Sobrien 398918334Speter n_switches++; 399018334Speter 399118334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 399218334Speter i += SWITCH_TAKES_ARG (c) - (p[1] != 0); 399318334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 399418334Speter i += WORD_SWITCH_TAKES_ARG (p); 399518334Speter } 399618334Speter } 399718334Speter else 399850599Sobrien { 399950599Sobrien n_infiles++; 400050599Sobrien lang_n_infiles++; 400150599Sobrien } 400218334Speter } 400318334Speter 4004169704Skan if (save_temps_flag && use_pipes) 4005132733Skan { 4006132733Skan /* -save-temps overrides -pipe, so that temp files are produced */ 4007132733Skan if (save_temps_flag) 4008132733Skan error ("warning: -pipe ignored because -save-temps specified"); 4009132733Skan use_pipes = 0; 4010132733Skan } 4011132733Skan 401218334Speter /* Set up the search paths before we go looking for config files. */ 4013169704Skan#ifdef FREEBSD_NATIVE 4014169704Skan add_prefix (&exec_prefixes, PREFIX"/bin/", "BINUTILS", 4015169704Skan PREFIX_PRIORITY_LAST, 0, 0); 4016169704Skan#endif /* FREEBSD_NATIVE */ 401718334Speter 401818334Speter /* These come before the md prefixes so that we will find gcc's subcommands 401918334Speter (such as cpp) rather than those of the host system. */ 402018334Speter /* Use 2 as fourth arg meaning try just the machine as a suffix, 402118334Speter as well as trying the machine and the version. */ 402218334Speter#ifndef OS2 4023132733Skan add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC", 4024169704Skan PREFIX_PRIORITY_LAST, 1, 0); 4025132733Skan add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS", 4026169704Skan PREFIX_PRIORITY_LAST, 2, 0); 4027169704Skan#ifndef FREEBSD_NATIVE 402850599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", 4029169704Skan PREFIX_PRIORITY_LAST, 2, 0); 403050599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS", 4031169704Skan PREFIX_PRIORITY_LAST, 2, 0); 4032132733Skan add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS", 4033169704Skan PREFIX_PRIORITY_LAST, 2, 0); 403418334Speter#endif 4035169704Skan#endif 403618334Speter 4037169704Skan#ifndef FREEBSD_NATIVE 403850599Sobrien add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", 4039169704Skan PREFIX_PRIORITY_LAST, 1, 0); 4040132733Skan add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS", 4041169704Skan PREFIX_PRIORITY_LAST, 1, 0); 404218334Speter 404390277Sobrien tooldir_prefix = concat (tooldir_base_prefix, spec_machine, 404490277Sobrien dir_separator_str, NULL); 404518334Speter 404618334Speter /* If tooldir is relative, base it on exec_prefixes. A relative 404718334Speter tooldir lets us move the installed tree as a unit. 404818334Speter 404918334Speter If GCC_EXEC_PREFIX is defined, then we want to add two relative 405018334Speter directories, so that we can search both the user specified directory 405118334Speter and the standard place. */ 405218334Speter 4053132733Skan if (!IS_ABSOLUTE_PATH (tooldir_prefix)) 405418334Speter { 405518334Speter if (gcc_exec_prefix) 405618334Speter { 405718334Speter char *gcc_exec_tooldir_prefix 405850599Sobrien = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 405990277Sobrien spec_version, dir_separator_str, tooldir_prefix, NULL); 406018334Speter 406118334Speter add_prefix (&exec_prefixes, 406290277Sobrien concat (gcc_exec_tooldir_prefix, "bin", 406390277Sobrien dir_separator_str, NULL), 4064169704Skan NULL, PREFIX_PRIORITY_LAST, 0, 0); 406518334Speter add_prefix (&startfile_prefixes, 406690277Sobrien concat (gcc_exec_tooldir_prefix, "lib", 406790277Sobrien dir_separator_str, NULL), 4068169704Skan NULL, PREFIX_PRIORITY_LAST, 0, 1); 406918334Speter } 407018334Speter 407150599Sobrien tooldir_prefix = concat (standard_exec_prefix, spec_machine, 407290277Sobrien dir_separator_str, spec_version, 407390277Sobrien dir_separator_str, tooldir_prefix, NULL); 407418334Speter } 407518334Speter 407690277Sobrien add_prefix (&exec_prefixes, 407790277Sobrien concat (tooldir_prefix, "bin", dir_separator_str, NULL), 4078169704Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, 0); 407918334Speter add_prefix (&startfile_prefixes, 408090277Sobrien concat (tooldir_prefix, "lib", dir_separator_str, NULL), 4081169704Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1); 4082132733Skan 4083132733Skan#if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS) 4084132733Skan /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix, 4085132733Skan then consider it to relocate with the rest of the GCC installation 4086132733Skan if GCC_EXEC_PREFIX is set. 4087132733Skan ``make_relative_prefix'' is not compiled for VMS, so don't call it. */ 4088132733Skan if (target_system_root && gcc_exec_prefix) 4089132733Skan { 4090132733Skan char *tmp_prefix = make_relative_prefix (argv[0], 4091132733Skan standard_bindir_prefix, 4092132733Skan target_system_root); 4093132733Skan if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0) 4094132733Skan { 4095132733Skan target_system_root = tmp_prefix; 4096132733Skan target_system_root_changed = 1; 4097132733Skan } 4098132733Skan } 4099132733Skan#endif 410018346Speter#endif /* FREEBSD_NATIVE */ 410118334Speter 410218334Speter /* More prefixes are enabled in main, after we read the specs file 410318334Speter and determine whether this is cross-compilation or not. */ 410418334Speter 410518334Speter /* Then create the space for the vectors and scan again. */ 410618334Speter 4107169704Skan switches = XNEWVEC (struct switchstr, n_switches + 1); 4108169704Skan infiles = XNEWVEC (struct infile, n_infiles + 1); 410918334Speter n_switches = 0; 411018334Speter n_infiles = 0; 411118334Speter last_language_n_infiles = -1; 411218334Speter 411318334Speter /* This, time, copy the text of each switch and store a pointer 411418334Speter to the copy in the vector of switches. 411518334Speter Store all the infiles in their vector. */ 411618334Speter 411718334Speter for (i = 1; i < argc; i++) 411818334Speter { 411918334Speter /* Just skip the switches that were handled by the preceding loop. */ 412090277Sobrien#ifdef MODIFY_TARGET_NAME 412190277Sobrien is_modify_target_name = 0; 412290277Sobrien 4123117413Skan for (j = 0; j < ARRAY_SIZE (modify_target); j++) 412490277Sobrien if (! strcmp (argv[i], modify_target[j].sw)) 412590277Sobrien is_modify_target_name = 1; 412690277Sobrien 412790277Sobrien if (is_modify_target_name) 412890277Sobrien ; 412990277Sobrien else 413090277Sobrien#endif 413118334Speter if (! strncmp (argv[i], "-Wa,", 4)) 413218334Speter ; 413318334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 413418334Speter ; 413590277Sobrien else if (! strcmp (argv[i], "-pass-exit-codes")) 413690277Sobrien ; 413718334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 413818334Speter ; 413918334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 414018334Speter ; 414118334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 414218334Speter ; 414318334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 414418334Speter ; 414518334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 414618334Speter ; 414718334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 414818334Speter ; 4149104763Skan else if (! strcmp (argv[i], "-print-multi-os-directory")) 4150104763Skan ; 415190277Sobrien else if (! strcmp (argv[i], "-ftarget-help")) 415290277Sobrien ; 415390277Sobrien else if (! strcmp (argv[i], "-fhelp")) 415490277Sobrien ; 4155169704Skan else if (! strncmp (argv[i], "--sysroot=", strlen ("--sysroot="))) 4156169704Skan { 4157169704Skan target_system_root = argv[i] + strlen ("--sysroot="); 4158169704Skan target_system_root_changed = 1; 4159169704Skan } 416018334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 416118334Speter { 416218334Speter /* Compensate for the +e options to the C++ front-end; 416318334Speter they're there simply for cfront call-compatibility. We do 416418334Speter some magic in default_compilers to pass them down properly. 416518334Speter Note we deliberately start at the `+' here, to avoid passing 416618334Speter -e0 or -e1 down into the linker. */ 416718334Speter switches[n_switches].part1 = &argv[i][0]; 416818334Speter switches[n_switches].args = 0; 416990277Sobrien switches[n_switches].live_cond = SWITCH_OK; 417052520Sobrien switches[n_switches].validated = 0; 417118334Speter n_switches++; 417218334Speter } 417318334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 417418334Speter { 417518334Speter int prev, j; 417618334Speter /* Split the argument at commas. */ 417718334Speter prev = 4; 417818334Speter for (j = 4; argv[i][j]; j++) 417918334Speter if (argv[i][j] == ',') 418018334Speter { 418150599Sobrien infiles[n_infiles].language = "*"; 418218334Speter infiles[n_infiles++].name 418318334Speter = save_string (argv[i] + prev, j - prev); 418418334Speter prev = j + 1; 418518334Speter } 418618334Speter /* Record the part after the last comma. */ 418750599Sobrien infiles[n_infiles].language = "*"; 418818334Speter infiles[n_infiles++].name = argv[i] + prev; 418918334Speter } 419018334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 419118334Speter { 419250599Sobrien infiles[n_infiles].language = "*"; 419318334Speter infiles[n_infiles++].name = argv[++i]; 419418334Speter } 4195169704Skan /* Xassembler and Xpreprocessor were already handled in the first argv 4196169704Skan scan, so all we need to do here is ignore them and their argument. */ 4197132733Skan else if (strcmp (argv[i], "-Xassembler") == 0) 4198169704Skan i++; 4199132733Skan else if (strcmp (argv[i], "-Xpreprocessor") == 0) 4200169704Skan i++; 420177389Sobrien else if (strcmp (argv[i], "-l") == 0) 420277389Sobrien { /* POSIX allows separation of -l and the lib arg; 420377389Sobrien canonicalize by concatenating -l with its arg */ 420477389Sobrien infiles[n_infiles].language = "*"; 420577389Sobrien infiles[n_infiles++].name = concat ("-l", argv[++i], NULL); 420677389Sobrien } 420718334Speter else if (strncmp (argv[i], "-l", 2) == 0) 420818334Speter { 420950599Sobrien infiles[n_infiles].language = "*"; 421018334Speter infiles[n_infiles++].name = argv[i]; 421118334Speter } 421250599Sobrien else if (strcmp (argv[i], "-specs") == 0) 421350599Sobrien i++; 421450599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 421550599Sobrien ; 421690277Sobrien else if (strcmp (argv[i], "-time") == 0) 421790277Sobrien ; 421890277Sobrien else if (strcmp (argv[i], "-###") == 0) 421990277Sobrien ; 422018334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 422118334Speter { 422290277Sobrien const char *p = &argv[i][1]; 422390277Sobrien int c = *p; 422418334Speter 422518334Speter if (c == 'x') 422618334Speter { 422718334Speter if (p[1] == 0 && i + 1 == argc) 4228169704Skan fatal ("argument to '-x' is missing"); 422918334Speter if (p[1] == 0) 423018334Speter spec_lang = argv[++i]; 423118334Speter else 423218334Speter spec_lang = p + 1; 423318334Speter if (! strcmp (spec_lang, "none")) 423418334Speter /* Suppress the warning if -xnone comes after the last input 423518334Speter file, because alternate command interfaces like g++ might 423618334Speter find it useful to place -xnone after each input file. */ 423718334Speter spec_lang = 0; 423818334Speter else 423918334Speter last_language_n_infiles = n_infiles; 424018334Speter continue; 424118334Speter } 424218334Speter switches[n_switches].part1 = p; 424318334Speter /* Deal with option arguments in separate argv elements. */ 424418334Speter if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) 424518334Speter || WORD_SWITCH_TAKES_ARG (p)) 424618334Speter { 424718334Speter int j = 0; 424818334Speter int n_args = WORD_SWITCH_TAKES_ARG (p); 424918334Speter 425018334Speter if (n_args == 0) 425118334Speter { 425218334Speter /* Count only the option arguments in separate argv elements. */ 425318334Speter n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); 425418334Speter } 425518334Speter if (i + n_args >= argc) 4256169704Skan fatal ("argument to '-%s' is missing", p); 425718334Speter switches[n_switches].args 4258169704Skan = XNEWVEC (const char *, n_args + 1); 425918334Speter while (j < n_args) 426018334Speter switches[n_switches].args[j++] = argv[++i]; 426118334Speter /* Null-terminate the vector. */ 426218334Speter switches[n_switches].args[j] = 0; 426318334Speter } 426490277Sobrien else if (strchr (switches_need_spaces, c)) 426518334Speter { 426650599Sobrien /* On some systems, ld cannot handle some options without 426750599Sobrien a space. So split the option from its argument. */ 4268169704Skan char *part1 = XNEWVEC (char, 2); 426950599Sobrien part1[0] = c; 427050599Sobrien part1[1] = '\0'; 427190277Sobrien 427250599Sobrien switches[n_switches].part1 = part1; 4273169704Skan switches[n_switches].args = XNEWVEC (const char *, 2); 427490277Sobrien switches[n_switches].args[0] = xstrdup (p+1); 427518334Speter switches[n_switches].args[1] = 0; 427618334Speter } 427718334Speter else 427818334Speter switches[n_switches].args = 0; 427918334Speter 428090277Sobrien switches[n_switches].live_cond = SWITCH_OK; 428152520Sobrien switches[n_switches].validated = 0; 428290277Sobrien switches[n_switches].ordering = 0; 4283132733Skan /* These are always valid, since gcc.c itself understands them. */ 428490277Sobrien if (!strcmp (p, "save-temps") 428590277Sobrien || !strcmp (p, "static-libgcc") 4286132733Skan || !strcmp (p, "shared-libgcc") 4287132733Skan || !strcmp (p, "pipe")) 428852520Sobrien switches[n_switches].validated = 1; 428990277Sobrien else 429090277Sobrien { 429190277Sobrien char ch = switches[n_switches].part1[0]; 4292117413Skan if (ch == 'B') 429390277Sobrien switches[n_switches].validated = 1; 429490277Sobrien } 429518334Speter n_switches++; 429618334Speter } 429718334Speter else 429818334Speter { 429990277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX 430090277Sobrien argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK)); 430118334Speter#endif 430218334Speter 430390277Sobrien if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0) 430418334Speter { 430518334Speter perror_with_name (argv[i]); 430618334Speter error_count++; 430718334Speter } 430818334Speter else 430918334Speter { 431018334Speter infiles[n_infiles].language = spec_lang; 431118334Speter infiles[n_infiles++].name = argv[i]; 431218334Speter } 431318334Speter } 431418334Speter } 431518334Speter 431618334Speter if (n_infiles == last_language_n_infiles && spec_lang != 0) 4317169704Skan error ("warning: '-x %s' after last input file has no effect", spec_lang); 431818334Speter 431990277Sobrien /* Ensure we only invoke each subprocess once. */ 432090277Sobrien if (target_help_flag || print_help_list) 432190277Sobrien { 432290277Sobrien n_infiles = 1; 432390277Sobrien 432490277Sobrien /* Create a dummy input file, so that we can pass --target-help on to 432590277Sobrien the various sub-processes. */ 432690277Sobrien infiles[0].language = "c"; 432790277Sobrien infiles[0].name = "help-dummy"; 432890277Sobrien 432990277Sobrien if (target_help_flag) 433090277Sobrien { 433190277Sobrien switches[n_switches].part1 = "--target-help"; 433290277Sobrien switches[n_switches].args = 0; 433390277Sobrien switches[n_switches].live_cond = SWITCH_OK; 433490277Sobrien switches[n_switches].validated = 0; 433590277Sobrien 433690277Sobrien n_switches++; 433790277Sobrien } 433890277Sobrien 433990277Sobrien if (print_help_list) 434090277Sobrien { 434190277Sobrien switches[n_switches].part1 = "--help"; 434290277Sobrien switches[n_switches].args = 0; 434390277Sobrien switches[n_switches].live_cond = SWITCH_OK; 434490277Sobrien switches[n_switches].validated = 0; 434590277Sobrien 434690277Sobrien n_switches++; 434790277Sobrien } 434890277Sobrien } 434990277Sobrien 435018334Speter switches[n_switches].part1 = 0; 435118334Speter infiles[n_infiles].name = 0; 435218334Speter} 435390277Sobrien 4354132733Skan/* Store switches not filtered out by %<S in spec in COLLECT_GCC_OPTIONS 435590277Sobrien and place that in the environment. */ 435690277Sobrien 435790277Sobrienstatic void 4358132733Skanset_collect_gcc_options (void) 435990277Sobrien{ 436090277Sobrien int i; 436190277Sobrien int first_time; 436290277Sobrien 436390277Sobrien /* Build COLLECT_GCC_OPTIONS to have all of the options specified to 436490277Sobrien the compiler. */ 436590277Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=", 436690277Sobrien sizeof ("COLLECT_GCC_OPTIONS=") - 1); 436790277Sobrien 436890277Sobrien first_time = TRUE; 436990277Sobrien for (i = 0; (int) i < n_switches; i++) 437090277Sobrien { 437190277Sobrien const char *const *args; 437290277Sobrien const char *p, *q; 437390277Sobrien if (!first_time) 437490277Sobrien obstack_grow (&collect_obstack, " ", 1); 437590277Sobrien 437690277Sobrien first_time = FALSE; 437790277Sobrien 437890277Sobrien /* Ignore elided switches. */ 437990277Sobrien if (switches[i].live_cond == SWITCH_IGNORE) 438090277Sobrien continue; 438190277Sobrien 438290277Sobrien obstack_grow (&collect_obstack, "'-", 2); 438390277Sobrien q = switches[i].part1; 438490277Sobrien while ((p = strchr (q, '\''))) 438590277Sobrien { 438690277Sobrien obstack_grow (&collect_obstack, q, p - q); 438790277Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 438890277Sobrien q = ++p; 438990277Sobrien } 439090277Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 439190277Sobrien obstack_grow (&collect_obstack, "'", 1); 439290277Sobrien 439390277Sobrien for (args = switches[i].args; args && *args; args++) 439490277Sobrien { 439590277Sobrien obstack_grow (&collect_obstack, " '", 2); 439690277Sobrien q = *args; 439790277Sobrien while ((p = strchr (q, '\''))) 439890277Sobrien { 439990277Sobrien obstack_grow (&collect_obstack, q, p - q); 440090277Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 440190277Sobrien q = ++p; 440290277Sobrien } 440390277Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 440490277Sobrien obstack_grow (&collect_obstack, "'", 1); 440590277Sobrien } 440690277Sobrien } 440790277Sobrien obstack_grow (&collect_obstack, "\0", 1); 4408169704Skan putenv (XOBFINISH (&collect_obstack, char *)); 440990277Sobrien} 441018334Speter 441118334Speter/* Process a spec string, accumulating and running commands. */ 441218334Speter 441318334Speter/* These variables describe the input file name. 441418334Speter input_file_number is the index on outfiles of this file, 441518334Speter so that the output file name can be stored for later use by %o. 441618334Speter input_basename is the start of the part of the input file 441718334Speter sans all directory names, and basename_length is the number 441818334Speter of characters starting there excluding the suffix .c or whatever. */ 441918334Speter 4420132733Skanstatic const char *input_filename; 442118334Speterstatic int input_file_number; 442250599Sobriensize_t input_filename_length; 442318334Speterstatic int basename_length; 442490277Sobrienstatic int suffixed_basename_length; 442552520Sobrienstatic const char *input_basename; 442652520Sobrienstatic const char *input_suffix; 4427169704Skan#ifndef HOST_LACKS_INODE_NUMBERS 442890277Sobrienstatic struct stat input_stat; 4429169704Skan#endif 443090277Sobrienstatic int input_stat_set; 443118334Speter 443290277Sobrien/* The compiler used to process the current input file. */ 443390277Sobrienstatic struct compiler *input_file_compiler; 443490277Sobrien 443518334Speter/* These are variables used within do_spec and do_spec_1. */ 443618334Speter 443718334Speter/* Nonzero if an arg has been started and not yet terminated 443818334Speter (with space, tab or newline). */ 443918334Speterstatic int arg_going; 444018334Speter 444118334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated 444218334Speter is a temporary file name. */ 444318334Speterstatic int delete_this_arg; 444418334Speter 444518334Speter/* Nonzero means %w has been seen; the next arg to be terminated 444618334Speter is the output file name of this compilation. */ 444718334Speterstatic int this_is_output_file; 444818334Speter 444918334Speter/* Nonzero means %s has been seen; the next arg to be terminated 445018334Speter is the name of a library file and we should try the standard 445118334Speter search dirs for it. */ 445218334Speterstatic int this_is_library_file; 445318334Speter 445418334Speter/* Nonzero means that the input of this command is coming from a pipe. */ 445518334Speterstatic int input_from_pipe; 445618334Speter 445790277Sobrien/* Nonnull means substitute this for any suffix when outputting a switches 445890277Sobrien arguments. */ 445990277Sobrienstatic const char *suffix_subst; 446090277Sobrien 446118334Speter/* Process the spec SPEC and run the commands specified therein. 446218334Speter Returns 0 if the spec is successfully processed; -1 if failed. */ 446318334Speter 446450599Sobrienint 4465132733Skando_spec (const char *spec) 446618334Speter{ 446718334Speter int value; 446818334Speter 4469117413Skan value = do_spec_2 (spec); 447018334Speter 447118334Speter /* Force out any unfinished command. 447218334Speter If -pipe, this forces out the last command if it ended in `|'. */ 447318334Speter if (value == 0) 447418334Speter { 447518334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 447618334Speter argbuf_index--; 447718334Speter 447890277Sobrien set_collect_gcc_options (); 447990277Sobrien 448018334Speter if (argbuf_index > 0) 448118334Speter value = execute (); 448218334Speter } 448318334Speter 448418334Speter return value; 448518334Speter} 448618334Speter 4487117413Skanstatic int 4488132733Skando_spec_2 (const char *spec) 4489117413Skan{ 4490132733Skan const char *string; 4491132733Skan int result; 4492132733Skan 4493117413Skan clear_args (); 4494117413Skan arg_going = 0; 4495117413Skan delete_this_arg = 0; 4496117413Skan this_is_output_file = 0; 4497117413Skan this_is_library_file = 0; 4498117413Skan input_from_pipe = 0; 4499117413Skan suffix_subst = NULL; 4500117413Skan 4501132733Skan result = do_spec_1 (spec, 0, NULL); 4502132733Skan 4503132733Skan /* End any pending argument. */ 4504132733Skan if (arg_going) 4505132733Skan { 4506132733Skan obstack_1grow (&obstack, 0); 4507169704Skan string = XOBFINISH (&obstack, const char *); 4508132733Skan if (this_is_library_file) 4509132733Skan string = find_file (string); 4510132733Skan store_arg (string, delete_this_arg, this_is_output_file); 4511132733Skan if (this_is_output_file) 4512132733Skan outfiles[input_file_number] = string; 4513132733Skan arg_going = 0; 4514132733Skan } 4515132733Skan 4516132733Skan return result; 4517117413Skan} 4518117413Skan 4519117413Skan 4520117413Skan/* Process the given spec string and add any new options to the end 4521117413Skan of the switches/n_switches array. */ 4522117413Skan 4523117413Skanstatic void 4524132733Skando_option_spec (const char *name, const char *spec) 4525117413Skan{ 4526132733Skan unsigned int i, value_count, value_len; 4527132733Skan const char *p, *q, *value; 4528132733Skan char *tmp_spec, *tmp_spec_p; 4529132733Skan 4530132733Skan if (configure_default_options[0].name == NULL) 4531132733Skan return; 4532132733Skan 4533132733Skan for (i = 0; i < ARRAY_SIZE (configure_default_options); i++) 4534132733Skan if (strcmp (configure_default_options[i].name, name) == 0) 4535132733Skan break; 4536132733Skan if (i == ARRAY_SIZE (configure_default_options)) 4537132733Skan return; 4538132733Skan 4539132733Skan value = configure_default_options[i].value; 4540132733Skan value_len = strlen (value); 4541132733Skan 4542132733Skan /* Compute the size of the final spec. */ 4543132733Skan value_count = 0; 4544132733Skan p = spec; 4545132733Skan while ((p = strstr (p, "%(VALUE)")) != NULL) 4546132733Skan { 4547132733Skan p ++; 4548132733Skan value_count ++; 4549132733Skan } 4550132733Skan 4551132733Skan /* Replace each %(VALUE) by the specified value. */ 4552132733Skan tmp_spec = alloca (strlen (spec) + 1 4553132733Skan + value_count * (value_len - strlen ("%(VALUE)"))); 4554132733Skan tmp_spec_p = tmp_spec; 4555132733Skan q = spec; 4556132733Skan while ((p = strstr (q, "%(VALUE)")) != NULL) 4557132733Skan { 4558132733Skan memcpy (tmp_spec_p, q, p - q); 4559132733Skan tmp_spec_p = tmp_spec_p + (p - q); 4560132733Skan memcpy (tmp_spec_p, value, value_len); 4561132733Skan tmp_spec_p += value_len; 4562132733Skan q = p + strlen ("%(VALUE)"); 4563132733Skan } 4564132733Skan strcpy (tmp_spec_p, q); 4565132733Skan 4566132733Skan do_self_spec (tmp_spec); 4567132733Skan} 4568132733Skan 4569132733Skan/* Process the given spec string and add any new options to the end 4570132733Skan of the switches/n_switches array. */ 4571132733Skan 4572132733Skanstatic void 4573132733Skando_self_spec (const char *spec) 4574132733Skan{ 4575117413Skan do_spec_2 (spec); 4576117413Skan do_spec_1 (" ", 0, NULL); 4577117413Skan 4578117413Skan if (argbuf_index > 0) 4579117413Skan { 4580117413Skan int i, first; 4581117413Skan 4582117413Skan first = n_switches; 4583117413Skan n_switches += argbuf_index; 4584117413Skan switches = xrealloc (switches, 4585117413Skan sizeof (struct switchstr) * (n_switches + 1)); 4586117413Skan 4587117413Skan switches[n_switches] = switches[first]; 4588117413Skan for (i = 0; i < argbuf_index; i++) 4589117413Skan { 4590117413Skan struct switchstr *sw; 4591117413Skan 4592117413Skan /* Each switch should start with '-'. */ 4593117413Skan if (argbuf[i][0] != '-') 4594169704Skan fatal ("switch '%s' does not start with '-'", argbuf[i]); 4595117413Skan 4596117413Skan sw = &switches[i + first]; 4597117413Skan sw->part1 = &argbuf[i][1]; 4598117413Skan sw->args = 0; 4599117413Skan sw->live_cond = SWITCH_OK; 4600117413Skan sw->validated = 0; 4601117413Skan sw->ordering = 0; 4602117413Skan } 4603117413Skan } 4604117413Skan} 4605117413Skan 4606169704Skan/* Callback for processing %D and %I specs. */ 4607169704Skan 4608169704Skanstruct spec_path_info { 4609169704Skan const char *option; 4610169704Skan const char *append; 4611169704Skan size_t append_len; 4612169704Skan bool omit_relative; 4613169704Skan bool separate_options; 4614169704Skan}; 4615169704Skan 4616169704Skanstatic void * 4617169704Skanspec_path (char *path, void *data) 4618169704Skan{ 4619169704Skan struct spec_path_info *info = data; 4620169704Skan size_t len = 0; 4621169704Skan char save = 0; 4622169704Skan 4623169704Skan if (info->omit_relative && !IS_ABSOLUTE_PATH (path)) 4624169704Skan return NULL; 4625169704Skan 4626169704Skan if (info->append_len != 0) 4627169704Skan { 4628169704Skan len = strlen (path); 4629169704Skan memcpy (path + len, info->append, info->append_len + 1); 4630169704Skan } 4631169704Skan 4632169704Skan if (!is_directory (path, true)) 4633169704Skan return NULL; 4634169704Skan 4635169704Skan do_spec_1 (info->option, 1, NULL); 4636169704Skan if (info->separate_options) 4637169704Skan do_spec_1 (" ", 0, NULL); 4638169704Skan 4639169704Skan if (info->append_len == 0) 4640169704Skan { 4641169704Skan len = strlen (path); 4642169704Skan save = path[len - 1]; 4643169704Skan if (IS_DIR_SEPARATOR (path[len - 1])) 4644169704Skan path[len - 1] = '\0'; 4645169704Skan } 4646169704Skan 4647169704Skan do_spec_1 (path, 1, NULL); 4648169704Skan do_spec_1 (" ", 0, NULL); 4649169704Skan 4650169704Skan /* Must not damage the original path. */ 4651169704Skan if (info->append_len == 0) 4652169704Skan path[len - 1] = save; 4653169704Skan 4654169704Skan return NULL; 4655169704Skan} 4656169704Skan 465718334Speter/* Process the sub-spec SPEC as a portion of a larger spec. 465818334Speter This is like processing a whole spec except that we do 465918334Speter not initialize at the beginning and we do not supply a 466018334Speter newline by default at the end. 466118334Speter INSWITCH nonzero means don't process %-sequences in SPEC; 466218334Speter in this case, % is treated as an ordinary character. 466318334Speter This is used while substituting switches. 466418334Speter INSWITCH nonzero also causes SPC not to terminate an argument. 466518334Speter 466618334Speter Value is zero unless a line was finished 466718334Speter and the command on that line reported an error. */ 466818334Speter 466918334Speterstatic int 4670132733Skando_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) 467118334Speter{ 467290277Sobrien const char *p = spec; 467390277Sobrien int c; 467418334Speter int i; 467552520Sobrien const char *string; 467618334Speter int value; 467718334Speter 467850599Sobrien while ((c = *p++)) 467918334Speter /* If substituting a switch, treat all chars like letters. 468018334Speter Otherwise, NL, SPC, TAB and % are special. */ 468118334Speter switch (inswitch ? 'a' : c) 468218334Speter { 468318334Speter case '\n': 468418334Speter /* End of line: finish any pending argument, 468518334Speter then run the pending command if one has been started. */ 468618334Speter if (arg_going) 468718334Speter { 468818334Speter obstack_1grow (&obstack, 0); 4689169704Skan string = XOBFINISH (&obstack, const char *); 469018334Speter if (this_is_library_file) 469118334Speter string = find_file (string); 469218334Speter store_arg (string, delete_this_arg, this_is_output_file); 469318334Speter if (this_is_output_file) 469418334Speter outfiles[input_file_number] = string; 469518334Speter } 469618334Speter arg_going = 0; 469718334Speter 469818334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 469918334Speter { 470018334Speter /* A `|' before the newline means use a pipe here, 470118334Speter but only if -pipe was specified. 470218334Speter Otherwise, execute now and don't pass the `|' as an arg. */ 4703132733Skan if (use_pipes) 470418334Speter { 470518334Speter input_from_pipe = 1; 470618334Speter break; 470718334Speter } 470818334Speter else 470918334Speter argbuf_index--; 471018334Speter } 471118334Speter 471290277Sobrien set_collect_gcc_options (); 471390277Sobrien 471418334Speter if (argbuf_index > 0) 471518334Speter { 471618334Speter value = execute (); 471718334Speter if (value) 471818334Speter return value; 471918334Speter } 472018334Speter /* Reinitialize for a new command, and for a new argument. */ 472118334Speter clear_args (); 472218334Speter arg_going = 0; 472318334Speter delete_this_arg = 0; 472418334Speter this_is_output_file = 0; 472518334Speter this_is_library_file = 0; 472618334Speter input_from_pipe = 0; 472718334Speter break; 472818334Speter 472918334Speter case '|': 473018334Speter /* End any pending argument. */ 473118334Speter if (arg_going) 473218334Speter { 473318334Speter obstack_1grow (&obstack, 0); 4734169704Skan string = XOBFINISH (&obstack, const char *); 473518334Speter if (this_is_library_file) 473618334Speter string = find_file (string); 473718334Speter store_arg (string, delete_this_arg, this_is_output_file); 473818334Speter if (this_is_output_file) 473918334Speter outfiles[input_file_number] = string; 474018334Speter } 474118334Speter 474218334Speter /* Use pipe */ 474318334Speter obstack_1grow (&obstack, c); 474418334Speter arg_going = 1; 474518334Speter break; 474618334Speter 474718334Speter case '\t': 474818334Speter case ' ': 474918334Speter /* Space or tab ends an argument if one is pending. */ 475018334Speter if (arg_going) 475118334Speter { 475218334Speter obstack_1grow (&obstack, 0); 4753169704Skan string = XOBFINISH (&obstack, const char *); 475418334Speter if (this_is_library_file) 475518334Speter string = find_file (string); 475618334Speter store_arg (string, delete_this_arg, this_is_output_file); 475718334Speter if (this_is_output_file) 475818334Speter outfiles[input_file_number] = string; 475918334Speter } 476018334Speter /* Reinitialize for a new argument. */ 476118334Speter arg_going = 0; 476218334Speter delete_this_arg = 0; 476318334Speter this_is_output_file = 0; 476418334Speter this_is_library_file = 0; 476518334Speter break; 476618334Speter 476718334Speter case '%': 476818334Speter switch (c = *p++) 476918334Speter { 477018334Speter case 0: 4771169704Skan fatal ("spec '%s' invalid", spec); 477218334Speter 477318334Speter case 'b': 477418334Speter obstack_grow (&obstack, input_basename, basename_length); 477518334Speter arg_going = 1; 477618334Speter break; 477718334Speter 477890277Sobrien case 'B': 477990277Sobrien obstack_grow (&obstack, input_basename, suffixed_basename_length); 478090277Sobrien arg_going = 1; 478190277Sobrien break; 478290277Sobrien 478318334Speter case 'd': 478418334Speter delete_this_arg = 2; 478518334Speter break; 478618334Speter 478718334Speter /* Dump out the directories specified with LIBRARY_PATH, 478818334Speter followed by the absolute directories 478918334Speter that we search for startfiles. */ 479018334Speter case 'D': 479118334Speter { 4792169704Skan struct spec_path_info info; 479318334Speter 4794169704Skan info.option = "-L"; 4795169704Skan info.append_len = 0; 479618334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR 4797169704Skan /* Used on systems which record the specified -L dirs 4798169704Skan and use them to search for dynamic linking. 4799169704Skan Relative directories always come from -B, 4800169704Skan and it is better not to use them for searching 4801169704Skan at run time. In particular, stage1 loses. */ 4802169704Skan info.omit_relative = true; 4803169704Skan#else 4804169704Skan info.omit_relative = false; 480518334Speter#endif 4806169704Skan info.separate_options = false; 4807104763Skan 4808169704Skan for_each_path (&startfile_prefixes, true, 0, spec_path, &info); 480918334Speter } 481018334Speter break; 481118334Speter 481218334Speter case 'e': 481352520Sobrien /* %efoo means report an error with `foo' as error message 481418334Speter and don't execute any more commands for this file. */ 481518334Speter { 481652520Sobrien const char *q = p; 481718334Speter char *buf; 481890277Sobrien while (*p != 0 && *p != '\n') 481990277Sobrien p++; 4820132733Skan buf = alloca (p - q + 1); 482118334Speter strncpy (buf, q, p - q); 482218334Speter buf[p - q] = 0; 482390277Sobrien error ("%s", buf); 482418334Speter return -1; 482518334Speter } 482618334Speter break; 482790277Sobrien case 'n': 4828117413Skan /* %nfoo means report a notice with `foo' on stderr. */ 482990277Sobrien { 483090277Sobrien const char *q = p; 483190277Sobrien char *buf; 483290277Sobrien while (*p != 0 && *p != '\n') 483390277Sobrien p++; 4834132733Skan buf = alloca (p - q + 1); 483590277Sobrien strncpy (buf, q, p - q); 483690277Sobrien buf[p - q] = 0; 483790277Sobrien notice ("%s\n", buf); 483890277Sobrien if (*p) 483990277Sobrien p++; 484090277Sobrien } 484190277Sobrien break; 484218334Speter 484390277Sobrien case 'j': 484490277Sobrien { 484590277Sobrien struct stat st; 484690277Sobrien 4847132733Skan /* If save_temps_flag is off, and the HOST_BIT_BUCKET is 4848132733Skan defined, and it is not a directory, and it is 4849132733Skan writable, use it. Otherwise, treat this like any 4850132733Skan other temporary file. */ 485190277Sobrien 485290277Sobrien if ((!save_temps_flag) 485390277Sobrien && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode)) 485490277Sobrien && (access (HOST_BIT_BUCKET, W_OK) == 0)) 485590277Sobrien { 485690277Sobrien obstack_grow (&obstack, HOST_BIT_BUCKET, 485790277Sobrien strlen (HOST_BIT_BUCKET)); 485890277Sobrien delete_this_arg = 0; 485990277Sobrien arg_going = 1; 486090277Sobrien break; 486190277Sobrien } 486290277Sobrien } 4863132733Skan goto create_temp_file; 4864132733Skan case '|': 4865132733Skan if (use_pipes) 4866132733Skan { 4867132733Skan obstack_1grow (&obstack, '-'); 4868132733Skan delete_this_arg = 0; 4869132733Skan arg_going = 1; 4870132733Skan 4871132733Skan /* consume suffix */ 4872169704Skan while (*p == '.' || ISALNUM ((unsigned char) *p)) 4873132733Skan p++; 4874132733Skan if (p[0] == '%' && p[1] == 'O') 4875132733Skan p += 2; 4876132733Skan 4877132733Skan break; 4878132733Skan } 4879132733Skan goto create_temp_file; 4880132733Skan case 'm': 4881132733Skan if (use_pipes) 4882132733Skan { 4883132733Skan /* consume suffix */ 4884169704Skan while (*p == '.' || ISALNUM ((unsigned char) *p)) 4885132733Skan p++; 4886132733Skan if (p[0] == '%' && p[1] == 'O') 4887132733Skan p += 2; 4888132733Skan 4889132733Skan break; 4890132733Skan } 4891132733Skan goto create_temp_file; 489218334Speter case 'g': 489318334Speter case 'u': 489418334Speter case 'U': 4895132733Skan create_temp_file: 489618334Speter { 489718334Speter struct temp_name *t; 489850599Sobrien int suffix_length; 489952520Sobrien const char *suffix = p; 490090277Sobrien char *saved_suffix = NULL; 490118334Speter 4902169704Skan while (*p == '.' || ISALNUM ((unsigned char) *p)) 490390277Sobrien p++; 490490277Sobrien suffix_length = p - suffix; 490550599Sobrien if (p[0] == '%' && p[1] == 'O') 490650599Sobrien { 490750599Sobrien p += 2; 490850599Sobrien /* We don't support extra suffix characters after %O. */ 4909169704Skan if (*p == '.' || ISALNUM ((unsigned char) *p)) 4910169704Skan fatal ("spec '%s' has invalid '%%0%c'", spec, *p); 491190277Sobrien if (suffix_length == 0) 491290277Sobrien suffix = TARGET_OBJECT_SUFFIX; 491390277Sobrien else 491490277Sobrien { 491590277Sobrien saved_suffix 4916169704Skan = XNEWVEC (char, suffix_length 4917132733Skan + strlen (TARGET_OBJECT_SUFFIX)); 491890277Sobrien strncpy (saved_suffix, suffix, suffix_length); 491990277Sobrien strcpy (saved_suffix + suffix_length, 492090277Sobrien TARGET_OBJECT_SUFFIX); 492190277Sobrien } 492290277Sobrien suffix_length += strlen (TARGET_OBJECT_SUFFIX); 492350599Sobrien } 4924117413Skan 492590277Sobrien /* If the input_filename has the same suffix specified 492690277Sobrien for the %g, %u, or %U, and -save-temps is specified, 492790277Sobrien we could end up using that file as an intermediate 492890277Sobrien thus clobbering the user's source file (.e.g., 492990277Sobrien gcc -save-temps foo.s would clobber foo.s with the 493090277Sobrien output of cpp0). So check for this condition and 493190277Sobrien generate a temp file as the intermediate. */ 4932117413Skan 493390277Sobrien if (save_temps_flag) 493450599Sobrien { 493590277Sobrien temp_filename_length = basename_length + suffix_length; 493690277Sobrien temp_filename = alloca (temp_filename_length + 1); 493790277Sobrien strncpy ((char *) temp_filename, input_basename, basename_length); 493890277Sobrien strncpy ((char *) temp_filename + basename_length, suffix, 4939132733Skan suffix_length); 494090277Sobrien *((char *) temp_filename + temp_filename_length) = '\0'; 494190277Sobrien if (strcmp (temp_filename, input_filename) != 0) 494290277Sobrien { 4943169704Skan#ifndef HOST_LACKS_INODE_NUMBERS 4944132733Skan struct stat st_temp; 4945117413Skan 4946132733Skan /* Note, set_input() resets input_stat_set to 0. */ 4947132733Skan if (input_stat_set == 0) 4948132733Skan { 4949132733Skan input_stat_set = stat (input_filename, &input_stat); 4950132733Skan if (input_stat_set >= 0) 4951132733Skan input_stat_set = 1; 4952132733Skan } 4953117413Skan 4954132733Skan /* If we have the stat for the input_filename 4955132733Skan and we can do the stat for the temp_filename 4956132733Skan then the they could still refer to the same 4957132733Skan file if st_dev/st_ino's are the same. */ 495890277Sobrien if (input_stat_set != 1 495990277Sobrien || stat (temp_filename, &st_temp) < 0 496090277Sobrien || input_stat.st_dev != st_temp.st_dev 496190277Sobrien || input_stat.st_ino != st_temp.st_ino) 4962169704Skan#else 4963169704Skan /* Just compare canonical pathnames. */ 4964169704Skan char* input_realname = lrealpath (input_filename); 4965169704Skan char* temp_realname = lrealpath (temp_filename); 4966169704Skan bool files_differ = strcmp (input_realname, temp_realname); 4967169704Skan free (input_realname); 4968169704Skan free (temp_realname); 4969169704Skan if (files_differ) 4970169704Skan#endif 4971117413Skan { 497290277Sobrien temp_filename = save_string (temp_filename, 497390277Sobrien temp_filename_length + 1); 497490277Sobrien obstack_grow (&obstack, temp_filename, 4975132733Skan temp_filename_length); 497690277Sobrien arg_going = 1; 4977117413Skan delete_this_arg = 0; 497890277Sobrien break; 497990277Sobrien } 498090277Sobrien } 498150599Sobrien } 498250599Sobrien 498318334Speter /* See if we already have an association of %g/%u/%U and 498418334Speter suffix. */ 498518334Speter for (t = temp_names; t; t = t->next) 498650599Sobrien if (t->length == suffix_length 498750599Sobrien && strncmp (t->suffix, suffix, suffix_length) == 0 4988132733Skan && t->unique == (c == 'u' || c == 'U' || c == 'j')) 498918334Speter break; 499018334Speter 499190277Sobrien /* Make a new association if needed. %u and %j 499290277Sobrien require one. */ 499390277Sobrien if (t == 0 || c == 'u' || c == 'j') 499418334Speter { 499518334Speter if (t == 0) 499618334Speter { 4997132733Skan t = xmalloc (sizeof (struct temp_name)); 499818334Speter t->next = temp_names; 499918334Speter temp_names = t; 500018334Speter } 500150599Sobrien t->length = suffix_length; 500290277Sobrien if (saved_suffix) 500390277Sobrien { 500490277Sobrien t->suffix = saved_suffix; 500590277Sobrien saved_suffix = NULL; 500690277Sobrien } 500790277Sobrien else 500890277Sobrien t->suffix = save_string (suffix, suffix_length); 5009132733Skan t->unique = (c == 'u' || c == 'U' || c == 'j'); 501050599Sobrien temp_filename = make_temp_file (t->suffix); 501150599Sobrien temp_filename_length = strlen (temp_filename); 501218334Speter t->filename = temp_filename; 501318334Speter t->filename_length = temp_filename_length; 501418334Speter } 501518334Speter 501690277Sobrien if (saved_suffix) 501790277Sobrien free (saved_suffix); 501890277Sobrien 501918334Speter obstack_grow (&obstack, t->filename, t->filename_length); 502018334Speter delete_this_arg = 1; 502118334Speter } 502218334Speter arg_going = 1; 502318334Speter break; 502418334Speter 502518334Speter case 'i': 5026132733Skan if (combine_inputs) 5027132733Skan { 5028132733Skan for (i = 0; (int) i < n_infiles; i++) 5029169704Skan if ((!infiles[i].language) || (infiles[i].language[0] != '*')) 5030169704Skan if (infiles[i].incompiler == input_file_compiler) 5031169704Skan { 5032169704Skan store_arg (infiles[i].name, 0, 0); 5033169704Skan infiles[i].compiled = true; 5034169704Skan } 5035132733Skan } 5036132733Skan else 5037132733Skan { 5038132733Skan obstack_grow (&obstack, input_filename, input_filename_length); 5039132733Skan arg_going = 1; 5040132733Skan } 504118334Speter break; 504218334Speter 504318334Speter case 'I': 504418334Speter { 5045169704Skan struct spec_path_info info; 504618334Speter 5047169704Skan if (multilib_dir) 5048169704Skan { 5049169704Skan do_spec_1 ("-imultilib", 1, NULL); 5050169704Skan /* Make this a separate argument. */ 5051169704Skan do_spec_1 (" ", 0, NULL); 5052169704Skan do_spec_1 (multilib_dir, 1, NULL); 5053169704Skan do_spec_1 (" ", 0, NULL); 5054169704Skan } 5055169704Skan 505618334Speter if (gcc_exec_prefix) 505718334Speter { 505890277Sobrien do_spec_1 ("-iprefix", 1, NULL); 505918334Speter /* Make this a separate argument. */ 506090277Sobrien do_spec_1 (" ", 0, NULL); 506190277Sobrien do_spec_1 (gcc_exec_prefix, 1, NULL); 506290277Sobrien do_spec_1 (" ", 0, NULL); 506318334Speter } 506418334Speter 5065132733Skan if (target_system_root_changed || 5066132733Skan (target_system_root && target_sysroot_hdrs_suffix)) 5067132733Skan { 5068132733Skan do_spec_1 ("-isysroot", 1, NULL); 5069132733Skan /* Make this a separate argument. */ 5070132733Skan do_spec_1 (" ", 0, NULL); 5071132733Skan do_spec_1 (target_system_root, 1, NULL); 5072132733Skan if (target_sysroot_hdrs_suffix) 5073132733Skan do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL); 5074132733Skan do_spec_1 (" ", 0, NULL); 5075132733Skan } 5076132733Skan 5077169704Skan info.option = "-isystem"; 5078169704Skan info.append = "include"; 5079169704Skan info.append_len = strlen (info.append); 5080169704Skan info.omit_relative = false; 5081169704Skan info.separate_options = true; 5082169704Skan 5083169704Skan for_each_path (&include_prefixes, false, info.append_len, 5084169704Skan spec_path, &info); 508518334Speter } 508618334Speter break; 508718334Speter 508818334Speter case 'o': 508952520Sobrien { 509052520Sobrien int max = n_infiles; 509152520Sobrien max += lang_specific_extra_outfiles; 509218334Speter 509352520Sobrien for (i = 0; i < max; i++) 509452520Sobrien if (outfiles[i]) 509552520Sobrien store_arg (outfiles[i], 0, 0); 509652520Sobrien break; 509752520Sobrien } 509852520Sobrien 509918334Speter case 'O': 510090277Sobrien obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); 510118334Speter arg_going = 1; 510218334Speter break; 510318334Speter 510418334Speter case 's': 510518334Speter this_is_library_file = 1; 510618334Speter break; 510718334Speter 5108132733Skan case 'V': 5109132733Skan outfiles[input_file_number] = NULL; 5110132733Skan break; 5111132733Skan 511218334Speter case 'w': 511318334Speter this_is_output_file = 1; 511418334Speter break; 511518334Speter 511618334Speter case 'W': 511718334Speter { 511850599Sobrien int cur_index = argbuf_index; 511918334Speter /* Handle the {...} following the %W. */ 512018334Speter if (*p != '{') 5121169704Skan fatal ("spec '%s' has invalid '%%W%c", spec, *p); 512218334Speter p = handle_braces (p + 1); 512318334Speter if (p == 0) 512418334Speter return -1; 5125132733Skan /* End any pending argument. */ 5126132733Skan if (arg_going) 5127132733Skan { 5128132733Skan obstack_1grow (&obstack, 0); 5129169704Skan string = XOBFINISH (&obstack, const char *); 5130132733Skan if (this_is_library_file) 5131132733Skan string = find_file (string); 5132132733Skan store_arg (string, delete_this_arg, this_is_output_file); 5133132733Skan if (this_is_output_file) 5134132733Skan outfiles[input_file_number] = string; 5135132733Skan arg_going = 0; 5136132733Skan } 513718334Speter /* If any args were output, mark the last one for deletion 513818334Speter on failure. */ 513950599Sobrien if (argbuf_index != cur_index) 514018334Speter record_temp_file (argbuf[argbuf_index - 1], 0, 1); 514118334Speter break; 514218334Speter } 514318334Speter 514418334Speter /* %x{OPTION} records OPTION for %X to output. */ 514518334Speter case 'x': 514618334Speter { 514752520Sobrien const char *p1 = p; 514818334Speter char *string; 514918334Speter 515018334Speter /* Skip past the option value and make a copy. */ 515118334Speter if (*p != '{') 5152169704Skan fatal ("spec '%s' has invalid '%%x%c'", spec, *p); 515318334Speter while (*p++ != '}') 515418334Speter ; 515518334Speter string = save_string (p1 + 1, p - p1 - 2); 515618334Speter 515718334Speter /* See if we already recorded this option. */ 515818334Speter for (i = 0; i < n_linker_options; i++) 515918334Speter if (! strcmp (string, linker_options[i])) 516018334Speter { 516118334Speter free (string); 516218334Speter return 0; 516318334Speter } 516418334Speter 516518334Speter /* This option is new; add it. */ 516650599Sobrien add_linker_option (string, strlen (string)); 516718334Speter } 516818334Speter break; 516918334Speter 517018334Speter /* Dump out the options accumulated previously using %x. */ 517118334Speter case 'X': 517218334Speter for (i = 0; i < n_linker_options; i++) 517318334Speter { 517490277Sobrien do_spec_1 (linker_options[i], 1, NULL); 517518334Speter /* Make each accumulated option a separate argument. */ 517690277Sobrien do_spec_1 (" ", 0, NULL); 517718334Speter } 517818334Speter break; 517918334Speter 518018334Speter /* Dump out the options accumulated previously using -Wa,. */ 518118334Speter case 'Y': 518218334Speter for (i = 0; i < n_assembler_options; i++) 518318334Speter { 518490277Sobrien do_spec_1 (assembler_options[i], 1, NULL); 518518334Speter /* Make each accumulated option a separate argument. */ 518690277Sobrien do_spec_1 (" ", 0, NULL); 518718334Speter } 518818334Speter break; 518918334Speter 519018334Speter /* Dump out the options accumulated previously using -Wp,. */ 519118334Speter case 'Z': 519218334Speter for (i = 0; i < n_preprocessor_options; i++) 519318334Speter { 519490277Sobrien do_spec_1 (preprocessor_options[i], 1, NULL); 519518334Speter /* Make each accumulated option a separate argument. */ 519690277Sobrien do_spec_1 (" ", 0, NULL); 519718334Speter } 519818334Speter break; 519918334Speter 520018334Speter /* Here are digits and numbers that just process 520118334Speter a certain constant string as a spec. */ 520218334Speter 520318334Speter case '1': 520490277Sobrien value = do_spec_1 (cc1_spec, 0, NULL); 520518334Speter if (value != 0) 520618334Speter return value; 520718334Speter break; 520818334Speter 520918334Speter case '2': 521090277Sobrien value = do_spec_1 (cc1plus_spec, 0, NULL); 521118334Speter if (value != 0) 521218334Speter return value; 521318334Speter break; 521418334Speter 521518334Speter case 'a': 521690277Sobrien value = do_spec_1 (asm_spec, 0, NULL); 521718334Speter if (value != 0) 521818334Speter return value; 521918334Speter break; 522018334Speter 522118334Speter case 'A': 522290277Sobrien value = do_spec_1 (asm_final_spec, 0, NULL); 522318334Speter if (value != 0) 522418334Speter return value; 522518334Speter break; 522618334Speter 522718334Speter case 'C': 522890277Sobrien { 522990277Sobrien const char *const spec 5230117413Skan = (input_file_compiler->cpp_spec 5231117413Skan ? input_file_compiler->cpp_spec 523290277Sobrien : cpp_spec); 523390277Sobrien value = do_spec_1 (spec, 0, NULL); 523490277Sobrien if (value != 0) 523590277Sobrien return value; 523690277Sobrien } 523718334Speter break; 523818334Speter 523918334Speter case 'E': 524090277Sobrien value = do_spec_1 (endfile_spec, 0, NULL); 524118334Speter if (value != 0) 524218334Speter return value; 524318334Speter break; 524418334Speter 524518334Speter case 'l': 524690277Sobrien value = do_spec_1 (link_spec, 0, NULL); 524718334Speter if (value != 0) 524818334Speter return value; 524918334Speter break; 525018334Speter 525118334Speter case 'L': 525290277Sobrien value = do_spec_1 (lib_spec, 0, NULL); 525318334Speter if (value != 0) 525418334Speter return value; 525518334Speter break; 525618334Speter 525718334Speter case 'G': 525890277Sobrien value = do_spec_1 (libgcc_spec, 0, NULL); 525918334Speter if (value != 0) 526018334Speter return value; 526118334Speter break; 526218334Speter 5263132733Skan case 'R': 5264132733Skan /* We assume there is a directory 5265132733Skan separator at the end of this string. */ 5266132733Skan if (target_system_root) 5267132733Skan { 5268132733Skan obstack_grow (&obstack, target_system_root, 5269132733Skan strlen (target_system_root)); 5270132733Skan if (target_sysroot_suffix) 5271132733Skan obstack_grow (&obstack, target_sysroot_suffix, 5272132733Skan strlen (target_sysroot_suffix)); 5273132733Skan } 527418334Speter break; 527518334Speter 527618334Speter case 'S': 527790277Sobrien value = do_spec_1 (startfile_spec, 0, NULL); 527818334Speter if (value != 0) 527918334Speter return value; 528018334Speter break; 528118334Speter 528218334Speter /* Here we define characters other than letters and digits. */ 528318334Speter 528418334Speter case '{': 528518334Speter p = handle_braces (p); 528618334Speter if (p == 0) 528718334Speter return -1; 528818334Speter break; 528918334Speter 5290117413Skan case ':': 5291117413Skan p = handle_spec_function (p); 5292117413Skan if (p == 0) 5293117413Skan return -1; 5294117413Skan break; 5295117413Skan 529618334Speter case '%': 529718334Speter obstack_1grow (&obstack, '%'); 529818334Speter break; 529918334Speter 5300117413Skan case '.': 5301117413Skan { 5302117413Skan unsigned len = 0; 530390277Sobrien 5304117413Skan while (p[len] && p[len] != ' ' && p[len] != '%') 5305117413Skan len++; 5306117413Skan suffix_subst = save_string (p - 1, len + 1); 5307117413Skan p += len; 5308117413Skan } 530990277Sobrien break; 5310117413Skan 5311132733Skan /* Henceforth ignore the option(s) matching the pattern 5312132733Skan after the %<. */ 5313132733Skan case '<': 5314132733Skan { 5315132733Skan unsigned len = 0; 5316132733Skan int have_wildcard = 0; 5317132733Skan int i; 5318132733Skan 5319132733Skan while (p[len] && p[len] != ' ' && p[len] != '\t') 5320132733Skan len++; 5321132733Skan 5322132733Skan if (p[len-1] == '*') 5323132733Skan have_wildcard = 1; 5324132733Skan 5325132733Skan for (i = 0; i < n_switches; i++) 5326132733Skan if (!strncmp (switches[i].part1, p, len - have_wildcard) 5327132733Skan && (have_wildcard || switches[i].part1[len] == '\0')) 5328132733Skan { 5329132733Skan switches[i].live_cond = SWITCH_IGNORE; 5330132733Skan switches[i].validated = 1; 5331132733Skan } 5332132733Skan 5333132733Skan p += len; 5334132733Skan } 5335132733Skan break; 5336132733Skan 533718334Speter case '*': 533890277Sobrien if (soft_matched_part) 533990277Sobrien { 534090277Sobrien do_spec_1 (soft_matched_part, 1, NULL); 534190277Sobrien do_spec_1 (" ", 0, NULL); 534290277Sobrien } 534390277Sobrien else 534490277Sobrien /* Catch the case where a spec string contains something like 5345169704Skan '%{foo:%*}'. i.e. there is no * in the pattern on the left 534690277Sobrien hand side of the :. */ 534790277Sobrien error ("spec failure: '%%*' has not been initialized by pattern match"); 534818334Speter break; 534918334Speter 535018334Speter /* Process a string found as the value of a spec given by name. 535118334Speter This feature allows individual machine descriptions 535218334Speter to add and use their own specs. 535318334Speter %[...] modifies -D options the way %P does; 535418334Speter %(...) uses the spec unmodified. */ 535550599Sobrien case '[': 535690277Sobrien error ("warning: use of obsolete %%[ operator in specs"); 535718334Speter case '(': 535818334Speter { 535952520Sobrien const char *name = p; 536018334Speter struct spec_list *sl; 536118334Speter int len; 536218334Speter 536318334Speter /* The string after the S/P is the name of a spec that is to be 536450599Sobrien processed. */ 536518334Speter while (*p && *p != ')' && *p != ']') 536618334Speter p++; 536718334Speter 536890277Sobrien /* See if it's in the list. */ 536918334Speter for (len = p - name, sl = specs; sl; sl = sl->next) 537050599Sobrien if (sl->name_len == len && !strncmp (sl->name, name, len)) 537118334Speter { 537250599Sobrien name = *(sl->ptr_spec); 537350599Sobrien#ifdef DEBUG_SPECS 537452520Sobrien notice ("Processing spec %c%s%c, which is '%s'\n", 537552520Sobrien c, sl->name, (c == '(') ? ')' : ']', name); 537650599Sobrien#endif 537718334Speter break; 537818334Speter } 537918334Speter 538018334Speter if (sl) 538118334Speter { 538218334Speter if (c == '(') 538318334Speter { 538490277Sobrien value = do_spec_1 (name, 0, NULL); 538518334Speter if (value != 0) 538618334Speter return value; 538718334Speter } 538818334Speter else 538918334Speter { 5390132733Skan char *x = alloca (strlen (name) * 2 + 1); 539118334Speter char *buf = x; 539252520Sobrien const char *y = name; 539350599Sobrien int flag = 0; 539418334Speter 539518334Speter /* Copy all of NAME into BUF, but put __ after 539690277Sobrien every -D and at the end of each arg. */ 539718334Speter while (1) 539818334Speter { 539918334Speter if (! strncmp (y, "-D", 2)) 540018334Speter { 540118334Speter *x++ = '-'; 540218334Speter *x++ = 'D'; 540318334Speter *x++ = '_'; 540418334Speter *x++ = '_'; 540518334Speter y += 2; 540650599Sobrien flag = 1; 540750599Sobrien continue; 540818334Speter } 540990277Sobrien else if (flag 541090277Sobrien && (*y == ' ' || *y == '\t' || *y == '=' 541190277Sobrien || *y == '}' || *y == 0)) 541218334Speter { 541318334Speter *x++ = '_'; 541418334Speter *x++ = '_'; 541550599Sobrien flag = 0; 541618334Speter } 541790277Sobrien if (*y == 0) 541850599Sobrien break; 541918334Speter else 542018334Speter *x++ = *y++; 542118334Speter } 542218334Speter *x = 0; 542318334Speter 542490277Sobrien value = do_spec_1 (buf, 0, NULL); 542518334Speter if (value != 0) 542618334Speter return value; 542718334Speter } 542818334Speter } 542918334Speter 543018334Speter /* Discard the closing paren or bracket. */ 543118334Speter if (*p) 543218334Speter p++; 543318334Speter } 543418334Speter break; 543518334Speter 543618334Speter default: 543790277Sobrien error ("spec failure: unrecognized spec option '%c'", c); 543890277Sobrien break; 543918334Speter } 544018334Speter break; 544118334Speter 544218334Speter case '\\': 544318334Speter /* Backslash: treat next character as ordinary. */ 544418334Speter c = *p++; 544518334Speter 5446132733Skan /* Fall through. */ 544718334Speter default: 544818334Speter /* Ordinary character: put it into the current argument. */ 544918334Speter obstack_1grow (&obstack, c); 545018334Speter arg_going = 1; 545118334Speter } 545218334Speter 5453117413Skan /* End of string. If we are processing a spec function, we need to 5454117413Skan end any pending argument. */ 5455117413Skan if (processing_spec_function && arg_going) 5456117413Skan { 5457117413Skan obstack_1grow (&obstack, 0); 5458169704Skan string = XOBFINISH (&obstack, const char *); 5459117413Skan if (this_is_library_file) 5460117413Skan string = find_file (string); 5461117413Skan store_arg (string, delete_this_arg, this_is_output_file); 5462117413Skan if (this_is_output_file) 5463117413Skan outfiles[input_file_number] = string; 5464117413Skan arg_going = 0; 5465117413Skan } 5466117413Skan 546790277Sobrien return 0; 546818334Speter} 546918334Speter 5470117413Skan/* Look up a spec function. */ 5471117413Skan 5472117413Skanstatic const struct spec_function * 5473132733Skanlookup_spec_function (const char *name) 5474117413Skan{ 5475117413Skan const struct spec_function *sf; 5476117413Skan 5477169704Skan for (sf = static_spec_functions; sf->name != NULL; sf++) 5478169704Skan if (strcmp (sf->name, name) == 0) 5479169704Skan return sf; 5480117413Skan 5481117413Skan return NULL; 5482117413Skan} 5483117413Skan 5484117413Skan/* Evaluate a spec function. */ 5485117413Skan 5486117413Skanstatic const char * 5487132733Skaneval_spec_function (const char *func, const char *args) 5488117413Skan{ 5489117413Skan const struct spec_function *sf; 5490117413Skan const char *funcval; 5491117413Skan 5492117413Skan /* Saved spec processing context. */ 5493117413Skan int save_argbuf_index; 5494117413Skan int save_argbuf_length; 5495117413Skan const char **save_argbuf; 5496117413Skan 5497117413Skan int save_arg_going; 5498117413Skan int save_delete_this_arg; 5499117413Skan int save_this_is_output_file; 5500117413Skan int save_this_is_library_file; 5501117413Skan int save_input_from_pipe; 5502117413Skan const char *save_suffix_subst; 5503117413Skan 5504117413Skan 5505117413Skan sf = lookup_spec_function (func); 5506117413Skan if (sf == NULL) 5507169704Skan fatal ("unknown spec function '%s'", func); 5508117413Skan 5509117413Skan /* Push the spec processing context. */ 5510117413Skan save_argbuf_index = argbuf_index; 5511117413Skan save_argbuf_length = argbuf_length; 5512117413Skan save_argbuf = argbuf; 5513117413Skan 5514117413Skan save_arg_going = arg_going; 5515117413Skan save_delete_this_arg = delete_this_arg; 5516117413Skan save_this_is_output_file = this_is_output_file; 5517117413Skan save_this_is_library_file = this_is_library_file; 5518117413Skan save_input_from_pipe = input_from_pipe; 5519117413Skan save_suffix_subst = suffix_subst; 5520117413Skan 5521117413Skan /* Create a new spec processing context, and build the function 5522117413Skan arguments. */ 5523117413Skan 5524117413Skan alloc_args (); 5525117413Skan if (do_spec_2 (args) < 0) 5526169704Skan fatal ("error in args to spec function '%s'", func); 5527117413Skan 5528117413Skan /* argbuf_index is an index for the next argument to be inserted, and 5529117413Skan so contains the count of the args already inserted. */ 5530117413Skan 5531117413Skan funcval = (*sf->func) (argbuf_index, argbuf); 5532117413Skan 5533117413Skan /* Pop the spec processing context. */ 5534117413Skan argbuf_index = save_argbuf_index; 5535117413Skan argbuf_length = save_argbuf_length; 5536117413Skan free (argbuf); 5537117413Skan argbuf = save_argbuf; 5538117413Skan 5539117413Skan arg_going = save_arg_going; 5540117413Skan delete_this_arg = save_delete_this_arg; 5541117413Skan this_is_output_file = save_this_is_output_file; 5542117413Skan this_is_library_file = save_this_is_library_file; 5543117413Skan input_from_pipe = save_input_from_pipe; 5544117413Skan suffix_subst = save_suffix_subst; 5545117413Skan 5546117413Skan return funcval; 5547117413Skan} 5548117413Skan 5549117413Skan/* Handle a spec function call of the form: 5550117413Skan 5551117413Skan %:function(args) 5552117413Skan 5553117413Skan ARGS is processed as a spec in a separate context and split into an 5554117413Skan argument vector in the normal fashion. The function returns a string 5555117413Skan containing a spec which we then process in the caller's context, or 5556117413Skan NULL if no processing is required. */ 5557117413Skan 5558117413Skanstatic const char * 5559132733Skanhandle_spec_function (const char *p) 5560117413Skan{ 5561117413Skan char *func, *args; 5562117413Skan const char *endp, *funcval; 5563117413Skan int count; 5564117413Skan 5565117413Skan processing_spec_function++; 5566117413Skan 5567117413Skan /* Get the function name. */ 5568117413Skan for (endp = p; *endp != '\0'; endp++) 5569117413Skan { 5570117413Skan if (*endp == '(') /* ) */ 5571117413Skan break; 5572117413Skan /* Only allow [A-Za-z0-9], -, and _ in function names. */ 5573117413Skan if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_')) 5574117413Skan fatal ("malformed spec function name"); 5575117413Skan } 5576117413Skan if (*endp != '(') /* ) */ 5577117413Skan fatal ("no arguments for spec function"); 5578117413Skan func = save_string (p, endp - p); 5579117413Skan p = ++endp; 5580117413Skan 5581117413Skan /* Get the arguments. */ 5582117413Skan for (count = 0; *endp != '\0'; endp++) 5583117413Skan { 5584117413Skan /* ( */ 5585117413Skan if (*endp == ')') 5586117413Skan { 5587117413Skan if (count == 0) 5588117413Skan break; 5589117413Skan count--; 5590117413Skan } 5591117413Skan else if (*endp == '(') /* ) */ 5592117413Skan count++; 5593117413Skan } 5594117413Skan /* ( */ 5595117413Skan if (*endp != ')') 5596117413Skan fatal ("malformed spec function arguments"); 5597117413Skan args = save_string (p, endp - p); 5598117413Skan p = ++endp; 5599117413Skan 5600117413Skan /* p now points to just past the end of the spec function expression. */ 5601117413Skan 5602117413Skan funcval = eval_spec_function (func, args); 5603117413Skan if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0) 5604117413Skan p = NULL; 5605117413Skan 5606117413Skan free (func); 5607117413Skan free (args); 5608117413Skan 5609117413Skan processing_spec_function--; 5610117413Skan 5611117413Skan return p; 5612117413Skan} 5613117413Skan 5614132733Skan/* Inline subroutine of handle_braces. Returns true if the current 5615132733Skan input suffix matches the atom bracketed by ATOM and END_ATOM. */ 5616132733Skanstatic inline bool 5617132733Skaninput_suffix_matches (const char *atom, const char *end_atom) 5618132733Skan{ 5619169704Skan /* We special case the semantics of {.s:...} and {.S:...} and their 5620169704Skan negative variants. Instead of testing the input filename suffix, 5621169704Skan we test whether the input source file is an assembler file or an 5622169704Skan assembler-with-cpp file respectively. This allows us to correctly 5623169704Skan handle the -x command line option. */ 5624169704Skan 5625169704Skan if (atom + 1 == end_atom 5626169704Skan && input_file_compiler 5627169704Skan && input_file_compiler->suffix) 5628169704Skan { 5629169704Skan if (*atom == 's') 5630169704Skan return !strcmp (input_file_compiler->suffix, "@assembler"); 5631169704Skan if (*atom == 'S') 5632169704Skan return !strcmp (input_file_compiler->suffix, "@assembler-with-cpp"); 5633169704Skan } 5634169704Skan 5635132733Skan return (input_suffix 5636132733Skan && !strncmp (input_suffix, atom, end_atom - atom) 5637132733Skan && input_suffix[end_atom - atom] == '\0'); 5638132733Skan} 563918334Speter 5640169704Skan/* Subroutine of handle_braces. Returns true if a switch 5641132733Skan matching the atom bracketed by ATOM and END_ATOM appeared on the 5642132733Skan command line. */ 5643169704Skanstatic bool 5644132733Skanswitch_matches (const char *atom, const char *end_atom, int starred) 564518334Speter{ 5646132733Skan int i; 5647132733Skan int len = end_atom - atom; 5648132733Skan int plen = starred ? len : -1; 564918334Speter 5650132733Skan for (i = 0; i < n_switches; i++) 5651132733Skan if (!strncmp (switches[i].part1, atom, len) 5652132733Skan && (starred || switches[i].part1[len] == '\0') 5653132733Skan && check_live_switch (i, plen)) 5654132733Skan return true; 565550599Sobrien 5656132733Skan return false; 5657132733Skan} 565818334Speter 5659132733Skan/* Inline subroutine of handle_braces. Mark all of the switches which 5660132733Skan match ATOM (extends to END_ATOM; STARRED indicates whether there 5661132733Skan was a star after the atom) for later processing. */ 5662132733Skanstatic inline void 5663132733Skanmark_matching_switches (const char *atom, const char *end_atom, int starred) 5664132733Skan{ 5665132733Skan int i; 5666132733Skan int len = end_atom - atom; 5667132733Skan int plen = starred ? len : -1; 566890277Sobrien 5669132733Skan for (i = 0; i < n_switches; i++) 5670132733Skan if (!strncmp (switches[i].part1, atom, len) 5671132733Skan && (starred || switches[i].part1[len] == '\0') 5672132733Skan && check_live_switch (i, plen)) 5673132733Skan switches[i].ordering = 1; 5674132733Skan} 567550599Sobrien 5676132733Skan/* Inline subroutine of handle_braces. Process all the currently 5677132733Skan marked switches through give_switch, and clear the marks. */ 5678132733Skanstatic inline void 5679132733Skanprocess_marked_switches (void) 5680132733Skan{ 5681132733Skan int i; 568218334Speter 5683132733Skan for (i = 0; i < n_switches; i++) 5684132733Skan if (switches[i].ordering == 1) 5685132733Skan { 5686132733Skan switches[i].ordering = 0; 5687132733Skan give_switch (i, 0); 5688132733Skan } 5689132733Skan} 569018334Speter 5691132733Skan/* Handle a %{ ... } construct. P points just inside the leading {. 5692132733Skan Returns a pointer one past the end of the brace block, or 0 5693132733Skan if we call do_spec_1 and that returns -1. */ 569418334Speter 5695132733Skanstatic const char * 5696132733Skanhandle_braces (const char *p) 5697132733Skan{ 5698132733Skan const char *atom, *end_atom; 5699132733Skan const char *d_atom = NULL, *d_end_atom = NULL; 5700169704Skan const char *orig = p; 570190277Sobrien 5702132733Skan bool a_is_suffix; 5703132733Skan bool a_is_starred; 5704132733Skan bool a_is_negated; 5705132733Skan bool a_matched; 570650599Sobrien 5707132733Skan bool a_must_be_last = false; 5708132733Skan bool ordered_set = false; 5709132733Skan bool disjunct_set = false; 5710132733Skan bool disj_matched = false; 5711132733Skan bool disj_starred = true; 5712132733Skan bool n_way_choice = false; 5713132733Skan bool n_way_matched = false; 571450599Sobrien 5715132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0) 5716132733Skan 5717132733Skan do 571818334Speter { 5719132733Skan if (a_must_be_last) 5720169704Skan goto invalid; 572150599Sobrien 5722132733Skan /* Scan one "atom" (S in the description above of %{}, possibly 5723132733Skan with !, ., or * modifiers). */ 5724132733Skan a_matched = a_is_suffix = a_is_starred = a_is_negated = false; 572590277Sobrien 5726132733Skan SKIP_WHITE(); 5727132733Skan if (*p == '!') 5728132733Skan p++, a_is_negated = true; 572918334Speter 5730132733Skan SKIP_WHITE(); 5731132733Skan if (*p == '.') 5732132733Skan p++, a_is_suffix = true; 573318334Speter 5734132733Skan atom = p; 5735132733Skan while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '=' 5736132733Skan || *p == ',' || *p == '.' || *p == '@') 5737132733Skan p++; 5738132733Skan end_atom = p; 573918334Speter 5740132733Skan if (*p == '*') 5741132733Skan p++, a_is_starred = 1; 574290277Sobrien 5743132733Skan SKIP_WHITE(); 5744169704Skan switch (*p) 5745132733Skan { 5746169704Skan case '&': case '}': 5747132733Skan /* Substitute the switch(es) indicated by the current atom. */ 5748132733Skan ordered_set = true; 5749132733Skan if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix 5750132733Skan || atom == end_atom) 5751169704Skan goto invalid; 575218334Speter 5753132733Skan mark_matching_switches (atom, end_atom, a_is_starred); 5754132733Skan 5755132733Skan if (*p == '}') 5756132733Skan process_marked_switches (); 5757169704Skan break; 5758169704Skan 5759169704Skan case '|': case ':': 5760132733Skan /* Substitute some text if the current atom appears as a switch 5761132733Skan or suffix. */ 5762132733Skan disjunct_set = true; 5763132733Skan if (ordered_set) 5764169704Skan goto invalid; 576518334Speter 5766132733Skan if (atom == end_atom) 576718334Speter { 5768132733Skan if (!n_way_choice || disj_matched || *p == '|' 5769132733Skan || a_is_negated || a_is_suffix || a_is_starred) 5770169704Skan goto invalid; 5771132733Skan 5772132733Skan /* An empty term may appear as the last choice of an 5773132733Skan N-way choice set; it means "otherwise". */ 5774132733Skan a_must_be_last = true; 5775132733Skan disj_matched = !n_way_matched; 5776132733Skan disj_starred = false; 577718334Speter } 5778132733Skan else 577918334Speter { 5780132733Skan if (a_is_suffix && a_is_starred) 5781169704Skan goto invalid; 578218334Speter 5783132733Skan if (!a_is_starred) 5784132733Skan disj_starred = false; 578518334Speter 5786132733Skan /* Don't bother testing this atom if we already have a 5787132733Skan match. */ 5788132733Skan if (!disj_matched && !n_way_matched) 5789132733Skan { 5790132733Skan if (a_is_suffix) 5791132733Skan a_matched = input_suffix_matches (atom, end_atom); 5792132733Skan else 5793132733Skan a_matched = switch_matches (atom, end_atom, a_is_starred); 579418334Speter 5795132733Skan if (a_matched != a_is_negated) 5796132733Skan { 5797132733Skan disj_matched = true; 5798132733Skan d_atom = atom; 5799132733Skan d_end_atom = end_atom; 5800132733Skan } 5801132733Skan } 580218334Speter } 580318334Speter 5804132733Skan if (*p == ':') 580518334Speter { 5806132733Skan /* Found the body, that is, the text to substitute if the 5807132733Skan current disjunction matches. */ 5808132733Skan p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred, 5809132733Skan disj_matched && !n_way_matched); 5810132733Skan if (p == 0) 5811132733Skan return 0; 581218334Speter 5813132733Skan /* If we have an N-way choice, reset state for the next 5814132733Skan disjunction. */ 5815132733Skan if (*p == ';') 581618334Speter { 5817132733Skan n_way_choice = true; 5818132733Skan n_way_matched |= disj_matched; 5819132733Skan disj_matched = false; 5820132733Skan disj_starred = true; 5821132733Skan d_atom = d_end_atom = NULL; 582218334Speter } 582318334Speter } 5824169704Skan break; 5825169704Skan 5826169704Skan default: 5827169704Skan goto invalid; 582818334Speter } 5829132733Skan } 5830132733Skan while (*p++ != '}'); 583118334Speter 5832132733Skan return p; 5833132733Skan 5834169704Skan invalid: 5835169704Skan fatal ("braced spec '%s' is invalid at '%c'", orig, *p); 5836169704Skan 5837132733Skan#undef SKIP_WHITE 5838132733Skan} 5839132733Skan 5840132733Skan/* Subroutine of handle_braces. Scan and process a brace substitution body 5841132733Skan (X in the description of %{} syntax). P points one past the colon; 5842132733Skan ATOM and END_ATOM bracket the first atom which was found to be true 5843132733Skan (present) in the current disjunction; STARRED indicates whether all 5844132733Skan the atoms in the current disjunction were starred (for syntax validation); 5845132733Skan MATCHED indicates whether the disjunction matched or not, and therefore 5846132733Skan whether or not the body is to be processed through do_spec_1 or just 5847132733Skan skipped. Returns a pointer to the closing } or ;, or 0 if do_spec_1 5848132733Skan returns -1. */ 5849132733Skan 5850132733Skanstatic const char * 5851132733Skanprocess_brace_body (const char *p, const char *atom, const char *end_atom, 5852132733Skan int starred, int matched) 5853132733Skan{ 5854132733Skan const char *body, *end_body; 5855132733Skan unsigned int nesting_level; 5856132733Skan bool have_subst = false; 5857132733Skan 5858132733Skan /* Locate the closing } or ;, honoring nested braces. 5859132733Skan Trim trailing whitespace. */ 5860132733Skan body = p; 5861132733Skan nesting_level = 1; 5862132733Skan for (;;) 5863132733Skan { 5864132733Skan if (*p == '{') 5865132733Skan nesting_level++; 5866132733Skan else if (*p == '}') 586718334Speter { 5868132733Skan if (!--nesting_level) 5869132733Skan break; 587018334Speter } 5871132733Skan else if (*p == ';' && nesting_level == 1) 5872132733Skan break; 5873132733Skan else if (*p == '%' && p[1] == '*' && nesting_level == 1) 5874132733Skan have_subst = true; 5875132733Skan else if (*p == '\0') 5876169704Skan goto invalid; 5877132733Skan p++; 587818334Speter } 587918334Speter 5880132733Skan end_body = p; 5881132733Skan while (end_body[-1] == ' ' || end_body[-1] == '\t') 5882132733Skan end_body--; 588350599Sobrien 5884132733Skan if (have_subst && !starred) 5885169704Skan goto invalid; 5886132733Skan 5887132733Skan if (matched) 588890277Sobrien { 5889132733Skan /* Copy the substitution body to permanent storage and execute it. 5890132733Skan If have_subst is false, this is a simple matter of running the 5891132733Skan body through do_spec_1... */ 5892132733Skan char *string = save_string (body, end_body - body); 5893132733Skan if (!have_subst) 5894132733Skan { 5895132733Skan if (do_spec_1 (string, 0, NULL) < 0) 5896132733Skan return 0; 5897132733Skan } 5898132733Skan else 5899132733Skan { 5900132733Skan /* ... but if have_subst is true, we have to process the 5901132733Skan body once for each matching switch, with %* set to the 5902132733Skan variant part of the switch. */ 5903132733Skan unsigned int hard_match_len = end_atom - atom; 5904132733Skan int i; 590590277Sobrien 5906132733Skan for (i = 0; i < n_switches; i++) 5907132733Skan if (!strncmp (switches[i].part1, atom, hard_match_len) 5908132733Skan && check_live_switch (i, hard_match_len)) 5909132733Skan { 5910132733Skan if (do_spec_1 (string, 0, 5911132733Skan &switches[i].part1[hard_match_len]) < 0) 5912132733Skan return 0; 5913132733Skan /* Pass any arguments this switch has. */ 5914132733Skan give_switch (i, 1); 5915132733Skan suffix_subst = NULL; 5916132733Skan } 5917132733Skan } 591890277Sobrien } 591990277Sobrien 5920132733Skan return p; 5921169704Skan 5922169704Skan invalid: 5923169704Skan fatal ("braced spec body '%s' is invalid", body); 592418334Speter} 592518334Speter 592618334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch 592718334Speter on the command line. PREFIX_LENGTH is the length of XXX in an {XXX*} 592818334Speter spec, or -1 if either exact match or %* is used. 592918334Speter 593018334Speter A -O switch is obsoleted by a later -O switch. A -f, -m, or -W switch 593118334Speter whose value does not begin with "no-" is obsoleted by the same value 593218334Speter with the "no-", similarly for a switch with the "no-" prefix. */ 593318334Speter 593418334Speterstatic int 5935132733Skancheck_live_switch (int switchnum, int prefix_length) 593618334Speter{ 593752520Sobrien const char *name = switches[switchnum].part1; 593818334Speter int i; 593918334Speter 594018334Speter /* In the common case of {<at-most-one-letter>*}, a negating 594118334Speter switch would always match, so ignore that case. We will just 594218334Speter send the conflicting switches to the compiler phase. */ 594318334Speter if (prefix_length >= 0 && prefix_length <= 1) 594418334Speter return 1; 594518334Speter 594618334Speter /* If we already processed this switch and determined if it was 594718334Speter live or not, return our past determination. */ 594818334Speter if (switches[switchnum].live_cond != 0) 594918334Speter return switches[switchnum].live_cond > 0; 595018334Speter 595118334Speter /* Now search for duplicate in a manner that depends on the name. */ 595218334Speter switch (*name) 595318334Speter { 595418334Speter case 'O': 595590277Sobrien for (i = switchnum + 1; i < n_switches; i++) 595690277Sobrien if (switches[i].part1[0] == 'O') 595790277Sobrien { 595890277Sobrien switches[switchnum].validated = 1; 595990277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 596090277Sobrien return 0; 596190277Sobrien } 596218334Speter break; 596318334Speter 596418334Speter case 'W': case 'f': case 'm': 596518334Speter if (! strncmp (name + 1, "no-", 3)) 596618334Speter { 596750599Sobrien /* We have Xno-YYY, search for XYYY. */ 596818334Speter for (i = switchnum + 1; i < n_switches; i++) 596918334Speter if (switches[i].part1[0] == name[0] 597018334Speter && ! strcmp (&switches[i].part1[1], &name[4])) 597190277Sobrien { 597290277Sobrien switches[switchnum].validated = 1; 597390277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 597490277Sobrien return 0; 597590277Sobrien } 597618334Speter } 597718334Speter else 597818334Speter { 597918334Speter /* We have XYYY, search for Xno-YYY. */ 598018334Speter for (i = switchnum + 1; i < n_switches; i++) 598118334Speter if (switches[i].part1[0] == name[0] 598218334Speter && switches[i].part1[1] == 'n' 598318334Speter && switches[i].part1[2] == 'o' 598418334Speter && switches[i].part1[3] == '-' 598518334Speter && !strcmp (&switches[i].part1[4], &name[1])) 598690277Sobrien { 598790277Sobrien switches[switchnum].validated = 1; 598890277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 598990277Sobrien return 0; 599090277Sobrien } 599118334Speter } 599218334Speter break; 599318334Speter } 599418334Speter 599518334Speter /* Otherwise the switch is live. */ 599690277Sobrien switches[switchnum].live_cond = SWITCH_LIVE; 599718334Speter return 1; 599818334Speter} 599918334Speter 600018334Speter/* Pass a switch to the current accumulating command 600118334Speter in the same form that we received it. 600218334Speter SWITCHNUM identifies the switch; it is an index into 600318334Speter the vector of switches gcc received, which is `switches'. 600418334Speter This cannot fail since it never finishes a command line. 600518334Speter 6006132733Skan If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. */ 600718334Speter 600818334Speterstatic void 6009132733Skangive_switch (int switchnum, int omit_first_word) 601018334Speter{ 601190277Sobrien if (switches[switchnum].live_cond == SWITCH_IGNORE) 601290277Sobrien return; 601390277Sobrien 601418334Speter if (!omit_first_word) 601518334Speter { 601690277Sobrien do_spec_1 ("-", 0, NULL); 601790277Sobrien do_spec_1 (switches[switchnum].part1, 1, NULL); 601818334Speter } 601950599Sobrien 602018334Speter if (switches[switchnum].args != 0) 602118334Speter { 602290277Sobrien const char **p; 602318334Speter for (p = switches[switchnum].args; *p; p++) 602418334Speter { 602590277Sobrien const char *arg = *p; 602690277Sobrien 6027132733Skan do_spec_1 (" ", 0, NULL); 602890277Sobrien if (suffix_subst) 602990277Sobrien { 603090277Sobrien unsigned length = strlen (arg); 603190277Sobrien int dot = 0; 603290277Sobrien 603390277Sobrien while (length-- && !IS_DIR_SEPARATOR (arg[length])) 603490277Sobrien if (arg[length] == '.') 603590277Sobrien { 603690277Sobrien ((char *)arg)[length] = 0; 603790277Sobrien dot = 1; 603890277Sobrien break; 603990277Sobrien } 604090277Sobrien do_spec_1 (arg, 1, NULL); 604190277Sobrien if (dot) 604290277Sobrien ((char *)arg)[length] = '.'; 604390277Sobrien do_spec_1 (suffix_subst, 1, NULL); 604490277Sobrien } 604590277Sobrien else 604690277Sobrien do_spec_1 (arg, 1, NULL); 604718334Speter } 604818334Speter } 604950599Sobrien 605090277Sobrien do_spec_1 (" ", 0, NULL); 605152520Sobrien switches[switchnum].validated = 1; 605218334Speter} 605318334Speter 605418334Speter/* Search for a file named NAME trying various prefixes including the 605518334Speter user's -B prefix and some standard ones. 605618334Speter Return the absolute file name found. If nothing is found, return NAME. */ 605718334Speter 605852520Sobrienstatic const char * 6059132733Skanfind_file (const char *name) 606018334Speter{ 6061169704Skan char *newname = find_a_file (&startfile_prefixes, name, R_OK, true); 606218334Speter return newname ? newname : name; 606318334Speter} 606418334Speter 606518334Speter/* Determine whether a directory exists. If LINKER, return 0 for 6066169704Skan certain fixed names not needed by the linker. */ 606718334Speter 606818334Speterstatic int 6069169704Skanis_directory (const char *path1, bool linker) 607018334Speter{ 6071169704Skan int len1; 6072169704Skan char *path; 607318334Speter char *cp; 607418334Speter struct stat st; 607518334Speter 6076169704Skan /* Ensure the string ends with "/.". The resulting path will be a 6077169704Skan directory even if the given path is a symbolic link. */ 6078169704Skan len1 = strlen (path1); 6079169704Skan path = alloca (3 + len1); 608052520Sobrien memcpy (path, path1, len1); 6081169704Skan cp = path + len1; 608252520Sobrien if (!IS_DIR_SEPARATOR (cp[-1])) 608318334Speter *cp++ = DIR_SEPARATOR; 608418334Speter *cp++ = '.'; 608518334Speter *cp = '\0'; 608618334Speter 608751232Sbde#ifndef FREEBSD_NATIVE 608818334Speter /* Exclude directories that the linker is known to search. */ 608918334Speter if (linker 6090169704Skan && IS_DIR_SEPARATOR (path[0]) 609118334Speter && ((cp - path == 6 6092169704Skan && strncmp (path + 1, "lib", 3) == 0) 609318334Speter || (cp - path == 10 6094169704Skan && strncmp (path + 1, "usr", 3) == 0 6095169704Skan && IS_DIR_SEPARATOR (path[4]) 6096169704Skan && strncmp (path + 5, "lib", 3) == 0))) 609718334Speter return 0; 609851232Sbde#endif /* FREEBSD_NATIVE */ 609918334Speter 610018334Speter return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode)); 610118334Speter} 610290277Sobrien 610390277Sobrien/* Set up the various global variables to indicate that we're processing 610490277Sobrien the input file named FILENAME. */ 610590277Sobrien 610690277Sobrienvoid 6107132733Skanset_input (const char *filename) 610890277Sobrien{ 610990277Sobrien const char *p; 611090277Sobrien 611190277Sobrien input_filename = filename; 611290277Sobrien input_filename_length = strlen (input_filename); 611390277Sobrien 611490277Sobrien input_basename = input_filename; 611590277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 611690277Sobrien /* Skip drive name so 'x:foo' is handled properly. */ 611790277Sobrien if (input_basename[1] == ':') 611890277Sobrien input_basename += 2; 611990277Sobrien#endif 612090277Sobrien for (p = input_basename; *p; p++) 612190277Sobrien if (IS_DIR_SEPARATOR (*p)) 612290277Sobrien input_basename = p + 1; 612390277Sobrien 612490277Sobrien /* Find a suffix starting with the last period, 612590277Sobrien and set basename_length to exclude that suffix. */ 612690277Sobrien basename_length = strlen (input_basename); 612790277Sobrien suffixed_basename_length = basename_length; 612890277Sobrien p = input_basename + basename_length; 612990277Sobrien while (p != input_basename && *p != '.') 613090277Sobrien --p; 613190277Sobrien if (*p == '.' && p != input_basename) 613290277Sobrien { 613390277Sobrien basename_length = p - input_basename; 613490277Sobrien input_suffix = p + 1; 613590277Sobrien } 613690277Sobrien else 613790277Sobrien input_suffix = ""; 6138117413Skan 613990277Sobrien /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then 614090277Sobrien we will need to do a stat on the input_filename. The 614190277Sobrien INPUT_STAT_SET signals that the stat is needed. */ 614290277Sobrien input_stat_set = 0; 614390277Sobrien} 614418334Speter 614518334Speter/* On fatal signals, delete all the temporary files. */ 614618334Speter 614718334Speterstatic void 6148132733Skanfatal_error (int signum) 614918334Speter{ 615018334Speter signal (signum, SIG_DFL); 615118334Speter delete_failure_queue (); 615218334Speter delete_temp_files (); 615318334Speter /* Get the same signal again, this time not handled, 615418334Speter so its normal effect occurs. */ 615518334Speter kill (getpid (), signum); 615618334Speter} 615718334Speter 6158169704Skanextern int main (int, char **); 615990277Sobrien 616018334Speterint 6161169704Skanmain (int argc, char **argv) 616218334Speter{ 616390277Sobrien size_t i; 616418334Speter int value; 616518334Speter int linker_was_run = 0; 6166169704Skan int lang_n_infiles = 0; 6167132733Skan int num_linker_inputs = 0; 616818334Speter char *explicit_link_files; 616918334Speter char *specs_file; 617052520Sobrien const char *p; 617150599Sobrien struct user_specs *uptr; 617218334Speter 617318334Speter p = argv[0] + strlen (argv[0]); 617452520Sobrien while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) 617552520Sobrien --p; 617618334Speter programname = p; 617718334Speter 617890277Sobrien xmalloc_set_program_name (programname); 617990277Sobrien 6180169704Skan expandargv (&argc, &argv); 6181169704Skan 6182169704Skan prune_options (&argc, &argv); 6183169704Skan 618490277Sobrien#ifdef GCC_DRIVER_HOST_INITIALIZATION 618590277Sobrien /* Perform host dependent initialization when needed. */ 618690277Sobrien GCC_DRIVER_HOST_INITIALIZATION; 618752520Sobrien#endif 618852520Sobrien 6189169704Skan /* Unlock the stdio streams. */ 6190169704Skan unlock_std_streams (); 6191169704Skan 619290277Sobrien gcc_init_libintl (); 619390277Sobrien 619418334Speter if (signal (SIGINT, SIG_IGN) != SIG_IGN) 619518334Speter signal (SIGINT, fatal_error); 619618334Speter#ifdef SIGHUP 619718334Speter if (signal (SIGHUP, SIG_IGN) != SIG_IGN) 619818334Speter signal (SIGHUP, fatal_error); 619918334Speter#endif 620018334Speter if (signal (SIGTERM, SIG_IGN) != SIG_IGN) 620118334Speter signal (SIGTERM, fatal_error); 620218334Speter#ifdef SIGPIPE 620318334Speter if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) 620418334Speter signal (SIGPIPE, fatal_error); 620518334Speter#endif 620690277Sobrien#ifdef SIGCHLD 620790277Sobrien /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will 620890277Sobrien receive the signal. A different setting is inheritable */ 620990277Sobrien signal (SIGCHLD, SIG_DFL); 621090277Sobrien#endif 621118334Speter 6212117413Skan /* Allocate the argument vector. */ 6213117413Skan alloc_args (); 621418334Speter 621518334Speter obstack_init (&obstack); 621618334Speter 621750599Sobrien /* Build multilib_select, et. al from the separate lines that make up each 621850599Sobrien multilib selection. */ 621950599Sobrien { 622090277Sobrien const char *const *q = multilib_raw; 622150599Sobrien int need_space; 622250599Sobrien 622350599Sobrien obstack_init (&multilib_obstack); 622450599Sobrien while ((p = *q++) != (char *) 0) 622550599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 622650599Sobrien 622750599Sobrien obstack_1grow (&multilib_obstack, 0); 6228169704Skan multilib_select = XOBFINISH (&multilib_obstack, const char *); 622950599Sobrien 623050599Sobrien q = multilib_matches_raw; 623150599Sobrien while ((p = *q++) != (char *) 0) 623250599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 623350599Sobrien 623450599Sobrien obstack_1grow (&multilib_obstack, 0); 6235169704Skan multilib_matches = XOBFINISH (&multilib_obstack, const char *); 623650599Sobrien 623790277Sobrien q = multilib_exclusions_raw; 623890277Sobrien while ((p = *q++) != (char *) 0) 623990277Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 624090277Sobrien 624190277Sobrien obstack_1grow (&multilib_obstack, 0); 6242169704Skan multilib_exclusions = XOBFINISH (&multilib_obstack, const char *); 624390277Sobrien 624450599Sobrien need_space = FALSE; 624590277Sobrien for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++) 624650599Sobrien { 624750599Sobrien if (need_space) 624850599Sobrien obstack_1grow (&multilib_obstack, ' '); 624950599Sobrien obstack_grow (&multilib_obstack, 625050599Sobrien multilib_defaults_raw[i], 625150599Sobrien strlen (multilib_defaults_raw[i])); 625250599Sobrien need_space = TRUE; 625350599Sobrien } 625450599Sobrien 625550599Sobrien obstack_1grow (&multilib_obstack, 0); 6256169704Skan multilib_defaults = XOBFINISH (&multilib_obstack, const char *); 625750599Sobrien } 625850599Sobrien 625918334Speter /* Set up to remember the pathname of gcc and any options 626018334Speter needed for collect. We use argv[0] instead of programname because 626118334Speter we need the complete pathname. */ 626218334Speter obstack_init (&collect_obstack); 626390277Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1); 626490277Sobrien obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1); 6265169704Skan putenv (XOBFINISH (&collect_obstack, char *)); 626618334Speter 626718334Speter#ifdef INIT_ENVIRONMENT 626818334Speter /* Set up any other necessary machine specific environment variables. */ 626918334Speter putenv (INIT_ENVIRONMENT); 627018334Speter#endif 627118334Speter 627218334Speter /* Make a table of what switches there are (switches, n_switches). 627318334Speter Make a table of specified input files (infiles, n_infiles). 627418334Speter Decode switches that are handled locally. */ 627518334Speter 6276169704Skan process_command (argc, (const char **) argv); 627718334Speter 627818334Speter /* Initialize the vector of specs to just the default. 627918334Speter This means one element containing 0s, as a terminator. */ 628018334Speter 6281132733Skan compilers = xmalloc (sizeof default_compilers); 6282132733Skan memcpy (compilers, default_compilers, sizeof default_compilers); 628318334Speter n_compilers = n_default_compilers; 628418334Speter 628518334Speter /* Read specs from a file if there is one. */ 628618334Speter 628791561Sobrien#ifdef FREEBSD_NATIVE 6288169704Skan machine_suffix = ""; 628991561Sobrien just_machine_suffix = ""; 629091561Sobrien#else /* FREEBSD_NATIVE */ 629150599Sobrien machine_suffix = concat (spec_machine, dir_separator_str, 629290277Sobrien spec_version, dir_separator_str, NULL); 629390277Sobrien just_machine_suffix = concat (spec_machine, dir_separator_str, NULL); 629450599Sobrien#endif /* FREEBSD_NATIVE */ 629518334Speter 6296169704Skan specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true); 629718334Speter /* Read the specs file unless it is a default one. */ 629818334Speter if (specs_file != 0 && strcmp (specs_file, "specs")) 629950599Sobrien read_specs (specs_file, TRUE); 630050599Sobrien else 630150599Sobrien init_spec (); 630218334Speter 630350599Sobrien /* We need to check standard_exec_prefix/just_machine_suffix/specs 630490277Sobrien for any override of as, ld and libraries. */ 630597902Sobrien specs_file = (char *) alloca (strlen (FBSD_DATA_PREFIX) 630650599Sobrien + strlen (just_machine_suffix) 630750599Sobrien + sizeof ("specs")); 630850599Sobrien 630997902Sobrien strcpy (specs_file, FBSD_DATA_PREFIX); 631050599Sobrien strcat (specs_file, just_machine_suffix); 631150599Sobrien strcat (specs_file, "specs"); 631250599Sobrien if (access (specs_file, R_OK) == 0) 631350599Sobrien read_specs (specs_file, TRUE); 631490277Sobrien 6315132733Skan /* Process any configure-time defaults specified for the command line 6316132733Skan options, via OPTION_DEFAULT_SPECS. */ 6317132733Skan for (i = 0; i < ARRAY_SIZE (option_default_specs); i++) 6318132733Skan do_option_spec (option_default_specs[i].name, 6319132733Skan option_default_specs[i].spec); 6320132733Skan 6321132733Skan /* Process DRIVER_SELF_SPECS, adding any new options to the end 6322132733Skan of the command line. */ 6323132733Skan 6324132733Skan for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++) 6325132733Skan do_self_spec (driver_self_specs[i]); 6326132733Skan 6327132733Skan /* If not cross-compiling, look for executables in the standard 6328132733Skan places. */ 6329132733Skan if (*cross_compile == '0') 633018334Speter { 633190277Sobrien if (*md_exec_prefix) 633290277Sobrien { 633390277Sobrien add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 6334169704Skan PREFIX_PRIORITY_LAST, 0, 0); 633590277Sobrien } 6336132733Skan } 633718334Speter 6338132733Skan /* Process sysroot_suffix_spec. */ 6339132733Skan if (*sysroot_suffix_spec != 0 6340132733Skan && do_spec_2 (sysroot_suffix_spec) == 0) 6341132733Skan { 6342132733Skan if (argbuf_index > 1) 6343169704Skan error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC"); 6344132733Skan else if (argbuf_index == 1) 6345132733Skan target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]); 6346132733Skan } 6347132733Skan 6348169704Skan#ifdef HAVE_LD_SYSROOT 6349169704Skan /* Pass the --sysroot option to the linker, if it supports that. If 6350169704Skan there is a sysroot_suffix_spec, it has already been processed by 6351169704Skan this point, so target_system_root really is the system root we 6352169704Skan should be using. */ 6353169704Skan if (target_system_root) 6354169704Skan { 6355169704Skan obstack_grow (&obstack, "%(sysroot_spec) ", strlen ("%(sysroot_spec) ")); 6356169704Skan obstack_grow0 (&obstack, link_spec, strlen (link_spec)); 6357169704Skan set_spec ("link", XOBFINISH (&obstack, const char *)); 6358169704Skan } 6359169704Skan#endif 6360169704Skan 6361132733Skan /* Process sysroot_hdrs_suffix_spec. */ 6362132733Skan if (*sysroot_hdrs_suffix_spec != 0 6363132733Skan && do_spec_2 (sysroot_hdrs_suffix_spec) == 0) 6364132733Skan { 6365132733Skan if (argbuf_index > 1) 6366169704Skan error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC"); 6367132733Skan else if (argbuf_index == 1) 6368132733Skan target_sysroot_hdrs_suffix = xstrdup (argbuf[argbuf_index -1]); 6369132733Skan } 6370132733Skan 6371132733Skan /* Look for startfiles in the standard places. */ 6372132733Skan if (*startfile_prefix_spec != 0 6373132733Skan && do_spec_2 (startfile_prefix_spec) == 0 6374132733Skan && do_spec_1 (" ", 0, NULL) == 0) 6375132733Skan { 6376132733Skan int ndx; 6377132733Skan for (ndx = 0; ndx < argbuf_index; ndx++) 6378132733Skan add_sysrooted_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS", 6379169704Skan PREFIX_PRIORITY_LAST, 0, 1); 6380132733Skan } 6381132733Skan /* We should eventually get rid of all these and stick to 6382132733Skan startfile_prefix_spec exclusively. */ 6383132733Skan else if (*cross_compile == '0' || target_system_root) 6384132733Skan { 638590277Sobrien if (*md_startfile_prefix) 6386132733Skan add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix, 6387169704Skan "GCC", PREFIX_PRIORITY_LAST, 0, 1); 638818334Speter 638990277Sobrien if (*md_startfile_prefix_1) 6390132733Skan add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix_1, 6391169704Skan "GCC", PREFIX_PRIORITY_LAST, 0, 1); 639218334Speter 639318334Speter /* If standard_startfile_prefix is relative, base it on 639418334Speter standard_exec_prefix. This lets us move the installed tree 639518334Speter as a unit. If GCC_EXEC_PREFIX is defined, base 6396132733Skan standard_startfile_prefix on that as well. 6397132733Skan 6398132733Skan If the prefix is relative, only search it for native compilers; 6399132733Skan otherwise we will search a directory containing host libraries. */ 6400132733Skan if (IS_ABSOLUTE_PATH (standard_startfile_prefix)) 6401132733Skan add_sysrooted_prefix (&startfile_prefixes, 6402132733Skan standard_startfile_prefix, "BINUTILS", 6403169704Skan PREFIX_PRIORITY_LAST, 0, 1); 6404132733Skan else if (*cross_compile == '0') 640518334Speter { 640618334Speter if (gcc_exec_prefix) 640718334Speter add_prefix (&startfile_prefixes, 640850599Sobrien concat (gcc_exec_prefix, machine_suffix, 640990277Sobrien standard_startfile_prefix, NULL), 6410169704Skan NULL, PREFIX_PRIORITY_LAST, 0, 1); 641118334Speter add_prefix (&startfile_prefixes, 641250599Sobrien concat (standard_exec_prefix, 641350599Sobrien machine_suffix, 641490277Sobrien standard_startfile_prefix, NULL), 6415169704Skan NULL, PREFIX_PRIORITY_LAST, 0, 1); 641690277Sobrien } 641718334Speter 641818346Speter#ifndef FREEBSD_NATIVE 6419169704Skan if (*standard_startfile_prefix_1) 6420169704Skan add_sysrooted_prefix (&startfile_prefixes, 6421169704Skan standard_startfile_prefix_1, "BINUTILS", 6422169704Skan PREFIX_PRIORITY_LAST, 0, 1); 6423169704Skan if (*standard_startfile_prefix_2) 6424169704Skan add_sysrooted_prefix (&startfile_prefixes, 6425169704Skan standard_startfile_prefix_2, "BINUTILS", 6426169704Skan PREFIX_PRIORITY_LAST, 0, 1); 642718334Speter#endif 642818334Speter } 642918334Speter 643052520Sobrien /* Process any user specified specs in the order given on the command 643152520Sobrien line. */ 643252520Sobrien for (uptr = user_specs_head; uptr; uptr = uptr->next) 643352520Sobrien { 6434104763Skan char *filename = find_a_file (&startfile_prefixes, uptr->filename, 6435169704Skan R_OK, true); 643652520Sobrien read_specs (filename ? filename : uptr->filename, FALSE); 643752520Sobrien } 643852520Sobrien 643918334Speter /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */ 644018334Speter if (gcc_exec_prefix) 644190277Sobrien gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 644290277Sobrien spec_version, dir_separator_str, NULL); 644318334Speter 644418334Speter /* Now we have the specs. 644518334Speter Set the `valid' bits for switches that match anything in any spec. */ 644618334Speter 644718334Speter validate_all_switches (); 644818334Speter 644918334Speter /* Now that we have the switches and the specs, set 645018334Speter the subdirectory based on the options. */ 645118334Speter set_multilib_dir (); 645218334Speter 645318334Speter /* Warn about any switches that no pass was interested in. */ 645418334Speter 645590277Sobrien for (i = 0; (int) i < n_switches; i++) 645652520Sobrien if (! switches[i].validated) 6457169704Skan error ("unrecognized option '-%s'", switches[i].part1); 645818334Speter 645918334Speter /* Obey some of the options. */ 646018334Speter 646118334Speter if (print_search_dirs) 646218334Speter { 6463169704Skan#ifndef FREEBSD_NATIVE 646490277Sobrien printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix); 6465169704Skan#else 6466169704Skan printf (_("install: %s\n"), standard_exec_prefix); 6467169704Skan#endif 6468169704Skan printf (_("programs: %s\n"), 6469169704Skan build_search_list (&exec_prefixes, "", false, false)); 6470169704Skan printf (_("libraries: %s\n"), 6471169704Skan build_search_list (&startfile_prefixes, "", false, true)); 647290277Sobrien return (0); 647318334Speter } 647418334Speter 647518334Speter if (print_file_name) 647618334Speter { 647718334Speter printf ("%s\n", find_file (print_file_name)); 647890277Sobrien return (0); 647918334Speter } 648018334Speter 648118334Speter if (print_prog_name) 648218334Speter { 6483104763Skan char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0); 648418334Speter printf ("%s\n", (newname ? newname : print_prog_name)); 648590277Sobrien return (0); 648618334Speter } 648718334Speter 648818334Speter if (print_multi_lib) 648918334Speter { 649018334Speter print_multilib_info (); 649190277Sobrien return (0); 649218334Speter } 649318334Speter 649418334Speter if (print_multi_directory) 649518334Speter { 649618334Speter if (multilib_dir == NULL) 649718334Speter printf (".\n"); 649818334Speter else 649918334Speter printf ("%s\n", multilib_dir); 650090277Sobrien return (0); 650118334Speter } 650218334Speter 6503104763Skan if (print_multi_os_directory) 6504104763Skan { 6505104763Skan if (multilib_os_dir == NULL) 6506104763Skan printf (".\n"); 6507104763Skan else 6508104763Skan printf ("%s\n", multilib_os_dir); 6509104763Skan return (0); 6510104763Skan } 6511104763Skan 651290277Sobrien if (target_help_flag) 651390277Sobrien { 651490277Sobrien /* Print if any target specific options. */ 651590277Sobrien 651690277Sobrien /* We do not exit here. Instead we have created a fake input file 651790277Sobrien called 'target-dummy' which needs to be compiled, and we pass this 651890277Sobrien on to the various sub-processes, along with the --target-help 651990277Sobrien switch. */ 652090277Sobrien } 652190277Sobrien 652250599Sobrien if (print_help_list) 652350599Sobrien { 652450599Sobrien display_help (); 652550599Sobrien 652650599Sobrien if (! verbose_flag) 652750599Sobrien { 6528260011Spfg printf ("%s", _("\nFor bug reporting instructions, please see:\n")); 6529117413Skan printf ("%s.\n", bug_report_url); 653090277Sobrien 653190277Sobrien return (0); 653250599Sobrien } 653350599Sobrien 653450599Sobrien /* We do not exit here. Instead we have created a fake input file 653550599Sobrien called 'help-dummy' which needs to be compiled, and we pass this 653690277Sobrien on the various sub-processes, along with the --help switch. */ 653750599Sobrien } 653890277Sobrien 653918334Speter if (verbose_flag) 654018334Speter { 654150599Sobrien int n; 654290277Sobrien const char *thrmod; 654350599Sobrien 6544169704Skan notice ("Target: %s\n", spec_machine); 654590277Sobrien notice ("Configured with: %s\n", configuration_arguments); 654690277Sobrien 654790277Sobrien#ifdef THREAD_MODEL_SPEC 654890277Sobrien /* We could have defined THREAD_MODEL_SPEC to "%*" by default, 654990277Sobrien but there's no point in doing all this processing just to get 655090277Sobrien thread_model back. */ 655190277Sobrien obstack_init (&obstack); 655290277Sobrien do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); 655390277Sobrien obstack_1grow (&obstack, '\0'); 6554169704Skan thrmod = XOBFINISH (&obstack, const char *); 655590277Sobrien#else 655690277Sobrien thrmod = thread_model; 655790277Sobrien#endif 655890277Sobrien 655990277Sobrien notice ("Thread model: %s\n", thrmod); 656090277Sobrien 656150599Sobrien /* compiler_version is truncated at the first space when initialized 656250599Sobrien from version string, so truncate version_string at the first space 656350599Sobrien before comparing. */ 656450599Sobrien for (n = 0; version_string[n]; n++) 656550599Sobrien if (version_string[n] == ' ') 656650599Sobrien break; 656750599Sobrien 656850599Sobrien if (! strncmp (version_string, compiler_version, n) 656950599Sobrien && compiler_version[n] == 0) 657052520Sobrien notice ("gcc version %s\n", version_string); 657118334Speter else 657252520Sobrien notice ("gcc driver version %s executing gcc version %s\n", 657352520Sobrien version_string, compiler_version); 657418334Speter 657518334Speter if (n_infiles == 0) 657690277Sobrien return (0); 657718334Speter } 657818334Speter 657950599Sobrien if (n_infiles == added_libraries) 658018346Speter fatal ("No input files specified"); 658118334Speter 658218334Speter /* Make a place to record the compiler output file names 658318334Speter that correspond to the input files. */ 658418334Speter 658550599Sobrien i = n_infiles; 658650599Sobrien i += lang_specific_extra_outfiles; 6587169704Skan outfiles = XCNEWVEC (const char *, i); 658818334Speter 658918334Speter /* Record which files were specified explicitly as link input. */ 659018334Speter 6591169704Skan explicit_link_files = XCNEWVEC (char, n_infiles); 659218334Speter 6593169704Skan if (combine_flag) 6594169704Skan combine_inputs = true; 6595169704Skan else 6596169704Skan combine_inputs = false; 6597169704Skan 6598169704Skan for (i = 0; (int) i < n_infiles; i++) 659918334Speter { 6600169704Skan const char *name = infiles[i].name; 6601169704Skan struct compiler *compiler = lookup_compiler (name, 6602169704Skan strlen (name), 6603169704Skan infiles[i].language); 6604169704Skan 6605169704Skan if (compiler && !(compiler->combinable)) 6606169704Skan combine_inputs = false; 6607169704Skan 6608169704Skan if (lang_n_infiles > 0 && compiler != input_file_compiler 6609169704Skan && infiles[i].language && infiles[i].language[0] != '*') 6610169704Skan infiles[i].incompiler = compiler; 6611169704Skan else if (compiler) 6612169704Skan { 6613169704Skan lang_n_infiles++; 6614169704Skan input_file_compiler = compiler; 6615169704Skan infiles[i].incompiler = compiler; 6616169704Skan } 6617169704Skan else 6618169704Skan { 6619169704Skan /* Since there is no compiler for this input file, assume it is a 6620169704Skan linker file. */ 6621169704Skan explicit_link_files[i] = 1; 6622169704Skan infiles[i].incompiler = NULL; 6623169704Skan } 6624169704Skan infiles[i].compiled = false; 6625169704Skan infiles[i].preprocessed = false; 6626132733Skan } 6627169704Skan 6628169704Skan if (!combine_inputs && have_c && have_o && lang_n_infiles > 1) 6629169704Skan fatal ("cannot specify -o with -c or -S with multiple files"); 6630169704Skan 6631169704Skan if (combine_flag && save_temps_flag) 6632132733Skan { 6633169704Skan bool save_combine_inputs = combine_inputs; 6634169704Skan /* Must do a separate pre-processing pass for C & Objective-C files, to 6635169704Skan obtain individual .i files. */ 6636169704Skan 6637169704Skan combine_inputs = false; 6638169704Skan for (i = 0; (int) i < n_infiles; i++) 6639169704Skan { 6640169704Skan int this_file_error = 0; 6641169704Skan 6642169704Skan input_file_number = i; 6643169704Skan set_input (infiles[i].name); 6644169704Skan if (infiles[i].incompiler 6645169704Skan && (infiles[i].incompiler)->needs_preprocessing) 6646169704Skan input_file_compiler = infiles[i].incompiler; 6647169704Skan else 6648169704Skan continue; 6649169704Skan 6650169704Skan if (input_file_compiler) 6651169704Skan { 6652169704Skan if (input_file_compiler->spec[0] == '#') 6653169704Skan { 6654169704Skan error ("%s: %s compiler not installed on this system", 6655169704Skan input_filename, &input_file_compiler->spec[1]); 6656169704Skan this_file_error = 1; 6657169704Skan } 6658169704Skan else 6659169704Skan { 6660169704Skan value = do_spec (input_file_compiler->spec); 6661169704Skan infiles[i].preprocessed = true; 6662169704Skan if (!have_o_argbuf_index) 6663169704Skan fatal ("spec '%s' is invalid", input_file_compiler->spec); 6664169704Skan infiles[i].name = argbuf[have_o_argbuf_index]; 6665169704Skan infiles[i].incompiler 6666169704Skan = lookup_compiler (infiles[i].name, 6667169704Skan strlen (infiles[i].name), 6668169704Skan infiles[i].language); 6669169704Skan 6670169704Skan if (value < 0) 6671169704Skan this_file_error = 1; 6672169704Skan } 6673169704Skan } 6674169704Skan 6675169704Skan if (this_file_error) 6676169704Skan { 6677169704Skan delete_failure_queue (); 6678169704Skan error_count++; 6679169704Skan break; 6680169704Skan } 6681169704Skan clear_failure_queue (); 6682169704Skan } 6683169704Skan combine_inputs = save_combine_inputs; 6684169704Skan } 6685169704Skan 6686169704Skan for (i = 0; (int) i < n_infiles; i++) 6687169704Skan { 668818334Speter int this_file_error = 0; 668918334Speter 669018334Speter /* Tell do_spec what to substitute for %i. */ 669118334Speter 669218334Speter input_file_number = i; 669390277Sobrien set_input (infiles[i].name); 669418334Speter 6695169704Skan if (infiles[i].compiled) 6696169704Skan continue; 6697169704Skan 669818334Speter /* Use the same thing in %o, unless cp->spec says otherwise. */ 669918334Speter 670018334Speter outfiles[i] = input_filename; 670118334Speter 670218334Speter /* Figure out which compiler from the file's suffix. */ 670318334Speter 6704132733Skan if (! combine_inputs) 6705132733Skan input_file_compiler 6706132733Skan = lookup_compiler (infiles[i].name, input_filename_length, 6707132733Skan infiles[i].language); 6708169704Skan else 6709169704Skan input_file_compiler = infiles[i].incompiler; 6710117413Skan 671190277Sobrien if (input_file_compiler) 671218334Speter { 671318334Speter /* Ok, we found an applicable compiler. Run its spec. */ 671418334Speter 671590277Sobrien if (input_file_compiler->spec[0] == '#') 671618334Speter { 671790277Sobrien error ("%s: %s compiler not installed on this system", 671890277Sobrien input_filename, &input_file_compiler->spec[1]); 671990277Sobrien this_file_error = 1; 672018334Speter } 672118334Speter else 672290277Sobrien { 672390277Sobrien value = do_spec (input_file_compiler->spec); 6724169704Skan infiles[i].compiled = true; 672590277Sobrien if (value < 0) 672690277Sobrien this_file_error = 1; 672790277Sobrien } 672818334Speter } 672918334Speter 673018334Speter /* If this file's name does not contain a recognized suffix, 673118334Speter record it as explicit linker input. */ 673218334Speter 673318334Speter else 673418334Speter explicit_link_files[i] = 1; 673518334Speter 673618334Speter /* Clear the delete-on-failure queue, deleting the files in it 673718334Speter if this compilation failed. */ 673818334Speter 673918334Speter if (this_file_error) 674018334Speter { 674118334Speter delete_failure_queue (); 674218334Speter error_count++; 674318334Speter } 674418334Speter /* If this compilation succeeded, don't delete those files later. */ 674518334Speter clear_failure_queue (); 674618334Speter } 674718334Speter 6748169704Skan /* Reset the input file name to the first compile/object file name, for use 6749169704Skan with %b in LINK_SPEC. We use the first input file that we can find 6750169704Skan a compiler to compile it instead of using infiles.language since for 6751169704Skan languages other than C we use aliases that we then lookup later. */ 675290277Sobrien if (n_infiles > 0) 6753169704Skan { 6754169704Skan int i; 675590277Sobrien 6756169704Skan for (i = 0; i < n_infiles ; i++) 6757169704Skan if (infiles[i].language && infiles[i].language[0] != '*') 6758169704Skan { 6759169704Skan set_input (infiles[i].name); 6760169704Skan break; 6761169704Skan } 6762169704Skan } 6763169704Skan 676452520Sobrien if (error_count == 0) 676552520Sobrien { 676652520Sobrien /* Make sure INPUT_FILE_NUMBER points to first available open 676752520Sobrien slot. */ 676852520Sobrien input_file_number = n_infiles; 676952520Sobrien if (lang_specific_pre_link ()) 677052520Sobrien error_count++; 677152520Sobrien } 677250599Sobrien 6773132733Skan /* Determine if there are any linker input files. */ 6774132733Skan num_linker_inputs = 0; 6775132733Skan for (i = 0; (int) i < n_infiles; i++) 6776132733Skan if (explicit_link_files[i] || outfiles[i] != NULL) 6777132733Skan num_linker_inputs++; 6778132733Skan 677918334Speter /* Run ld to link all the compiler output files. */ 678018334Speter 6781132733Skan if (num_linker_inputs > 0 && error_count == 0) 678218334Speter { 678318334Speter int tmp = execution_count; 678418334Speter 678590277Sobrien /* We'll use ld if we can't find collect2. */ 678650599Sobrien if (! strcmp (linker_name_spec, "collect2")) 678750599Sobrien { 6788169704Skan char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false); 678950599Sobrien if (s == NULL) 679050599Sobrien linker_name_spec = "ld"; 679150599Sobrien } 679218334Speter /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 679318334Speter for collect. */ 6794169704Skan putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false); 6795169704Skan putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV, true); 679618334Speter 679718334Speter value = do_spec (link_command_spec); 679818334Speter if (value < 0) 679918334Speter error_count = 1; 680018334Speter linker_was_run = (tmp != execution_count); 680118334Speter } 680218334Speter 680318334Speter /* If options said don't run linker, 680418334Speter complain about input files to be given to the linker. */ 680518334Speter 680618334Speter if (! linker_was_run && error_count == 0) 680790277Sobrien for (i = 0; (int) i < n_infiles; i++) 680818334Speter if (explicit_link_files[i]) 680990277Sobrien error ("%s: linker input file unused because linking not done", 681018334Speter outfiles[i]); 681118334Speter 681218334Speter /* Delete some or all of the temporary files we made. */ 681318334Speter 681418334Speter if (error_count) 681518334Speter delete_failure_queue (); 681618334Speter delete_temp_files (); 681718334Speter 681850599Sobrien if (print_help_list) 681950599Sobrien { 682090277Sobrien printf (("\nFor bug reporting instructions, please see:\n")); 6821117413Skan printf ("%s\n", bug_report_url); 682250599Sobrien } 682390277Sobrien 682490277Sobrien return (signal_count != 0 ? 2 682590277Sobrien : error_count > 0 ? (pass_exit_codes ? greatest_status : 1) 682690277Sobrien : 0); 682718334Speter} 682818334Speter 682918334Speter/* Find the proper compilation spec for the file name NAME, 683018334Speter whose length is LENGTH. LANGUAGE is the specified language, 683150599Sobrien or 0 if this file is to be passed to the linker. */ 683218334Speter 683318334Speterstatic struct compiler * 6834132733Skanlookup_compiler (const char *name, size_t length, const char *language) 683518334Speter{ 683618334Speter struct compiler *cp; 683718334Speter 683890277Sobrien /* If this was specified by the user to be a linker input, indicate that. */ 683950599Sobrien if (language != 0 && language[0] == '*') 684050599Sobrien return 0; 684150599Sobrien 684250599Sobrien /* Otherwise, look for the language, if one is spec'd. */ 684318334Speter if (language != 0) 684418334Speter { 684518334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 684650599Sobrien if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language)) 684750599Sobrien return cp; 684850599Sobrien 684918334Speter error ("language %s not recognized", language); 685050599Sobrien return 0; 685118334Speter } 685218334Speter 685318334Speter /* Look for a suffix. */ 685418334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 685518334Speter { 685618334Speter if (/* The suffix `-' matches only the file name `-'. */ 685718334Speter (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 685850599Sobrien || (strlen (cp->suffix) < length 685950599Sobrien /* See if the suffix matches the end of NAME. */ 686050599Sobrien && !strcmp (cp->suffix, 686150599Sobrien name + length - strlen (cp->suffix)) 686250599Sobrien )) 6863117413Skan break; 686490277Sobrien } 686550599Sobrien 686690277Sobrien#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM) 6867169704Skan /* Look again, but case-insensitively this time. */ 686890277Sobrien if (cp < compilers) 686990277Sobrien for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 687090277Sobrien { 687190277Sobrien if (/* The suffix `-' matches only the file name `-'. */ 687290277Sobrien (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 687390277Sobrien || (strlen (cp->suffix) < length 687490277Sobrien /* See if the suffix matches the end of NAME. */ 687590277Sobrien && ((!strcmp (cp->suffix, 687690277Sobrien name + length - strlen (cp->suffix)) 687790277Sobrien || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) 687890277Sobrien && !strcasecmp (cp->suffix, 687990277Sobrien name + length - strlen (cp->suffix))) 688090277Sobrien )) 688190277Sobrien break; 688290277Sobrien } 688390277Sobrien#endif 688450599Sobrien 688590277Sobrien if (cp >= compilers) 688690277Sobrien { 688790277Sobrien if (cp->spec[0] != '@') 688890277Sobrien /* A non-alias entry: return it. */ 688990277Sobrien return cp; 689090277Sobrien 689190277Sobrien /* An alias entry maps a suffix to a language. 689290277Sobrien Search for the language; pass 0 for NAME and LENGTH 689390277Sobrien to avoid infinite recursion if language not found. */ 689490277Sobrien return lookup_compiler (NULL, 0, cp->spec + 1); 689518334Speter } 689618334Speter return 0; 689718334Speter} 689818334Speter 689918334Speterstatic char * 6900132733Skansave_string (const char *s, int len) 690118334Speter{ 6902169704Skan char *result = XNEWVEC (char, len + 1); 690318334Speter 690490277Sobrien memcpy (result, s, len); 690518334Speter result[len] = 0; 690618334Speter return result; 690718334Speter} 690818334Speter 690990277Sobrienvoid 6910132733Skanpfatal_with_name (const char *name) 691118334Speter{ 691252520Sobrien perror_with_name (name); 691352520Sobrien delete_temp_files (); 691452520Sobrien exit (1); 691518334Speter} 691618334Speter 691718334Speterstatic void 6918132733Skanperror_with_name (const char *name) 691918334Speter{ 692052520Sobrien error ("%s: %s", name, xstrerror (errno)); 692118334Speter} 692218334Speter 6923132733Skan/* Output an error message and exit. */ 692418334Speter 692518334Spetervoid 6926169704Skanfancy_abort (const char *file, int line, const char *func) 692718334Speter{ 6928169704Skan fatal_ice ("internal gcc abort in %s, at %s:%d", func, file, line); 692918334Speter} 693018334Speter 6931132733Skan/* Output an error message and exit. */ 693218334Speter 693352520Sobrienvoid 6934169704Skanfatal_ice (const char *cmsgid, ...) 693518334Speter{ 6936132733Skan va_list ap; 693718334Speter 6938169704Skan va_start (ap, cmsgid); 6939132733Skan 694018334Speter fprintf (stderr, "%s: ", programname); 6941169704Skan vfprintf (stderr, _(cmsgid), ap); 6942132733Skan va_end (ap); 694318334Speter fprintf (stderr, "\n"); 694418334Speter delete_temp_files (); 6945169704Skan exit (pass_exit_codes ? ICE_EXIT_CODE : 1); 6946169704Skan} 6947169704Skan 6948169704Skanvoid 6949169704Skanfatal (const char *cmsgid, ...) 6950169704Skan{ 6951169704Skan va_list ap; 6952169704Skan 6953169704Skan va_start (ap, cmsgid); 6954169704Skan 6955169704Skan fprintf (stderr, "%s: ", programname); 6956169704Skan vfprintf (stderr, _(cmsgid), ap); 6957169704Skan va_end (ap); 6958169704Skan fprintf (stderr, "\n"); 6959169704Skan delete_temp_files (); 696018334Speter exit (1); 696118334Speter} 696218334Speter 6963169704Skan/* The argument is actually c-format, not gcc-internal-format, 6964169704Skan but because functions with identical names are used through 6965169704Skan the rest of the compiler with gcc-internal-format, we just 6966169704Skan need to hope all users of these functions use the common 6967169704Skan subset between c-format and gcc-internal-format. */ 6968169704Skan 696990277Sobrienvoid 6970169704Skanerror (const char *gmsgid, ...) 697118334Speter{ 6972132733Skan va_list ap; 697318334Speter 6974169704Skan va_start (ap, gmsgid); 697518334Speter fprintf (stderr, "%s: ", programname); 6976169704Skan vfprintf (stderr, _(gmsgid), ap); 6977132733Skan va_end (ap); 697818334Speter 697918334Speter fprintf (stderr, "\n"); 698018334Speter} 698152520Sobrien 698252520Sobrienstatic void 6983169704Skannotice (const char *cmsgid, ...) 698452520Sobrien{ 6985132733Skan va_list ap; 698652520Sobrien 6987169704Skan va_start (ap, cmsgid); 6988169704Skan vfprintf (stderr, _(cmsgid), ap); 6989132733Skan va_end (ap); 699052520Sobrien} 699118334Speter 6992132733Skanstatic inline void 6993132733Skanvalidate_switches_from_spec (const char *spec) 6994132733Skan{ 6995132733Skan const char *p = spec; 6996132733Skan char c; 6997132733Skan while ((c = *p++)) 6998132733Skan if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{'))) 6999132733Skan /* We have a switch spec. */ 7000132733Skan p = validate_switches (p + 1); 7001132733Skan} 7002132733Skan 700318334Speterstatic void 7004132733Skanvalidate_all_switches (void) 700518334Speter{ 700618334Speter struct compiler *comp; 700718334Speter struct spec_list *spec; 700818334Speter 700990277Sobrien for (comp = compilers; comp->spec; comp++) 7010132733Skan validate_switches_from_spec (comp->spec); 701118334Speter 701290277Sobrien /* Look through the linked list of specs read from the specs file. */ 701390277Sobrien for (spec = specs; spec; spec = spec->next) 7014132733Skan validate_switches_from_spec (*spec->ptr_spec); 701518334Speter 7016132733Skan validate_switches_from_spec (link_command_spec); 701718334Speter} 701818334Speter 701918334Speter/* Look at the switch-name that comes after START 702018334Speter and mark as valid all supplied switches that match it. */ 702118334Speter 7022132733Skanstatic const char * 7023132733Skanvalidate_switches (const char *start) 702418334Speter{ 702590277Sobrien const char *p = start; 7026132733Skan const char *atom; 7027132733Skan size_t len; 702890277Sobrien int i; 7029132733Skan bool suffix = false; 7030132733Skan bool starred = false; 703118334Speter 7032132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0) 703318334Speter 703490277Sobriennext_member: 7035132733Skan SKIP_WHITE (); 7036132733Skan 703718334Speter if (*p == '!') 7038132733Skan p++; 703918334Speter 7040132733Skan SKIP_WHITE (); 704118334Speter if (*p == '.') 7042132733Skan suffix = true, p++; 704318334Speter 7044132733Skan atom = p; 7045132733Skan while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '=' 7046132733Skan || *p == ',' || *p == '.' || *p == '@') 704790277Sobrien p++; 7048132733Skan len = p - atom; 704918334Speter 7050132733Skan if (*p == '*') 7051132733Skan starred = true, p++; 7052132733Skan 7053132733Skan SKIP_WHITE (); 7054132733Skan 7055132733Skan if (!suffix) 705618334Speter { 705718334Speter /* Mark all matching switches as valid. */ 705818334Speter for (i = 0; i < n_switches; i++) 7059132733Skan if (!strncmp (switches[i].part1, atom, len) 7060132733Skan && (starred || switches[i].part1[len] == 0)) 706152520Sobrien switches[i].validated = 1; 706218334Speter } 7063132733Skan 7064132733Skan if (*p) p++; 7065132733Skan if (*p && (p[-1] == '|' || p[-1] == '&')) 7066132733Skan goto next_member; 7067132733Skan 7068132733Skan if (*p && p[-1] == ':') 706918334Speter { 7070132733Skan while (*p && *p != ';' && *p != '}') 707118334Speter { 7072132733Skan if (*p == '%') 7073132733Skan { 7074132733Skan p++; 7075132733Skan if (*p == '{' || *p == '<') 7076132733Skan p = validate_switches (p+1); 7077132733Skan else if (p[0] == 'W' && p[1] == '{') 7078132733Skan p = validate_switches (p+2); 7079132733Skan } 7080132733Skan else 7081132733Skan p++; 708218334Speter } 7083132733Skan 7084132733Skan if (*p) p++; 7085132733Skan if (*p && p[-1] == ';') 7086132733Skan goto next_member; 708718334Speter } 708890277Sobrien 7089132733Skan return p; 7090132733Skan#undef SKIP_WHITE 709118334Speter} 709218334Speter 7093104763Skanstruct mdswitchstr 7094104763Skan{ 7095104763Skan const char *str; 7096104763Skan int len; 7097104763Skan}; 7098104763Skan 7099104763Skanstatic struct mdswitchstr *mdswitches; 7100104763Skanstatic int n_mdswitches; 7101104763Skan 710250599Sobrien/* Check whether a particular argument was used. The first time we 710350599Sobrien canonicalize the switches to keep only the ones we care about. */ 710418334Speter 710518334Speterstatic int 7106132733Skanused_arg (const char *p, int len) 710718334Speter{ 710890277Sobrien struct mswitchstr 710990277Sobrien { 711090277Sobrien const char *str; 711190277Sobrien const char *replace; 711250599Sobrien int len; 711350599Sobrien int rep_len; 711450599Sobrien }; 711518334Speter 711650599Sobrien static struct mswitchstr *mswitches; 711750599Sobrien static int n_mswitches; 711850599Sobrien int i, j; 711950599Sobrien 712050599Sobrien if (!mswitches) 712150599Sobrien { 712250599Sobrien struct mswitchstr *matches; 712390277Sobrien const char *q; 712450599Sobrien int cnt = 0; 712550599Sobrien 712690277Sobrien /* Break multilib_matches into the component strings of string 712790277Sobrien and replacement string. */ 712850599Sobrien for (q = multilib_matches; *q != '\0'; q++) 712950599Sobrien if (*q == ';') 713050599Sobrien cnt++; 713150599Sobrien 7132132733Skan matches = alloca ((sizeof (struct mswitchstr)) * cnt); 713350599Sobrien i = 0; 713450599Sobrien q = multilib_matches; 713550599Sobrien while (*q != '\0') 713650599Sobrien { 713750599Sobrien matches[i].str = q; 713850599Sobrien while (*q != ' ') 713950599Sobrien { 714050599Sobrien if (*q == '\0') 7141169704Skan { 7142169704Skan invalid_matches: 7143169704Skan fatal ("multilib spec '%s' is invalid", multilib_matches); 7144169704Skan } 714550599Sobrien q++; 714650599Sobrien } 714750599Sobrien matches[i].len = q - matches[i].str; 714850599Sobrien 714950599Sobrien matches[i].replace = ++q; 715050599Sobrien while (*q != ';' && *q != '\0') 715150599Sobrien { 715250599Sobrien if (*q == ' ') 7153169704Skan goto invalid_matches; 715450599Sobrien q++; 715550599Sobrien } 715650599Sobrien matches[i].rep_len = q - matches[i].replace; 715750599Sobrien i++; 715850599Sobrien if (*q == ';') 715990277Sobrien q++; 716050599Sobrien } 716150599Sobrien 716250599Sobrien /* Now build a list of the replacement string for switches that we care 716350599Sobrien about. Make sure we allocate at least one entry. This prevents 716450599Sobrien xmalloc from calling fatal, and prevents us from re-executing this 716550599Sobrien block of code. */ 716650599Sobrien mswitches 7167169704Skan = XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1)); 716850599Sobrien for (i = 0; i < n_switches; i++) 7169169704Skan if (switches[i].live_cond != SWITCH_IGNORE) 7170169704Skan { 7171169704Skan int xlen = strlen (switches[i].part1); 7172169704Skan for (j = 0; j < cnt; j++) 7173169704Skan if (xlen == matches[j].len 7174169704Skan && ! strncmp (switches[i].part1, matches[j].str, xlen)) 7175169704Skan { 7176169704Skan mswitches[n_mswitches].str = matches[j].replace; 7177169704Skan mswitches[n_mswitches].len = matches[j].rep_len; 7178169704Skan mswitches[n_mswitches].replace = (char *) 0; 7179169704Skan mswitches[n_mswitches].rep_len = 0; 7180169704Skan n_mswitches++; 7181169704Skan break; 7182169704Skan } 7183169704Skan } 7184104763Skan 7185104763Skan /* Add MULTILIB_DEFAULTS switches too, as long as they were not present 7186104763Skan on the command line nor any options mutually incompatible with 7187104763Skan them. */ 7188104763Skan for (i = 0; i < n_mdswitches; i++) 7189104763Skan { 7190104763Skan const char *r; 7191104763Skan 7192104763Skan for (q = multilib_options; *q != '\0'; q++) 7193104763Skan { 7194104763Skan while (*q == ' ') 7195104763Skan q++; 7196104763Skan 7197104763Skan r = q; 7198104763Skan while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0 7199104763Skan || strchr (" /", q[mdswitches[i].len]) == NULL) 7200104763Skan { 7201104763Skan while (*q != ' ' && *q != '/' && *q != '\0') 7202104763Skan q++; 7203104763Skan if (*q != '/') 7204104763Skan break; 7205104763Skan q++; 7206104763Skan } 7207104763Skan 7208104763Skan if (*q != ' ' && *q != '\0') 7209104763Skan { 7210104763Skan while (*r != ' ' && *r != '\0') 7211104763Skan { 7212104763Skan q = r; 7213104763Skan while (*q != ' ' && *q != '/' && *q != '\0') 7214104763Skan q++; 7215104763Skan 7216104763Skan if (used_arg (r, q - r)) 7217104763Skan break; 7218104763Skan 7219104763Skan if (*q != '/') 7220104763Skan { 7221104763Skan mswitches[n_mswitches].str = mdswitches[i].str; 7222104763Skan mswitches[n_mswitches].len = mdswitches[i].len; 7223104763Skan mswitches[n_mswitches].replace = (char *) 0; 7224104763Skan mswitches[n_mswitches].rep_len = 0; 7225104763Skan n_mswitches++; 7226104763Skan break; 7227104763Skan } 7228104763Skan 7229104763Skan r = q + 1; 7230104763Skan } 7231104763Skan break; 7232104763Skan } 7233104763Skan } 7234104763Skan } 723550599Sobrien } 723650599Sobrien 723750599Sobrien for (i = 0; i < n_mswitches; i++) 723850599Sobrien if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len)) 723918334Speter return 1; 724050599Sobrien 724118334Speter return 0; 724218334Speter} 724318334Speter 724418334Speterstatic int 7245132733Skandefault_arg (const char *p, int len) 724618334Speter{ 7247104763Skan int i; 724818334Speter 7249104763Skan for (i = 0; i < n_mdswitches; i++) 7250104763Skan if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len)) 7251104763Skan return 1; 725218334Speter 725318334Speter return 0; 725418334Speter} 725518334Speter 725690277Sobrien/* Work out the subdirectory to use based on the options. The format of 725790277Sobrien multilib_select is a list of elements. Each element is a subdirectory 725890277Sobrien name followed by a list of options followed by a semicolon. The format 725990277Sobrien of multilib_exclusions is the same, but without the preceding 726090277Sobrien directory. First gcc will check the exclusions, if none of the options 726190277Sobrien beginning with an exclamation point are present, and all of the other 726290277Sobrien options are present, then we will ignore this completely. Passing 726390277Sobrien that, gcc will consider each multilib_select in turn using the same 726490277Sobrien rules for matching the options. If a match is found, that subdirectory 726590277Sobrien will be used. */ 726618334Speter 726718334Speterstatic void 7268132733Skanset_multilib_dir (void) 726918334Speter{ 727090277Sobrien const char *p; 727190277Sobrien unsigned int this_path_len; 727290277Sobrien const char *this_path, *this_arg; 7273104763Skan const char *start, *end; 727418334Speter int not_arg; 7275104763Skan int ok, ndfltok, first; 727618334Speter 7277104763Skan n_mdswitches = 0; 7278104763Skan start = multilib_defaults; 7279104763Skan while (*start == ' ' || *start == '\t') 7280104763Skan start++; 7281104763Skan while (*start != '\0') 7282104763Skan { 7283104763Skan n_mdswitches++; 7284104763Skan while (*start != ' ' && *start != '\t' && *start != '\0') 7285104763Skan start++; 7286104763Skan while (*start == ' ' || *start == '\t') 7287104763Skan start++; 7288104763Skan } 7289104763Skan 7290104763Skan if (n_mdswitches) 7291104763Skan { 7292104763Skan int i = 0; 7293104763Skan 7294169704Skan mdswitches = XNEWVEC (struct mdswitchstr, n_mdswitches); 7295104763Skan for (start = multilib_defaults; *start != '\0'; start = end + 1) 7296104763Skan { 7297104763Skan while (*start == ' ' || *start == '\t') 7298104763Skan start++; 7299104763Skan 7300104763Skan if (*start == '\0') 7301104763Skan break; 7302132733Skan 7303104763Skan for (end = start + 1; 7304104763Skan *end != ' ' && *end != '\t' && *end != '\0'; end++) 7305104763Skan ; 7306104763Skan 7307104763Skan obstack_grow (&multilib_obstack, start, end - start); 7308104763Skan obstack_1grow (&multilib_obstack, 0); 7309169704Skan mdswitches[i].str = XOBFINISH (&multilib_obstack, const char *); 7310104763Skan mdswitches[i++].len = end - start; 7311104763Skan 7312104763Skan if (*end == '\0') 7313104763Skan break; 7314104763Skan } 7315104763Skan } 7316104763Skan 731790277Sobrien p = multilib_exclusions; 731818334Speter while (*p != '\0') 731918334Speter { 732018334Speter /* Ignore newlines. */ 732118334Speter if (*p == '\n') 732218334Speter { 732318334Speter ++p; 732418334Speter continue; 732518334Speter } 732618334Speter 732790277Sobrien /* Check the arguments. */ 732890277Sobrien ok = 1; 732990277Sobrien while (*p != ';') 733090277Sobrien { 733190277Sobrien if (*p == '\0') 7332169704Skan { 7333169704Skan invalid_exclusions: 7334169704Skan fatal ("multilib exclusions '%s' is invalid", 7335169704Skan multilib_exclusions); 7336169704Skan } 733790277Sobrien 733890277Sobrien if (! ok) 733990277Sobrien { 734090277Sobrien ++p; 734190277Sobrien continue; 734290277Sobrien } 734390277Sobrien 734490277Sobrien this_arg = p; 734590277Sobrien while (*p != ' ' && *p != ';') 734690277Sobrien { 734790277Sobrien if (*p == '\0') 7348169704Skan goto invalid_exclusions; 734990277Sobrien ++p; 735090277Sobrien } 735190277Sobrien 735290277Sobrien if (*this_arg != '!') 735390277Sobrien not_arg = 0; 735490277Sobrien else 735590277Sobrien { 735690277Sobrien not_arg = 1; 735790277Sobrien ++this_arg; 735890277Sobrien } 735990277Sobrien 736090277Sobrien ok = used_arg (this_arg, p - this_arg); 736190277Sobrien if (not_arg) 736290277Sobrien ok = ! ok; 736390277Sobrien 736490277Sobrien if (*p == ' ') 736590277Sobrien ++p; 736690277Sobrien } 736790277Sobrien 736890277Sobrien if (ok) 736990277Sobrien return; 737090277Sobrien 737190277Sobrien ++p; 737290277Sobrien } 737390277Sobrien 7374104763Skan first = 1; 737590277Sobrien p = multilib_select; 737690277Sobrien while (*p != '\0') 737790277Sobrien { 737890277Sobrien /* Ignore newlines. */ 737990277Sobrien if (*p == '\n') 738090277Sobrien { 738190277Sobrien ++p; 738290277Sobrien continue; 738390277Sobrien } 738490277Sobrien 738518334Speter /* Get the initial path. */ 738618334Speter this_path = p; 738718334Speter while (*p != ' ') 738818334Speter { 738918334Speter if (*p == '\0') 7390169704Skan { 7391169704Skan invalid_select: 7392169704Skan fatal ("multilib select '%s' is invalid", 7393169704Skan multilib_select); 7394169704Skan } 739518334Speter ++p; 739618334Speter } 739718334Speter this_path_len = p - this_path; 739818334Speter 739918334Speter /* Check the arguments. */ 740018334Speter ok = 1; 7401104763Skan ndfltok = 1; 740218334Speter ++p; 740318334Speter while (*p != ';') 740418334Speter { 740518334Speter if (*p == '\0') 7406169704Skan goto invalid_select; 740718334Speter 740818334Speter if (! ok) 740918334Speter { 741018334Speter ++p; 741118334Speter continue; 741218334Speter } 741318334Speter 741418334Speter this_arg = p; 741518334Speter while (*p != ' ' && *p != ';') 741618334Speter { 741718334Speter if (*p == '\0') 7418169704Skan goto invalid_select; 741918334Speter ++p; 742018334Speter } 742118334Speter 742218334Speter if (*this_arg != '!') 742318334Speter not_arg = 0; 742418334Speter else 742518334Speter { 742618334Speter not_arg = 1; 742718334Speter ++this_arg; 742818334Speter } 742918334Speter 743018334Speter /* If this is a default argument, we can just ignore it. 743118334Speter This is true even if this_arg begins with '!'. Beginning 743218334Speter with '!' does not mean that this argument is necessarily 743318334Speter inappropriate for this library: it merely means that 743418334Speter there is a more specific library which uses this 743518334Speter argument. If this argument is a default, we need not 743618334Speter consider that more specific library. */ 7437104763Skan ok = used_arg (this_arg, p - this_arg); 7438104763Skan if (not_arg) 7439104763Skan ok = ! ok; 744018334Speter 7441104763Skan if (! ok) 7442104763Skan ndfltok = 0; 7443104763Skan 7444104763Skan if (default_arg (this_arg, p - this_arg)) 7445104763Skan ok = 1; 7446104763Skan 744718334Speter if (*p == ' ') 744818334Speter ++p; 744918334Speter } 745018334Speter 7451104763Skan if (ok && first) 745218334Speter { 745318334Speter if (this_path_len != 1 745418334Speter || this_path[0] != '.') 745518334Speter { 7456169704Skan char *new_multilib_dir = XNEWVEC (char, this_path_len + 1); 7457104763Skan char *q; 7458104763Skan 745952520Sobrien strncpy (new_multilib_dir, this_path, this_path_len); 746052520Sobrien new_multilib_dir[this_path_len] = '\0'; 7461104763Skan q = strchr (new_multilib_dir, ':'); 7462104763Skan if (q != NULL) 7463104763Skan *q = '\0'; 746452520Sobrien multilib_dir = new_multilib_dir; 746518334Speter } 7466104763Skan first = 0; 746718334Speter } 746818334Speter 7469104763Skan if (ndfltok) 7470104763Skan { 7471104763Skan const char *q = this_path, *end = this_path + this_path_len; 7472104763Skan 7473104763Skan while (q < end && *q != ':') 7474104763Skan q++; 7475104763Skan if (q < end) 7476104763Skan { 7477169704Skan char *new_multilib_os_dir = XNEWVEC (char, end - q); 7478104763Skan memcpy (new_multilib_os_dir, q + 1, end - q - 1); 7479104763Skan new_multilib_os_dir[end - q - 1] = '\0'; 7480104763Skan multilib_os_dir = new_multilib_os_dir; 7481104763Skan break; 7482104763Skan } 7483104763Skan } 7484104763Skan 748518334Speter ++p; 748690277Sobrien } 7487104763Skan 7488104763Skan if (multilib_dir == NULL && multilib_os_dir != NULL 7489104763Skan && strcmp (multilib_os_dir, ".") == 0) 7490104763Skan { 7491104763Skan free ((char *) multilib_os_dir); 7492104763Skan multilib_os_dir = NULL; 7493104763Skan } 7494104763Skan else if (multilib_dir != NULL && multilib_os_dir == NULL) 7495104763Skan multilib_os_dir = multilib_dir; 749618334Speter} 749718334Speter 749818334Speter/* Print out the multiple library subdirectory selection 749918334Speter information. This prints out a series of lines. Each line looks 750018334Speter like SUBDIRECTORY;@OPTION@OPTION, with as many options as is 750118334Speter required. Only the desired options are printed out, the negative 750218334Speter matches. The options are print without a leading dash. There are 750318334Speter no spaces to make it easy to use the information in the shell. 750418334Speter Each subdirectory is printed only once. This assumes the ordering 750590277Sobrien generated by the genmultilib script. Also, we leave out ones that match 750690277Sobrien the exclusions. */ 750718334Speter 750818334Speterstatic void 7509132733Skanprint_multilib_info (void) 751018334Speter{ 751190277Sobrien const char *p = multilib_select; 751290277Sobrien const char *last_path = 0, *this_path; 751318334Speter int skip; 751490277Sobrien unsigned int last_path_len = 0; 751518334Speter 751618334Speter while (*p != '\0') 751718334Speter { 751890277Sobrien skip = 0; 751918334Speter /* Ignore newlines. */ 752018334Speter if (*p == '\n') 752118334Speter { 752218334Speter ++p; 752318334Speter continue; 752418334Speter } 752518334Speter 752618334Speter /* Get the initial path. */ 752718334Speter this_path = p; 752818334Speter while (*p != ' ') 752918334Speter { 753018334Speter if (*p == '\0') 7531169704Skan { 7532169704Skan invalid_select: 7533169704Skan fatal ("multilib select '%s' is invalid", multilib_select); 7534169704Skan } 7535169704Skan 753618334Speter ++p; 753718334Speter } 753818334Speter 7539104763Skan /* When --disable-multilib was used but target defines 7540104763Skan MULTILIB_OSDIRNAMES, entries starting with .: are there just 7541104763Skan to find multilib_os_dir, so skip them from output. */ 7542104763Skan if (this_path[0] == '.' && this_path[1] == ':') 7543104763Skan skip = 1; 7544104763Skan 754590277Sobrien /* Check for matches with the multilib_exclusions. We don't bother 754690277Sobrien with the '!' in either list. If any of the exclusion rules match 754790277Sobrien all of its options with the select rule, we skip it. */ 754890277Sobrien { 754990277Sobrien const char *e = multilib_exclusions; 755090277Sobrien const char *this_arg; 755118334Speter 755290277Sobrien while (*e != '\0') 755390277Sobrien { 755490277Sobrien int m = 1; 755590277Sobrien /* Ignore newlines. */ 755690277Sobrien if (*e == '\n') 755790277Sobrien { 755890277Sobrien ++e; 755990277Sobrien continue; 756090277Sobrien } 756118334Speter 756290277Sobrien /* Check the arguments. */ 756390277Sobrien while (*e != ';') 756490277Sobrien { 756590277Sobrien const char *q; 756690277Sobrien int mp = 0; 756790277Sobrien 756890277Sobrien if (*e == '\0') 7569169704Skan { 7570169704Skan invalid_exclusion: 7571169704Skan fatal ("multilib exclusion '%s' is invalid", 7572169704Skan multilib_exclusions); 7573169704Skan } 757490277Sobrien 757590277Sobrien if (! m) 757690277Sobrien { 757790277Sobrien ++e; 757890277Sobrien continue; 757990277Sobrien } 758090277Sobrien 758190277Sobrien this_arg = e; 758290277Sobrien 758390277Sobrien while (*e != ' ' && *e != ';') 758490277Sobrien { 758590277Sobrien if (*e == '\0') 7586169704Skan goto invalid_exclusion; 758790277Sobrien ++e; 758890277Sobrien } 758990277Sobrien 759090277Sobrien q = p + 1; 759190277Sobrien while (*q != ';') 759290277Sobrien { 759390277Sobrien const char *arg; 759490277Sobrien int len = e - this_arg; 759590277Sobrien 759690277Sobrien if (*q == '\0') 7597169704Skan goto invalid_select; 759890277Sobrien 759990277Sobrien arg = q; 760090277Sobrien 760190277Sobrien while (*q != ' ' && *q != ';') 760290277Sobrien { 760390277Sobrien if (*q == '\0') 7604169704Skan goto invalid_select; 760590277Sobrien ++q; 760690277Sobrien } 760790277Sobrien 7608169704Skan if (! strncmp (arg, this_arg, 7609169704Skan (len < q - arg) ? q - arg : len) 7610169704Skan || default_arg (this_arg, e - this_arg)) 761190277Sobrien { 761290277Sobrien mp = 1; 761390277Sobrien break; 761490277Sobrien } 761590277Sobrien 761690277Sobrien if (*q == ' ') 761790277Sobrien ++q; 761890277Sobrien } 761990277Sobrien 762090277Sobrien if (! mp) 762190277Sobrien m = 0; 762290277Sobrien 762390277Sobrien if (*e == ' ') 762490277Sobrien ++e; 762590277Sobrien } 762690277Sobrien 762790277Sobrien if (m) 762890277Sobrien { 762990277Sobrien skip = 1; 763090277Sobrien break; 763190277Sobrien } 763290277Sobrien 763390277Sobrien if (*e != '\0') 763490277Sobrien ++e; 763590277Sobrien } 763690277Sobrien } 763790277Sobrien 763890277Sobrien if (! skip) 763990277Sobrien { 764090277Sobrien /* If this is a duplicate, skip it. */ 7641169704Skan skip = (last_path != 0 7642169704Skan && (unsigned int) (p - this_path) == last_path_len 764390277Sobrien && ! strncmp (last_path, this_path, last_path_len)); 764490277Sobrien 764590277Sobrien last_path = this_path; 764690277Sobrien last_path_len = p - this_path; 764790277Sobrien } 764890277Sobrien 764918334Speter /* If this directory requires any default arguments, we can skip 765018334Speter it. We will already have printed a directory identical to 765118334Speter this one which does not require that default argument. */ 765218334Speter if (! skip) 765318334Speter { 765490277Sobrien const char *q; 765518334Speter 765618334Speter q = p + 1; 765718334Speter while (*q != ';') 765818334Speter { 765990277Sobrien const char *arg; 766018334Speter 766118334Speter if (*q == '\0') 7662169704Skan goto invalid_select; 766318334Speter 766418334Speter if (*q == '!') 766518334Speter arg = NULL; 766618334Speter else 766718334Speter arg = q; 766818334Speter 766918334Speter while (*q != ' ' && *q != ';') 767018334Speter { 767118334Speter if (*q == '\0') 7672169704Skan goto invalid_select; 767318334Speter ++q; 767418334Speter } 767518334Speter 767618334Speter if (arg != NULL 767718334Speter && default_arg (arg, q - arg)) 767818334Speter { 767918334Speter skip = 1; 768018334Speter break; 768118334Speter } 768218334Speter 768318334Speter if (*q == ' ') 768418334Speter ++q; 768518334Speter } 768618334Speter } 768718334Speter 768818334Speter if (! skip) 768918334Speter { 769090277Sobrien const char *p1; 769118334Speter 7692104763Skan for (p1 = last_path; p1 < p && *p1 != ':'; p1++) 769318334Speter putchar (*p1); 769418334Speter putchar (';'); 769518334Speter } 769618334Speter 769718334Speter ++p; 769818334Speter while (*p != ';') 769918334Speter { 770018334Speter int use_arg; 770118334Speter 770218334Speter if (*p == '\0') 7703169704Skan goto invalid_select; 770418334Speter 770518334Speter if (skip) 770618334Speter { 770718334Speter ++p; 770818334Speter continue; 770918334Speter } 771018334Speter 771118334Speter use_arg = *p != '!'; 771218334Speter 771318334Speter if (use_arg) 771418334Speter putchar ('@'); 771518334Speter 771618334Speter while (*p != ' ' && *p != ';') 771718334Speter { 771818334Speter if (*p == '\0') 7719169704Skan goto invalid_select; 772018334Speter if (use_arg) 772118334Speter putchar (*p); 772218334Speter ++p; 772318334Speter } 772418334Speter 772518334Speter if (*p == ' ') 772618334Speter ++p; 772718334Speter } 772818334Speter 772918334Speter if (! skip) 773050599Sobrien { 773190277Sobrien /* If there are extra options, print them now. */ 773250599Sobrien if (multilib_extra && *multilib_extra) 773350599Sobrien { 773450599Sobrien int print_at = TRUE; 773590277Sobrien const char *q; 773618334Speter 773750599Sobrien for (q = multilib_extra; *q != '\0'; q++) 773850599Sobrien { 773950599Sobrien if (*q == ' ') 774050599Sobrien print_at = TRUE; 774150599Sobrien else 774250599Sobrien { 774350599Sobrien if (print_at) 774450599Sobrien putchar ('@'); 774550599Sobrien putchar (*q); 774650599Sobrien print_at = FALSE; 774750599Sobrien } 774850599Sobrien } 774950599Sobrien } 775090277Sobrien 775150599Sobrien putchar ('\n'); 775250599Sobrien } 775350599Sobrien 775418334Speter ++p; 775518334Speter } 775618334Speter} 7757117413Skan 7758117413Skan/* if-exists built-in spec function. 7759117413Skan 7760117413Skan Checks to see if the file specified by the absolute pathname in 7761117413Skan ARGS exists. Returns that pathname if found. 7762117413Skan 7763117413Skan The usual use for this function is to check for a library file 7764117413Skan (whose name has been expanded with %s). */ 7765117413Skan 7766117413Skanstatic const char * 7767132733Skanif_exists_spec_function (int argc, const char **argv) 7768117413Skan{ 7769117413Skan /* Must have only one argument. */ 7770132733Skan if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK)) 7771117413Skan return argv[0]; 7772117413Skan 7773117413Skan return NULL; 7774117413Skan} 7775117413Skan 7776117413Skan/* if-exists-else built-in spec function. 7777117413Skan 7778117413Skan This is like if-exists, but takes an additional argument which 7779117413Skan is returned if the first argument does not exist. */ 7780117413Skan 7781117413Skanstatic const char * 7782132733Skanif_exists_else_spec_function (int argc, const char **argv) 7783117413Skan{ 7784117413Skan /* Must have exactly two arguments. */ 7785117413Skan if (argc != 2) 7786117413Skan return NULL; 7787117413Skan 7788132733Skan if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK)) 7789117413Skan return argv[0]; 7790117413Skan 7791117413Skan return argv[1]; 7792117413Skan} 7793169704Skan 7794169704Skan/* replace-outfile built-in spec function. 7795169704Skan 7796169704Skan This looks for the first argument in the outfiles array's name and 7797169704Skan replaces it with the second argument. */ 7798169704Skan 7799169704Skanstatic const char * 7800169704Skanreplace_outfile_spec_function (int argc, const char **argv) 7801169704Skan{ 7802169704Skan int i; 7803169704Skan /* Must have exactly two arguments. */ 7804169704Skan if (argc != 2) 7805169704Skan abort (); 7806169704Skan 7807169704Skan for (i = 0; i < n_infiles; i++) 7808169704Skan { 7809169704Skan if (outfiles[i] && !strcmp (outfiles[i], argv[0])) 7810169704Skan outfiles[i] = xstrdup (argv[1]); 7811169704Skan } 7812169704Skan return NULL; 7813169704Skan} 7814169704Skan 7815169704Skan/* Given two version numbers, compares the two numbers. 7816169704Skan A version number must match the regular expression 7817169704Skan ([1-9][0-9]*|0)(\.([1-9][0-9]*|0))* 7818169704Skan*/ 7819169704Skanstatic int 7820169704Skancompare_version_strings (const char *v1, const char *v2) 7821169704Skan{ 7822169704Skan int rresult; 7823169704Skan regex_t r; 7824169704Skan 7825169704Skan if (regcomp (&r, "^([1-9][0-9]*|0)(\\.([1-9][0-9]*|0))*$", 7826169704Skan REG_EXTENDED | REG_NOSUB) != 0) 7827169704Skan abort (); 7828169704Skan rresult = regexec (&r, v1, 0, NULL, 0); 7829169704Skan if (rresult == REG_NOMATCH) 7830169704Skan fatal ("invalid version number `%s'", v1); 7831169704Skan else if (rresult != 0) 7832169704Skan abort (); 7833169704Skan rresult = regexec (&r, v2, 0, NULL, 0); 7834169704Skan if (rresult == REG_NOMATCH) 7835169704Skan fatal ("invalid version number `%s'", v2); 7836169704Skan else if (rresult != 0) 7837169704Skan abort (); 7838169704Skan 7839169704Skan return strverscmp (v1, v2); 7840169704Skan} 7841169704Skan 7842169704Skan 7843169704Skan/* version_compare built-in spec function. 7844169704Skan 7845169704Skan This takes an argument of the following form: 7846169704Skan 7847169704Skan <comparison-op> <arg1> [<arg2>] <switch> <result> 7848169704Skan 7849169704Skan and produces "result" if the comparison evaluates to true, 7850169704Skan and nothing if it doesn't. 7851169704Skan 7852169704Skan The supported <comparison-op> values are: 7853169704Skan 7854169704Skan >= true if switch is a later (or same) version than arg1 7855169704Skan !> opposite of >= 7856169704Skan < true if switch is an earlier version than arg1 7857169704Skan !< opposite of < 7858169704Skan >< true if switch is arg1 or later, and earlier than arg2 7859169704Skan <> true if switch is earlier than arg1 or is arg2 or later 7860169704Skan 7861169704Skan If the switch is not present, the condition is false unless 7862169704Skan the first character of the <comparison-op> is '!'. 7863169704Skan 7864169704Skan For example, 7865169704Skan %:version-compare(>= 10.3 mmacosx-version-min= -lmx) 7866169704Skan adds -lmx if -mmacosx-version-min=10.3.9 was passed. */ 7867169704Skan 7868169704Skanstatic const char * 7869169704Skanversion_compare_spec_function (int argc, const char **argv) 7870169704Skan{ 7871169704Skan int comp1, comp2; 7872169704Skan size_t switch_len; 7873169704Skan const char *switch_value = NULL; 7874169704Skan int nargs = 1, i; 7875169704Skan bool result; 7876169704Skan 7877169704Skan if (argc < 3) 7878169704Skan fatal ("too few arguments to %%:version-compare"); 7879169704Skan if (argv[0][0] == '\0') 7880169704Skan abort (); 7881169704Skan if ((argv[0][1] == '<' || argv[0][1] == '>') && argv[0][0] != '!') 7882169704Skan nargs = 2; 7883169704Skan if (argc != nargs + 3) 7884169704Skan fatal ("too many arguments to %%:version-compare"); 7885169704Skan 7886169704Skan switch_len = strlen (argv[nargs + 1]); 7887169704Skan for (i = 0; i < n_switches; i++) 7888169704Skan if (!strncmp (switches[i].part1, argv[nargs + 1], switch_len) 7889169704Skan && check_live_switch (i, switch_len)) 7890169704Skan switch_value = switches[i].part1 + switch_len; 7891169704Skan 7892169704Skan if (switch_value == NULL) 7893169704Skan comp1 = comp2 = -1; 7894169704Skan else 7895169704Skan { 7896169704Skan comp1 = compare_version_strings (switch_value, argv[1]); 7897169704Skan if (nargs == 2) 7898169704Skan comp2 = compare_version_strings (switch_value, argv[2]); 7899169704Skan else 7900169704Skan comp2 = -1; /* This value unused. */ 7901169704Skan } 7902169704Skan 7903169704Skan switch (argv[0][0] << 8 | argv[0][1]) 7904169704Skan { 7905169704Skan case '>' << 8 | '=': 7906169704Skan result = comp1 >= 0; 7907169704Skan break; 7908169704Skan case '!' << 8 | '<': 7909169704Skan result = comp1 >= 0 || switch_value == NULL; 7910169704Skan break; 7911169704Skan case '<' << 8: 7912169704Skan result = comp1 < 0; 7913169704Skan break; 7914169704Skan case '!' << 8 | '>': 7915169704Skan result = comp1 < 0 || switch_value == NULL; 7916169704Skan break; 7917169704Skan case '>' << 8 | '<': 7918169704Skan result = comp1 >= 0 && comp2 < 0; 7919169704Skan break; 7920169704Skan case '<' << 8 | '>': 7921169704Skan result = comp1 < 0 || comp2 >= 0; 7922169704Skan break; 7923169704Skan 7924169704Skan default: 7925169704Skan fatal ("unknown operator '%s' in %%:version-compare", argv[0]); 7926169704Skan } 7927169704Skan if (! result) 7928169704Skan return NULL; 7929169704Skan 7930169704Skan return argv[nargs + 2]; 7931169704Skan} 7932169704Skan 7933169704Skan/* %:include builtin spec function. This differs from %include in that it 7934169704Skan can be nested inside a spec, and thus be conditionalized. It takes 7935169704Skan one argument, the filename, and looks for it in the startfile path. 7936169704Skan The result is always NULL, i.e. an empty expansion. */ 7937169704Skan 7938169704Skanstatic const char * 7939169704Skaninclude_spec_function (int argc, const char **argv) 7940169704Skan{ 7941169704Skan char *file; 7942169704Skan 7943169704Skan if (argc != 1) 7944169704Skan abort (); 7945169704Skan 7946169704Skan file = find_a_file (&startfile_prefixes, argv[0], R_OK, 0); 7947169704Skan read_specs (file ? file : argv[0], FALSE); 7948169704Skan 7949169704Skan return NULL; 7950169704Skan} 7951