gcc.c revision 146908
118334Speter/* Compiler driver program that can handle many languages. 290277Sobrien Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3132733Skan 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 418334Speter 590277SobrienThis file is part of GCC. 618334Speter 790277SobrienGCC is free software; you can redistribute it and/or modify it under 890277Sobrienthe terms of the GNU General Public License as published by the Free 990277SobrienSoftware Foundation; either version 2, or (at your option) any later 1090277Sobrienversion. 1118334Speter 1290277SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1390277SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1490277SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1590277Sobrienfor more details. 1618334Speter 1718334SpeterYou should have received a copy of the GNU General Public License 1890277Sobrienalong with GCC; see the file COPYING. If not, write to the Free 1990277SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2090277Sobrien02111-1307, USA. 2118334Speter 2218334SpeterThis paragraph is here to try to keep Sun CC from dying. 2318334SpeterThe number of chars here seems crucial!!!! */ 2418334Speter 2551232Sbde/* $FreeBSD: head/contrib/gcc/gcc.c 146908 2005-06-03 04:02:20Z kan $ */ 2651232Sbde 2718334Speter/* This program is the user interface to the C compiler and possibly to 2818334Speterother compilers. It is used because compilation is a complicated procedure 2918334Speterwhich involves running several programs and passing temporary files between 3018334Speterthem, forwarding the users switches to those programs selectively, 3118334Speterand deleting the temporary files at the end. 3218334Speter 3318334SpeterCC recognizes how to compile each input file by suffixes in the file names. 3418334SpeterOnce it knows which kind of compilation to perform, the procedure for 3518334Spetercompilation is specified by a string called a "spec". */ 3690277Sobrien 3790277Sobrien/* A Short Introduction to Adding a Command-Line Option. 3890277Sobrien 3990277Sobrien Before adding a command-line option, consider if it is really 4090277Sobrien necessary. Each additional command-line option adds complexity and 4190277Sobrien is difficult to remove in subsequent versions. 4290277Sobrien 4390277Sobrien In the following, consider adding the command-line argument 4490277Sobrien `--bar'. 4590277Sobrien 4690277Sobrien 1. Each command-line option is specified in the specs file. The 4790277Sobrien notation is described below in the comment entitled "The Specs 4890277Sobrien Language". Read it. 4990277Sobrien 5090277Sobrien 2. In this file, add an entry to "option_map" equating the long 5190277Sobrien `--' argument version and any shorter, single letter version. Read 5290277Sobrien the comments in the declaration of "struct option_map" for an 5390277Sobrien explanation. Do not omit the first `-'. 5490277Sobrien 5590277Sobrien 3. Look in the "specs" file to determine which program or option 5690277Sobrien list should be given the argument, e.g., "cc1_options". Add the 5790277Sobrien appropriate syntax for the shorter option version to the 5890277Sobrien corresponding "const char *" entry in this file. Omit the first 5990277Sobrien `-' from the option. For example, use `-bar', rather than `--bar'. 6090277Sobrien 6190277Sobrien 4. If the argument takes an argument, e.g., `--baz argument1', 6290277Sobrien modify either DEFAULT_SWITCH_TAKES_ARG or 6390277Sobrien DEFAULT_WORD_SWITCH_TAKES_ARG in this file. Omit the first `-' 6490277Sobrien from `--baz'. 6590277Sobrien 6690277Sobrien 5. Document the option in this file's display_help(). If the 6790277Sobrien option is passed to a subprogram, modify its corresponding 6890277Sobrien function, e.g., cppinit.c:print_help() or toplev.c:display_help(), 6990277Sobrien instead. 7090277Sobrien 7190277Sobrien 6. Compile and test. Make sure that your new specs file is being 7290277Sobrien read. For example, use a debugger to investigate the value of 7390277Sobrien "specs_file" in main(). */ 7490277Sobrien 7550599Sobrien#include "config.h" 7650599Sobrien#include "system.h" 77132733Skan#include "coretypes.h" 78132733Skan#include "multilib.h" /* before tm.h */ 79132733Skan#include "tm.h" 8050599Sobrien#include <signal.h> 8190277Sobrien#if ! defined( SIGCHLD ) && defined( SIGCLD ) 8290277Sobrien# define SIGCHLD SIGCLD 8390277Sobrien#endif 8450599Sobrien#include "obstack.h" 8552520Sobrien#include "intl.h" 8652520Sobrien#include "prefix.h" 8790277Sobrien#include "gcc.h" 8890277Sobrien#include "flags.h" 8918334Speter 9090277Sobrien#ifdef HAVE_SYS_RESOURCE_H 9190277Sobrien#include <sys/resource.h> 9218334Speter#endif 9390277Sobrien#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE 94132733Skanextern int getrusage (int, struct rusage *); 9590277Sobrien#endif 9618334Speter 9790277Sobrien/* By default there is no special suffix for target executables. */ 9890277Sobrien/* FIXME: when autoconf is fixed, remove the host check - dj */ 9990277Sobrien#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX) 10090277Sobrien#define HAVE_TARGET_EXECUTABLE_SUFFIX 10118334Speter#endif 10218334Speter 10390277Sobrien/* By default there is no special suffix for host executables. */ 10490277Sobrien#ifdef HOST_EXECUTABLE_SUFFIX 10590277Sobrien#define HAVE_HOST_EXECUTABLE_SUFFIX 10618334Speter#else 10790277Sobrien#define HOST_EXECUTABLE_SUFFIX "" 10818334Speter#endif 10918334Speter 11090277Sobrien/* By default, the suffix for target object files is ".o". */ 11190277Sobrien#ifdef TARGET_OBJECT_SUFFIX 11290277Sobrien#define HAVE_TARGET_OBJECT_SUFFIX 11390277Sobrien#else 11490277Sobrien#define TARGET_OBJECT_SUFFIX ".o" 11518334Speter#endif 11618334Speter 11790277Sobrienstatic const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; 11852520Sobrien 11990277Sobrien/* Most every one is fine with LIBRARY_PATH. For some, it conflicts. */ 12090277Sobrien#ifndef LIBRARY_PATH_ENV 12190277Sobrien#define LIBRARY_PATH_ENV "LIBRARY_PATH" 12290277Sobrien#endif 12390277Sobrien 12450599Sobrien#ifndef HAVE_KILL 12550599Sobrien#define kill(p,s) raise(s) 12618334Speter#endif 12718334Speter 12818334Speter/* If a stage of compilation returns an exit status >= 1, 12918334Speter compilation of that file ceases. */ 13018334Speter 13118334Speter#define MIN_FATAL_STATUS 1 13218334Speter 13390277Sobrien/* Flag set by cppspec.c to 1. */ 13490277Sobrienint is_cpp_driver; 13590277Sobrien 13690277Sobrien/* Flag saying to pass the greatest exit code returned by a sub-process 13790277Sobrien to the calling program. */ 13890277Sobrienstatic int pass_exit_codes; 13990277Sobrien 14090277Sobrien/* Definition of string containing the arguments given to configure. */ 14190277Sobrien#include "configargs.h" 14290277Sobrien 14318334Speter/* Flag saying to print the directories gcc will search through looking for 14418334Speter programs, libraries, etc. */ 14518334Speter 14618334Speterstatic int print_search_dirs; 14718334Speter 14818334Speter/* Flag saying to print the full filename of this file 14918334Speter as found through our usual search mechanism. */ 15018334Speter 15152520Sobrienstatic const char *print_file_name = NULL; 15218334Speter 15350599Sobrien/* As print_file_name, but search for executable file. */ 15418334Speter 15552520Sobrienstatic const char *print_prog_name = NULL; 15618334Speter 15718334Speter/* Flag saying to print the relative path we'd use to 15818334Speter find libgcc.a given the current compiler flags. */ 15918334Speter 16018334Speterstatic int print_multi_directory; 16118334Speter 162104763Skan/* Flag saying to print the relative path we'd use to 163104763Skan find OS libraries given the current compiler flags. */ 164104763Skan 165104763Skanstatic int print_multi_os_directory; 166104763Skan 16718334Speter/* Flag saying to print the list of subdirectories and 16818334Speter compiler flags used to select them in a standard form. */ 16918334Speter 17018334Speterstatic int print_multi_lib; 17118334Speter 17250599Sobrien/* Flag saying to print the command line options understood by gcc and its 17350599Sobrien sub-processes. */ 17450599Sobrien 17550599Sobrienstatic int print_help_list; 17650599Sobrien 17718334Speter/* Flag indicating whether we should print the command and arguments */ 17818334Speter 17918334Speterstatic int verbose_flag; 18018334Speter 18190277Sobrien/* Flag indicating whether we should ONLY print the command and 18290277Sobrien arguments (like verbose_flag) without executing the command. 18390277Sobrien Displayed arguments are quoted so that the generated command 18490277Sobrien line is suitable for execution. This is intended for use in 18590277Sobrien shell scripts to capture the driver-generated command line. */ 18690277Sobrienstatic int verbose_only_flag; 18790277Sobrien 18890277Sobrien/* Flag indicating to print target specific command line options. */ 18990277Sobrien 19090277Sobrienstatic int target_help_flag; 19190277Sobrien 19290277Sobrien/* Flag indicating whether we should report subprocess execution times 19390277Sobrien (if this is supported by the system - see pexecute.c). */ 19490277Sobrien 19590277Sobrienstatic int report_times; 19690277Sobrien 197132733Skan/* Nonzero means place this string before uses of /, so that include 198132733Skan and library files can be found in an alternate location. */ 199132733Skan 200132733Skan#ifdef TARGET_SYSTEM_ROOT 201132733Skanstatic const char *target_system_root = TARGET_SYSTEM_ROOT; 202132733Skan#else 203132733Skanstatic const char *target_system_root = 0; 204132733Skan#endif 205132733Skan 206132733Skan/* Nonzero means pass the updated target_system_root to the compiler. */ 207132733Skan 208132733Skanstatic int target_system_root_changed; 209132733Skan 210132733Skan/* Nonzero means append this string to target_system_root. */ 211132733Skan 212132733Skanstatic const char *target_sysroot_suffix = 0; 213132733Skan 214132733Skan/* Nonzero means append this string to target_system_root for headers. */ 215132733Skan 216132733Skanstatic const char *target_sysroot_hdrs_suffix = 0; 217132733Skan 21818334Speter/* Nonzero means write "temp" files in source directory 21918334Speter and use the source file's name in them, and don't delete them. */ 22018334Speter 22118334Speterstatic int save_temps_flag; 22218334Speter 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 24318334Speter#ifdef CROSS_COMPILE 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 28390277Sobrien/* These structs are used to collect resource usage information for 28490277Sobrien subprocesses. */ 28590277Sobrien#ifdef HAVE_GETRUSAGE 28690277Sobrienstatic struct rusage rus, prus; 28790277Sobrien#endif 28818334Speter 28918334Speter/* Forward declaration for prototypes. */ 29018334Speterstruct path_prefix; 29118334Speter 292132733Skanstatic void init_spec (void); 293132733Skanstatic void store_arg (const char *, int, int); 294132733Skanstatic char *load_specs (const char *); 295132733Skanstatic void read_specs (const char *, int); 296132733Skanstatic void set_spec (const char *, const char *); 297132733Skanstatic struct compiler *lookup_compiler (const char *, size_t, const char *); 298132733Skanstatic char *build_search_list (struct path_prefix *, const char *, int); 299132733Skanstatic void putenv_from_prefixes (struct path_prefix *, const char *); 300132733Skanstatic int access_check (const char *, int); 301132733Skanstatic char *find_a_file (struct path_prefix *, const char *, int, int); 302132733Skanstatic void add_prefix (struct path_prefix *, const char *, const char *, 303132733Skan int, int, int *, int); 304132733Skanstatic void add_sysrooted_prefix (struct path_prefix *, const char *, 305132733Skan const char *, int, int, int *, int); 306132733Skanstatic void translate_options (int *, const char *const **); 307132733Skanstatic char *skip_whitespace (char *); 308132733Skanstatic void delete_if_ordinary (const char *); 309132733Skanstatic void delete_temp_files (void); 310132733Skanstatic void delete_failure_queue (void); 311132733Skanstatic void clear_failure_queue (void); 312132733Skanstatic int check_live_switch (int, int); 313132733Skanstatic const char *handle_braces (const char *); 314132733Skanstatic inline bool input_suffix_matches (const char *, const char *); 315132733Skanstatic inline bool switch_matches (const char *, const char *, int); 316132733Skanstatic inline void mark_matching_switches (const char *, const char *, int); 317132733Skanstatic inline void process_marked_switches (void); 318132733Skanstatic const char *process_brace_body (const char *, const char *, const char *, int, int); 319132733Skanstatic const struct spec_function *lookup_spec_function (const char *); 320132733Skanstatic const char *eval_spec_function (const char *, const char *); 321132733Skanstatic const char *handle_spec_function (const char *); 322132733Skanstatic char *save_string (const char *, int); 323132733Skanstatic void set_collect_gcc_options (void); 324132733Skanstatic int do_spec_1 (const char *, int, const char *); 325132733Skanstatic int do_spec_2 (const char *); 326132733Skanstatic void do_option_spec (const char *, const char *); 327132733Skanstatic void do_self_spec (const char *); 328132733Skanstatic const char *find_file (const char *); 329132733Skanstatic int is_directory (const char *, const char *, int); 330132733Skanstatic const char *validate_switches (const char *); 331132733Skanstatic void validate_all_switches (void); 332132733Skanstatic inline void validate_switches_from_spec (const char *); 333132733Skanstatic void give_switch (int, int); 334132733Skanstatic int used_arg (const char *, int); 335132733Skanstatic int default_arg (const char *, int); 336132733Skanstatic void set_multilib_dir (void); 337132733Skanstatic void print_multilib_info (void); 338132733Skanstatic void perror_with_name (const char *); 339132733Skanstatic void pfatal_pexecute (const char *, const char *) ATTRIBUTE_NORETURN; 340132733Skanstatic void notice (const char *, ...) ATTRIBUTE_PRINTF_1; 341132733Skanstatic void display_help (void); 342132733Skanstatic void add_preprocessor_option (const char *, int); 343132733Skanstatic void add_assembler_option (const char *, int); 344132733Skanstatic void add_linker_option (const char *, int); 345132733Skanstatic void process_command (int, const char **); 346132733Skanstatic int execute (void); 347132733Skanstatic void alloc_args (void); 348132733Skanstatic void clear_args (void); 349132733Skanstatic void fatal_error (int); 35090277Sobrien#ifdef ENABLE_SHARED_LIBGCC 351132733Skanstatic void init_gcc_specs (struct obstack *, const char *, const char *, 352132733Skan const char *); 35390277Sobrien#endif 35490277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 355132733Skanstatic const char *convert_filename (const char *, int, int); 35690277Sobrien#endif 357117413Skan 358132733Skanstatic const char *if_exists_spec_function (int, const char **); 359132733Skanstatic const char *if_exists_else_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 38990277Sobrien the regexp "[.A-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 448132733Skan (made from TARGET_SYSTEM_ROOT), and -isystem (made from COMPILER_PATH 449132733Skan and -B options) 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. 47090277Sobrien %M output multilib_dir with directory separators replaced with "_"; 47190277Sobrien if multilib_dir is not set or is ".", output "". 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 60018334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is 60118334Speter included. */ 60218334Speter#ifndef LIBGCC_SPEC 60318334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1) 60418334Speter/* Have gcc do the search for libgcc.a. */ 60550599Sobrien#define LIBGCC_SPEC "libgcc.a%s" 60618334Speter#else 60750599Sobrien#define LIBGCC_SPEC "-lgcc" 60818334Speter#endif 60918334Speter#endif 61018334Speter 61118334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files. */ 61218334Speter#ifndef STARTFILE_SPEC 61318334Speter#define STARTFILE_SPEC \ 61418334Speter "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}" 61518334Speter#endif 61618334Speter 61750599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options 61850599Sobrien require spaces between the option and the argument. */ 61918334Speter#ifndef SWITCHES_NEED_SPACES 62018334Speter#define SWITCHES_NEED_SPACES "" 62118334Speter#endif 62218334Speter 62318334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files. */ 62418334Speter#ifndef ENDFILE_SPEC 62518334Speter#define ENDFILE_SPEC "" 62618334Speter#endif 62718334Speter 62850599Sobrien#ifndef LINKER_NAME 62950599Sobrien#define LINKER_NAME "collect2" 63018334Speter#endif 63118334Speter 63290277Sobrien/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g' 63390277Sobrien to the assembler. */ 63490277Sobrien#ifndef ASM_DEBUG_SPEC 63590277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \ 63690277Sobrien && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) 63790277Sobrien# define ASM_DEBUG_SPEC \ 63890277Sobrien (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \ 63990277Sobrien ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" \ 64090277Sobrien : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}") 64190277Sobrien# else 64290277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) 64390277Sobrien# define ASM_DEBUG_SPEC "%{g*:--gstabs}" 64490277Sobrien# endif 64590277Sobrien# if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) 64690277Sobrien# define ASM_DEBUG_SPEC "%{g*:--gdwarf2}" 64790277Sobrien# endif 64890277Sobrien# endif 64990277Sobrien#endif 65090277Sobrien#ifndef ASM_DEBUG_SPEC 65190277Sobrien# define ASM_DEBUG_SPEC "" 65290277Sobrien#endif 65318334Speter 65490277Sobrien/* Here is the spec for running the linker, after compiling all files. */ 65590277Sobrien 65696285Sobrien/* This is overridable by the target in case they need to specify the 65796285Sobrien -lgcc and -lc order specially, yet not require them to override all 65896285Sobrien of LINK_COMMAND_SPEC. */ 65996285Sobrien#ifndef LINK_GCC_C_SEQUENCE_SPEC 66096285Sobrien#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G" 66196285Sobrien#endif 66296285Sobrien 663132733Skan#ifndef LINK_PIE_SPEC 664132733Skan#ifdef HAVE_LD_PIE 665132733Skan#define LINK_PIE_SPEC "%{pie:-pie} " 666132733Skan#else 667132733Skan#define LINK_PIE_SPEC "%{pie:} " 668132733Skan#endif 669132733Skan#endif 670132733Skan 67190277Sobrien/* -u* was put back because both BSD and SysV seem to support it. */ 67290277Sobrien/* %{static:} simply prevents an error message if the target machine 67390277Sobrien doesn't handle -static. */ 67490277Sobrien/* We want %{T*} after %{L*} and %D so that it can be used to specify linker 67590277Sobrien scripts which exist in user specified directories, or in standard 67690277Sobrien directories. */ 67790277Sobrien#ifndef LINK_COMMAND_SPEC 67890277Sobrien#define LINK_COMMAND_SPEC "\ 67990277Sobrien%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ 680132733Skan %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\ 681132733Skan %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ 682132733Skan %{static:} %{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate:-lgcov}\ 683132733Skan %{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\ 68490277Sobrien %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}" 68590277Sobrien#endif 68690277Sobrien 68790277Sobrien#ifndef LINK_LIBGCC_SPEC 68890277Sobrien# ifdef LINK_LIBGCC_SPECIAL 68990277Sobrien/* Don't generate -L options for startfile prefix list. */ 69090277Sobrien# define LINK_LIBGCC_SPEC "" 69190277Sobrien# else 69290277Sobrien/* Do generate them. */ 69390277Sobrien# define LINK_LIBGCC_SPEC "%D" 69490277Sobrien# endif 69590277Sobrien#endif 69690277Sobrien 697117413Skan#ifndef STARTFILE_PREFIX_SPEC 698117413Skan# define STARTFILE_PREFIX_SPEC "" 699117413Skan#endif 700117413Skan 701132733Skan#ifndef SYSROOT_SUFFIX_SPEC 702132733Skan# define SYSROOT_SUFFIX_SPEC "" 703132733Skan#endif 704132733Skan 705132733Skan#ifndef SYSROOT_HEADERS_SUFFIX_SPEC 706132733Skan# define SYSROOT_HEADERS_SUFFIX_SPEC "" 707132733Skan#endif 708132733Skan 709117413Skanstatic const char *asm_debug; 71090277Sobrienstatic const char *cpp_spec = CPP_SPEC; 71190277Sobrienstatic const char *cc1_spec = CC1_SPEC; 71290277Sobrienstatic const char *cc1plus_spec = CC1PLUS_SPEC; 71396285Sobrienstatic const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC; 71490277Sobrienstatic const char *asm_spec = ASM_SPEC; 71590277Sobrienstatic const char *asm_final_spec = ASM_FINAL_SPEC; 71690277Sobrienstatic const char *link_spec = LINK_SPEC; 71790277Sobrienstatic const char *lib_spec = LIB_SPEC; 71890277Sobrienstatic const char *libgcc_spec = LIBGCC_SPEC; 71990277Sobrienstatic const char *endfile_spec = ENDFILE_SPEC; 72090277Sobrienstatic const char *startfile_spec = STARTFILE_SPEC; 72190277Sobrienstatic const char *switches_need_spaces = SWITCHES_NEED_SPACES; 72290277Sobrienstatic const char *linker_name_spec = LINKER_NAME; 72390277Sobrienstatic const char *link_command_spec = LINK_COMMAND_SPEC; 72490277Sobrienstatic const char *link_libgcc_spec = LINK_LIBGCC_SPEC; 725117413Skanstatic const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC; 726132733Skanstatic const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC; 727132733Skanstatic const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC; 72890277Sobrien 72990277Sobrien/* Standard options to cpp, cc1, and as, to reduce duplication in specs. 73090277Sobrien There should be no need to override these in target dependent files, 73190277Sobrien but we need to copy them to the specs file so that newer versions 73290277Sobrien of the GCC driver can correctly drive older tool chains with the 73390277Sobrien appropriate -B options. */ 73490277Sobrien 735117413Skan/* When cpplib handles traditional preprocessing, get rid of this, and 736117413Skan call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so 737117413Skan that we default the front end language better. */ 73890277Sobrienstatic const char *trad_capable_cpp = 739117413Skan"cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}"; 74090277Sobrien 741107594Sobrien/* We don't wrap .d files in %W{} since a missing .d file, and 742107594Sobrien therefore no dependency entry, confuses make into thinking a .o 743107594Sobrien file that happens to exist is up-to-date. */ 74490277Sobrienstatic const char *cpp_unique_options = 745132733Skan"%{C|CC:%{!E:%eGCC does not support -C or -CC without -E}}\ 746117413Skan %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*} %{P} %I\ 747107594Sobrien %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\ 748107594Sobrien %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\ 749107594Sobrien %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\ 75096285Sobrien %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\ 751146908Skan %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\ 75296285Sobrien %{E|M|MM:%W{o*}}"; 75390277Sobrien 75490277Sobrien/* This contains cpp options which are common with cc1_options and are passed 755117413Skan only when preprocessing only to avoid duplication. We pass the cc1 spec 756117413Skan options to the preprocessor so that it the cc1 spec may manipulate 757117413Skan options used to set target flags. Those special target flags settings may 758117413Skan in turn cause preprocessor symbols to be defined specially. */ 75990277Sobrienstatic const char *cpp_options = 760146908Skan"%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\ 761146908Skan %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\ 762146908Skan %{undef}"; 76390277Sobrien 764117413Skan/* This contains cpp options which are not passed when the preprocessor 765117413Skan output will be used by another program. */ 766117413Skanstatic const char *cpp_debug_options = "%{d*}"; 767117413Skan 76890277Sobrien/* NB: This is shared amongst all front-ends. */ 76990277Sobrienstatic const char *cc1_options = 77090277Sobrien"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 77190277Sobrien %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\ 772132733Skan %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\ 773146908Skan %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\ 774117413Skan %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\ 77590277Sobrien %{Qn:-fno-ident} %{--help:--help}\ 77690277Sobrien %{--target-help:--target-help}\ 77790277Sobrien %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\ 77890277Sobrien %{fsyntax-only:-o %j} %{-param*}"; 77990277Sobrien 78090277Sobrienstatic const char *asm_options = 78190277Sobrien"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}"; 78290277Sobrien 78390277Sobrienstatic const char *invoke_as = 784132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT 785132733Skan"%{!S:-o %|.s |\n as %(asm_options) %|.s %A }"; 786132733Skan#else 787132733Skan"%{!S:-o %|.s |\n as %(asm_options) %m.s %A }"; 788132733Skan#endif 78990277Sobrien 79050599Sobrien/* Some compilers have limits on line lengths, and the multilib_select 79150599Sobrien and/or multilib_matches strings can be very long, so we build them at 79250599Sobrien run time. */ 79350599Sobrienstatic struct obstack multilib_obstack; 79490277Sobrienstatic const char *multilib_select; 79590277Sobrienstatic const char *multilib_matches; 79690277Sobrienstatic const char *multilib_defaults; 79790277Sobrienstatic const char *multilib_exclusions; 79850599Sobrien 79950599Sobrien/* Check whether a particular argument is a default argument. */ 80050599Sobrien 80150599Sobrien#ifndef MULTILIB_DEFAULTS 80250599Sobrien#define MULTILIB_DEFAULTS { "" } 80350599Sobrien#endif 80450599Sobrien 80590277Sobrienstatic const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS; 80650599Sobrien 807117413Skan#ifndef DRIVER_SELF_SPECS 808117413Skan#define DRIVER_SELF_SPECS "" 809117413Skan#endif 810117413Skan 811117413Skanstatic const char *const driver_self_specs[] = { DRIVER_SELF_SPECS }; 812117413Skan 813132733Skan#ifndef OPTION_DEFAULT_SPECS 814132733Skan#define OPTION_DEFAULT_SPECS { "", "" } 815132733Skan#endif 816132733Skan 817132733Skanstruct default_spec 818132733Skan{ 819132733Skan const char *name; 820132733Skan const char *spec; 821132733Skan}; 822132733Skan 823132733Skanstatic const struct default_spec 824132733Skan option_default_specs[] = { OPTION_DEFAULT_SPECS }; 825132733Skan 82690277Sobrienstruct user_specs 82790277Sobrien{ 82850599Sobrien struct user_specs *next; 82952520Sobrien const char *filename; 83050599Sobrien}; 83150599Sobrien 83250599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail; 83350599Sobrien 83450599Sobrien#ifndef SWITCH_TAKES_ARG 83550599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR) 83618334Speter#endif 83718334Speter 83818334Speter#ifndef WORD_SWITCH_TAKES_ARG 83918334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR) 84018334Speter#endif 84118334Speter 84290277Sobrien#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX 84350599Sobrien/* This defines which switches stop a full compilation. */ 84450599Sobrien#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \ 84550599Sobrien ((CHAR) == 'c' || (CHAR) == 'S') 84650599Sobrien 84750599Sobrien#ifndef SWITCH_CURTAILS_COMPILATION 84850599Sobrien#define SWITCH_CURTAILS_COMPILATION(CHAR) \ 84950599Sobrien DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) 85050599Sobrien#endif 85150599Sobrien#endif 85250599Sobrien 85318334Speter/* Record the mapping from file suffixes for compilation specs. */ 85418334Speter 85518334Speterstruct compiler 85618334Speter{ 85752520Sobrien const char *suffix; /* Use this compiler for input files 85818334Speter whose names end in this suffix. */ 85918334Speter 86090277Sobrien const char *spec; /* To use this compiler, run this spec. */ 86190277Sobrien 86290277Sobrien const char *cpp_spec; /* If non-NULL, substitute this spec 86390277Sobrien for `%C', rather than the usual 86490277Sobrien cpp_spec. */ 86518334Speter}; 86618334Speter 86718334Speter/* Pointer to a vector of `struct compiler' that gives the spec for 86818334Speter compiling a file, based on its suffix. 86918334Speter A file that does not end in any of these suffixes will be passed 87018334Speter unchanged to the loader and nothing else will be done to it. 87118334Speter 87218334Speter An entry containing two 0s is used to terminate the vector. 87318334Speter 87418334Speter If multiple entries match a file, the last matching one is used. */ 87518334Speter 87618334Speterstatic struct compiler *compilers; 87718334Speter 87818334Speter/* Number of entries in `compilers', not counting the null terminator. */ 87918334Speter 88018334Speterstatic int n_compilers; 88118334Speter 88218334Speter/* The default list of file name suffixes and their compilation specs. */ 88318334Speter 88490277Sobrienstatic const struct compiler default_compilers[] = 88518334Speter{ 88650599Sobrien /* Add lists of suffixes of known languages here. If those languages 88750599Sobrien were not present when we built the driver, we will hit these copies 88850599Sobrien and be given a more meaningful error than "file not used since 88950599Sobrien linking is not done". */ 89090277Sobrien {".m", "#Objective-C", 0}, {".mi", "#Objective-C", 0}, 89190277Sobrien {".cc", "#C++", 0}, {".cxx", "#C++", 0}, {".cpp", "#C++", 0}, 89290277Sobrien {".cp", "#C++", 0}, {".c++", "#C++", 0}, {".C", "#C++", 0}, 893132733Skan {".CPP", "#C++", 0}, {".ii", "#C++", 0}, 89490277Sobrien {".ads", "#Ada", 0}, {".adb", "#Ada", 0}, 89590277Sobrien {".f", "#Fortran", 0}, {".for", "#Fortran", 0}, {".fpp", "#Fortran", 0}, 89690277Sobrien {".F", "#Fortran", 0}, {".FOR", "#Fortran", 0}, {".FPP", "#Fortran", 0}, 89790277Sobrien {".r", "#Ratfor", 0}, 89890277Sobrien {".p", "#Pascal", 0}, {".pas", "#Pascal", 0}, 89990277Sobrien {".java", "#Java", 0}, {".class", "#Java", 0}, 90090277Sobrien {".zip", "#Java", 0}, {".jar", "#Java", 0}, 90150599Sobrien /* Next come the entries for C. */ 90290277Sobrien {".c", "@c", 0}, 90318334Speter {"@c", 90490277Sobrien /* cc1 has an integrated ISO C preprocessor. We should invoke the 905117413Skan external preprocessor if -save-temps is given. */ 906117413Skan "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\ 90790277Sobrien %{!E:%{!M:%{!MM:\ 908117413Skan %{traditional|ftraditional:\ 909117413Skan%eGNU C no longer supports -traditional without -E}\ 910117413Skan %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ 911132733Skan %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\ 912132733Skan cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \ 913132733Skan %(cc1_options)}\ 914117413Skan %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\ 915117413Skan cc1 %(cpp_unique_options) %(cc1_options)}}}\ 91690277Sobrien %{!fsyntax-only:%(invoke_as)}}}}", 0}, 91718334Speter {"-", 918146908Skan "%{!E:%e-E or -x required when input is from standard input}\ 919117413Skan %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0}, 92090277Sobrien {".h", "@c-header", 0}, 92118334Speter {"@c-header", 922132733Skan /* cc1 has an integrated ISO C preprocessor. We should invoke the 923132733Skan external preprocessor if -save-temps is given. */ 924132733Skan "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\ 925132733Skan %{!E:%{!M:%{!MM:\ 926132733Skan %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ 927132733Skan %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\ 928132733Skan cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \ 929132733Skan %(cc1_options)\ 930132733Skan -o %g.s %{!o*:--output-pch=%i.gch}\ 931132733Skan %W{o*:--output-pch=%*}%V}\ 932132733Skan %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\ 933132733Skan cc1 %(cpp_unique_options) %(cc1_options)\ 934132733Skan -o %g.s %{!o*:--output-pch=%i.gch}\ 935132733Skan %W{o*:--output-pch=%*}%V}}}}}}", 0}, 93690277Sobrien {".i", "@cpp-output", 0}, 93718334Speter {"@cpp-output", 93890277Sobrien "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0}, 93990277Sobrien {".s", "@assembler", 0}, 94018334Speter {"@assembler", 94190277Sobrien "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0}, 94290277Sobrien {".S", "@assembler-with-cpp", 0}, 94318334Speter {"@assembler-with-cpp", 944132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT 94590277Sobrien "%(trad_capable_cpp) -lang-asm %(cpp_options)\ 946117413Skan %{E|M|MM:%(cpp_debug_options)}\ 947132733Skan %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\ 948132733Skan as %(asm_debug) %(asm_options) %|.s %A }}}}" 949132733Skan#else 950132733Skan "%(trad_capable_cpp) -lang-asm %(cpp_options)\ 951132733Skan %{E|M|MM:%(cpp_debug_options)}\ 952132733Skan %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\ 953132733Skan as %(asm_debug) %(asm_options) %m.s %A }}}}" 954132733Skan#endif 955132733Skan , 0}, 956132733Skan 95718334Speter#include "specs.h" 958132733Skan /* Mark end of table. */ 95990277Sobrien {0, 0, 0} 96018334Speter}; 96118334Speter 96218334Speter/* Number of elements in default_compilers, not counting the terminator. */ 96318334Speter 964117413Skanstatic const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1; 96518334Speter 96618334Speter/* A vector of options to give to the linker. 96718334Speter These options are accumulated by %x, 96818334Speter and substituted into the linker command with %X. */ 96918334Speterstatic int n_linker_options; 97018334Speterstatic char **linker_options; 97118334Speter 97218334Speter/* A vector of options to give to the assembler. 97318334Speter These options are accumulated by -Wa, 97418334Speter and substituted into the assembler command with %Y. */ 97518334Speterstatic int n_assembler_options; 97618334Speterstatic char **assembler_options; 97718334Speter 97818334Speter/* A vector of options to give to the preprocessor. 97918334Speter These options are accumulated by -Wp, 98018334Speter and substituted into the preprocessor command with %Z. */ 98118334Speterstatic int n_preprocessor_options; 98218334Speterstatic char **preprocessor_options; 98318334Speter 98418334Speter/* Define how to map long options into short ones. */ 98518334Speter 98618334Speter/* This structure describes one mapping. */ 98718334Speterstruct option_map 98818334Speter{ 98918334Speter /* The long option's name. */ 99090277Sobrien const char *const name; 99118334Speter /* The equivalent short option. */ 99290277Sobrien const char *const equivalent; 99318334Speter /* Argument info. A string of flag chars; NULL equals no options. 99418334Speter a => argument required. 99518334Speter o => argument optional. 99618334Speter j => join argument to equivalent, making one word. 99718334Speter * => require other text after NAME as an argument. */ 99890277Sobrien const char *const arg_info; 99918334Speter}; 100018334Speter 100118334Speter/* This is the table of mappings. Mappings are tried sequentially 100218334Speter for each option encountered; the first one that matches, wins. */ 100318334Speter 100490277Sobrienstatic const struct option_map option_map[] = 100518334Speter { 100618334Speter {"--all-warnings", "-Wall", 0}, 100718334Speter {"--ansi", "-ansi", 0}, 100818334Speter {"--assemble", "-S", 0}, 100918334Speter {"--assert", "-A", "a"}, 101052520Sobrien {"--classpath", "-fclasspath=", "aj"}, 101196285Sobrien {"--bootclasspath", "-fbootclasspath=", "aj"}, 101296285Sobrien {"--CLASSPATH", "-fclasspath=", "aj"}, 101318334Speter {"--comments", "-C", 0}, 1014117413Skan {"--comments-in-macros", "-CC", 0}, 101518334Speter {"--compile", "-c", 0}, 101618334Speter {"--debug", "-g", "oj"}, 101750599Sobrien {"--define-macro", "-D", "aj"}, 101818334Speter {"--dependencies", "-M", 0}, 101918334Speter {"--dump", "-d", "a"}, 102018334Speter {"--dumpbase", "-dumpbase", "a"}, 102118334Speter {"--entry", "-e", 0}, 102218334Speter {"--extra-warnings", "-W", 0}, 102318334Speter {"--for-assembler", "-Wa", "a"}, 102418334Speter {"--for-linker", "-Xlinker", "a"}, 102518334Speter {"--force-link", "-u", "a"}, 102618334Speter {"--imacros", "-imacros", "a"}, 102718334Speter {"--include", "-include", "a"}, 102818334Speter {"--include-barrier", "-I-", 0}, 102950599Sobrien {"--include-directory", "-I", "aj"}, 103018334Speter {"--include-directory-after", "-idirafter", "a"}, 103118334Speter {"--include-prefix", "-iprefix", "a"}, 103218334Speter {"--include-with-prefix", "-iwithprefix", "a"}, 103318334Speter {"--include-with-prefix-before", "-iwithprefixbefore", "a"}, 103418334Speter {"--include-with-prefix-after", "-iwithprefix", "a"}, 103518334Speter {"--language", "-x", "a"}, 103618334Speter {"--library-directory", "-L", "a"}, 103718334Speter {"--machine", "-m", "aj"}, 103818334Speter {"--machine-", "-m", "*j"}, 103996285Sobrien {"--no-integrated-cpp", "-no-integrated-cpp", 0}, 104018334Speter {"--no-line-commands", "-P", 0}, 104118334Speter {"--no-precompiled-includes", "-noprecomp", 0}, 104218334Speter {"--no-standard-includes", "-nostdinc", 0}, 104318334Speter {"--no-standard-libraries", "-nostdlib", 0}, 104418334Speter {"--no-warnings", "-w", 0}, 104518334Speter {"--optimize", "-O", "oj"}, 104618334Speter {"--output", "-o", "a"}, 104752520Sobrien {"--output-class-directory", "-foutput-class-dir=", "ja"}, 104890277Sobrien {"--param", "--param", "a"}, 104918334Speter {"--pedantic", "-pedantic", 0}, 105018334Speter {"--pedantic-errors", "-pedantic-errors", 0}, 1051132733Skan {"--pie", "-pie", 0}, 105218334Speter {"--pipe", "-pipe", 0}, 105318334Speter {"--prefix", "-B", "a"}, 105418334Speter {"--preprocess", "-E", 0}, 105518334Speter {"--print-search-dirs", "-print-search-dirs", 0}, 105618334Speter {"--print-file-name", "-print-file-name=", "aj"}, 105718334Speter {"--print-libgcc-file-name", "-print-libgcc-file-name", 0}, 105818334Speter {"--print-missing-file-dependencies", "-MG", 0}, 105918334Speter {"--print-multi-lib", "-print-multi-lib", 0}, 106018334Speter {"--print-multi-directory", "-print-multi-directory", 0}, 1061104763Skan {"--print-multi-os-directory", "-print-multi-os-directory", 0}, 106218334Speter {"--print-prog-name", "-print-prog-name=", "aj"}, 106318334Speter {"--profile", "-p", 0}, 106418334Speter {"--profile-blocks", "-a", 0}, 106518334Speter {"--quiet", "-q", 0}, 106696285Sobrien {"--resource", "-fcompile-resource=", "aj"}, 106718334Speter {"--save-temps", "-save-temps", 0}, 106818334Speter {"--shared", "-shared", 0}, 106918334Speter {"--silent", "-q", 0}, 107050599Sobrien {"--specs", "-specs=", "aj"}, 107118334Speter {"--static", "-static", 0}, 107252520Sobrien {"--std", "-std=", "aj"}, 107318334Speter {"--symbolic", "-symbolic", 0}, 107490277Sobrien {"--time", "-time", 0}, 107518334Speter {"--trace-includes", "-H", 0}, 107618334Speter {"--traditional", "-traditional", 0}, 107718334Speter {"--traditional-cpp", "-traditional-cpp", 0}, 107818334Speter {"--trigraphs", "-trigraphs", 0}, 107950599Sobrien {"--undefine-macro", "-U", "aj"}, 108018334Speter {"--user-dependencies", "-MM", 0}, 108118334Speter {"--verbose", "-v", 0}, 108218334Speter {"--warn-", "-W", "*j"}, 108318334Speter {"--write-dependencies", "-MD", 0}, 108418334Speter {"--write-user-dependencies", "-MMD", 0}, 108518334Speter {"--", "-f", "*j"} 108618334Speter }; 108718334Speter 108890277Sobrien 108990277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE 109090277Sobrienstatic const struct { 109190277Sobrien const char *const option_found; 109290277Sobrien const char *const replacements; 109390277Sobrien} target_option_translations[] = 109490277Sobrien{ 109590277Sobrien TARGET_OPTION_TRANSLATE_TABLE, 109690277Sobrien { 0, 0 } 109790277Sobrien}; 109890277Sobrien#endif 109990277Sobrien 110018334Speter/* Translate the options described by *ARGCP and *ARGVP. 110118334Speter Make a new vector and store it back in *ARGVP, 110218334Speter and store its length in *ARGVC. */ 110318334Speter 110418334Speterstatic void 1105132733Skantranslate_options (int *argcp, const char *const **argvp) 110618334Speter{ 110752520Sobrien int i; 110818334Speter int argc = *argcp; 110990277Sobrien const char *const *argv = *argvp; 111090277Sobrien int newvsize = (argc + 2) * 2 * sizeof (const char *); 1111132733Skan const char **newv = xmalloc (newvsize); 111218334Speter int newindex = 0; 111318334Speter 111418334Speter i = 0; 111518334Speter newv[newindex++] = argv[i++]; 111618334Speter 111718334Speter while (i < argc) 111818334Speter { 111990277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE 112090277Sobrien int tott_idx; 112190277Sobrien 112290277Sobrien for (tott_idx = 0; 112390277Sobrien target_option_translations[tott_idx].option_found; 112490277Sobrien tott_idx++) 112590277Sobrien { 112690277Sobrien if (strcmp (target_option_translations[tott_idx].option_found, 112790277Sobrien argv[i]) == 0) 112890277Sobrien { 112990277Sobrien int spaces = 1; 113090277Sobrien const char *sp; 113190277Sobrien char *np; 113290277Sobrien 113390277Sobrien for (sp = target_option_translations[tott_idx].replacements; 113490277Sobrien *sp; sp++) 113590277Sobrien { 113690277Sobrien if (*sp == ' ') 113790277Sobrien spaces ++; 113890277Sobrien } 113990277Sobrien 114090277Sobrien newvsize += spaces * sizeof (const char *); 1141132733Skan newv = xrealloc (newv, newvsize); 114290277Sobrien 114390277Sobrien sp = target_option_translations[tott_idx].replacements; 114490277Sobrien np = xstrdup (sp); 114590277Sobrien 114690277Sobrien while (1) 114790277Sobrien { 114890277Sobrien while (*np == ' ') 114990277Sobrien np++; 115090277Sobrien if (*np == 0) 115190277Sobrien break; 115290277Sobrien newv[newindex++] = np; 115390277Sobrien while (*np != ' ' && *np) 115490277Sobrien np++; 115590277Sobrien if (*np == 0) 115690277Sobrien break; 115790277Sobrien *np++ = 0; 115890277Sobrien } 115990277Sobrien 116090277Sobrien i ++; 116190277Sobrien break; 116290277Sobrien } 116390277Sobrien } 116490277Sobrien if (target_option_translations[tott_idx].option_found) 116590277Sobrien continue; 116690277Sobrien#endif 116790277Sobrien 116818334Speter /* Translate -- options. */ 116918334Speter if (argv[i][0] == '-' && argv[i][1] == '-') 117018334Speter { 117152520Sobrien size_t j; 117218334Speter /* Find a mapping that applies to this option. */ 117390277Sobrien for (j = 0; j < ARRAY_SIZE (option_map); j++) 117418334Speter { 117550599Sobrien size_t optlen = strlen (option_map[j].name); 117650599Sobrien size_t arglen = strlen (argv[i]); 117750599Sobrien size_t complen = arglen > optlen ? optlen : arglen; 117852520Sobrien const char *arginfo = option_map[j].arg_info; 117918334Speter 118018334Speter if (arginfo == 0) 118118334Speter arginfo = ""; 118218334Speter 118318334Speter if (!strncmp (argv[i], option_map[j].name, complen)) 118418334Speter { 118552520Sobrien const char *arg = 0; 118618334Speter 118718334Speter if (arglen < optlen) 118818334Speter { 118952520Sobrien size_t k; 119090277Sobrien for (k = j + 1; k < ARRAY_SIZE (option_map); k++) 119118334Speter if (strlen (option_map[k].name) >= arglen 119218334Speter && !strncmp (argv[i], option_map[k].name, arglen)) 119318334Speter { 119490277Sobrien error ("ambiguous abbreviation %s", argv[i]); 119518334Speter break; 119618334Speter } 119718334Speter 119890277Sobrien if (k != ARRAY_SIZE (option_map)) 119918334Speter break; 120018334Speter } 120118334Speter 120218334Speter if (arglen > optlen) 120318334Speter { 120418334Speter /* If the option has an argument, accept that. */ 120518334Speter if (argv[i][optlen] == '=') 120618334Speter arg = argv[i] + optlen + 1; 120718334Speter 120818334Speter /* If this mapping requires extra text at end of name, 120918334Speter accept that as "argument". */ 121090277Sobrien else if (strchr (arginfo, '*') != 0) 121118334Speter arg = argv[i] + optlen; 121218334Speter 121318334Speter /* Otherwise, extra text at end means mismatch. 121418334Speter Try other mappings. */ 121518334Speter else 121618334Speter continue; 121718334Speter } 121818334Speter 121990277Sobrien else if (strchr (arginfo, '*') != 0) 122018334Speter { 122190277Sobrien error ("incomplete `%s' option", option_map[j].name); 122218334Speter break; 122318334Speter } 122418334Speter 122518334Speter /* Handle arguments. */ 122690277Sobrien if (strchr (arginfo, 'a') != 0) 122718334Speter { 122818334Speter if (arg == 0) 122918334Speter { 123018334Speter if (i + 1 == argc) 123118334Speter { 123290277Sobrien error ("missing argument to `%s' option", 123318334Speter option_map[j].name); 123418334Speter break; 123518334Speter } 123618334Speter 123718334Speter arg = argv[++i]; 123818334Speter } 123918334Speter } 124090277Sobrien else if (strchr (arginfo, '*') != 0) 124118334Speter ; 124290277Sobrien else if (strchr (arginfo, 'o') == 0) 124318334Speter { 124418334Speter if (arg != 0) 124590277Sobrien error ("extraneous argument to `%s' option", 124618334Speter option_map[j].name); 124718334Speter arg = 0; 124818334Speter } 124918334Speter 125018334Speter /* Store the translation as one argv elt or as two. */ 125190277Sobrien if (arg != 0 && strchr (arginfo, 'j') != 0) 125250599Sobrien newv[newindex++] = concat (option_map[j].equivalent, arg, 125390277Sobrien NULL); 125418334Speter else if (arg != 0) 125518334Speter { 125618334Speter newv[newindex++] = option_map[j].equivalent; 125718334Speter newv[newindex++] = arg; 125818334Speter } 125918334Speter else 126018334Speter newv[newindex++] = option_map[j].equivalent; 126118334Speter 126218334Speter break; 126318334Speter } 126418334Speter } 126518334Speter i++; 126618334Speter } 126718334Speter 126818334Speter /* Handle old-fashioned options--just copy them through, 126918334Speter with their arguments. */ 127018334Speter else if (argv[i][0] == '-') 127118334Speter { 127252520Sobrien const char *p = argv[i] + 1; 127318334Speter int c = *p; 127418334Speter int nskip = 1; 127518334Speter 127618334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 127718334Speter nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0); 127818334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 127918334Speter nskip += WORD_SWITCH_TAKES_ARG (p); 1280117413Skan else if ((c == 'B' || c == 'b' || c == 'x') 128118334Speter && p[1] == 0) 128218334Speter nskip += 1; 128318334Speter else if (! strcmp (p, "Xlinker")) 128418334Speter nskip += 1; 1285132733Skan else if (! strcmp (p, "Xpreprocessor")) 1286132733Skan nskip += 1; 1287132733Skan else if (! strcmp (p, "Xassembler")) 1288132733Skan nskip += 1; 128918334Speter 129018334Speter /* Watch out for an option at the end of the command line that 129118334Speter is missing arguments, and avoid skipping past the end of the 129218334Speter command line. */ 129318334Speter if (nskip + i > argc) 129418334Speter nskip = argc - i; 129518334Speter 129618334Speter while (nskip > 0) 129718334Speter { 129818334Speter newv[newindex++] = argv[i++]; 129918334Speter nskip--; 130018334Speter } 130118334Speter } 130218334Speter else 130318334Speter /* Ordinary operands, or +e options. */ 130418334Speter newv[newindex++] = argv[i++]; 130518334Speter } 130618334Speter 130718334Speter newv[newindex] = 0; 130818334Speter 130918334Speter *argvp = newv; 131018334Speter *argcp = newindex; 131118334Speter} 131218334Speter 131318334Speterstatic char * 1314132733Skanskip_whitespace (char *p) 131518334Speter{ 131618334Speter while (1) 131718334Speter { 131818334Speter /* A fully-blank line is a delimiter in the SPEC file and shouldn't 131918334Speter be considered whitespace. */ 132018334Speter if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n') 132118334Speter return p + 1; 132218334Speter else if (*p == '\n' || *p == ' ' || *p == '\t') 132318334Speter p++; 132418334Speter else if (*p == '#') 132518334Speter { 132690277Sobrien while (*p != '\n') 132790277Sobrien p++; 132818334Speter p++; 132918334Speter } 133018334Speter else 133118334Speter break; 133218334Speter } 133318334Speter 133418334Speter return p; 133518334Speter} 133690277Sobrien/* Structures to keep track of prefixes to try when looking for files. */ 133790277Sobrien 133890277Sobrienstruct prefix_list 133990277Sobrien{ 134090277Sobrien const char *prefix; /* String to prepend to the path. */ 134190277Sobrien struct prefix_list *next; /* Next in linked list. */ 134290277Sobrien int require_machine_suffix; /* Don't use without machine_suffix. */ 134390277Sobrien /* 2 means try both machine_suffix and just_machine_suffix. */ 134490277Sobrien int *used_flag_ptr; /* 1 if a file was found with this prefix. */ 1345104763Skan int priority; /* Sort key - priority within list. */ 1346104763Skan int os_multilib; /* 1 if OS multilib scheme should be used, 1347104763Skan 0 for GCC multilib scheme. */ 134890277Sobrien}; 134990277Sobrien 135090277Sobrienstruct path_prefix 135190277Sobrien{ 135290277Sobrien struct prefix_list *plist; /* List of prefixes to try */ 135390277Sobrien int max_len; /* Max length of a prefix in PLIST */ 135490277Sobrien const char *name; /* Name of this list (used in config stuff) */ 135590277Sobrien}; 135690277Sobrien 135790277Sobrien/* List of prefixes to try when looking for executables. */ 135890277Sobrien 135990277Sobrienstatic struct path_prefix exec_prefixes = { 0, 0, "exec" }; 136090277Sobrien 136190277Sobrien/* List of prefixes to try when looking for startup (crt0) files. */ 136290277Sobrien 136390277Sobrienstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" }; 136490277Sobrien 136590277Sobrien/* List of prefixes to try when looking for include files. */ 136690277Sobrien 136790277Sobrienstatic struct path_prefix include_prefixes = { 0, 0, "include" }; 136890277Sobrien 136990277Sobrien/* Suffix to attach to directories searched for commands. 137090277Sobrien This looks like `MACHINE/VERSION/'. */ 137190277Sobrien 137290277Sobrienstatic const char *machine_suffix = 0; 137390277Sobrien 137490277Sobrien/* Suffix to attach to directories searched for commands. 137590277Sobrien This is just `MACHINE/'. */ 137690277Sobrien 137790277Sobrienstatic const char *just_machine_suffix = 0; 137890277Sobrien 137990277Sobrien/* Adjusted value of GCC_EXEC_PREFIX envvar. */ 138090277Sobrien 138190277Sobrienstatic const char *gcc_exec_prefix; 138290277Sobrien 1383132733Skan/* Adjusted value of standard_libexec_prefix. */ 1384132733Skan 1385132733Skanstatic const char *gcc_libexec_prefix; 1386132733Skan 138790277Sobrien/* Default prefixes to attach to command names. */ 138890277Sobrien 138990277Sobrien#ifdef CROSS_COMPILE /* Don't use these prefixes for a cross compiler. */ 139090277Sobrien#undef MD_EXEC_PREFIX 139190277Sobrien#undef MD_STARTFILE_PREFIX 139290277Sobrien#undef MD_STARTFILE_PREFIX_1 139390277Sobrien#endif 139490277Sobrien 139590277Sobrien/* If no prefixes defined, use the null string, which will disable them. */ 139690277Sobrien#ifndef MD_EXEC_PREFIX 139790277Sobrien#define MD_EXEC_PREFIX "" 139890277Sobrien#endif 139990277Sobrien#ifndef MD_STARTFILE_PREFIX 140090277Sobrien#define MD_STARTFILE_PREFIX "" 140190277Sobrien#endif 140290277Sobrien#ifndef MD_STARTFILE_PREFIX_1 140390277Sobrien#define MD_STARTFILE_PREFIX_1 "" 140490277Sobrien#endif 140590277Sobrien 140690277Sobrienstatic const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX; 1407132733Skanstatic const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/"; 1408132733Skanstatic const char *const standard_exec_prefix_2 = "/usr/lib/gcc/"; 140990277Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX; 141090277Sobrien 141190277Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX; 141290277Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1; 141390277Sobrienstatic const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; 141490277Sobrienstatic const char *const standard_startfile_prefix_1 = "/lib/"; 141590277Sobrienstatic const char *const standard_startfile_prefix_2 = "/usr/lib/"; 141690277Sobrien 141790277Sobrienstatic const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX; 141890277Sobrienstatic const char *tooldir_prefix; 141990277Sobrien 142096736Sru#ifndef FREEBSD_NATIVE 142190277Sobrienstatic const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX; 142296736Sru#endif /* not FREEBSD_NATIVE */ 142390277Sobrien 1424132733Skanstatic const char *standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX; 1425132733Skan 142690277Sobrien/* Subdirectory to use for locating libraries. Set by 142790277Sobrien set_multilib_dir based on the compilation options. */ 142890277Sobrien 142990277Sobrienstatic const char *multilib_dir; 1430104763Skan 1431104763Skan/* Subdirectory to use for locating libraries in OS conventions. Set by 1432104763Skan set_multilib_dir based on the compilation options. */ 1433104763Skan 1434104763Skanstatic const char *multilib_os_dir; 143518334Speter 143650599Sobrien/* Structure to keep track of the specs that have been defined so far. 143750599Sobrien These are accessed using %(specname) or %[specname] in a compiler 143850599Sobrien or link spec. */ 143918334Speter 144018334Speterstruct spec_list 144118334Speter{ 144250599Sobrien /* The following 2 fields must be first */ 144350599Sobrien /* to allow EXTRA_SPECS to be initialized */ 144490277Sobrien const char *name; /* name of the spec. */ 144590277Sobrien const char *ptr; /* available ptr if no static pointer */ 144650599Sobrien 144750599Sobrien /* The following fields are not initialized */ 144850599Sobrien /* by EXTRA_SPECS */ 144990277Sobrien const char **ptr_spec; /* pointer to the spec itself. */ 145050599Sobrien struct spec_list *next; /* Next spec in linked list. */ 145150599Sobrien int name_len; /* length of the name */ 145250599Sobrien int alloc_p; /* whether string was allocated */ 145318334Speter}; 145418334Speter 145550599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \ 145690277Sobrien{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 } 145718334Speter 145890277Sobrien/* List of statically defined specs. */ 145990277Sobrienstatic struct spec_list static_specs[] = 146090277Sobrien{ 146150599Sobrien INIT_STATIC_SPEC ("asm", &asm_spec), 146290277Sobrien INIT_STATIC_SPEC ("asm_debug", &asm_debug), 146350599Sobrien INIT_STATIC_SPEC ("asm_final", &asm_final_spec), 146490277Sobrien INIT_STATIC_SPEC ("asm_options", &asm_options), 146590277Sobrien INIT_STATIC_SPEC ("invoke_as", &invoke_as), 146650599Sobrien INIT_STATIC_SPEC ("cpp", &cpp_spec), 146790277Sobrien INIT_STATIC_SPEC ("cpp_options", &cpp_options), 1468117413Skan INIT_STATIC_SPEC ("cpp_debug_options", &cpp_debug_options), 146990277Sobrien INIT_STATIC_SPEC ("cpp_unique_options", &cpp_unique_options), 147090277Sobrien INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp), 147150599Sobrien INIT_STATIC_SPEC ("cc1", &cc1_spec), 147290277Sobrien INIT_STATIC_SPEC ("cc1_options", &cc1_options), 147350599Sobrien INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec), 147496285Sobrien INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec), 147550599Sobrien INIT_STATIC_SPEC ("endfile", &endfile_spec), 147650599Sobrien INIT_STATIC_SPEC ("link", &link_spec), 147750599Sobrien INIT_STATIC_SPEC ("lib", &lib_spec), 147850599Sobrien INIT_STATIC_SPEC ("libgcc", &libgcc_spec), 147950599Sobrien INIT_STATIC_SPEC ("startfile", &startfile_spec), 148050599Sobrien INIT_STATIC_SPEC ("switches_need_spaces", &switches_need_spaces), 148150599Sobrien INIT_STATIC_SPEC ("cross_compile", &cross_compile), 148250599Sobrien INIT_STATIC_SPEC ("version", &compiler_version), 148350599Sobrien INIT_STATIC_SPEC ("multilib", &multilib_select), 148450599Sobrien INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults), 148550599Sobrien INIT_STATIC_SPEC ("multilib_extra", &multilib_extra), 148650599Sobrien INIT_STATIC_SPEC ("multilib_matches", &multilib_matches), 148790277Sobrien INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions), 1488104763Skan INIT_STATIC_SPEC ("multilib_options", &multilib_options), 148950599Sobrien INIT_STATIC_SPEC ("linker", &linker_name_spec), 149090277Sobrien INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec), 149190277Sobrien INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix), 149290277Sobrien INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix), 149390277Sobrien INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1), 1494117413Skan INIT_STATIC_SPEC ("startfile_prefix_spec", &startfile_prefix_spec), 1495132733Skan INIT_STATIC_SPEC ("sysroot_suffix_spec", &sysroot_suffix_spec), 1496132733Skan INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec", &sysroot_hdrs_suffix_spec), 149750599Sobrien}; 149850599Sobrien 149950599Sobrien#ifdef EXTRA_SPECS /* additional specs needed */ 150052520Sobrien/* Structure to keep track of just the first two args of a spec_list. 150190277Sobrien That is all that the EXTRA_SPECS macro gives us. */ 150252520Sobrienstruct spec_list_1 150352520Sobrien{ 150490277Sobrien const char *const name; 150590277Sobrien const char *const ptr; 150652520Sobrien}; 150752520Sobrien 150890277Sobrienstatic const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS }; 150990277Sobrienstatic struct spec_list *extra_specs = (struct spec_list *) 0; 151050599Sobrien#endif 151150599Sobrien 151250599Sobrien/* List of dynamically allocates specs that have been defined so far. */ 151350599Sobrien 151490277Sobrienstatic struct spec_list *specs = (struct spec_list *) 0; 151590277Sobrien 1516117413Skan/* List of static spec functions. */ 1517117413Skan 1518117413Skanstatic const struct spec_function static_spec_functions[] = 1519117413Skan{ 1520117413Skan { "if-exists", if_exists_spec_function }, 1521117413Skan { "if-exists-else", if_exists_else_spec_function }, 1522117413Skan { 0, 0 } 1523117413Skan}; 1524117413Skan 1525117413Skanstatic int processing_spec_function; 1526117413Skan 152790277Sobrien/* Add appropriate libgcc specs to OBSTACK, taking into account 152890277Sobrien various permutations of -shared-libgcc, -shared, and such. */ 152950599Sobrien 153090277Sobrien#ifdef ENABLE_SHARED_LIBGCC 153190277Sobrienstatic void 1532132733Skaninit_gcc_specs (struct obstack *obstack, const char *shared_name, 1533132733Skan const char *static_name, const char *eh_name) 153490277Sobrien{ 153596285Sobrien char *buf; 153690277Sobrien 153796285Sobrien buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name, 153896285Sobrien "}%{!static:%{!static-libgcc:", 1539132733Skan#ifdef HAVE_LD_AS_NEEDED 1540132733Skan "%{!shared-libgcc:", static_name, 1541132733Skan " --as-needed ", shared_name, " --no-as-needed}" 1542132733Skan "%{shared-libgcc:", shared_name, "%{!shared: ", static_name, 1543132733Skan "}", 1544132733Skan#else 154596285Sobrien "%{!shared:%{!shared-libgcc:", static_name, " ", 154696285Sobrien eh_name, "}%{shared-libgcc:", shared_name, " ", 154796285Sobrien static_name, "}}%{shared:", 154890277Sobrien#ifdef LINK_EH_SPEC 154996285Sobrien "%{shared-libgcc:", shared_name, 155096285Sobrien "}%{!shared-libgcc:", static_name, "}", 155190277Sobrien#else 155296285Sobrien shared_name, 155390277Sobrien#endif 1554132733Skan#endif 155596285Sobrien "}}}", NULL); 155696285Sobrien 155796285Sobrien obstack_grow (obstack, buf, strlen (buf)); 155896285Sobrien free (buf); 155990277Sobrien} 156090277Sobrien#endif /* ENABLE_SHARED_LIBGCC */ 156190277Sobrien 156250599Sobrien/* Initialize the specs lookup routines. */ 156350599Sobrien 156450599Sobrienstatic void 1565132733Skaninit_spec (void) 156650599Sobrien{ 156790277Sobrien struct spec_list *next = (struct spec_list *) 0; 156890277Sobrien struct spec_list *sl = (struct spec_list *) 0; 156950599Sobrien int i; 157050599Sobrien 157150599Sobrien if (specs) 157290277Sobrien return; /* Already initialized. */ 157350599Sobrien 157450599Sobrien if (verbose_flag) 157590277Sobrien notice ("Using built-in specs.\n"); 157650599Sobrien 157750599Sobrien#ifdef EXTRA_SPECS 1578132733Skan extra_specs = xcalloc (sizeof (struct spec_list), 1579132733Skan ARRAY_SIZE (extra_specs_1)); 158090277Sobrien 158190277Sobrien for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--) 158250599Sobrien { 158350599Sobrien sl = &extra_specs[i]; 158452520Sobrien sl->name = extra_specs_1[i].name; 158552520Sobrien sl->ptr = extra_specs_1[i].ptr; 158650599Sobrien sl->next = next; 158750599Sobrien sl->name_len = strlen (sl->name); 158850599Sobrien sl->ptr_spec = &sl->ptr; 158950599Sobrien next = sl; 159050599Sobrien } 159150599Sobrien#endif 159250599Sobrien 1593117413Skan /* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes 1594117413Skan on ?: in file-scope variable initializations. */ 1595117413Skan asm_debug = ASM_DEBUG_SPEC; 1596117413Skan 159790277Sobrien for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) 159850599Sobrien { 159950599Sobrien sl = &static_specs[i]; 160050599Sobrien sl->next = next; 160150599Sobrien next = sl; 160250599Sobrien } 160350599Sobrien 160490277Sobrien#ifdef ENABLE_SHARED_LIBGCC 160590277Sobrien /* ??? If neither -shared-libgcc nor --static-libgcc was 160690277Sobrien seen, then we should be making an educated guess. Some proposed 160790277Sobrien heuristics for ELF include: 160890277Sobrien 160990277Sobrien (1) If "-Wl,--export-dynamic", then it's a fair bet that the 161090277Sobrien program will be doing dynamic loading, which will likely 161190277Sobrien need the shared libgcc. 161290277Sobrien 161390277Sobrien (2) If "-ldl", then it's also a fair bet that we're doing 161490277Sobrien dynamic loading. 161590277Sobrien 161690277Sobrien (3) For each ET_DYN we're linking against (either through -lfoo 161790277Sobrien or /some/path/foo.so), check to see whether it or one of 161890277Sobrien its dependencies depends on a shared libgcc. 161990277Sobrien 162090277Sobrien (4) If "-shared" 162190277Sobrien 162290277Sobrien If the runtime is fixed to look for program headers instead 162390277Sobrien of calling __register_frame_info at all, for each object, 162490277Sobrien use the shared libgcc if any EH symbol referenced. 162590277Sobrien 162690277Sobrien If crtstuff is fixed to not invoke __register_frame_info 162790277Sobrien automatically, for each object, use the shared libgcc if 162890277Sobrien any non-empty unwind section found. 162990277Sobrien 163090277Sobrien Doing any of this probably requires invoking an external program to 163190277Sobrien do the actual object file scanning. */ 163290277Sobrien { 163390277Sobrien const char *p = libgcc_spec; 163490277Sobrien int in_sep = 1; 1635117413Skan 163690277Sobrien /* Transform the extant libgcc_spec into one that uses the shared libgcc 163790277Sobrien when given the proper command line arguments. */ 163890277Sobrien while (*p) 163990277Sobrien { 1640117413Skan if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0) 164190277Sobrien { 164290277Sobrien init_gcc_specs (&obstack, 164390277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB 164490277Sobrien "-lgcc_s" 164590277Sobrien#else 164690277Sobrien "-lgcc_s%M" 164790277Sobrien#endif 1648146908Skan#ifdef USE_LIBUNWIND_EXCEPTIONS 1649146908Skan " -lunwind" 1650146908Skan#endif 1651132733Skan , 1652132733Skan "-lgcc", 1653132733Skan "-lgcc_eh" 1654122197Skan#ifdef USE_LIBUNWIND_EXCEPTIONS 1655146908Skan# ifdef HAVE_LD_STATIC_DYNAMIC 1656146908Skan " %{!static:-Bstatic} -lunwind %{!static:-Bdynamic}" 1657146908Skan# else 1658122197Skan " -lunwind" 1659146908Skan# endif 1660122197Skan#endif 1661132733Skan ); 1662132733Skan 166390277Sobrien p += 5; 166490277Sobrien in_sep = 0; 166590277Sobrien } 166690277Sobrien else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0) 166790277Sobrien { 166890277Sobrien /* Ug. We don't know shared library extensions. Hope that 166990277Sobrien systems that use this form don't do shared libraries. */ 167090277Sobrien init_gcc_specs (&obstack, 167190277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB 167290277Sobrien "-lgcc_s" 167390277Sobrien#else 167490277Sobrien "-lgcc_s%M" 167590277Sobrien#endif 167690277Sobrien , 167790277Sobrien "libgcc.a%s", 1678132733Skan "libgcc_eh.a%s" 1679132733Skan#ifdef USE_LIBUNWIND_EXCEPTIONS 1680132733Skan " -lunwind" 1681132733Skan#endif 1682132733Skan ); 168390277Sobrien p += 10; 168490277Sobrien in_sep = 0; 168590277Sobrien } 168690277Sobrien else 168790277Sobrien { 168890277Sobrien obstack_1grow (&obstack, *p); 168990277Sobrien in_sep = (*p == ' '); 169090277Sobrien p += 1; 169190277Sobrien } 169290277Sobrien } 169390277Sobrien 169490277Sobrien obstack_1grow (&obstack, '\0'); 169590277Sobrien libgcc_spec = obstack_finish (&obstack); 169690277Sobrien } 169790277Sobrien#endif 169890277Sobrien#ifdef USE_AS_TRADITIONAL_FORMAT 169990277Sobrien /* Prepend "--traditional-format" to whatever asm_spec we had before. */ 170090277Sobrien { 170190277Sobrien static const char tf[] = "--traditional-format "; 170290277Sobrien obstack_grow (&obstack, tf, sizeof(tf) - 1); 170390277Sobrien obstack_grow0 (&obstack, asm_spec, strlen (asm_spec)); 170490277Sobrien asm_spec = obstack_finish (&obstack); 170590277Sobrien } 170690277Sobrien#endif 170790277Sobrien#ifdef LINK_EH_SPEC 170890277Sobrien /* Prepend LINK_EH_SPEC to whatever link_spec we had before. */ 170990277Sobrien obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1); 171090277Sobrien obstack_grow0 (&obstack, link_spec, strlen (link_spec)); 171190277Sobrien link_spec = obstack_finish (&obstack); 171290277Sobrien#endif 171390277Sobrien 171450599Sobrien specs = sl; 171550599Sobrien} 171650599Sobrien 171718334Speter/* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is 171818334Speter removed; If the spec starts with a + then SPEC is added to the end of the 171950599Sobrien current spec. */ 172018334Speter 172118334Speterstatic void 1722132733Skanset_spec (const char *name, const char *spec) 172318334Speter{ 172418334Speter struct spec_list *sl; 172590277Sobrien const char *old_spec; 172650599Sobrien int name_len = strlen (name); 172750599Sobrien int i; 172818334Speter 172990277Sobrien /* If this is the first call, initialize the statically allocated specs. */ 173050599Sobrien if (!specs) 173150599Sobrien { 173290277Sobrien struct spec_list *next = (struct spec_list *) 0; 173390277Sobrien for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) 173450599Sobrien { 173550599Sobrien sl = &static_specs[i]; 173650599Sobrien sl->next = next; 173750599Sobrien next = sl; 173850599Sobrien } 173950599Sobrien specs = sl; 174050599Sobrien } 174150599Sobrien 174290277Sobrien /* See if the spec already exists. */ 174318334Speter for (sl = specs; sl; sl = sl->next) 174450599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, name)) 174518334Speter break; 174618334Speter 174718334Speter if (!sl) 174818334Speter { 174990277Sobrien /* Not found - make it. */ 1750132733Skan sl = xmalloc (sizeof (struct spec_list)); 175190277Sobrien sl->name = xstrdup (name); 175250599Sobrien sl->name_len = name_len; 175350599Sobrien sl->ptr_spec = &sl->ptr; 175450599Sobrien sl->alloc_p = 0; 175550599Sobrien *(sl->ptr_spec) = ""; 175618334Speter sl->next = specs; 175718334Speter specs = sl; 175818334Speter } 175918334Speter 176050599Sobrien old_spec = *(sl->ptr_spec); 176152520Sobrien *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1])) 176290277Sobrien ? concat (old_spec, spec + 1, NULL) 176390277Sobrien : xstrdup (spec)); 176418334Speter 176550599Sobrien#ifdef DEBUG_SPECS 176650599Sobrien if (verbose_flag) 176752520Sobrien notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec)); 176850599Sobrien#endif 176950599Sobrien 177090277Sobrien /* Free the old spec. */ 177150599Sobrien if (old_spec && sl->alloc_p) 1772132733Skan free ((void *) old_spec); 177350599Sobrien 177450599Sobrien sl->alloc_p = 1; 177518334Speter} 177618334Speter 177718334Speter/* Accumulate a command (program name and args), and run it. */ 177818334Speter 177918334Speter/* Vector of pointers to arguments in the current line of specifications. */ 178018334Speter 178190277Sobrienstatic const char **argbuf; 178218334Speter 178318334Speter/* Number of elements allocated in argbuf. */ 178418334Speter 178518334Speterstatic int argbuf_length; 178618334Speter 178718334Speter/* Number of elements in argbuf currently in use (containing args). */ 178818334Speter 178918334Speterstatic int argbuf_index; 179018334Speter 179190277Sobrien/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated 179290277Sobrien temp file. If the HOST_BIT_BUCKET is used for %j, no entry is made for 179390277Sobrien it here. */ 179450599Sobrien 179518334Speterstatic struct temp_name { 179652520Sobrien const char *suffix; /* suffix associated with the code. */ 179718334Speter int length; /* strlen (suffix). */ 179818334Speter int unique; /* Indicates whether %g or %u/%U was used. */ 179952520Sobrien const char *filename; /* associated filename. */ 180018334Speter int filename_length; /* strlen (filename). */ 180118334Speter struct temp_name *next; 180218334Speter} *temp_names; 180318334Speter 180418334Speter/* Number of commands executed so far. */ 180518334Speter 180618334Speterstatic int execution_count; 180718334Speter 180818334Speter/* Number of commands that exited with a signal. */ 180918334Speter 181018334Speterstatic int signal_count; 181118334Speter 181218334Speter/* Name with which this program was invoked. */ 181318334Speter 181452520Sobrienstatic const char *programname; 181518334Speter 1816117413Skan/* Allocate the argument vector. */ 1817117413Skan 1818117413Skanstatic void 1819132733Skanalloc_args (void) 1820117413Skan{ 1821117413Skan argbuf_length = 10; 1822132733Skan argbuf = xmalloc (argbuf_length * sizeof (const char *)); 1823117413Skan} 1824117413Skan 182518334Speter/* Clear out the vector of arguments (after a command is executed). */ 182618334Speter 182718334Speterstatic void 1828132733Skanclear_args (void) 182918334Speter{ 183018334Speter argbuf_index = 0; 183118334Speter} 183218334Speter 183318334Speter/* Add one argument to the vector at the end. 183418334Speter This is done when a space is seen or at the end of the line. 183518334Speter If DELETE_ALWAYS is nonzero, the arg is a filename 183618334Speter and the file should be deleted eventually. 183718334Speter If DELETE_FAILURE is nonzero, the arg is a filename 183818334Speter and the file should be deleted if this compilation fails. */ 183918334Speter 184018334Speterstatic void 1841132733Skanstore_arg (const char *arg, int delete_always, int delete_failure) 184218334Speter{ 184318334Speter if (argbuf_index + 1 == argbuf_length) 1844132733Skan argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *)); 184518334Speter 184618334Speter argbuf[argbuf_index++] = arg; 184718334Speter argbuf[argbuf_index] = 0; 184818334Speter 184918334Speter if (delete_always || delete_failure) 185018334Speter record_temp_file (arg, delete_always, delete_failure); 185118334Speter} 185218334Speter 185390277Sobrien/* Load specs from a file name named FILENAME, replacing occurrences of 185490277Sobrien various different types of line-endings, \r\n, \n\r and just \r, with 185590277Sobrien a single \n. */ 185650599Sobrien 185790277Sobrienstatic char * 1858132733Skanload_specs (const char *filename) 185950599Sobrien{ 186050599Sobrien int desc; 186150599Sobrien int readlen; 186250599Sobrien struct stat statbuf; 186350599Sobrien char *buffer; 186490277Sobrien char *buffer_p; 186590277Sobrien char *specs; 186690277Sobrien char *specs_p; 186750599Sobrien 186850599Sobrien if (verbose_flag) 186952520Sobrien notice ("Reading specs from %s\n", filename); 187050599Sobrien 187150599Sobrien /* Open and stat the file. */ 187250599Sobrien desc = open (filename, O_RDONLY, 0); 187350599Sobrien if (desc < 0) 187450599Sobrien pfatal_with_name (filename); 187550599Sobrien if (stat (filename, &statbuf) < 0) 187650599Sobrien pfatal_with_name (filename); 187750599Sobrien 187850599Sobrien /* Read contents of file into BUFFER. */ 187950599Sobrien buffer = xmalloc ((unsigned) statbuf.st_size + 1); 188050599Sobrien readlen = read (desc, buffer, (unsigned) statbuf.st_size); 188150599Sobrien if (readlen < 0) 188250599Sobrien pfatal_with_name (filename); 188350599Sobrien buffer[readlen] = 0; 188450599Sobrien close (desc); 188550599Sobrien 188690277Sobrien specs = xmalloc (readlen + 1); 188790277Sobrien specs_p = specs; 188890277Sobrien for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++) 188990277Sobrien { 189090277Sobrien int skip = 0; 189190277Sobrien char c = *buffer_p; 189290277Sobrien if (c == '\r') 189390277Sobrien { 189490277Sobrien if (buffer_p > buffer && *(buffer_p - 1) == '\n') /* \n\r */ 189590277Sobrien skip = 1; 189690277Sobrien else if (*(buffer_p + 1) == '\n') /* \r\n */ 189790277Sobrien skip = 1; 189890277Sobrien else /* \r */ 189990277Sobrien c = '\n'; 190090277Sobrien } 190190277Sobrien if (! skip) 190290277Sobrien *specs_p++ = c; 190390277Sobrien } 190490277Sobrien *specs_p = '\0'; 190590277Sobrien 190690277Sobrien free (buffer); 190790277Sobrien return (specs); 190890277Sobrien} 190990277Sobrien 191090277Sobrien/* Read compilation specs from a file named FILENAME, 191190277Sobrien replacing the default ones. 191290277Sobrien 191390277Sobrien A suffix which starts with `*' is a definition for 191490277Sobrien one of the machine-specific sub-specs. The "suffix" should be 191596285Sobrien *asm, *cc1, *cpp, *link, *startfile, etc. 191690277Sobrien The corresponding spec is stored in asm_spec, etc., 191790277Sobrien rather than in the `compilers' vector. 191890277Sobrien 191990277Sobrien Anything invalid in the file is a fatal error. */ 192090277Sobrien 192190277Sobrienstatic void 1922132733Skanread_specs (const char *filename, int main_p) 192390277Sobrien{ 192490277Sobrien char *buffer; 192590277Sobrien char *p; 192690277Sobrien 192790277Sobrien buffer = load_specs (filename); 192890277Sobrien 192950599Sobrien /* Scan BUFFER for specs, putting them in the vector. */ 193050599Sobrien p = buffer; 193150599Sobrien while (1) 193250599Sobrien { 193350599Sobrien char *suffix; 193450599Sobrien char *spec; 193550599Sobrien char *in, *out, *p1, *p2, *p3; 193650599Sobrien 193750599Sobrien /* Advance P in BUFFER to the next nonblank nocomment line. */ 193850599Sobrien p = skip_whitespace (p); 193950599Sobrien if (*p == 0) 194050599Sobrien break; 194150599Sobrien 194250599Sobrien /* Is this a special command that starts with '%'? */ 194350599Sobrien /* Don't allow this for the main specs file, since it would 194450599Sobrien encourage people to overwrite it. */ 194550599Sobrien if (*p == '%' && !main_p) 194650599Sobrien { 194750599Sobrien p1 = p; 194850599Sobrien while (*p && *p != '\n') 194950599Sobrien p++; 195050599Sobrien 195190277Sobrien /* Skip '\n'. */ 195290277Sobrien p++; 195350599Sobrien 195490277Sobrien if (!strncmp (p1, "%include", sizeof ("%include") - 1) 195550599Sobrien && (p1[sizeof "%include" - 1] == ' ' 195650599Sobrien || p1[sizeof "%include" - 1] == '\t')) 195750599Sobrien { 195850599Sobrien char *new_filename; 195950599Sobrien 196050599Sobrien p1 += sizeof ("%include"); 196150599Sobrien while (*p1 == ' ' || *p1 == '\t') 196250599Sobrien p1++; 196350599Sobrien 196450599Sobrien if (*p1++ != '<' || p[-2] != '>') 196552520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 196652520Sobrien (long) (p1 - buffer + 1)); 196750599Sobrien 196850599Sobrien p[-2] = '\0'; 1969104763Skan new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0); 197050599Sobrien read_specs (new_filename ? new_filename : p1, FALSE); 197150599Sobrien continue; 197250599Sobrien } 197350599Sobrien else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1) 197450599Sobrien && (p1[sizeof "%include_noerr" - 1] == ' ' 197550599Sobrien || p1[sizeof "%include_noerr" - 1] == '\t')) 197650599Sobrien { 197750599Sobrien char *new_filename; 197850599Sobrien 197950599Sobrien p1 += sizeof "%include_noerr"; 198090277Sobrien while (*p1 == ' ' || *p1 == '\t') 198190277Sobrien p1++; 198250599Sobrien 198350599Sobrien if (*p1++ != '<' || p[-2] != '>') 198452520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 198552520Sobrien (long) (p1 - buffer + 1)); 198650599Sobrien 198750599Sobrien p[-2] = '\0'; 1988104763Skan new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0); 198950599Sobrien if (new_filename) 199050599Sobrien read_specs (new_filename, FALSE); 199150599Sobrien else if (verbose_flag) 199290277Sobrien notice ("could not find specs file %s\n", p1); 199350599Sobrien continue; 199450599Sobrien } 199550599Sobrien else if (!strncmp (p1, "%rename", sizeof "%rename" - 1) 199650599Sobrien && (p1[sizeof "%rename" - 1] == ' ' 199750599Sobrien || p1[sizeof "%rename" - 1] == '\t')) 199850599Sobrien { 199950599Sobrien int name_len; 200050599Sobrien struct spec_list *sl; 2001117413Skan struct spec_list *newsl; 200250599Sobrien 2003117413Skan /* Get original name. */ 200450599Sobrien p1 += sizeof "%rename"; 200550599Sobrien while (*p1 == ' ' || *p1 == '\t') 200650599Sobrien p1++; 200750599Sobrien 200890277Sobrien if (! ISALPHA ((unsigned char) *p1)) 200952520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 201052520Sobrien (long) (p1 - buffer)); 201150599Sobrien 201250599Sobrien p2 = p1; 201390277Sobrien while (*p2 && !ISSPACE ((unsigned char) *p2)) 201450599Sobrien p2++; 201550599Sobrien 201650599Sobrien if (*p2 != ' ' && *p2 != '\t') 201752520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 201852520Sobrien (long) (p2 - buffer)); 201950599Sobrien 202050599Sobrien name_len = p2 - p1; 202150599Sobrien *p2++ = '\0'; 202250599Sobrien while (*p2 == ' ' || *p2 == '\t') 202350599Sobrien p2++; 202450599Sobrien 202590277Sobrien if (! ISALPHA ((unsigned char) *p2)) 202652520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 202752520Sobrien (long) (p2 - buffer)); 202850599Sobrien 202990277Sobrien /* Get new spec name. */ 203050599Sobrien p3 = p2; 203190277Sobrien while (*p3 && !ISSPACE ((unsigned char) *p3)) 203250599Sobrien p3++; 203350599Sobrien 203490277Sobrien if (p3 != p - 1) 203552520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 203652520Sobrien (long) (p3 - buffer)); 203750599Sobrien *p3 = '\0'; 203850599Sobrien 203950599Sobrien for (sl = specs; sl; sl = sl->next) 204050599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, p1)) 204150599Sobrien break; 204250599Sobrien 204350599Sobrien if (!sl) 204450599Sobrien fatal ("specs %s spec was not found to be renamed", p1); 204550599Sobrien 204650599Sobrien if (strcmp (p1, p2) == 0) 204750599Sobrien continue; 204850599Sobrien 2049117413Skan for (newsl = specs; newsl; newsl = newsl->next) 2050117413Skan if (strcmp (newsl->name, p2) == 0) 2051117413Skan fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'", 2052117413Skan filename, p1, p2); 2053117413Skan 205450599Sobrien if (verbose_flag) 205550599Sobrien { 205652520Sobrien notice ("rename spec %s to %s\n", p1, p2); 205750599Sobrien#ifdef DEBUG_SPECS 205852520Sobrien notice ("spec is '%s'\n\n", *(sl->ptr_spec)); 205950599Sobrien#endif 206050599Sobrien } 206150599Sobrien 206250599Sobrien set_spec (p2, *(sl->ptr_spec)); 206350599Sobrien if (sl->alloc_p) 2064132733Skan free ((void *) *(sl->ptr_spec)); 206550599Sobrien 206650599Sobrien *(sl->ptr_spec) = ""; 206750599Sobrien sl->alloc_p = 0; 206850599Sobrien continue; 206950599Sobrien } 207050599Sobrien else 207152520Sobrien fatal ("specs unknown %% command after %ld characters", 207252520Sobrien (long) (p1 - buffer)); 207350599Sobrien } 207450599Sobrien 207550599Sobrien /* Find the colon that should end the suffix. */ 207650599Sobrien p1 = p; 207750599Sobrien while (*p1 && *p1 != ':' && *p1 != '\n') 207850599Sobrien p1++; 207950599Sobrien 208050599Sobrien /* The colon shouldn't be missing. */ 208150599Sobrien if (*p1 != ':') 208252520Sobrien fatal ("specs file malformed after %ld characters", 208352520Sobrien (long) (p1 - buffer)); 208450599Sobrien 208550599Sobrien /* Skip back over trailing whitespace. */ 208650599Sobrien p2 = p1; 208750599Sobrien while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) 208850599Sobrien p2--; 208950599Sobrien 209050599Sobrien /* Copy the suffix to a string. */ 209150599Sobrien suffix = save_string (p, p2 - p); 209250599Sobrien /* Find the next line. */ 209350599Sobrien p = skip_whitespace (p1 + 1); 209450599Sobrien if (p[1] == 0) 209552520Sobrien fatal ("specs file malformed after %ld characters", 209652520Sobrien (long) (p - buffer)); 209750599Sobrien 209850599Sobrien p1 = p; 209950599Sobrien /* Find next blank line or end of string. */ 210050599Sobrien while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0'))) 210150599Sobrien p1++; 210250599Sobrien 210350599Sobrien /* Specs end at the blank line and do not include the newline. */ 210450599Sobrien spec = save_string (p, p1 - p); 210550599Sobrien p = p1; 210650599Sobrien 210750599Sobrien /* Delete backslash-newline sequences from the spec. */ 210850599Sobrien in = spec; 210950599Sobrien out = spec; 211050599Sobrien while (*in != 0) 211150599Sobrien { 211250599Sobrien if (in[0] == '\\' && in[1] == '\n') 211350599Sobrien in += 2; 211450599Sobrien else if (in[0] == '#') 211550599Sobrien while (*in && *in != '\n') 211650599Sobrien in++; 211750599Sobrien 211850599Sobrien else 211950599Sobrien *out++ = *in++; 212050599Sobrien } 212150599Sobrien *out = 0; 212250599Sobrien 212350599Sobrien if (suffix[0] == '*') 212450599Sobrien { 212550599Sobrien if (! strcmp (suffix, "*link_command")) 212650599Sobrien link_command_spec = spec; 212750599Sobrien else 212850599Sobrien set_spec (suffix + 1, spec); 212950599Sobrien } 213050599Sobrien else 213150599Sobrien { 213250599Sobrien /* Add this pair to the vector. */ 213350599Sobrien compilers 2134132733Skan = xrealloc (compilers, 2135132733Skan (n_compilers + 2) * sizeof (struct compiler)); 213650599Sobrien 213750599Sobrien compilers[n_compilers].suffix = suffix; 213890277Sobrien compilers[n_compilers].spec = spec; 213950599Sobrien n_compilers++; 214090277Sobrien memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]); 214150599Sobrien } 214250599Sobrien 214350599Sobrien if (*suffix == 0) 214450599Sobrien link_command_spec = spec; 214550599Sobrien } 214650599Sobrien 214750599Sobrien if (link_command_spec == 0) 214850599Sobrien fatal ("spec file has no spec for linking"); 214950599Sobrien} 215050599Sobrien 215118334Speter/* Record the names of temporary files we tell compilers to write, 215218334Speter and delete them at the end of the run. */ 215318334Speter 215418334Speter/* This is the common prefix we use to make temp file names. 215518334Speter It is chosen once for each run of this program. 215690277Sobrien It is substituted into a spec by %g or %j. 215718334Speter Thus, all temp file names contain this prefix. 215818334Speter In practice, all temp file names start with this prefix. 215918334Speter 216018334Speter This prefix comes from the envvar TMPDIR if it is defined; 216118334Speter otherwise, from the P_tmpdir macro if that is defined; 216250599Sobrien otherwise, in /usr/tmp or /tmp; 216350599Sobrien or finally the current directory if all else fails. */ 216418334Speter 216552520Sobrienstatic const char *temp_filename; 216618334Speter 216718334Speter/* Length of the prefix. */ 216818334Speter 216918334Speterstatic int temp_filename_length; 217018334Speter 217118334Speter/* Define the list of temporary files to delete. */ 217218334Speter 217318334Speterstruct temp_file 217418334Speter{ 217552520Sobrien const char *name; 217618334Speter struct temp_file *next; 217718334Speter}; 217818334Speter 217918334Speter/* Queue of files to delete on success or failure of compilation. */ 218018334Speterstatic struct temp_file *always_delete_queue; 218118334Speter/* Queue of files to delete on failure of compilation. */ 218218334Speterstatic struct temp_file *failure_delete_queue; 218318334Speter 218418334Speter/* Record FILENAME as a file to be deleted automatically. 218518334Speter ALWAYS_DELETE nonzero means delete it if all compilation succeeds; 218618334Speter otherwise delete it in any case. 218718334Speter FAIL_DELETE nonzero means delete it if a compilation step fails; 218818334Speter otherwise delete it in any case. */ 218918334Speter 219090277Sobrienvoid 2191132733Skanrecord_temp_file (const char *filename, int always_delete, int fail_delete) 219218334Speter{ 219390277Sobrien char *const name = xstrdup (filename); 219418334Speter 219518334Speter if (always_delete) 219618334Speter { 219790277Sobrien struct temp_file *temp; 219818334Speter for (temp = always_delete_queue; temp; temp = temp->next) 219918334Speter if (! strcmp (name, temp->name)) 220018334Speter goto already1; 220150599Sobrien 2202132733Skan temp = xmalloc (sizeof (struct temp_file)); 220318334Speter temp->next = always_delete_queue; 220418334Speter temp->name = name; 220518334Speter always_delete_queue = temp; 220650599Sobrien 220718334Speter already1:; 220818334Speter } 220918334Speter 221018334Speter if (fail_delete) 221118334Speter { 221290277Sobrien struct temp_file *temp; 221318334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 221418334Speter if (! strcmp (name, temp->name)) 221518334Speter goto already2; 221650599Sobrien 2217132733Skan temp = xmalloc (sizeof (struct temp_file)); 221818334Speter temp->next = failure_delete_queue; 221918334Speter temp->name = name; 222018334Speter failure_delete_queue = temp; 222150599Sobrien 222218334Speter already2:; 222318334Speter } 222418334Speter} 222518334Speter 222618334Speter/* Delete all the temporary files whose names we previously recorded. */ 222718334Speter 222818334Speterstatic void 2229132733Skandelete_if_ordinary (const char *name) 223018334Speter{ 223118334Speter struct stat st; 223218334Speter#ifdef DEBUG 223318334Speter int i, c; 223418334Speter 223518334Speter printf ("Delete %s? (y or n) ", name); 223618334Speter fflush (stdout); 223718334Speter i = getchar (); 223818334Speter if (i != '\n') 223950599Sobrien while ((c = getchar ()) != '\n' && c != EOF) 224050599Sobrien ; 224150599Sobrien 224218334Speter if (i == 'y' || i == 'Y') 224318334Speter#endif /* DEBUG */ 224418334Speter if (stat (name, &st) >= 0 && S_ISREG (st.st_mode)) 224518334Speter if (unlink (name) < 0) 224618334Speter if (verbose_flag) 224718334Speter perror_with_name (name); 224818334Speter} 224918334Speter 225018334Speterstatic void 2251132733Skandelete_temp_files (void) 225218334Speter{ 225390277Sobrien struct temp_file *temp; 225418334Speter 225518334Speter for (temp = always_delete_queue; temp; temp = temp->next) 225618334Speter delete_if_ordinary (temp->name); 225718334Speter always_delete_queue = 0; 225818334Speter} 225918334Speter 226018334Speter/* Delete all the files to be deleted on error. */ 226118334Speter 226218334Speterstatic void 2263132733Skandelete_failure_queue (void) 226418334Speter{ 226590277Sobrien struct temp_file *temp; 226618334Speter 226718334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 226818334Speter delete_if_ordinary (temp->name); 226918334Speter} 227018334Speter 227118334Speterstatic void 2272132733Skanclear_failure_queue (void) 227318334Speter{ 227418334Speter failure_delete_queue = 0; 227518334Speter} 227618334Speter 227718334Speter/* Build a list of search directories from PATHS. 227818334Speter PREFIX is a string to prepend to the list. 2279117413Skan If CHECK_DIR_P is nonzero we ensure the directory exists. 228018334Speter This is used mostly by putenv_from_prefixes so we use `collect_obstack'. 228118334Speter It is also used by the --print-search-dirs flag. */ 228218334Speter 228318334Speterstatic char * 2284132733Skanbuild_search_list (struct path_prefix *paths, const char *prefix, 2285132733Skan int check_dir_p) 228618334Speter{ 228718334Speter int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0; 228818334Speter int just_suffix_len 228918334Speter = (just_machine_suffix) ? strlen (just_machine_suffix) : 0; 229018334Speter int first_time = TRUE; 229118334Speter struct prefix_list *pprefix; 229218334Speter 229318334Speter obstack_grow (&collect_obstack, prefix, strlen (prefix)); 229490277Sobrien obstack_1grow (&collect_obstack, '='); 229518334Speter 229618334Speter for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next) 229718334Speter { 229818334Speter int len = strlen (pprefix->prefix); 229918334Speter 230018334Speter if (machine_suffix 230150599Sobrien && (! check_dir_p 230218334Speter || is_directory (pprefix->prefix, machine_suffix, 0))) 230318334Speter { 230418334Speter if (!first_time) 230518334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 230690277Sobrien 230718334Speter first_time = FALSE; 230818334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 230918334Speter obstack_grow (&collect_obstack, machine_suffix, suffix_len); 231018334Speter } 231118334Speter 231218334Speter if (just_machine_suffix 231318334Speter && pprefix->require_machine_suffix == 2 231450599Sobrien && (! check_dir_p 231518334Speter || is_directory (pprefix->prefix, just_machine_suffix, 0))) 231618334Speter { 231750599Sobrien if (! first_time) 231818334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 231990277Sobrien 232018334Speter first_time = FALSE; 232118334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 232218334Speter obstack_grow (&collect_obstack, just_machine_suffix, 232318334Speter just_suffix_len); 232418334Speter } 232518334Speter 232650599Sobrien if (! pprefix->require_machine_suffix) 232718334Speter { 232850599Sobrien if (! first_time) 232918334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 233018334Speter 233118334Speter first_time = FALSE; 233218334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 233318334Speter } 233418334Speter } 233550599Sobrien 233618334Speter obstack_1grow (&collect_obstack, '\0'); 233718334Speter return obstack_finish (&collect_obstack); 233818334Speter} 233918334Speter 234050599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 234150599Sobrien for collect. */ 234218334Speter 234318334Speterstatic void 2344132733Skanputenv_from_prefixes (struct path_prefix *paths, const char *env_var) 234518334Speter{ 234618334Speter putenv (build_search_list (paths, env_var, 1)); 234718334Speter} 234818334Speter 234990277Sobrien/* Check whether NAME can be accessed in MODE. This is like access, 235090277Sobrien except that it never considers directories to be executable. */ 235190277Sobrien 235290277Sobrienstatic int 2353132733Skanaccess_check (const char *name, int mode) 235490277Sobrien{ 235590277Sobrien if (mode == X_OK) 235690277Sobrien { 235790277Sobrien struct stat st; 235890277Sobrien 235990277Sobrien if (stat (name, &st) < 0 236090277Sobrien || S_ISDIR (st.st_mode)) 236190277Sobrien return -1; 236290277Sobrien } 236390277Sobrien 236490277Sobrien return access (name, mode); 236590277Sobrien} 236690277Sobrien 236718334Speter/* Search for NAME using the prefix list PREFIXES. MODE is passed to 236818334Speter access to check permissions. 236950599Sobrien Return 0 if not found, otherwise return its name, allocated with malloc. */ 237018334Speter 237118334Speterstatic char * 2372132733Skanfind_a_file (struct path_prefix *pprefix, const char *name, int mode, 2373132733Skan int multilib) 237418334Speter{ 237518334Speter char *temp; 237690277Sobrien const char *const file_suffix = 237790277Sobrien ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : ""); 237818334Speter struct prefix_list *pl; 237918334Speter int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1; 2380104763Skan const char *multilib_name, *multilib_os_name; 238118334Speter 238252520Sobrien#ifdef DEFAULT_ASSEMBLER 238390277Sobrien if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) 238490277Sobrien return xstrdup (DEFAULT_ASSEMBLER); 238552520Sobrien#endif 238652520Sobrien 238752520Sobrien#ifdef DEFAULT_LINKER 238890277Sobrien if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) 238990277Sobrien return xstrdup (DEFAULT_LINKER); 239052520Sobrien#endif 239152520Sobrien 239218334Speter if (machine_suffix) 239318334Speter len += strlen (machine_suffix); 239418334Speter 2395104763Skan multilib_name = name; 2396104763Skan multilib_os_name = name; 2397104763Skan if (multilib && multilib_os_dir) 2398104763Skan { 2399104763Skan int len1 = multilib_dir ? strlen (multilib_dir) + 1 : 0; 2400104763Skan int len2 = strlen (multilib_os_dir) + 1; 2401104763Skan 2402104763Skan len += len1 > len2 ? len1 : len2; 2403104763Skan if (multilib_dir) 2404104763Skan multilib_name = ACONCAT ((multilib_dir, dir_separator_str, name, 2405104763Skan NULL)); 2406104763Skan if (strcmp (multilib_os_dir, ".") != 0) 2407104763Skan multilib_os_name = ACONCAT ((multilib_os_dir, dir_separator_str, name, 2408104763Skan NULL)); 2409104763Skan } 2410104763Skan 241118334Speter temp = xmalloc (len); 241218334Speter 241318334Speter /* Determine the filename to execute (special case for absolute paths). */ 241418334Speter 2415132733Skan if (IS_ABSOLUTE_PATH (name)) 241618334Speter { 241752520Sobrien if (access (name, mode) == 0) 241818334Speter { 241918334Speter strcpy (temp, name); 242018334Speter return temp; 242118334Speter } 242218334Speter } 242318334Speter else 242418334Speter for (pl = pprefix->plist; pl; pl = pl->next) 242518334Speter { 2426104763Skan const char *this_name 2427104763Skan = pl->os_multilib ? multilib_os_name : multilib_name; 2428104763Skan 242918334Speter if (machine_suffix) 243018334Speter { 243118334Speter /* Some systems have a suffix for executable files. 243218334Speter So try appending that first. */ 243318334Speter if (file_suffix[0] != 0) 243418334Speter { 243518334Speter strcpy (temp, pl->prefix); 243618334Speter strcat (temp, machine_suffix); 2437104763Skan strcat (temp, multilib_name); 243818334Speter strcat (temp, file_suffix); 243990277Sobrien if (access_check (temp, mode) == 0) 244018334Speter { 244118334Speter if (pl->used_flag_ptr != 0) 244218334Speter *pl->used_flag_ptr = 1; 244318334Speter return temp; 244418334Speter } 244518334Speter } 244618334Speter 2447104763Skan /* Now try just the multilib_name. */ 244818334Speter strcpy (temp, pl->prefix); 244918334Speter strcat (temp, machine_suffix); 2450104763Skan strcat (temp, multilib_name); 245190277Sobrien if (access_check (temp, mode) == 0) 245218334Speter { 245318334Speter if (pl->used_flag_ptr != 0) 245418334Speter *pl->used_flag_ptr = 1; 245518334Speter return temp; 245618334Speter } 245718334Speter } 245818334Speter 245918334Speter /* Certain prefixes are tried with just the machine type, 246018334Speter not the version. This is used for finding as, ld, etc. */ 246118334Speter if (just_machine_suffix && pl->require_machine_suffix == 2) 246218334Speter { 246318334Speter /* Some systems have a suffix for executable files. 246418334Speter So try appending that first. */ 246518334Speter if (file_suffix[0] != 0) 246618334Speter { 246718334Speter strcpy (temp, pl->prefix); 246818334Speter strcat (temp, just_machine_suffix); 2469104763Skan strcat (temp, multilib_name); 247018334Speter strcat (temp, file_suffix); 247190277Sobrien if (access_check (temp, mode) == 0) 247218334Speter { 247318334Speter if (pl->used_flag_ptr != 0) 247418334Speter *pl->used_flag_ptr = 1; 247518334Speter return temp; 247618334Speter } 247718334Speter } 247818334Speter 247918334Speter strcpy (temp, pl->prefix); 248018334Speter strcat (temp, just_machine_suffix); 2481104763Skan strcat (temp, multilib_name); 248290277Sobrien if (access_check (temp, mode) == 0) 248318334Speter { 248418334Speter if (pl->used_flag_ptr != 0) 248518334Speter *pl->used_flag_ptr = 1; 248618334Speter return temp; 248718334Speter } 248818334Speter } 248918334Speter 249018334Speter /* Certain prefixes can't be used without the machine suffix 249118334Speter when the machine or version is explicitly specified. */ 249250599Sobrien if (! pl->require_machine_suffix) 249318334Speter { 249418334Speter /* Some systems have a suffix for executable files. 249518334Speter So try appending that first. */ 249618334Speter if (file_suffix[0] != 0) 249718334Speter { 249818334Speter strcpy (temp, pl->prefix); 2499104763Skan strcat (temp, this_name); 250018334Speter strcat (temp, file_suffix); 250190277Sobrien if (access_check (temp, mode) == 0) 250218334Speter { 250318334Speter if (pl->used_flag_ptr != 0) 250418334Speter *pl->used_flag_ptr = 1; 250518334Speter return temp; 250618334Speter } 250718334Speter } 250818334Speter 250918334Speter strcpy (temp, pl->prefix); 2510104763Skan strcat (temp, this_name); 251190277Sobrien if (access_check (temp, mode) == 0) 251218334Speter { 251318334Speter if (pl->used_flag_ptr != 0) 251418334Speter *pl->used_flag_ptr = 1; 251518334Speter return temp; 251618334Speter } 251718334Speter } 251818334Speter } 251918334Speter 252018334Speter free (temp); 252118334Speter return 0; 252218334Speter} 252318334Speter 252490277Sobrien/* Ranking of prefixes in the sort list. -B prefixes are put before 252590277Sobrien all others. */ 252618334Speter 252790277Sobrienenum path_prefix_priority 252890277Sobrien{ 252990277Sobrien PREFIX_PRIORITY_B_OPT, 253090277Sobrien PREFIX_PRIORITY_LAST 253190277Sobrien}; 253290277Sobrien 2533132733Skan/* Add an entry for PREFIX in PLIST. The PLIST is kept in ascending 253490277Sobrien order according to PRIORITY. Within each PRIORITY, new entries are 253590277Sobrien appended. 253690277Sobrien 253718334Speter If WARN is nonzero, we will warn if no file is found 253818334Speter through this prefix. WARN should point to an int 253918334Speter which will be set to 1 if this entry is used. 254018334Speter 254150599Sobrien COMPONENT is the value to be passed to update_path. 254250599Sobrien 254318334Speter REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without 254418334Speter the complete value of machine_suffix. 254518334Speter 2 means try both machine_suffix and just_machine_suffix. */ 254618334Speter 254718334Speterstatic void 2548132733Skanadd_prefix (struct path_prefix *pprefix, const char *prefix, 2549132733Skan const char *component, /* enum prefix_priority */ int priority, 2550132733Skan int require_machine_suffix, int *warn, int os_multilib) 255118334Speter{ 255218334Speter struct prefix_list *pl, **prev; 255318334Speter int len; 255418334Speter 255590277Sobrien for (prev = &pprefix->plist; 255690277Sobrien (*prev) != NULL && (*prev)->priority <= priority; 255790277Sobrien prev = &(*prev)->next) 255890277Sobrien ; 255918334Speter 2560132733Skan /* Keep track of the longest prefix. */ 256118334Speter 256250599Sobrien prefix = update_path (prefix, component); 256318334Speter len = strlen (prefix); 256418334Speter if (len > pprefix->max_len) 256518334Speter pprefix->max_len = len; 256618334Speter 2567132733Skan pl = xmalloc (sizeof (struct prefix_list)); 256890277Sobrien pl->prefix = prefix; 256918334Speter pl->require_machine_suffix = require_machine_suffix; 257018334Speter pl->used_flag_ptr = warn; 257190277Sobrien pl->priority = priority; 2572104763Skan pl->os_multilib = os_multilib; 257318334Speter if (warn) 257418334Speter *warn = 0; 257518334Speter 2576132733Skan /* Insert after PREV. */ 257790277Sobrien pl->next = (*prev); 257890277Sobrien (*prev) = pl; 257918334Speter} 2580132733Skan 2581132733Skan/* Same as add_prefix, but prepending target_system_root to prefix. */ 2582132733Skanstatic void 2583132733Skanadd_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix, 2584132733Skan const char *component, 2585132733Skan /* enum prefix_priority */ int priority, 2586132733Skan int require_machine_suffix, int *warn, int os_multilib) 2587132733Skan{ 2588132733Skan if (!IS_ABSOLUTE_PATH (prefix)) 2589132733Skan abort (); 2590132733Skan 2591132733Skan if (target_system_root) 2592132733Skan { 2593132733Skan if (target_sysroot_suffix) 2594132733Skan prefix = concat (target_sysroot_suffix, prefix, NULL); 2595132733Skan prefix = concat (target_system_root, prefix, NULL); 2596132733Skan 2597132733Skan /* We have to override this because GCC's notion of sysroot 2598132733Skan moves along with GCC. */ 2599132733Skan component = "GCC"; 2600132733Skan } 2601132733Skan 2602132733Skan add_prefix (pprefix, prefix, component, priority, 2603132733Skan require_machine_suffix, warn, os_multilib); 2604132733Skan} 260518334Speter 260618334Speter/* Execute the command specified by the arguments on the current line of spec. 260718334Speter When using pipes, this includes several piped-together commands 260818334Speter with `|' between them. 260918334Speter 261018334Speter Return 0 if successful, -1 if failed. */ 261118334Speter 261218334Speterstatic int 2613132733Skanexecute (void) 261418334Speter{ 261518334Speter int i; 261618334Speter int n_commands; /* # of command. */ 261718334Speter char *string; 261818334Speter struct command 261990277Sobrien { 262090277Sobrien const char *prog; /* program name. */ 262190277Sobrien const char **argv; /* vector of args. */ 262290277Sobrien int pid; /* pid of process for this command. */ 262390277Sobrien }; 262418334Speter 262518334Speter struct command *commands; /* each command buffer with above info. */ 262618334Speter 2627117413Skan if (processing_spec_function) 2628117413Skan abort (); 2629117413Skan 263018334Speter /* Count # of piped commands. */ 263118334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 263218334Speter if (strcmp (argbuf[i], "|") == 0) 263318334Speter n_commands++; 263418334Speter 263518334Speter /* Get storage for each command. */ 2636132733Skan commands = alloca (n_commands * sizeof (struct command)); 263718334Speter 263818334Speter /* Split argbuf into its separate piped processes, 263918334Speter and record info about each one. 264018334Speter Also search for the programs that are to be run. */ 264118334Speter 264218334Speter commands[0].prog = argbuf[0]; /* first command. */ 264318334Speter commands[0].argv = &argbuf[0]; 2644104763Skan string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, 0); 264550599Sobrien 264618334Speter if (string) 264718334Speter commands[0].argv[0] = string; 264818334Speter 264918334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 265018334Speter if (strcmp (argbuf[i], "|") == 0) 265118334Speter { /* each command. */ 265252520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS) 265390277Sobrien fatal ("-pipe not supported"); 265418334Speter#endif 265518334Speter argbuf[i] = 0; /* termination of command args. */ 265618334Speter commands[n_commands].prog = argbuf[i + 1]; 265718334Speter commands[n_commands].argv = &argbuf[i + 1]; 2658104763Skan string = find_a_file (&exec_prefixes, commands[n_commands].prog, 2659104763Skan X_OK, 0); 266018334Speter if (string) 266118334Speter commands[n_commands].argv[0] = string; 266218334Speter n_commands++; 266318334Speter } 266418334Speter 266518334Speter argbuf[argbuf_index] = 0; 266618334Speter 266718334Speter /* If -v, print what we are about to do, and maybe query. */ 266818334Speter 266918334Speter if (verbose_flag) 267018334Speter { 267150599Sobrien /* For help listings, put a blank line between sub-processes. */ 267250599Sobrien if (print_help_list) 267350599Sobrien fputc ('\n', stderr); 267490277Sobrien 267518334Speter /* Print each piped command as a separate line. */ 267690277Sobrien for (i = 0; i < n_commands; i++) 267718334Speter { 267890277Sobrien const char *const *j; 267918334Speter 2680117413Skan if (verbose_only_flag) 2681117413Skan { 268290277Sobrien for (j = commands[i].argv; *j; j++) 268390277Sobrien { 268490277Sobrien const char *p; 268590277Sobrien fprintf (stderr, " \""); 268690277Sobrien for (p = *j; *p; ++p) 268790277Sobrien { 268890277Sobrien if (*p == '"' || *p == '\\' || *p == '$') 268990277Sobrien fputc ('\\', stderr); 269090277Sobrien fputc (*p, stderr); 269190277Sobrien } 269290277Sobrien fputc ('"', stderr); 269390277Sobrien } 2694117413Skan } 2695117413Skan else 269690277Sobrien for (j = commands[i].argv; *j; j++) 269790277Sobrien fprintf (stderr, " %s", *j); 269818334Speter 269918334Speter /* Print a pipe symbol after all but the last command. */ 270018334Speter if (i + 1 != n_commands) 270118334Speter fprintf (stderr, " |"); 270218334Speter fprintf (stderr, "\n"); 270318334Speter } 270418334Speter fflush (stderr); 270590277Sobrien if (verbose_only_flag != 0) 2706132733Skan { 2707132733Skan /* verbose_only_flag should act as if the spec was 2708132733Skan executed, so increment execution_count before 2709132733Skan returning. This prevents spurious warnings about 2710132733Skan unused linker input files, etc. */ 2711132733Skan execution_count++; 2712132733Skan return 0; 2713132733Skan } 271418334Speter#ifdef DEBUG 271552520Sobrien notice ("\nGo ahead? (y or n) "); 271618334Speter fflush (stderr); 271718334Speter i = getchar (); 271818334Speter if (i != '\n') 271950599Sobrien while (getchar () != '\n') 272050599Sobrien ; 272150599Sobrien 272218334Speter if (i != 'y' && i != 'Y') 272318334Speter return 0; 272418334Speter#endif /* DEBUG */ 272518334Speter } 272618334Speter 2727117413Skan#ifdef ENABLE_VALGRIND_CHECKING 2728132733Skan /* Run the each command through valgrind. To simplify prepending the 2729117413Skan path to valgrind and the option "-q" (for quiet operation unless 2730117413Skan something triggers), we allocate a separate argv array. */ 2731117413Skan 2732117413Skan for (i = 0; i < n_commands; i++) 2733117413Skan { 2734117413Skan const char **argv; 2735117413Skan int argc; 2736117413Skan int j; 2737117413Skan 2738117413Skan for (argc = 0; commands[i].argv[argc] != NULL; argc++) 2739117413Skan ; 2740117413Skan 2741117413Skan argv = alloca ((argc + 3) * sizeof (char *)); 2742117413Skan 2743117413Skan argv[0] = VALGRIND_PATH; 2744117413Skan argv[1] = "-q"; 2745117413Skan for (j = 2; j < argc + 2; j++) 2746117413Skan argv[j] = commands[i].argv[j - 2]; 2747117413Skan argv[j] = NULL; 2748117413Skan 2749117413Skan commands[i].argv = argv; 2750117413Skan commands[i].prog = argv[0]; 2751117413Skan } 2752117413Skan#endif 2753117413Skan 275418334Speter /* Run each piped subprocess. */ 275518334Speter 275618334Speter for (i = 0; i < n_commands; i++) 275718334Speter { 275850599Sobrien char *errmsg_fmt, *errmsg_arg; 275990277Sobrien const char *string = commands[i].argv[0]; 276018334Speter 276190277Sobrien /* For some bizarre reason, the second argument of execvp() is 276290277Sobrien char *const *, not const char *const *. */ 276390277Sobrien commands[i].pid = pexecute (string, (char *const *) commands[i].argv, 276450599Sobrien programname, temp_filename, 276550599Sobrien &errmsg_fmt, &errmsg_arg, 276650599Sobrien ((i == 0 ? PEXECUTE_FIRST : 0) 276750599Sobrien | (i + 1 == n_commands ? PEXECUTE_LAST : 0) 276850599Sobrien | (string == commands[i].prog 276950599Sobrien ? PEXECUTE_SEARCH : 0) 277050599Sobrien | (verbose_flag ? PEXECUTE_VERBOSE : 0))); 277118334Speter 277250599Sobrien if (commands[i].pid == -1) 277350599Sobrien pfatal_pexecute (errmsg_fmt, errmsg_arg); 277450599Sobrien 277518334Speter if (string != commands[i].prog) 2776132733Skan free ((void *) string); 277718334Speter } 277818334Speter 277918334Speter execution_count++; 278018334Speter 278118334Speter /* Wait for all the subprocesses to finish. 278218334Speter We don't care what order they finish in; 278318334Speter we know that N_COMMANDS waits will get them all. 278418334Speter Ignore subprocesses that we don't know about, 278518334Speter since they can be spawned by the process that exec'ed us. */ 278618334Speter 278718334Speter { 278818334Speter int ret_code = 0; 278990277Sobrien#ifdef HAVE_GETRUSAGE 279090277Sobrien struct timeval d; 279190277Sobrien double ut = 0.0, st = 0.0; 279290277Sobrien#endif 279318334Speter 279490277Sobrien for (i = 0; i < n_commands;) 279518334Speter { 279618334Speter int j; 279718334Speter int status; 279818334Speter int pid; 279918334Speter 280050599Sobrien pid = pwait (commands[i].pid, &status, 0); 280118334Speter if (pid < 0) 280218334Speter abort (); 280318334Speter 280490277Sobrien#ifdef HAVE_GETRUSAGE 280590277Sobrien if (report_times) 280690277Sobrien { 280790277Sobrien /* getrusage returns the total resource usage of all children 280890277Sobrien up to now. Copy the previous values into prus, get the 280990277Sobrien current statistics, then take the difference. */ 281090277Sobrien 281190277Sobrien prus = rus; 281290277Sobrien getrusage (RUSAGE_CHILDREN, &rus); 281390277Sobrien d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec; 281490277Sobrien d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec; 281590277Sobrien ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6; 281690277Sobrien 281790277Sobrien d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec; 281890277Sobrien d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec; 281990277Sobrien st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6; 282090277Sobrien } 282190277Sobrien#endif 282290277Sobrien 282318334Speter for (j = 0; j < n_commands; j++) 282418334Speter if (commands[j].pid == pid) 282518334Speter { 282618334Speter i++; 282790277Sobrien if (WIFSIGNALED (status)) 282818334Speter { 282990277Sobrien#ifdef SIGPIPE 283090277Sobrien /* SIGPIPE is a special case. It happens in -pipe mode 283190277Sobrien when the compiler dies before the preprocessor is 283290277Sobrien done, or the assembler dies before the compiler is 283390277Sobrien done. There's generally been an error already, and 283490277Sobrien this is just fallout. So don't generate another error 283590277Sobrien unless we would otherwise have succeeded. */ 283690277Sobrien if (WTERMSIG (status) == SIGPIPE 283790277Sobrien && (signal_count || greatest_status >= MIN_FATAL_STATUS)) 283890277Sobrien ; 283990277Sobrien else 284090277Sobrien#endif 284190277Sobrien fatal ("\ 284290277SobrienInternal error: %s (program %s)\n\ 284390277SobrienPlease submit a full bug report.\n\ 284490277SobrienSee %s for instructions.", 284590277Sobrien strsignal (WTERMSIG (status)), commands[j].prog, 2846117413Skan bug_report_url); 284790277Sobrien signal_count++; 284890277Sobrien ret_code = -1; 284918334Speter } 285090277Sobrien else if (WIFEXITED (status) 285190277Sobrien && WEXITSTATUS (status) >= MIN_FATAL_STATUS) 285290277Sobrien { 285390277Sobrien if (WEXITSTATUS (status) > greatest_status) 285490277Sobrien greatest_status = WEXITSTATUS (status); 285590277Sobrien ret_code = -1; 285690277Sobrien } 285790277Sobrien#ifdef HAVE_GETRUSAGE 285890277Sobrien if (report_times && ut + st != 0) 285990277Sobrien notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st); 286090277Sobrien#endif 286118334Speter break; 286218334Speter } 286318334Speter } 286418334Speter return ret_code; 286518334Speter } 286618334Speter} 286718334Speter 286818334Speter/* Find all the switches given to us 286918334Speter and make a vector describing them. 287018334Speter The elements of the vector are strings, one per switch given. 287118334Speter If a switch uses following arguments, then the `part1' field 287218334Speter is the switch itself and the `args' field 287318334Speter is a null-terminated vector containing the following arguments. 287490277Sobrien The `live_cond' field is: 287590277Sobrien 0 when initialized 287690277Sobrien 1 if the switch is true in a conditional spec, 287790277Sobrien -1 if false (overridden by a later switch) 2878132733Skan -2 if this switch should be ignored (used in %<S) 287952520Sobrien The `validated' field is nonzero if any spec has looked at this switch; 288018334Speter if it remains zero at the end of the run, it must be meaningless. */ 288118334Speter 288290277Sobrien#define SWITCH_OK 0 288390277Sobrien#define SWITCH_FALSE -1 288490277Sobrien#define SWITCH_IGNORE -2 288590277Sobrien#define SWITCH_LIVE 1 288690277Sobrien 288718334Speterstruct switchstr 288818334Speter{ 288952520Sobrien const char *part1; 289090277Sobrien const char **args; 289118334Speter int live_cond; 289290277Sobrien unsigned char validated; 289390277Sobrien unsigned char ordering; 289418334Speter}; 289518334Speter 289618334Speterstatic struct switchstr *switches; 289718334Speter 289818334Speterstatic int n_switches; 289918334Speter 290018334Speterstruct infile 290118334Speter{ 290252520Sobrien const char *name; 290352520Sobrien const char *language; 290418334Speter}; 290518334Speter 290618334Speter/* Also a vector of input files specified. */ 290718334Speter 290818334Speterstatic struct infile *infiles; 290918334Speter 291090277Sobrienint n_infiles; 291118334Speter 2912132733Skan/* True if multiple input files are being compiled to a single 2913132733Skan assembly file. */ 2914132733Skan 2915132733Skanstatic bool combine_inputs; 2916132733Skan 291752520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that 291850599Sobrien we can tell if there were any user supplied any files or libraries. */ 291950599Sobrien 292050599Sobrienstatic int added_libraries; 292150599Sobrien 292218334Speter/* And a vector of corresponding output files is made up later. */ 292318334Speter 292490277Sobrienconst char **outfiles; 292518334Speter 292650599Sobrien/* Used to track if none of the -B paths are used. */ 292750599Sobrienstatic int warn_B; 292850599Sobrien 292950599Sobrien/* Gives value to pass as "warn" to add_prefix for standard prefixes. */ 293050599Sobrienstatic int *warn_std_ptr = 0; 293150599Sobrien 293290277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 293350599Sobrien 293450599Sobrien/* Convert NAME to a new name if it is the standard suffix. DO_EXE 293590277Sobrien is true if we should look for an executable suffix. DO_OBJ 293690277Sobrien is true if we should look for an object suffix. */ 293750599Sobrien 293890277Sobrienstatic const char * 2939132733Skanconvert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED, 2940132733Skan int do_obj ATTRIBUTE_UNUSED) 294150599Sobrien{ 294290277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 294350599Sobrien int i; 294490277Sobrien#endif 294552520Sobrien int len; 294650599Sobrien 294752520Sobrien if (name == NULL) 294852520Sobrien return NULL; 294990277Sobrien 295052520Sobrien len = strlen (name); 295152520Sobrien 295290277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX 295390277Sobrien /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj". */ 295490277Sobrien if (do_obj && len > 2 295550599Sobrien && name[len - 2] == '.' 295650599Sobrien && name[len - 1] == 'o') 295750599Sobrien { 295850599Sobrien obstack_grow (&obstack, name, len - 2); 295990277Sobrien obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); 296050599Sobrien name = obstack_finish (&obstack); 296150599Sobrien } 296250599Sobrien#endif 296350599Sobrien 296490277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 296550599Sobrien /* If there is no filetype, make it the executable suffix (which includes 296650599Sobrien the "."). But don't get confused if we have just "-o". */ 296790277Sobrien if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-')) 296850599Sobrien return name; 296950599Sobrien 297050599Sobrien for (i = len - 1; i >= 0; i--) 297152520Sobrien if (IS_DIR_SEPARATOR (name[i])) 297250599Sobrien break; 297350599Sobrien 297450599Sobrien for (i++; i < len; i++) 297550599Sobrien if (name[i] == '.') 297650599Sobrien return name; 297750599Sobrien 297850599Sobrien obstack_grow (&obstack, name, len); 297990277Sobrien obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX, 298090277Sobrien strlen (TARGET_EXECUTABLE_SUFFIX)); 298150599Sobrien name = obstack_finish (&obstack); 298250599Sobrien#endif 298350599Sobrien 298450599Sobrien return name; 298550599Sobrien} 298650599Sobrien#endif 298750599Sobrien 298850599Sobrien/* Display the command line switches accepted by gcc. */ 298950599Sobrienstatic void 2990132733Skandisplay_help (void) 299150599Sobrien{ 299290277Sobrien printf (_("Usage: %s [options] file...\n"), programname); 299390277Sobrien fputs (_("Options:\n"), stdout); 299450599Sobrien 299590277Sobrien fputs (_(" -pass-exit-codes Exit with highest error code from a phase\n"), stdout); 299690277Sobrien fputs (_(" --help Display this information\n"), stdout); 299790277Sobrien fputs (_(" --target-help Display target specific command line options\n"), stdout); 299850599Sobrien if (! verbose_flag) 299990277Sobrien fputs (_(" (Use '-v --help' to display command line options of sub-processes)\n"), stdout); 300090277Sobrien fputs (_(" -dumpspecs Display all of the built in spec strings\n"), stdout); 300190277Sobrien fputs (_(" -dumpversion Display the version of the compiler\n"), stdout); 300290277Sobrien fputs (_(" -dumpmachine Display the compiler's target processor\n"), stdout); 300390277Sobrien fputs (_(" -print-search-dirs Display the directories in the compiler's search path\n"), stdout); 300490277Sobrien fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library\n"), stdout); 300590277Sobrien fputs (_(" -print-file-name=<lib> Display the full path to library <lib>\n"), stdout); 300690277Sobrien fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>\n"), stdout); 300790277Sobrien fputs (_(" -print-multi-directory Display the root directory for versions of libgcc\n"), stdout); 300890277Sobrien fputs (_("\ 300990277Sobrien -print-multi-lib Display the mapping between command line options and\n\ 301090277Sobrien multiple library search directories\n"), stdout); 3011104763Skan fputs (_(" -print-multi-os-directory Display the relative path to OS libraries\n"), stdout); 301290277Sobrien fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler\n"), stdout); 301390277Sobrien fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout); 301490277Sobrien fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker\n"), stdout); 3015132733Skan fputs (_(" -Xassembler <arg> Pass <arg> on to the assembler\n"), stdout); 3016132733Skan fputs (_(" -Xpreprocessor <arg> Pass <arg> on to the preprocessor\n"), stdout); 301790277Sobrien fputs (_(" -Xlinker <arg> Pass <arg> on to the linker\n"), stdout); 301890277Sobrien fputs (_(" -save-temps Do not delete intermediate files\n"), stdout); 301990277Sobrien fputs (_(" -pipe Use pipes rather than intermediate files\n"), stdout); 302090277Sobrien fputs (_(" -time Time the execution of each subprocess\n"), stdout); 302190277Sobrien fputs (_(" -specs=<file> Override built-in specs with the contents of <file>\n"), stdout); 302290277Sobrien fputs (_(" -std=<standard> Assume that the input sources are for <standard>\n"), stdout); 302390277Sobrien fputs (_(" -B <directory> Add <directory> to the compiler's search paths\n"), stdout); 302490277Sobrien fputs (_(" -b <machine> Run gcc for target <machine>, if installed\n"), stdout); 302590277Sobrien fputs (_(" -V <version> Run gcc version number <version>, if installed\n"), stdout); 302690277Sobrien fputs (_(" -v Display the programs invoked by the compiler\n"), stdout); 302790277Sobrien fputs (_(" -### Like -v but options quoted and commands not executed\n"), stdout); 302890277Sobrien fputs (_(" -E Preprocess only; do not compile, assemble or link\n"), stdout); 302990277Sobrien fputs (_(" -S Compile only; do not assemble or link\n"), stdout); 303090277Sobrien fputs (_(" -c Compile and assemble, but do not link\n"), stdout); 303190277Sobrien fputs (_(" -o <file> Place the output into <file>\n"), stdout); 303290277Sobrien fputs (_("\ 303390277Sobrien -x <language> Specify the language of the following input files\n\ 3034117413Skan Permissible languages include: c c++ assembler none\n\ 303590277Sobrien 'none' means revert to the default behavior of\n\ 303690277Sobrien guessing the language based on the file's extension\n\ 303790277Sobrien"), stdout); 303850599Sobrien 303990277Sobrien printf (_("\ 304090277Sobrien\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\ 304190277Sobrien passed on to the various sub-processes invoked by %s. In order to pass\n\ 304290277Sobrien other options on to these processes the -W<letter> options must be used.\n\ 304390277Sobrien"), programname); 304450599Sobrien 304550599Sobrien /* The rest of the options are displayed by invocations of the various 304650599Sobrien sub-processes. */ 304750599Sobrien} 304850599Sobrien 304990277Sobrienstatic void 3050132733Skanadd_preprocessor_option (const char *option, int len) 305190277Sobrien{ 305252520Sobrien n_preprocessor_options++; 305390277Sobrien 305452520Sobrien if (! preprocessor_options) 3055132733Skan preprocessor_options = xmalloc (n_preprocessor_options * sizeof (char *)); 305652520Sobrien else 3057132733Skan preprocessor_options = xrealloc (preprocessor_options, 3058132733Skan n_preprocessor_options * sizeof (char *)); 305990277Sobrien 306052520Sobrien preprocessor_options [n_preprocessor_options - 1] = 306152520Sobrien save_string (option, len); 306250599Sobrien} 306390277Sobrien 306490277Sobrienstatic void 3065132733Skanadd_assembler_option (const char *option, int len) 306652520Sobrien{ 306752520Sobrien n_assembler_options++; 306852520Sobrien 306952520Sobrien if (! assembler_options) 3070132733Skan assembler_options = xmalloc (n_assembler_options * sizeof (char *)); 307152520Sobrien else 3072132733Skan assembler_options = xrealloc (assembler_options, 3073132733Skan n_assembler_options * sizeof (char *)); 307452520Sobrien 307552520Sobrien assembler_options [n_assembler_options - 1] = save_string (option, len); 307650599Sobrien} 307790277Sobrien 307890277Sobrienstatic void 3079132733Skanadd_linker_option (const char *option, int len) 308052520Sobrien{ 308152520Sobrien n_linker_options++; 308252520Sobrien 308352520Sobrien if (! linker_options) 3084132733Skan linker_options = xmalloc (n_linker_options * sizeof (char *)); 308552520Sobrien else 3086132733Skan linker_options = xrealloc (linker_options, 3087132733Skan n_linker_options * sizeof (char *)); 308852520Sobrien 308952520Sobrien linker_options [n_linker_options - 1] = save_string (option, len); 309050599Sobrien} 309150599Sobrien 309218334Speter/* Create the vector `switches' and its contents. 309318334Speter Store its length in `n_switches'. */ 309418334Speter 309518334Speterstatic void 3096132733Skanprocess_command (int argc, const char **argv) 309718334Speter{ 309890277Sobrien int i; 309952520Sobrien const char *temp; 310052520Sobrien char *temp1; 310190277Sobrien const char *spec_lang = 0; 310218334Speter int last_language_n_infiles; 310350599Sobrien int have_c = 0; 310450599Sobrien int have_o = 0; 310550599Sobrien int lang_n_infiles = 0; 310690277Sobrien#ifdef MODIFY_TARGET_NAME 310790277Sobrien int is_modify_target_name; 310890277Sobrien int j; 310990277Sobrien#endif 311018334Speter 3111117413Skan GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX"); 311218334Speter 311318334Speter n_switches = 0; 311418334Speter n_infiles = 0; 311550599Sobrien added_libraries = 0; 311618334Speter 311718334Speter /* Figure compiler version from version string. */ 311818334Speter 311990277Sobrien compiler_version = temp1 = xstrdup (version_string); 312090277Sobrien 312152520Sobrien for (; *temp1; ++temp1) 312218334Speter { 312352520Sobrien if (*temp1 == ' ') 312418334Speter { 312552520Sobrien *temp1 = '\0'; 312618334Speter break; 312718334Speter } 312818334Speter } 312918334Speter 3130117413Skan /* If there is a -V or -b option (or both), process it now, before 3131117413Skan trying to interpret the rest of the command line. */ 3132117413Skan if (argc > 1 && argv[1][0] == '-' 3133117413Skan && (argv[1][1] == 'V' || argv[1][1] == 'b')) 3134117413Skan { 3135117413Skan const char *new_version = DEFAULT_TARGET_VERSION; 3136117413Skan const char *new_machine = DEFAULT_TARGET_MACHINE; 3137117413Skan const char *progname = argv[0]; 3138117413Skan char **new_argv; 3139117413Skan char *new_argv0; 3140117413Skan int baselen; 3141132733Skan 3142117413Skan while (argc > 1 && argv[1][0] == '-' 3143117413Skan && (argv[1][1] == 'V' || argv[1][1] == 'b')) 3144117413Skan { 3145117413Skan char opt = argv[1][1]; 3146117413Skan const char *arg; 3147117413Skan if (argv[1][2] != '\0') 3148117413Skan { 3149117413Skan arg = argv[1] + 2; 3150117413Skan argc -= 1; 3151117413Skan argv += 1; 3152117413Skan } 3153117413Skan else if (argc > 2) 3154117413Skan { 3155117413Skan arg = argv[2]; 3156117413Skan argc -= 2; 3157117413Skan argv += 2; 3158117413Skan } 3159117413Skan else 3160117413Skan fatal ("`-%c' option must have argument", opt); 3161117413Skan if (opt == 'V') 3162117413Skan new_version = arg; 3163117413Skan else 3164117413Skan new_machine = arg; 3165117413Skan } 3166117413Skan 3167117413Skan for (baselen = strlen (progname); baselen > 0; baselen--) 3168117413Skan if (IS_DIR_SEPARATOR (progname[baselen-1])) 3169117413Skan break; 3170132733Skan new_argv0 = xmemdup (progname, baselen, 3171117413Skan baselen + concat_length (new_version, new_machine, 3172117413Skan "-gcc-", NULL) + 1); 3173117413Skan strcpy (new_argv0 + baselen, new_machine); 3174117413Skan strcat (new_argv0, "-gcc-"); 3175117413Skan strcat (new_argv0, new_version); 3176117413Skan 3177117413Skan new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]), 3178117413Skan (argc + 1) * sizeof (argv[0])); 3179117413Skan new_argv[0] = new_argv0; 3180117413Skan 3181117413Skan execvp (new_argv0, new_argv); 3182117413Skan fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno)); 3183117413Skan } 3184117413Skan 318590277Sobrien /* Set up the default search paths. If there is no GCC_EXEC_PREFIX, 318690277Sobrien see if we can create it from the pathname specified in argv[0]. */ 318718334Speter 3188132733Skan gcc_libexec_prefix = standard_libexec_prefix; 318996736Sru#ifndef FREEBSD_NATIVE 319090277Sobrien#ifndef VMS 319190277Sobrien /* FIXME: make_relative_prefix doesn't yet work for VMS. */ 319290277Sobrien if (!gcc_exec_prefix) 319390277Sobrien { 319490277Sobrien gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix, 319590277Sobrien standard_exec_prefix); 3196132733Skan gcc_libexec_prefix = make_relative_prefix (argv[0], 3197132733Skan standard_bindir_prefix, 3198132733Skan standard_libexec_prefix); 319990277Sobrien if (gcc_exec_prefix) 320090277Sobrien putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL)); 320190277Sobrien } 3202132733Skan else 3203132733Skan gcc_libexec_prefix = make_relative_prefix (gcc_exec_prefix, 3204132733Skan standard_exec_prefix, 3205132733Skan standard_libexec_prefix); 3206132733Skan#else 320790277Sobrien#endif 320896736Sru#endif /* not FREEBSD_NATIVE */ 320990277Sobrien 321018334Speter if (gcc_exec_prefix) 321118334Speter { 321250599Sobrien int len = strlen (gcc_exec_prefix); 321390277Sobrien 3214132733Skan if (len > (int) sizeof ("/lib/gcc/") - 1 321552520Sobrien && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1]))) 321650599Sobrien { 3217132733Skan temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1; 321852520Sobrien if (IS_DIR_SEPARATOR (*temp) 321990277Sobrien && strncmp (temp + 1, "lib", 3) == 0 322052520Sobrien && IS_DIR_SEPARATOR (temp[4]) 3221132733Skan && strncmp (temp + 5, "gcc", 3) == 0) 3222132733Skan len -= sizeof ("/lib/gcc/") - 1; 322350599Sobrien } 322450599Sobrien 322550599Sobrien set_std_prefix (gcc_exec_prefix, len); 3226132733Skan add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC", 3227104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 322890277Sobrien add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 3229104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 323018334Speter } 323118334Speter 323218334Speter /* COMPILER_PATH and LIBRARY_PATH have values 323318334Speter that are lists of directory names with colons. */ 323418334Speter 3235117413Skan GET_ENVIRONMENT (temp, "COMPILER_PATH"); 323618334Speter if (temp) 323718334Speter { 323852520Sobrien const char *startp, *endp; 3239132733Skan char *nstore = alloca (strlen (temp) + 3); 324018334Speter 324118334Speter startp = endp = temp; 324218334Speter while (1) 324318334Speter { 324418334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 324518334Speter { 324690277Sobrien strncpy (nstore, startp, endp - startp); 324718334Speter if (endp == startp) 324890277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 324952520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 325018334Speter { 325190277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 325290277Sobrien nstore[endp - startp + 1] = 0; 325318334Speter } 325418334Speter else 325590277Sobrien nstore[endp - startp] = 0; 325690277Sobrien add_prefix (&exec_prefixes, nstore, 0, 3257104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 325850599Sobrien add_prefix (&include_prefixes, 325990277Sobrien concat (nstore, "include", NULL), 3260104763Skan 0, PREFIX_PRIORITY_LAST, 0, NULL, 0); 326118334Speter if (*endp == 0) 326218334Speter break; 326318334Speter endp = startp = endp + 1; 326418334Speter } 326518334Speter else 326618334Speter endp++; 326718334Speter } 326818334Speter } 326918334Speter 3270117413Skan GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV); 327191651Sobrien if (temp && *cross_compile == '0') 327218334Speter { 327352520Sobrien const char *startp, *endp; 3274132733Skan char *nstore = alloca (strlen (temp) + 3); 327518334Speter 327618334Speter startp = endp = temp; 327718334Speter while (1) 327818334Speter { 327918334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 328018334Speter { 328190277Sobrien strncpy (nstore, startp, endp - startp); 328218334Speter if (endp == startp) 328390277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 328452520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 328518334Speter { 328690277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 328790277Sobrien nstore[endp - startp + 1] = 0; 328818334Speter } 328918334Speter else 329090277Sobrien nstore[endp - startp] = 0; 329190277Sobrien add_prefix (&startfile_prefixes, nstore, NULL, 3292104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 329318334Speter if (*endp == 0) 329418334Speter break; 329518334Speter endp = startp = endp + 1; 329618334Speter } 329718334Speter else 329818334Speter endp++; 329918334Speter } 330018334Speter } 330118334Speter 330218334Speter /* Use LPATH like LIBRARY_PATH (for the CMU build program). */ 3303117413Skan GET_ENVIRONMENT (temp, "LPATH"); 330450599Sobrien if (temp && *cross_compile == '0') 330518334Speter { 330652520Sobrien const char *startp, *endp; 3307132733Skan char *nstore = alloca (strlen (temp) + 3); 330818334Speter 330918334Speter startp = endp = temp; 331018334Speter while (1) 331118334Speter { 331218334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 331318334Speter { 331490277Sobrien strncpy (nstore, startp, endp - startp); 331518334Speter if (endp == startp) 331690277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 331752520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 331818334Speter { 331990277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 332090277Sobrien nstore[endp - startp + 1] = 0; 332118334Speter } 332218334Speter else 332390277Sobrien nstore[endp - startp] = 0; 332490277Sobrien add_prefix (&startfile_prefixes, nstore, NULL, 3325104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 332618334Speter if (*endp == 0) 332718334Speter break; 332818334Speter endp = startp = endp + 1; 332918334Speter } 333018334Speter else 333118334Speter endp++; 333218334Speter } 333318334Speter } 333418334Speter 333577389Sobrien /* Options specified as if they appeared on the command line. */ 333677389Sobrien temp = getenv ("GCC_OPTIONS"); 333777389Sobrien if ((temp) && (strlen (temp) > 0)) 333877389Sobrien { 333977389Sobrien int len; 334077389Sobrien int optc = 1; 334177389Sobrien int new_argc; 3342110024Sobrien const char **new_argv; 334377389Sobrien char *envopts; 334477389Sobrien 334577389Sobrien while (isspace (*temp)) 334677389Sobrien temp++; 334777389Sobrien len = strlen (temp); 334877389Sobrien envopts = (char *) xmalloc (len + 1); 334977389Sobrien strcpy (envopts, temp); 335077389Sobrien 335177389Sobrien for (i = 0; i < (len - 1); i++) 335277389Sobrien if ((isspace (envopts[i])) && ! (isspace (envopts[i+1]))) 335377389Sobrien optc++; 335477389Sobrien 3355110024Sobrien new_argv = (const char **) alloca ((optc + argc) * sizeof(char *)); 335677389Sobrien 335777389Sobrien for (i = 0, new_argc = 1; new_argc <= optc; new_argc++) 335877389Sobrien { 335977389Sobrien while (isspace (envopts[i])) 336077389Sobrien i++; 336177389Sobrien new_argv[new_argc] = envopts + i; 336277389Sobrien while (!isspace (envopts[i]) && (envopts[i] != '\0')) 336377389Sobrien i++; 336477389Sobrien envopts[i++] = '\0'; 336577389Sobrien } 336677389Sobrien for (i = 1; i < argc; i++) 336777389Sobrien new_argv[new_argc++] = argv[i]; 336877389Sobrien 336977389Sobrien argv = new_argv; 337077389Sobrien argc = new_argc; 337177389Sobrien } 337277389Sobrien 337318334Speter /* Convert new-style -- options to old-style. */ 3374132733Skan translate_options (&argc, (const char *const **) &argv); 337518334Speter 337650599Sobrien /* Do language-specific adjustment/addition of flags. */ 3377132733Skan lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries); 337850599Sobrien 337918334Speter /* Scan argv twice. Here, the first time, just count how many switches 338018334Speter there will be in their vector, and how many input files in theirs. 338118334Speter Here we also parse the switches that cc itself uses (e.g. -v). */ 338218334Speter 338318334Speter for (i = 1; i < argc; i++) 338418334Speter { 338518334Speter if (! strcmp (argv[i], "-dumpspecs")) 338618334Speter { 338750599Sobrien struct spec_list *sl; 338850599Sobrien init_spec (); 338950599Sobrien for (sl = specs; sl; sl = sl->next) 339050599Sobrien printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec)); 339190277Sobrien if (link_command_spec) 339290277Sobrien printf ("*link_command:\n%s\n\n", link_command_spec); 339318334Speter exit (0); 339418334Speter } 339518334Speter else if (! strcmp (argv[i], "-dumpversion")) 339618334Speter { 339750599Sobrien printf ("%s\n", spec_version); 339818334Speter exit (0); 339918334Speter } 340018334Speter else if (! strcmp (argv[i], "-dumpmachine")) 340118334Speter { 340218334Speter printf ("%s\n", spec_machine); 340390277Sobrien exit (0); 340418334Speter } 340590277Sobrien else if (strcmp (argv[i], "-fversion") == 0) 340690277Sobrien { 340790277Sobrien /* translate_options () has turned --version into -fversion. */ 340890277Sobrien printf (_("%s (GCC) %s\n"), programname, version_string); 3409132733Skan printf ("Copyright %s 2004 Free Software Foundation, Inc.\n", 3410132733Skan _("(C)")); 341190277Sobrien fputs (_("This is free software; see the source for copying conditions. There is NO\n\ 341290277Sobrienwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"), 341390277Sobrien stdout); 341490277Sobrien exit (0); 341590277Sobrien } 341650599Sobrien else if (strcmp (argv[i], "-fhelp") == 0) 341750599Sobrien { 341850599Sobrien /* translate_options () has turned --help into -fhelp. */ 341950599Sobrien print_help_list = 1; 342050599Sobrien 342150599Sobrien /* We will be passing a dummy file on to the sub-processes. */ 342250599Sobrien n_infiles++; 342350599Sobrien n_switches++; 342490277Sobrien 342590277Sobrien /* CPP driver cannot obtain switch from cc1_options. */ 342690277Sobrien if (is_cpp_driver) 342790277Sobrien add_preprocessor_option ("--help", 6); 342850599Sobrien add_assembler_option ("--help", 6); 342950599Sobrien add_linker_option ("--help", 6); 343050599Sobrien } 343190277Sobrien else if (strcmp (argv[i], "-ftarget-help") == 0) 3432117413Skan { 3433117413Skan /* translate_options() has turned --target-help into -ftarget-help. */ 3434117413Skan target_help_flag = 1; 343590277Sobrien 3436117413Skan /* We will be passing a dummy file on to the sub-processes. */ 3437117413Skan n_infiles++; 3438117413Skan n_switches++; 343990277Sobrien 344090277Sobrien /* CPP driver cannot obtain switch from cc1_options. */ 344190277Sobrien if (is_cpp_driver) 344290277Sobrien add_preprocessor_option ("--target-help", 13); 3443117413Skan add_assembler_option ("--target-help", 13); 3444117413Skan add_linker_option ("--target-help", 13); 3445117413Skan } 344690277Sobrien else if (! strcmp (argv[i], "-pass-exit-codes")) 344790277Sobrien { 344890277Sobrien pass_exit_codes = 1; 344990277Sobrien n_switches++; 345090277Sobrien } 345118334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 345218334Speter print_search_dirs = 1; 345318334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 345418334Speter print_file_name = "libgcc.a"; 345518334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 345618334Speter print_file_name = argv[i] + 17; 345718334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 345818334Speter print_prog_name = argv[i] + 17; 345918334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 346018334Speter print_multi_lib = 1; 346118334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 346218334Speter print_multi_directory = 1; 3463104763Skan else if (! strcmp (argv[i], "-print-multi-os-directory")) 3464104763Skan print_multi_os_directory = 1; 346518334Speter else if (! strncmp (argv[i], "-Wa,", 4)) 346618334Speter { 346718334Speter int prev, j; 346818334Speter /* Pass the rest of this option to the assembler. */ 346918334Speter 347018334Speter /* Split the argument at commas. */ 347118334Speter prev = 4; 347218334Speter for (j = 4; argv[i][j]; j++) 347318334Speter if (argv[i][j] == ',') 347418334Speter { 347550599Sobrien add_assembler_option (argv[i] + prev, j - prev); 347618334Speter prev = j + 1; 347718334Speter } 347890277Sobrien 347918334Speter /* Record the part after the last comma. */ 348050599Sobrien add_assembler_option (argv[i] + prev, j - prev); 348118334Speter } 348218334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 348318334Speter { 348418334Speter int prev, j; 348518334Speter /* Pass the rest of this option to the preprocessor. */ 348618334Speter 348718334Speter /* Split the argument at commas. */ 348818334Speter prev = 4; 348918334Speter for (j = 4; argv[i][j]; j++) 349018334Speter if (argv[i][j] == ',') 349118334Speter { 349250599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 349318334Speter prev = j + 1; 349418334Speter } 349590277Sobrien 349618334Speter /* Record the part after the last comma. */ 349750599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 349818334Speter } 349918334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 350018334Speter /* The +e options to the C++ front-end. */ 350118334Speter n_switches++; 350218334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 350318334Speter { 350418334Speter int j; 350518334Speter /* Split the argument at commas. */ 350618334Speter for (j = 3; argv[i][j]; j++) 350718334Speter n_infiles += (argv[i][j] == ','); 350818334Speter } 350918334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 351018334Speter { 351118334Speter if (i + 1 == argc) 351218334Speter fatal ("argument to `-Xlinker' is missing"); 351318334Speter 351418334Speter n_infiles++; 351518334Speter i++; 351618334Speter } 3517132733Skan else if (strcmp (argv[i], "-Xpreprocessor") == 0) 3518132733Skan { 3519132733Skan if (i + 1 == argc) 3520132733Skan fatal ("argument to `-Xpreprocessor' is missing"); 3521132733Skan 3522132733Skan add_preprocessor_option (argv[i+1], strlen (argv[i+1])); 3523132733Skan } 3524132733Skan else if (strcmp (argv[i], "-Xassembler") == 0) 3525132733Skan { 3526132733Skan if (i + 1 == argc) 3527132733Skan fatal ("argument to `-Xassembler' is missing"); 3528132733Skan 3529132733Skan add_assembler_option (argv[i+1], strlen (argv[i+1])); 3530132733Skan } 353177389Sobrien else if (strcmp (argv[i], "-l") == 0) 353277389Sobrien { 353377389Sobrien if (i + 1 == argc) 353477389Sobrien fatal ("argument to `-l' is missing"); 353577389Sobrien 353677389Sobrien n_infiles++; 353777389Sobrien i++; 353877389Sobrien } 353918334Speter else if (strncmp (argv[i], "-l", 2) == 0) 354018334Speter n_infiles++; 354150599Sobrien else if (strcmp (argv[i], "-save-temps") == 0) 354250599Sobrien { 354350599Sobrien save_temps_flag = 1; 354450599Sobrien n_switches++; 354550599Sobrien } 354650599Sobrien else if (strcmp (argv[i], "-specs") == 0) 354750599Sobrien { 3548132733Skan struct user_specs *user = xmalloc (sizeof (struct user_specs)); 354950599Sobrien if (++i >= argc) 355050599Sobrien fatal ("argument to `-specs' is missing"); 355150599Sobrien 355290277Sobrien user->next = (struct user_specs *) 0; 355350599Sobrien user->filename = argv[i]; 355450599Sobrien if (user_specs_tail) 355550599Sobrien user_specs_tail->next = user; 355650599Sobrien else 355750599Sobrien user_specs_head = user; 355850599Sobrien user_specs_tail = user; 355950599Sobrien } 356050599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 356150599Sobrien { 3562132733Skan struct user_specs *user = xmalloc (sizeof (struct user_specs)); 356350599Sobrien if (strlen (argv[i]) == 7) 356450599Sobrien fatal ("argument to `-specs=' is missing"); 356550599Sobrien 356690277Sobrien user->next = (struct user_specs *) 0; 356790277Sobrien user->filename = argv[i] + 7; 356850599Sobrien if (user_specs_tail) 356950599Sobrien user_specs_tail->next = user; 357050599Sobrien else 357150599Sobrien user_specs_head = user; 357250599Sobrien user_specs_tail = user; 357350599Sobrien } 357490277Sobrien else if (strcmp (argv[i], "-time") == 0) 357590277Sobrien report_times = 1; 3576132733Skan else if (strcmp (argv[i], "-pipe") == 0) 3577132733Skan { 3578132733Skan /* -pipe has to go into the switches array as well as 3579132733Skan setting a flag. */ 3580132733Skan use_pipes = 1; 3581132733Skan n_switches++; 3582132733Skan } 358390277Sobrien else if (strcmp (argv[i], "-###") == 0) 358490277Sobrien { 358590277Sobrien /* This is similar to -v except that there is no execution 358690277Sobrien of the commands and the echoed arguments are quoted. It 358790277Sobrien is intended for use in shell scripts to capture the 358890277Sobrien driver-generated command line. */ 358990277Sobrien verbose_only_flag++; 359090277Sobrien verbose_flag++; 359190277Sobrien } 359218334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 359318334Speter { 359490277Sobrien const char *p = &argv[i][1]; 359590277Sobrien int c = *p; 359618334Speter 359718334Speter switch (c) 359818334Speter { 359918334Speter case 'b': 3600117413Skan case 'V': 3601117413Skan fatal ("`-%c' must come at the start of the command line", c); 360218334Speter break; 360318334Speter 360418334Speter case 'B': 360518334Speter { 360690277Sobrien const char *value; 360790277Sobrien int len; 360890277Sobrien 360918334Speter if (p[1] == 0 && i + 1 == argc) 361018334Speter fatal ("argument to `-B' is missing"); 361118334Speter if (p[1] == 0) 361218334Speter value = argv[++i]; 361318334Speter else 361418334Speter value = p + 1; 361518334Speter 361690277Sobrien len = strlen (value); 361790277Sobrien 361890277Sobrien /* Catch the case where the user has forgotten to append a 361990277Sobrien directory separator to the path. Note, they may be using 362090277Sobrien -B to add an executable name prefix, eg "i386-elf-", in 362190277Sobrien order to distinguish between multiple installations of 362290277Sobrien GCC in the same directory. Hence we must check to see 362390277Sobrien if appending a directory separator actually makes a 362490277Sobrien valid directory name. */ 362590277Sobrien if (! IS_DIR_SEPARATOR (value [len - 1]) 362690277Sobrien && is_directory (value, "", 0)) 362790277Sobrien { 362890277Sobrien char *tmp = xmalloc (len + 2); 362990277Sobrien strcpy (tmp, value); 363090277Sobrien tmp[len] = DIR_SEPARATOR; 363190277Sobrien tmp[++ len] = 0; 363290277Sobrien value = tmp; 363390277Sobrien } 3634117413Skan 363590277Sobrien /* As a kludge, if the arg is "[foo/]stageN/", just 363690277Sobrien add "[foo/]include" to the include prefix. */ 363790277Sobrien if ((len == 7 363890277Sobrien || (len > 7 363990277Sobrien && (IS_DIR_SEPARATOR (value[len - 8])))) 364090277Sobrien && strncmp (value + len - 7, "stage", 5) == 0 364190277Sobrien && ISDIGIT (value[len - 2]) 364290277Sobrien && (IS_DIR_SEPARATOR (value[len - 1]))) 364390277Sobrien { 364490277Sobrien if (len == 7) 364590277Sobrien add_prefix (&include_prefixes, "include", NULL, 3646104763Skan PREFIX_PRIORITY_B_OPT, 0, NULL, 0); 364790277Sobrien else 364890277Sobrien { 364990277Sobrien char * string = xmalloc (len + 1); 365090277Sobrien 365190277Sobrien strncpy (string, value, len - 7); 365290277Sobrien strcpy (string + len - 7, "include"); 365390277Sobrien add_prefix (&include_prefixes, string, NULL, 3654104763Skan PREFIX_PRIORITY_B_OPT, 0, NULL, 0); 365590277Sobrien } 365690277Sobrien } 365790277Sobrien 365890277Sobrien add_prefix (&exec_prefixes, value, NULL, 3659104763Skan PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0); 366090277Sobrien add_prefix (&startfile_prefixes, value, NULL, 3661104763Skan PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0); 366290277Sobrien add_prefix (&include_prefixes, concat (value, "include", NULL), 3663104763Skan NULL, PREFIX_PRIORITY_B_OPT, 0, NULL, 0); 366490277Sobrien n_switches++; 366518334Speter } 366618334Speter break; 366718334Speter 366818334Speter case 'v': /* Print our subcommands and print versions. */ 366918334Speter n_switches++; 367018334Speter /* If they do anything other than exactly `-v', don't set 367118334Speter verbose_flag; rather, continue on to give the error. */ 367218334Speter if (p[1] != 0) 367318334Speter break; 367418334Speter verbose_flag++; 367518334Speter break; 367618334Speter 367750599Sobrien case 'S': 367850599Sobrien case 'c': 367950599Sobrien if (p[1] == 0) 368018334Speter { 368150599Sobrien have_c = 1; 368218334Speter n_switches++; 368318334Speter break; 368418334Speter } 368550599Sobrien goto normal_switch; 368650599Sobrien 368750599Sobrien case 'o': 368850599Sobrien have_o = 1; 368990277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 369050599Sobrien if (! have_c) 369150599Sobrien { 369250599Sobrien int skip; 369390277Sobrien 369450599Sobrien /* Forward scan, just in case -S or -c is specified 369550599Sobrien after -o. */ 369650599Sobrien int j = i + 1; 369750599Sobrien if (p[1] == 0) 369850599Sobrien ++j; 369950599Sobrien while (j < argc) 370050599Sobrien { 370150599Sobrien if (argv[j][0] == '-') 370250599Sobrien { 370350599Sobrien if (SWITCH_CURTAILS_COMPILATION (argv[j][1]) 370450599Sobrien && argv[j][2] == 0) 370550599Sobrien { 370650599Sobrien have_c = 1; 370750599Sobrien break; 370850599Sobrien } 370990277Sobrien else if ((skip = SWITCH_TAKES_ARG (argv[j][1]))) 371050599Sobrien j += skip - (argv[j][2] != 0); 371190277Sobrien else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1))) 371250599Sobrien j += skip; 371350599Sobrien } 371450599Sobrien j++; 371550599Sobrien } 371650599Sobrien } 371750599Sobrien#endif 371890277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX) 371950599Sobrien if (p[1] == 0) 372090277Sobrien argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0); 372150599Sobrien else 372290277Sobrien argv[i] = convert_filename (argv[i], ! have_c, 0); 372350599Sobrien#endif 372450599Sobrien goto normal_switch; 372550599Sobrien 372618334Speter default: 372750599Sobrien normal_switch: 372890277Sobrien 372990277Sobrien#ifdef MODIFY_TARGET_NAME 373090277Sobrien is_modify_target_name = 0; 373190277Sobrien 3732117413Skan for (j = 0; j < ARRAY_SIZE (modify_target); j++) 373390277Sobrien if (! strcmp (argv[i], modify_target[j].sw)) 373490277Sobrien { 3735132733Skan char *new_name = xmalloc (strlen (modify_target[j].str) 3736132733Skan + strlen (spec_machine)); 373790277Sobrien const char *p, *r; 373890277Sobrien char *q; 373990277Sobrien int made_addition = 0; 374090277Sobrien 374190277Sobrien is_modify_target_name = 1; 374290277Sobrien for (p = spec_machine, q = new_name; *p != 0; ) 374390277Sobrien { 374490277Sobrien if (modify_target[j].add_del == DELETE 374590277Sobrien && (! strncmp (q, modify_target[j].str, 374690277Sobrien strlen (modify_target[j].str)))) 374790277Sobrien p += strlen (modify_target[j].str); 374890277Sobrien else if (modify_target[j].add_del == ADD 374990277Sobrien && ! made_addition && *p == '-') 375090277Sobrien { 375190277Sobrien for (r = modify_target[j].str; *r != 0; ) 375290277Sobrien *q++ = *r++; 375390277Sobrien made_addition = 1; 375490277Sobrien } 375590277Sobrien 375690277Sobrien *q++ = *p++; 375790277Sobrien } 375890277Sobrien 375990277Sobrien spec_machine = new_name; 376090277Sobrien } 376190277Sobrien 376290277Sobrien if (is_modify_target_name) 376390277Sobrien break; 3764117413Skan#endif 376590277Sobrien 376618334Speter n_switches++; 376718334Speter 376818334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 376918334Speter i += SWITCH_TAKES_ARG (c) - (p[1] != 0); 377018334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 377118334Speter i += WORD_SWITCH_TAKES_ARG (p); 377218334Speter } 377318334Speter } 377418334Speter else 377550599Sobrien { 377650599Sobrien n_infiles++; 377750599Sobrien lang_n_infiles++; 377850599Sobrien } 377918334Speter } 378018334Speter 3781132733Skan combine_inputs = (have_c && have_o && lang_n_infiles > 1); 378250599Sobrien 3783132733Skan if ((save_temps_flag || report_times) && use_pipes) 3784132733Skan { 3785132733Skan /* -save-temps overrides -pipe, so that temp files are produced */ 3786132733Skan if (save_temps_flag) 3787132733Skan error ("warning: -pipe ignored because -save-temps specified"); 3788132733Skan /* -time overrides -pipe because we can't get correct stats when 3789132733Skan multiple children are running at once. */ 3790132733Skan else if (report_times) 3791132733Skan error ("warning: -pipe ignored because -time specified"); 3792132733Skan 3793132733Skan use_pipes = 0; 3794132733Skan } 3795132733Skan 379618334Speter /* Set up the search paths before we go looking for config files. */ 379718334Speter 379818334Speter /* These come before the md prefixes so that we will find gcc's subcommands 379918334Speter (such as cpp) rather than those of the host system. */ 380018334Speter /* Use 2 as fourth arg meaning try just the machine as a suffix, 380118334Speter as well as trying the machine and the version. */ 380218346Speter#ifdef FREEBSD_NATIVE 3803104953Sobrien add_prefix (&exec_prefixes, PREFIX"/bin/", "BINUTILS", 3804122632Skan PREFIX_PRIORITY_LAST, 0, warn_std_ptr, 0); 380591561Sobrien#endif /* FREEBSD_NATIVE */ 380618334Speter#ifndef OS2 3807132733Skan add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC", 3808104763Skan PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); 3809132733Skan add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS", 3810132733Skan PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); 3811132733Skan#ifndef FREEBSD_NATIVE 381250599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", 3813104763Skan PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); 381450599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS", 3815104763Skan PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); 3816132733Skan add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS", 3817132733Skan PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); 3818132733Skan#endif /* FREEBSD_NATIVE */ 381918334Speter#endif 382018334Speter 382191578Sobrien#ifndef FREEBSD_NATIVE 382250599Sobrien add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", 3823104763Skan PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); 3824132733Skan add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS", 3825104763Skan PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); 382691561Sobrien#endif /* not FREEBSD_NATIVE */ 382718334Speter 382890277Sobrien tooldir_prefix = concat (tooldir_base_prefix, spec_machine, 382990277Sobrien dir_separator_str, NULL); 383018334Speter 383118334Speter /* If tooldir is relative, base it on exec_prefixes. A relative 383218334Speter tooldir lets us move the installed tree as a unit. 383318334Speter 383418334Speter If GCC_EXEC_PREFIX is defined, then we want to add two relative 383518334Speter directories, so that we can search both the user specified directory 383618334Speter and the standard place. */ 383718334Speter 3838132733Skan if (!IS_ABSOLUTE_PATH (tooldir_prefix)) 383918334Speter { 384018334Speter if (gcc_exec_prefix) 384118334Speter { 384218334Speter char *gcc_exec_tooldir_prefix 384350599Sobrien = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 384490277Sobrien spec_version, dir_separator_str, tooldir_prefix, NULL); 384518334Speter 384618334Speter add_prefix (&exec_prefixes, 384790277Sobrien concat (gcc_exec_tooldir_prefix, "bin", 384890277Sobrien dir_separator_str, NULL), 3849104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 0); 385018334Speter add_prefix (&startfile_prefixes, 385190277Sobrien concat (gcc_exec_tooldir_prefix, "lib", 385290277Sobrien dir_separator_str, NULL), 3853104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); 385418334Speter } 385518334Speter 385650599Sobrien tooldir_prefix = concat (standard_exec_prefix, spec_machine, 385790277Sobrien dir_separator_str, spec_version, 385890277Sobrien dir_separator_str, tooldir_prefix, NULL); 385918334Speter } 386018334Speter 386118346Speter#ifndef FREEBSD_NATIVE 386290277Sobrien add_prefix (&exec_prefixes, 386390277Sobrien concat (tooldir_prefix, "bin", dir_separator_str, NULL), 3864104763Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 0); 386518334Speter add_prefix (&startfile_prefixes, 386690277Sobrien concat (tooldir_prefix, "lib", dir_separator_str, NULL), 3867104763Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); 3868132733Skan 3869132733Skan#if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS) 3870132733Skan /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix, 3871132733Skan then consider it to relocate with the rest of the GCC installation 3872132733Skan if GCC_EXEC_PREFIX is set. 3873132733Skan ``make_relative_prefix'' is not compiled for VMS, so don't call it. */ 3874132733Skan if (target_system_root && gcc_exec_prefix) 3875132733Skan { 3876132733Skan char *tmp_prefix = make_relative_prefix (argv[0], 3877132733Skan standard_bindir_prefix, 3878132733Skan target_system_root); 3879132733Skan if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0) 3880132733Skan { 3881132733Skan target_system_root = tmp_prefix; 3882132733Skan target_system_root_changed = 1; 3883132733Skan } 3884132733Skan } 3885132733Skan#endif 388618346Speter#endif /* FREEBSD_NATIVE */ 388718334Speter 388818334Speter /* More prefixes are enabled in main, after we read the specs file 388918334Speter and determine whether this is cross-compilation or not. */ 389018334Speter 389118334Speter /* Then create the space for the vectors and scan again. */ 389218334Speter 3893132733Skan switches = xmalloc ((n_switches + 1) * sizeof (struct switchstr)); 3894132733Skan infiles = xmalloc ((n_infiles + 1) * sizeof (struct infile)); 389518334Speter n_switches = 0; 389618334Speter n_infiles = 0; 389718334Speter last_language_n_infiles = -1; 389818334Speter 389918334Speter /* This, time, copy the text of each switch and store a pointer 390018334Speter to the copy in the vector of switches. 390118334Speter Store all the infiles in their vector. */ 390218334Speter 390318334Speter for (i = 1; i < argc; i++) 390418334Speter { 390518334Speter /* Just skip the switches that were handled by the preceding loop. */ 390690277Sobrien#ifdef MODIFY_TARGET_NAME 390790277Sobrien is_modify_target_name = 0; 390890277Sobrien 3909117413Skan for (j = 0; j < ARRAY_SIZE (modify_target); j++) 391090277Sobrien if (! strcmp (argv[i], modify_target[j].sw)) 391190277Sobrien is_modify_target_name = 1; 391290277Sobrien 391390277Sobrien if (is_modify_target_name) 391490277Sobrien ; 391590277Sobrien else 391690277Sobrien#endif 391718334Speter if (! strncmp (argv[i], "-Wa,", 4)) 391818334Speter ; 391918334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 392018334Speter ; 392190277Sobrien else if (! strcmp (argv[i], "-pass-exit-codes")) 392290277Sobrien ; 392318334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 392418334Speter ; 392518334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 392618334Speter ; 392718334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 392818334Speter ; 392918334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 393018334Speter ; 393118334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 393218334Speter ; 393318334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 393418334Speter ; 3935104763Skan else if (! strcmp (argv[i], "-print-multi-os-directory")) 3936104763Skan ; 393790277Sobrien else if (! strcmp (argv[i], "-ftarget-help")) 393890277Sobrien ; 393990277Sobrien else if (! strcmp (argv[i], "-fhelp")) 394090277Sobrien ; 394118334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 394218334Speter { 394318334Speter /* Compensate for the +e options to the C++ front-end; 394418334Speter they're there simply for cfront call-compatibility. We do 394518334Speter some magic in default_compilers to pass them down properly. 394618334Speter Note we deliberately start at the `+' here, to avoid passing 394718334Speter -e0 or -e1 down into the linker. */ 394818334Speter switches[n_switches].part1 = &argv[i][0]; 394918334Speter switches[n_switches].args = 0; 395090277Sobrien switches[n_switches].live_cond = SWITCH_OK; 395152520Sobrien switches[n_switches].validated = 0; 395218334Speter n_switches++; 395318334Speter } 395418334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 395518334Speter { 395618334Speter int prev, j; 395718334Speter /* Split the argument at commas. */ 395818334Speter prev = 4; 395918334Speter for (j = 4; argv[i][j]; j++) 396018334Speter if (argv[i][j] == ',') 396118334Speter { 396250599Sobrien infiles[n_infiles].language = "*"; 396318334Speter infiles[n_infiles++].name 396418334Speter = save_string (argv[i] + prev, j - prev); 396518334Speter prev = j + 1; 396618334Speter } 396718334Speter /* Record the part after the last comma. */ 396850599Sobrien infiles[n_infiles].language = "*"; 396918334Speter infiles[n_infiles++].name = argv[i] + prev; 397018334Speter } 397118334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 397218334Speter { 397350599Sobrien infiles[n_infiles].language = "*"; 397418334Speter infiles[n_infiles++].name = argv[++i]; 397518334Speter } 3976132733Skan else if (strcmp (argv[i], "-Xassembler") == 0) 3977132733Skan { 3978132733Skan infiles[n_infiles].language = "*"; 3979132733Skan infiles[n_infiles++].name = argv[++i]; 3980132733Skan } 3981132733Skan else if (strcmp (argv[i], "-Xpreprocessor") == 0) 3982132733Skan { 3983132733Skan infiles[n_infiles].language = "*"; 3984132733Skan infiles[n_infiles++].name = argv[++i]; 3985132733Skan } 398677389Sobrien else if (strcmp (argv[i], "-l") == 0) 398777389Sobrien { /* POSIX allows separation of -l and the lib arg; 398877389Sobrien canonicalize by concatenating -l with its arg */ 398977389Sobrien infiles[n_infiles].language = "*"; 399077389Sobrien infiles[n_infiles++].name = concat ("-l", argv[++i], NULL); 399177389Sobrien } 399218334Speter else if (strncmp (argv[i], "-l", 2) == 0) 399318334Speter { 399450599Sobrien infiles[n_infiles].language = "*"; 399518334Speter infiles[n_infiles++].name = argv[i]; 399618334Speter } 399750599Sobrien else if (strcmp (argv[i], "-specs") == 0) 399850599Sobrien i++; 399950599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 400050599Sobrien ; 400190277Sobrien else if (strcmp (argv[i], "-time") == 0) 400290277Sobrien ; 400390277Sobrien else if (strcmp (argv[i], "-###") == 0) 400490277Sobrien ; 400518334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 400618334Speter { 400790277Sobrien const char *p = &argv[i][1]; 400890277Sobrien int c = *p; 400918334Speter 401018334Speter if (c == 'x') 401118334Speter { 401218334Speter if (p[1] == 0 && i + 1 == argc) 401318334Speter fatal ("argument to `-x' is missing"); 401418334Speter if (p[1] == 0) 401518334Speter spec_lang = argv[++i]; 401618334Speter else 401718334Speter spec_lang = p + 1; 401818334Speter if (! strcmp (spec_lang, "none")) 401918334Speter /* Suppress the warning if -xnone comes after the last input 402018334Speter file, because alternate command interfaces like g++ might 402118334Speter find it useful to place -xnone after each input file. */ 402218334Speter spec_lang = 0; 402318334Speter else 402418334Speter last_language_n_infiles = n_infiles; 402518334Speter continue; 402618334Speter } 402718334Speter switches[n_switches].part1 = p; 402818334Speter /* Deal with option arguments in separate argv elements. */ 402918334Speter if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) 403018334Speter || WORD_SWITCH_TAKES_ARG (p)) 403118334Speter { 403218334Speter int j = 0; 403318334Speter int n_args = WORD_SWITCH_TAKES_ARG (p); 403418334Speter 403518334Speter if (n_args == 0) 403618334Speter { 403718334Speter /* Count only the option arguments in separate argv elements. */ 403818334Speter n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); 403918334Speter } 404018334Speter if (i + n_args >= argc) 404118334Speter fatal ("argument to `-%s' is missing", p); 404218334Speter switches[n_switches].args 4043132733Skan = xmalloc ((n_args + 1) * sizeof(const char *)); 404418334Speter while (j < n_args) 404518334Speter switches[n_switches].args[j++] = argv[++i]; 404618334Speter /* Null-terminate the vector. */ 404718334Speter switches[n_switches].args[j] = 0; 404818334Speter } 404990277Sobrien else if (strchr (switches_need_spaces, c)) 405018334Speter { 405150599Sobrien /* On some systems, ld cannot handle some options without 405250599Sobrien a space. So split the option from its argument. */ 4053132733Skan char *part1 = xmalloc (2); 405450599Sobrien part1[0] = c; 405550599Sobrien part1[1] = '\0'; 405690277Sobrien 405750599Sobrien switches[n_switches].part1 = part1; 4058132733Skan switches[n_switches].args = xmalloc (2 * sizeof (const char *)); 405990277Sobrien switches[n_switches].args[0] = xstrdup (p+1); 406018334Speter switches[n_switches].args[1] = 0; 406118334Speter } 406218334Speter else 406318334Speter switches[n_switches].args = 0; 406418334Speter 406590277Sobrien switches[n_switches].live_cond = SWITCH_OK; 406652520Sobrien switches[n_switches].validated = 0; 406790277Sobrien switches[n_switches].ordering = 0; 4068132733Skan /* These are always valid, since gcc.c itself understands them. */ 406990277Sobrien if (!strcmp (p, "save-temps") 407090277Sobrien || !strcmp (p, "static-libgcc") 4071132733Skan || !strcmp (p, "shared-libgcc") 4072132733Skan || !strcmp (p, "pipe")) 407352520Sobrien switches[n_switches].validated = 1; 407490277Sobrien else 407590277Sobrien { 407690277Sobrien char ch = switches[n_switches].part1[0]; 4077117413Skan if (ch == 'B') 407890277Sobrien switches[n_switches].validated = 1; 407990277Sobrien } 408018334Speter n_switches++; 408118334Speter } 408218334Speter else 408318334Speter { 408490277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX 408590277Sobrien argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK)); 408618334Speter#endif 408718334Speter 408890277Sobrien if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0) 408918334Speter { 409018334Speter perror_with_name (argv[i]); 409118334Speter error_count++; 409218334Speter } 409318334Speter else 409418334Speter { 409518334Speter infiles[n_infiles].language = spec_lang; 409618334Speter infiles[n_infiles++].name = argv[i]; 409718334Speter } 409818334Speter } 409918334Speter } 410018334Speter 410118334Speter if (n_infiles == last_language_n_infiles && spec_lang != 0) 410290277Sobrien error ("warning: `-x %s' after last input file has no effect", spec_lang); 410318334Speter 410490277Sobrien /* Ensure we only invoke each subprocess once. */ 410590277Sobrien if (target_help_flag || print_help_list) 410690277Sobrien { 410790277Sobrien n_infiles = 1; 410890277Sobrien 410990277Sobrien /* Create a dummy input file, so that we can pass --target-help on to 411090277Sobrien the various sub-processes. */ 411190277Sobrien infiles[0].language = "c"; 411290277Sobrien infiles[0].name = "help-dummy"; 411390277Sobrien 411490277Sobrien if (target_help_flag) 411590277Sobrien { 411690277Sobrien switches[n_switches].part1 = "--target-help"; 411790277Sobrien switches[n_switches].args = 0; 411890277Sobrien switches[n_switches].live_cond = SWITCH_OK; 411990277Sobrien switches[n_switches].validated = 0; 412090277Sobrien 412190277Sobrien n_switches++; 412290277Sobrien } 412390277Sobrien 412490277Sobrien if (print_help_list) 412590277Sobrien { 412690277Sobrien switches[n_switches].part1 = "--help"; 412790277Sobrien switches[n_switches].args = 0; 412890277Sobrien switches[n_switches].live_cond = SWITCH_OK; 412990277Sobrien switches[n_switches].validated = 0; 413090277Sobrien 413190277Sobrien n_switches++; 413290277Sobrien } 413390277Sobrien } 413490277Sobrien 413518334Speter switches[n_switches].part1 = 0; 413618334Speter infiles[n_infiles].name = 0; 413718334Speter} 413890277Sobrien 4139132733Skan/* Store switches not filtered out by %<S in spec in COLLECT_GCC_OPTIONS 414090277Sobrien and place that in the environment. */ 414190277Sobrien 414290277Sobrienstatic void 4143132733Skanset_collect_gcc_options (void) 414490277Sobrien{ 414590277Sobrien int i; 414690277Sobrien int first_time; 414790277Sobrien 414890277Sobrien /* Build COLLECT_GCC_OPTIONS to have all of the options specified to 414990277Sobrien the compiler. */ 415090277Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=", 415190277Sobrien sizeof ("COLLECT_GCC_OPTIONS=") - 1); 415290277Sobrien 415390277Sobrien first_time = TRUE; 415490277Sobrien for (i = 0; (int) i < n_switches; i++) 415590277Sobrien { 415690277Sobrien const char *const *args; 415790277Sobrien const char *p, *q; 415890277Sobrien if (!first_time) 415990277Sobrien obstack_grow (&collect_obstack, " ", 1); 416090277Sobrien 416190277Sobrien first_time = FALSE; 416290277Sobrien 416390277Sobrien /* Ignore elided switches. */ 416490277Sobrien if (switches[i].live_cond == SWITCH_IGNORE) 416590277Sobrien continue; 416690277Sobrien 416790277Sobrien obstack_grow (&collect_obstack, "'-", 2); 416890277Sobrien q = switches[i].part1; 416990277Sobrien while ((p = strchr (q, '\''))) 417090277Sobrien { 417190277Sobrien obstack_grow (&collect_obstack, q, p - q); 417290277Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 417390277Sobrien q = ++p; 417490277Sobrien } 417590277Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 417690277Sobrien obstack_grow (&collect_obstack, "'", 1); 417790277Sobrien 417890277Sobrien for (args = switches[i].args; args && *args; args++) 417990277Sobrien { 418090277Sobrien obstack_grow (&collect_obstack, " '", 2); 418190277Sobrien q = *args; 418290277Sobrien while ((p = strchr (q, '\''))) 418390277Sobrien { 418490277Sobrien obstack_grow (&collect_obstack, q, p - q); 418590277Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 418690277Sobrien q = ++p; 418790277Sobrien } 418890277Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 418990277Sobrien obstack_grow (&collect_obstack, "'", 1); 419090277Sobrien } 419190277Sobrien } 419290277Sobrien obstack_grow (&collect_obstack, "\0", 1); 419390277Sobrien putenv (obstack_finish (&collect_obstack)); 419490277Sobrien} 419518334Speter 419618334Speter/* Process a spec string, accumulating and running commands. */ 419718334Speter 419818334Speter/* These variables describe the input file name. 419918334Speter input_file_number is the index on outfiles of this file, 420018334Speter so that the output file name can be stored for later use by %o. 420118334Speter input_basename is the start of the part of the input file 420218334Speter sans all directory names, and basename_length is the number 420318334Speter of characters starting there excluding the suffix .c or whatever. */ 420418334Speter 4205132733Skanstatic const char *input_filename; 420618334Speterstatic int input_file_number; 420750599Sobriensize_t input_filename_length; 420818334Speterstatic int basename_length; 420990277Sobrienstatic int suffixed_basename_length; 421052520Sobrienstatic const char *input_basename; 421152520Sobrienstatic const char *input_suffix; 421290277Sobrienstatic struct stat input_stat; 421390277Sobrienstatic int input_stat_set; 421418334Speter 421590277Sobrien/* The compiler used to process the current input file. */ 421690277Sobrienstatic struct compiler *input_file_compiler; 421790277Sobrien 421818334Speter/* These are variables used within do_spec and do_spec_1. */ 421918334Speter 422018334Speter/* Nonzero if an arg has been started and not yet terminated 422118334Speter (with space, tab or newline). */ 422218334Speterstatic int arg_going; 422318334Speter 422418334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated 422518334Speter is a temporary file name. */ 422618334Speterstatic int delete_this_arg; 422718334Speter 422818334Speter/* Nonzero means %w has been seen; the next arg to be terminated 422918334Speter is the output file name of this compilation. */ 423018334Speterstatic int this_is_output_file; 423118334Speter 423218334Speter/* Nonzero means %s has been seen; the next arg to be terminated 423318334Speter is the name of a library file and we should try the standard 423418334Speter search dirs for it. */ 423518334Speterstatic int this_is_library_file; 423618334Speter 423718334Speter/* Nonzero means that the input of this command is coming from a pipe. */ 423818334Speterstatic int input_from_pipe; 423918334Speter 424090277Sobrien/* Nonnull means substitute this for any suffix when outputting a switches 424190277Sobrien arguments. */ 424290277Sobrienstatic const char *suffix_subst; 424390277Sobrien 424418334Speter/* Process the spec SPEC and run the commands specified therein. 424518334Speter Returns 0 if the spec is successfully processed; -1 if failed. */ 424618334Speter 424750599Sobrienint 4248132733Skando_spec (const char *spec) 424918334Speter{ 425018334Speter int value; 425118334Speter 4252117413Skan value = do_spec_2 (spec); 425318334Speter 425418334Speter /* Force out any unfinished command. 425518334Speter If -pipe, this forces out the last command if it ended in `|'. */ 425618334Speter if (value == 0) 425718334Speter { 425818334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 425918334Speter argbuf_index--; 426018334Speter 426190277Sobrien set_collect_gcc_options (); 426290277Sobrien 426318334Speter if (argbuf_index > 0) 426418334Speter value = execute (); 426518334Speter } 426618334Speter 426718334Speter return value; 426818334Speter} 426918334Speter 4270117413Skanstatic int 4271132733Skando_spec_2 (const char *spec) 4272117413Skan{ 4273132733Skan const char *string; 4274132733Skan int result; 4275132733Skan 4276117413Skan clear_args (); 4277117413Skan arg_going = 0; 4278117413Skan delete_this_arg = 0; 4279117413Skan this_is_output_file = 0; 4280117413Skan this_is_library_file = 0; 4281117413Skan input_from_pipe = 0; 4282117413Skan suffix_subst = NULL; 4283117413Skan 4284132733Skan result = do_spec_1 (spec, 0, NULL); 4285132733Skan 4286132733Skan /* End any pending argument. */ 4287132733Skan if (arg_going) 4288132733Skan { 4289132733Skan obstack_1grow (&obstack, 0); 4290132733Skan string = obstack_finish (&obstack); 4291132733Skan if (this_is_library_file) 4292132733Skan string = find_file (string); 4293132733Skan store_arg (string, delete_this_arg, this_is_output_file); 4294132733Skan if (this_is_output_file) 4295132733Skan outfiles[input_file_number] = string; 4296132733Skan arg_going = 0; 4297132733Skan } 4298132733Skan 4299132733Skan return result; 4300117413Skan} 4301117413Skan 4302117413Skan 4303117413Skan/* Process the given spec string and add any new options to the end 4304117413Skan of the switches/n_switches array. */ 4305117413Skan 4306117413Skanstatic void 4307132733Skando_option_spec (const char *name, const char *spec) 4308117413Skan{ 4309132733Skan unsigned int i, value_count, value_len; 4310132733Skan const char *p, *q, *value; 4311132733Skan char *tmp_spec, *tmp_spec_p; 4312132733Skan 4313132733Skan if (configure_default_options[0].name == NULL) 4314132733Skan return; 4315132733Skan 4316132733Skan for (i = 0; i < ARRAY_SIZE (configure_default_options); i++) 4317132733Skan if (strcmp (configure_default_options[i].name, name) == 0) 4318132733Skan break; 4319132733Skan if (i == ARRAY_SIZE (configure_default_options)) 4320132733Skan return; 4321132733Skan 4322132733Skan value = configure_default_options[i].value; 4323132733Skan value_len = strlen (value); 4324132733Skan 4325132733Skan /* Compute the size of the final spec. */ 4326132733Skan value_count = 0; 4327132733Skan p = spec; 4328132733Skan while ((p = strstr (p, "%(VALUE)")) != NULL) 4329132733Skan { 4330132733Skan p ++; 4331132733Skan value_count ++; 4332132733Skan } 4333132733Skan 4334132733Skan /* Replace each %(VALUE) by the specified value. */ 4335132733Skan tmp_spec = alloca (strlen (spec) + 1 4336132733Skan + value_count * (value_len - strlen ("%(VALUE)"))); 4337132733Skan tmp_spec_p = tmp_spec; 4338132733Skan q = spec; 4339132733Skan while ((p = strstr (q, "%(VALUE)")) != NULL) 4340132733Skan { 4341132733Skan memcpy (tmp_spec_p, q, p - q); 4342132733Skan tmp_spec_p = tmp_spec_p + (p - q); 4343132733Skan memcpy (tmp_spec_p, value, value_len); 4344132733Skan tmp_spec_p += value_len; 4345132733Skan q = p + strlen ("%(VALUE)"); 4346132733Skan } 4347132733Skan strcpy (tmp_spec_p, q); 4348132733Skan 4349132733Skan do_self_spec (tmp_spec); 4350132733Skan} 4351132733Skan 4352132733Skan/* Process the given spec string and add any new options to the end 4353132733Skan of the switches/n_switches array. */ 4354132733Skan 4355132733Skanstatic void 4356132733Skando_self_spec (const char *spec) 4357132733Skan{ 4358117413Skan do_spec_2 (spec); 4359117413Skan do_spec_1 (" ", 0, NULL); 4360117413Skan 4361117413Skan if (argbuf_index > 0) 4362117413Skan { 4363117413Skan int i, first; 4364117413Skan 4365117413Skan first = n_switches; 4366117413Skan n_switches += argbuf_index; 4367117413Skan switches = xrealloc (switches, 4368117413Skan sizeof (struct switchstr) * (n_switches + 1)); 4369117413Skan 4370117413Skan switches[n_switches] = switches[first]; 4371117413Skan for (i = 0; i < argbuf_index; i++) 4372117413Skan { 4373117413Skan struct switchstr *sw; 4374117413Skan 4375117413Skan /* Each switch should start with '-'. */ 4376117413Skan if (argbuf[i][0] != '-') 4377117413Skan abort (); 4378117413Skan 4379117413Skan sw = &switches[i + first]; 4380117413Skan sw->part1 = &argbuf[i][1]; 4381117413Skan sw->args = 0; 4382117413Skan sw->live_cond = SWITCH_OK; 4383117413Skan sw->validated = 0; 4384117413Skan sw->ordering = 0; 4385117413Skan } 4386117413Skan } 4387117413Skan} 4388117413Skan 438918334Speter/* Process the sub-spec SPEC as a portion of a larger spec. 439018334Speter This is like processing a whole spec except that we do 439118334Speter not initialize at the beginning and we do not supply a 439218334Speter newline by default at the end. 439318334Speter INSWITCH nonzero means don't process %-sequences in SPEC; 439418334Speter in this case, % is treated as an ordinary character. 439518334Speter This is used while substituting switches. 439618334Speter INSWITCH nonzero also causes SPC not to terminate an argument. 439718334Speter 439818334Speter Value is zero unless a line was finished 439918334Speter and the command on that line reported an error. */ 440018334Speter 440118334Speterstatic int 4402132733Skando_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) 440318334Speter{ 440490277Sobrien const char *p = spec; 440590277Sobrien int c; 440618334Speter int i; 440752520Sobrien const char *string; 440818334Speter int value; 440918334Speter 441050599Sobrien while ((c = *p++)) 441118334Speter /* If substituting a switch, treat all chars like letters. 441218334Speter Otherwise, NL, SPC, TAB and % are special. */ 441318334Speter switch (inswitch ? 'a' : c) 441418334Speter { 441518334Speter case '\n': 441618334Speter /* End of line: finish any pending argument, 441718334Speter then run the pending command if one has been started. */ 441818334Speter if (arg_going) 441918334Speter { 442018334Speter obstack_1grow (&obstack, 0); 442118334Speter string = obstack_finish (&obstack); 442218334Speter if (this_is_library_file) 442318334Speter string = find_file (string); 442418334Speter store_arg (string, delete_this_arg, this_is_output_file); 442518334Speter if (this_is_output_file) 442618334Speter outfiles[input_file_number] = string; 442718334Speter } 442818334Speter arg_going = 0; 442918334Speter 443018334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 443118334Speter { 443218334Speter /* A `|' before the newline means use a pipe here, 443318334Speter but only if -pipe was specified. 443418334Speter Otherwise, execute now and don't pass the `|' as an arg. */ 4435132733Skan if (use_pipes) 443618334Speter { 443718334Speter input_from_pipe = 1; 443818334Speter break; 443918334Speter } 444018334Speter else 444118334Speter argbuf_index--; 444218334Speter } 444318334Speter 444490277Sobrien set_collect_gcc_options (); 444590277Sobrien 444618334Speter if (argbuf_index > 0) 444718334Speter { 444818334Speter value = execute (); 444918334Speter if (value) 445018334Speter return value; 445118334Speter } 445218334Speter /* Reinitialize for a new command, and for a new argument. */ 445318334Speter clear_args (); 445418334Speter arg_going = 0; 445518334Speter delete_this_arg = 0; 445618334Speter this_is_output_file = 0; 445718334Speter this_is_library_file = 0; 445818334Speter input_from_pipe = 0; 445918334Speter break; 446018334Speter 446118334Speter case '|': 446218334Speter /* End any pending argument. */ 446318334Speter if (arg_going) 446418334Speter { 446518334Speter obstack_1grow (&obstack, 0); 446618334Speter string = obstack_finish (&obstack); 446718334Speter if (this_is_library_file) 446818334Speter string = find_file (string); 446918334Speter store_arg (string, delete_this_arg, this_is_output_file); 447018334Speter if (this_is_output_file) 447118334Speter outfiles[input_file_number] = string; 447218334Speter } 447318334Speter 447418334Speter /* Use pipe */ 447518334Speter obstack_1grow (&obstack, c); 447618334Speter arg_going = 1; 447718334Speter break; 447818334Speter 447918334Speter case '\t': 448018334Speter case ' ': 448118334Speter /* Space or tab ends an argument if one is pending. */ 448218334Speter if (arg_going) 448318334Speter { 448418334Speter obstack_1grow (&obstack, 0); 448518334Speter string = obstack_finish (&obstack); 448618334Speter if (this_is_library_file) 448718334Speter string = find_file (string); 448818334Speter store_arg (string, delete_this_arg, this_is_output_file); 448918334Speter if (this_is_output_file) 449018334Speter outfiles[input_file_number] = string; 449118334Speter } 449218334Speter /* Reinitialize for a new argument. */ 449318334Speter arg_going = 0; 449418334Speter delete_this_arg = 0; 449518334Speter this_is_output_file = 0; 449618334Speter this_is_library_file = 0; 449718334Speter break; 449818334Speter 449918334Speter case '%': 450018334Speter switch (c = *p++) 450118334Speter { 450218334Speter case 0: 450390277Sobrien fatal ("invalid specification! Bug in cc"); 450418334Speter 450518334Speter case 'b': 450618334Speter obstack_grow (&obstack, input_basename, basename_length); 450718334Speter arg_going = 1; 450818334Speter break; 450918334Speter 451090277Sobrien case 'B': 451190277Sobrien obstack_grow (&obstack, input_basename, suffixed_basename_length); 451290277Sobrien arg_going = 1; 451390277Sobrien break; 451490277Sobrien 451518334Speter case 'd': 451618334Speter delete_this_arg = 2; 451718334Speter break; 451818334Speter 451918334Speter /* Dump out the directories specified with LIBRARY_PATH, 452018334Speter followed by the absolute directories 452118334Speter that we search for startfiles. */ 452218334Speter case 'D': 452318334Speter { 452418334Speter struct prefix_list *pl = startfile_prefixes.plist; 452550599Sobrien size_t bufsize = 100; 4526132733Skan char *buffer = xmalloc (bufsize); 452718334Speter int idx; 452818334Speter 452918334Speter for (; pl; pl = pl->next) 453018334Speter { 453118334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR 453218334Speter /* Used on systems which record the specified -L dirs 453318334Speter and use them to search for dynamic linking. */ 453418334Speter /* Relative directories always come from -B, 453518334Speter and it is better not to use them for searching 453690277Sobrien at run time. In particular, stage1 loses. */ 4537132733Skan if (!IS_ABSOLUTE_PATH (pl->prefix)) 453818334Speter continue; 453918334Speter#endif 454018334Speter /* Try subdirectory if there is one. */ 4541104763Skan if (multilib_dir != NULL 4542104763Skan || (pl->os_multilib && multilib_os_dir != NULL)) 454318334Speter { 4544104763Skan const char *multi_dir; 4545104763Skan 4546104763Skan multi_dir = pl->os_multilib ? multilib_os_dir 4547104763Skan : multilib_dir; 4548104763Skan if (machine_suffix && multilib_dir) 454918334Speter { 455018334Speter if (strlen (pl->prefix) + strlen (machine_suffix) 455118334Speter >= bufsize) 455218334Speter bufsize = (strlen (pl->prefix) 455318334Speter + strlen (machine_suffix)) * 2 + 1; 4554132733Skan buffer = xrealloc (buffer, bufsize); 455518334Speter strcpy (buffer, pl->prefix); 455618334Speter strcat (buffer, machine_suffix); 455718334Speter if (is_directory (buffer, multilib_dir, 1)) 455818334Speter { 455990277Sobrien do_spec_1 ("-L", 0, NULL); 456018334Speter#ifdef SPACE_AFTER_L_OPTION 456190277Sobrien do_spec_1 (" ", 0, NULL); 456218334Speter#endif 456390277Sobrien do_spec_1 (buffer, 1, NULL); 456490277Sobrien do_spec_1 (multilib_dir, 1, NULL); 456518334Speter /* Make this a separate argument. */ 456690277Sobrien do_spec_1 (" ", 0, NULL); 456718334Speter } 456818334Speter } 456918334Speter if (!pl->require_machine_suffix) 457018334Speter { 4571104763Skan if (is_directory (pl->prefix, multi_dir, 1)) 457218334Speter { 457390277Sobrien do_spec_1 ("-L", 0, NULL); 457418334Speter#ifdef SPACE_AFTER_L_OPTION 457590277Sobrien do_spec_1 (" ", 0, NULL); 457618334Speter#endif 457790277Sobrien do_spec_1 (pl->prefix, 1, NULL); 4578104763Skan do_spec_1 (multi_dir, 1, NULL); 457918334Speter /* Make this a separate argument. */ 458090277Sobrien do_spec_1 (" ", 0, NULL); 458118334Speter } 458218334Speter } 458318334Speter } 458418334Speter if (machine_suffix) 458518334Speter { 458618334Speter if (is_directory (pl->prefix, machine_suffix, 1)) 458718334Speter { 458890277Sobrien do_spec_1 ("-L", 0, NULL); 458918334Speter#ifdef SPACE_AFTER_L_OPTION 459090277Sobrien do_spec_1 (" ", 0, NULL); 459118334Speter#endif 459290277Sobrien do_spec_1 (pl->prefix, 1, NULL); 459318334Speter /* Remove slash from machine_suffix. */ 459418334Speter if (strlen (machine_suffix) >= bufsize) 459518334Speter bufsize = strlen (machine_suffix) * 2 + 1; 4596132733Skan buffer = xrealloc (buffer, bufsize); 459718334Speter strcpy (buffer, machine_suffix); 459818334Speter idx = strlen (buffer); 459952520Sobrien if (IS_DIR_SEPARATOR (buffer[idx - 1])) 460018334Speter buffer[idx - 1] = 0; 460190277Sobrien do_spec_1 (buffer, 1, NULL); 460218334Speter /* Make this a separate argument. */ 460390277Sobrien do_spec_1 (" ", 0, NULL); 460418334Speter } 460518334Speter } 460618334Speter if (!pl->require_machine_suffix) 460718334Speter { 460818334Speter if (is_directory (pl->prefix, "", 1)) 460918334Speter { 461090277Sobrien do_spec_1 ("-L", 0, NULL); 461118334Speter#ifdef SPACE_AFTER_L_OPTION 461290277Sobrien do_spec_1 (" ", 0, NULL); 461318334Speter#endif 461418334Speter /* Remove slash from pl->prefix. */ 461518334Speter if (strlen (pl->prefix) >= bufsize) 461618334Speter bufsize = strlen (pl->prefix) * 2 + 1; 4617132733Skan buffer = xrealloc (buffer, bufsize); 461818334Speter strcpy (buffer, pl->prefix); 461918334Speter idx = strlen (buffer); 462052520Sobrien if (IS_DIR_SEPARATOR (buffer[idx - 1])) 462118334Speter buffer[idx - 1] = 0; 462290277Sobrien do_spec_1 (buffer, 1, NULL); 462318334Speter /* Make this a separate argument. */ 462490277Sobrien do_spec_1 (" ", 0, NULL); 462518334Speter } 462618334Speter } 462718334Speter } 462818334Speter free (buffer); 462918334Speter } 463018334Speter break; 463118334Speter 463218334Speter case 'e': 463352520Sobrien /* %efoo means report an error with `foo' as error message 463418334Speter and don't execute any more commands for this file. */ 463518334Speter { 463652520Sobrien const char *q = p; 463718334Speter char *buf; 463890277Sobrien while (*p != 0 && *p != '\n') 463990277Sobrien p++; 4640132733Skan buf = alloca (p - q + 1); 464118334Speter strncpy (buf, q, p - q); 464218334Speter buf[p - q] = 0; 464390277Sobrien error ("%s", buf); 464418334Speter return -1; 464518334Speter } 464618334Speter break; 464790277Sobrien case 'n': 4648117413Skan /* %nfoo means report a notice with `foo' on stderr. */ 464990277Sobrien { 465090277Sobrien const char *q = p; 465190277Sobrien char *buf; 465290277Sobrien while (*p != 0 && *p != '\n') 465390277Sobrien p++; 4654132733Skan buf = alloca (p - q + 1); 465590277Sobrien strncpy (buf, q, p - q); 465690277Sobrien buf[p - q] = 0; 465790277Sobrien notice ("%s\n", buf); 465890277Sobrien if (*p) 465990277Sobrien p++; 466090277Sobrien } 466190277Sobrien break; 466218334Speter 466390277Sobrien case 'j': 466490277Sobrien { 466590277Sobrien struct stat st; 466690277Sobrien 4667132733Skan /* If save_temps_flag is off, and the HOST_BIT_BUCKET is 4668132733Skan defined, and it is not a directory, and it is 4669132733Skan writable, use it. Otherwise, treat this like any 4670132733Skan other temporary file. */ 467190277Sobrien 467290277Sobrien if ((!save_temps_flag) 467390277Sobrien && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode)) 467490277Sobrien && (access (HOST_BIT_BUCKET, W_OK) == 0)) 467590277Sobrien { 467690277Sobrien obstack_grow (&obstack, HOST_BIT_BUCKET, 467790277Sobrien strlen (HOST_BIT_BUCKET)); 467890277Sobrien delete_this_arg = 0; 467990277Sobrien arg_going = 1; 468090277Sobrien break; 468190277Sobrien } 468290277Sobrien } 4683132733Skan goto create_temp_file; 4684132733Skan case '|': 4685132733Skan if (use_pipes) 4686132733Skan { 4687132733Skan obstack_1grow (&obstack, '-'); 4688132733Skan delete_this_arg = 0; 4689132733Skan arg_going = 1; 4690132733Skan 4691132733Skan /* consume suffix */ 4692132733Skan while (*p == '.' || ISALPHA ((unsigned char) *p)) 4693132733Skan p++; 4694132733Skan if (p[0] == '%' && p[1] == 'O') 4695132733Skan p += 2; 4696132733Skan 4697132733Skan break; 4698132733Skan } 4699132733Skan goto create_temp_file; 4700132733Skan case 'm': 4701132733Skan if (use_pipes) 4702132733Skan { 4703132733Skan /* consume suffix */ 4704132733Skan while (*p == '.' || ISALPHA ((unsigned char) *p)) 4705132733Skan p++; 4706132733Skan if (p[0] == '%' && p[1] == 'O') 4707132733Skan p += 2; 4708132733Skan 4709132733Skan break; 4710132733Skan } 4711132733Skan goto create_temp_file; 471218334Speter case 'g': 471318334Speter case 'u': 471418334Speter case 'U': 4715132733Skan create_temp_file: 471618334Speter { 471718334Speter struct temp_name *t; 471850599Sobrien int suffix_length; 471952520Sobrien const char *suffix = p; 472090277Sobrien char *saved_suffix = NULL; 472118334Speter 472290277Sobrien while (*p == '.' || ISALPHA ((unsigned char) *p)) 472390277Sobrien p++; 472490277Sobrien suffix_length = p - suffix; 472550599Sobrien if (p[0] == '%' && p[1] == 'O') 472650599Sobrien { 472750599Sobrien p += 2; 472850599Sobrien /* We don't support extra suffix characters after %O. */ 472990277Sobrien if (*p == '.' || ISALPHA ((unsigned char) *p)) 473050599Sobrien abort (); 473190277Sobrien if (suffix_length == 0) 473290277Sobrien suffix = TARGET_OBJECT_SUFFIX; 473390277Sobrien else 473490277Sobrien { 473590277Sobrien saved_suffix 4736132733Skan = xmalloc (suffix_length 4737132733Skan + strlen (TARGET_OBJECT_SUFFIX)); 473890277Sobrien strncpy (saved_suffix, suffix, suffix_length); 473990277Sobrien strcpy (saved_suffix + suffix_length, 474090277Sobrien TARGET_OBJECT_SUFFIX); 474190277Sobrien } 474290277Sobrien suffix_length += strlen (TARGET_OBJECT_SUFFIX); 474350599Sobrien } 4744117413Skan 474590277Sobrien /* If the input_filename has the same suffix specified 474690277Sobrien for the %g, %u, or %U, and -save-temps is specified, 474790277Sobrien we could end up using that file as an intermediate 474890277Sobrien thus clobbering the user's source file (.e.g., 474990277Sobrien gcc -save-temps foo.s would clobber foo.s with the 475090277Sobrien output of cpp0). So check for this condition and 475190277Sobrien generate a temp file as the intermediate. */ 4752117413Skan 475390277Sobrien if (save_temps_flag) 475450599Sobrien { 475590277Sobrien temp_filename_length = basename_length + suffix_length; 475690277Sobrien temp_filename = alloca (temp_filename_length + 1); 475790277Sobrien strncpy ((char *) temp_filename, input_basename, basename_length); 475890277Sobrien strncpy ((char *) temp_filename + basename_length, suffix, 4759132733Skan suffix_length); 476090277Sobrien *((char *) temp_filename + temp_filename_length) = '\0'; 476190277Sobrien if (strcmp (temp_filename, input_filename) != 0) 476290277Sobrien { 4763132733Skan struct stat st_temp; 4764117413Skan 4765132733Skan /* Note, set_input() resets input_stat_set to 0. */ 4766132733Skan if (input_stat_set == 0) 4767132733Skan { 4768132733Skan input_stat_set = stat (input_filename, &input_stat); 4769132733Skan if (input_stat_set >= 0) 4770132733Skan input_stat_set = 1; 4771132733Skan } 4772117413Skan 4773132733Skan /* If we have the stat for the input_filename 4774132733Skan and we can do the stat for the temp_filename 4775132733Skan then the they could still refer to the same 4776132733Skan file if st_dev/st_ino's are the same. */ 4777117413Skan 477890277Sobrien if (input_stat_set != 1 477990277Sobrien || stat (temp_filename, &st_temp) < 0 478090277Sobrien || input_stat.st_dev != st_temp.st_dev 478190277Sobrien || input_stat.st_ino != st_temp.st_ino) 4782117413Skan { 478390277Sobrien temp_filename = save_string (temp_filename, 478490277Sobrien temp_filename_length + 1); 478590277Sobrien obstack_grow (&obstack, temp_filename, 4786132733Skan temp_filename_length); 478790277Sobrien arg_going = 1; 4788117413Skan delete_this_arg = 0; 478990277Sobrien break; 479090277Sobrien } 479190277Sobrien } 479250599Sobrien } 479350599Sobrien 479418334Speter /* See if we already have an association of %g/%u/%U and 479518334Speter suffix. */ 479618334Speter for (t = temp_names; t; t = t->next) 479750599Sobrien if (t->length == suffix_length 479850599Sobrien && strncmp (t->suffix, suffix, suffix_length) == 0 4799132733Skan && t->unique == (c == 'u' || c == 'U' || c == 'j')) 480018334Speter break; 480118334Speter 480290277Sobrien /* Make a new association if needed. %u and %j 480390277Sobrien require one. */ 480490277Sobrien if (t == 0 || c == 'u' || c == 'j') 480518334Speter { 480618334Speter if (t == 0) 480718334Speter { 4808132733Skan t = xmalloc (sizeof (struct temp_name)); 480918334Speter t->next = temp_names; 481018334Speter temp_names = t; 481118334Speter } 481250599Sobrien t->length = suffix_length; 481390277Sobrien if (saved_suffix) 481490277Sobrien { 481590277Sobrien t->suffix = saved_suffix; 481690277Sobrien saved_suffix = NULL; 481790277Sobrien } 481890277Sobrien else 481990277Sobrien t->suffix = save_string (suffix, suffix_length); 4820132733Skan t->unique = (c == 'u' || c == 'U' || c == 'j'); 482150599Sobrien temp_filename = make_temp_file (t->suffix); 482250599Sobrien temp_filename_length = strlen (temp_filename); 482318334Speter t->filename = temp_filename; 482418334Speter t->filename_length = temp_filename_length; 482518334Speter } 482618334Speter 482790277Sobrien if (saved_suffix) 482890277Sobrien free (saved_suffix); 482990277Sobrien 483018334Speter obstack_grow (&obstack, t->filename, t->filename_length); 483118334Speter delete_this_arg = 1; 483218334Speter } 483318334Speter arg_going = 1; 483418334Speter break; 483518334Speter 483618334Speter case 'i': 4837132733Skan if (combine_inputs) 4838132733Skan { 4839132733Skan for (i = 0; (int) i < n_infiles; i++) 4840132733Skan store_arg (infiles[i].name, 0, 0); 4841132733Skan } 4842132733Skan else 4843132733Skan { 4844132733Skan obstack_grow (&obstack, input_filename, input_filename_length); 4845132733Skan arg_going = 1; 4846132733Skan } 484718334Speter break; 484818334Speter 484918334Speter case 'I': 485018334Speter { 485118334Speter struct prefix_list *pl = include_prefixes.plist; 485218334Speter 485318334Speter if (gcc_exec_prefix) 485418334Speter { 485590277Sobrien do_spec_1 ("-iprefix", 1, NULL); 485618334Speter /* Make this a separate argument. */ 485790277Sobrien do_spec_1 (" ", 0, NULL); 485890277Sobrien do_spec_1 (gcc_exec_prefix, 1, NULL); 485990277Sobrien do_spec_1 (" ", 0, NULL); 486018334Speter } 486118334Speter 4862132733Skan if (target_system_root_changed || 4863132733Skan (target_system_root && target_sysroot_hdrs_suffix)) 4864132733Skan { 4865132733Skan do_spec_1 ("-isysroot", 1, NULL); 4866132733Skan /* Make this a separate argument. */ 4867132733Skan do_spec_1 (" ", 0, NULL); 4868132733Skan do_spec_1 (target_system_root, 1, NULL); 4869132733Skan if (target_sysroot_hdrs_suffix) 4870132733Skan do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL); 4871132733Skan do_spec_1 (" ", 0, NULL); 4872132733Skan } 4873132733Skan 487418334Speter for (; pl; pl = pl->next) 487518334Speter { 487690277Sobrien do_spec_1 ("-isystem", 1, NULL); 487718334Speter /* Make this a separate argument. */ 487890277Sobrien do_spec_1 (" ", 0, NULL); 487990277Sobrien do_spec_1 (pl->prefix, 1, NULL); 488090277Sobrien do_spec_1 (" ", 0, NULL); 488118334Speter } 488218334Speter } 488318334Speter break; 488418334Speter 488518334Speter case 'o': 488652520Sobrien { 488752520Sobrien int max = n_infiles; 488852520Sobrien max += lang_specific_extra_outfiles; 488918334Speter 489052520Sobrien for (i = 0; i < max; i++) 489152520Sobrien if (outfiles[i]) 489252520Sobrien store_arg (outfiles[i], 0, 0); 489352520Sobrien break; 489452520Sobrien } 489552520Sobrien 489618334Speter case 'O': 489790277Sobrien obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); 489818334Speter arg_going = 1; 489918334Speter break; 490018334Speter 490118334Speter case 's': 490218334Speter this_is_library_file = 1; 490318334Speter break; 490418334Speter 4905132733Skan case 'V': 4906132733Skan outfiles[input_file_number] = NULL; 4907132733Skan break; 4908132733Skan 490918334Speter case 'w': 491018334Speter this_is_output_file = 1; 491118334Speter break; 491218334Speter 491318334Speter case 'W': 491418334Speter { 491550599Sobrien int cur_index = argbuf_index; 491618334Speter /* Handle the {...} following the %W. */ 491718334Speter if (*p != '{') 491818334Speter abort (); 491918334Speter p = handle_braces (p + 1); 492018334Speter if (p == 0) 492118334Speter return -1; 4922132733Skan /* End any pending argument. */ 4923132733Skan if (arg_going) 4924132733Skan { 4925132733Skan obstack_1grow (&obstack, 0); 4926132733Skan string = obstack_finish (&obstack); 4927132733Skan if (this_is_library_file) 4928132733Skan string = find_file (string); 4929132733Skan store_arg (string, delete_this_arg, this_is_output_file); 4930132733Skan if (this_is_output_file) 4931132733Skan outfiles[input_file_number] = string; 4932132733Skan arg_going = 0; 4933132733Skan } 493418334Speter /* If any args were output, mark the last one for deletion 493518334Speter on failure. */ 493650599Sobrien if (argbuf_index != cur_index) 493718334Speter record_temp_file (argbuf[argbuf_index - 1], 0, 1); 493818334Speter break; 493918334Speter } 494018334Speter 494118334Speter /* %x{OPTION} records OPTION for %X to output. */ 494218334Speter case 'x': 494318334Speter { 494452520Sobrien const char *p1 = p; 494518334Speter char *string; 494618334Speter 494718334Speter /* Skip past the option value and make a copy. */ 494818334Speter if (*p != '{') 494918334Speter abort (); 495018334Speter while (*p++ != '}') 495118334Speter ; 495218334Speter string = save_string (p1 + 1, p - p1 - 2); 495318334Speter 495418334Speter /* See if we already recorded this option. */ 495518334Speter for (i = 0; i < n_linker_options; i++) 495618334Speter if (! strcmp (string, linker_options[i])) 495718334Speter { 495818334Speter free (string); 495918334Speter return 0; 496018334Speter } 496118334Speter 496218334Speter /* This option is new; add it. */ 496350599Sobrien add_linker_option (string, strlen (string)); 496418334Speter } 496518334Speter break; 496618334Speter 496718334Speter /* Dump out the options accumulated previously using %x. */ 496818334Speter case 'X': 496918334Speter for (i = 0; i < n_linker_options; i++) 497018334Speter { 497190277Sobrien do_spec_1 (linker_options[i], 1, NULL); 497218334Speter /* Make each accumulated option a separate argument. */ 497390277Sobrien do_spec_1 (" ", 0, NULL); 497418334Speter } 497518334Speter break; 497618334Speter 497718334Speter /* Dump out the options accumulated previously using -Wa,. */ 497818334Speter case 'Y': 497918334Speter for (i = 0; i < n_assembler_options; i++) 498018334Speter { 498190277Sobrien do_spec_1 (assembler_options[i], 1, NULL); 498218334Speter /* Make each accumulated option a separate argument. */ 498390277Sobrien do_spec_1 (" ", 0, NULL); 498418334Speter } 498518334Speter break; 498618334Speter 498718334Speter /* Dump out the options accumulated previously using -Wp,. */ 498818334Speter case 'Z': 498918334Speter for (i = 0; i < n_preprocessor_options; i++) 499018334Speter { 499190277Sobrien do_spec_1 (preprocessor_options[i], 1, NULL); 499218334Speter /* Make each accumulated option a separate argument. */ 499390277Sobrien do_spec_1 (" ", 0, NULL); 499418334Speter } 499518334Speter break; 499618334Speter 499718334Speter /* Here are digits and numbers that just process 499818334Speter a certain constant string as a spec. */ 499918334Speter 500018334Speter case '1': 500190277Sobrien value = do_spec_1 (cc1_spec, 0, NULL); 500218334Speter if (value != 0) 500318334Speter return value; 500418334Speter break; 500518334Speter 500618334Speter case '2': 500790277Sobrien value = do_spec_1 (cc1plus_spec, 0, NULL); 500818334Speter if (value != 0) 500918334Speter return value; 501018334Speter break; 501118334Speter 501218334Speter case 'a': 501390277Sobrien value = do_spec_1 (asm_spec, 0, NULL); 501418334Speter if (value != 0) 501518334Speter return value; 501618334Speter break; 501718334Speter 501818334Speter case 'A': 501990277Sobrien value = do_spec_1 (asm_final_spec, 0, NULL); 502018334Speter if (value != 0) 502118334Speter return value; 502218334Speter break; 502318334Speter 502418334Speter case 'C': 502590277Sobrien { 502690277Sobrien const char *const spec 5027117413Skan = (input_file_compiler->cpp_spec 5028117413Skan ? input_file_compiler->cpp_spec 502990277Sobrien : cpp_spec); 503090277Sobrien value = do_spec_1 (spec, 0, NULL); 503190277Sobrien if (value != 0) 503290277Sobrien return value; 503390277Sobrien } 503418334Speter break; 503518334Speter 503618334Speter case 'E': 503790277Sobrien value = do_spec_1 (endfile_spec, 0, NULL); 503818334Speter if (value != 0) 503918334Speter return value; 504018334Speter break; 504118334Speter 504218334Speter case 'l': 504390277Sobrien value = do_spec_1 (link_spec, 0, NULL); 504418334Speter if (value != 0) 504518334Speter return value; 504618334Speter break; 504718334Speter 504818334Speter case 'L': 504990277Sobrien value = do_spec_1 (lib_spec, 0, NULL); 505018334Speter if (value != 0) 505118334Speter return value; 505218334Speter break; 505318334Speter 505418334Speter case 'G': 505590277Sobrien value = do_spec_1 (libgcc_spec, 0, NULL); 505618334Speter if (value != 0) 505718334Speter return value; 505818334Speter break; 505918334Speter 506090277Sobrien case 'M': 506190277Sobrien if (multilib_dir && strcmp (multilib_dir, ".") != 0) 506290277Sobrien { 506390277Sobrien char *p; 506490277Sobrien const char *q; 506590277Sobrien size_t len; 506690277Sobrien 506790277Sobrien len = strlen (multilib_dir); 506890277Sobrien obstack_blank (&obstack, len + 1); 506990277Sobrien p = obstack_next_free (&obstack) - (len + 1); 507090277Sobrien 507190277Sobrien *p++ = '_'; 507290277Sobrien for (q = multilib_dir; *q ; ++q, ++p) 507390277Sobrien *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q); 507490277Sobrien } 507590277Sobrien break; 507690277Sobrien 5077132733Skan case 'R': 5078132733Skan /* We assume there is a directory 5079132733Skan separator at the end of this string. */ 5080132733Skan if (target_system_root) 5081132733Skan { 5082132733Skan obstack_grow (&obstack, target_system_root, 5083132733Skan strlen (target_system_root)); 5084132733Skan if (target_sysroot_suffix) 5085132733Skan obstack_grow (&obstack, target_sysroot_suffix, 5086132733Skan strlen (target_sysroot_suffix)); 5087132733Skan } 508818334Speter break; 508918334Speter 509018334Speter case 'S': 509190277Sobrien value = do_spec_1 (startfile_spec, 0, NULL); 509218334Speter if (value != 0) 509318334Speter return value; 509418334Speter break; 509518334Speter 509618334Speter /* Here we define characters other than letters and digits. */ 509718334Speter 509818334Speter case '{': 509918334Speter p = handle_braces (p); 510018334Speter if (p == 0) 510118334Speter return -1; 510218334Speter break; 510318334Speter 5104117413Skan case ':': 5105117413Skan p = handle_spec_function (p); 5106117413Skan if (p == 0) 5107117413Skan return -1; 5108117413Skan break; 5109117413Skan 511018334Speter case '%': 511118334Speter obstack_1grow (&obstack, '%'); 511218334Speter break; 511318334Speter 5114117413Skan case '.': 5115117413Skan { 5116117413Skan unsigned len = 0; 511790277Sobrien 5118117413Skan while (p[len] && p[len] != ' ' && p[len] != '%') 5119117413Skan len++; 5120117413Skan suffix_subst = save_string (p - 1, len + 1); 5121117413Skan p += len; 5122117413Skan } 512390277Sobrien break; 5124117413Skan 5125132733Skan /* Henceforth ignore the option(s) matching the pattern 5126132733Skan after the %<. */ 5127132733Skan case '<': 5128132733Skan { 5129132733Skan unsigned len = 0; 5130132733Skan int have_wildcard = 0; 5131132733Skan int i; 5132132733Skan 5133132733Skan while (p[len] && p[len] != ' ' && p[len] != '\t') 5134132733Skan len++; 5135132733Skan 5136132733Skan if (p[len-1] == '*') 5137132733Skan have_wildcard = 1; 5138132733Skan 5139132733Skan for (i = 0; i < n_switches; i++) 5140132733Skan if (!strncmp (switches[i].part1, p, len - have_wildcard) 5141132733Skan && (have_wildcard || switches[i].part1[len] == '\0')) 5142132733Skan { 5143132733Skan switches[i].live_cond = SWITCH_IGNORE; 5144132733Skan switches[i].validated = 1; 5145132733Skan } 5146132733Skan 5147132733Skan p += len; 5148132733Skan } 5149132733Skan break; 5150132733Skan 515118334Speter case '*': 515290277Sobrien if (soft_matched_part) 515390277Sobrien { 515490277Sobrien do_spec_1 (soft_matched_part, 1, NULL); 515590277Sobrien do_spec_1 (" ", 0, NULL); 515690277Sobrien } 515790277Sobrien else 515890277Sobrien /* Catch the case where a spec string contains something like 515990277Sobrien '%{foo:%*}'. ie there is no * in the pattern on the left 516090277Sobrien hand side of the :. */ 516190277Sobrien error ("spec failure: '%%*' has not been initialized by pattern match"); 516218334Speter break; 516318334Speter 516418334Speter /* Process a string found as the value of a spec given by name. 516518334Speter This feature allows individual machine descriptions 516618334Speter to add and use their own specs. 516718334Speter %[...] modifies -D options the way %P does; 516818334Speter %(...) uses the spec unmodified. */ 516950599Sobrien case '[': 517090277Sobrien error ("warning: use of obsolete %%[ operator in specs"); 517118334Speter case '(': 517218334Speter { 517352520Sobrien const char *name = p; 517418334Speter struct spec_list *sl; 517518334Speter int len; 517618334Speter 517718334Speter /* The string after the S/P is the name of a spec that is to be 517850599Sobrien processed. */ 517918334Speter while (*p && *p != ')' && *p != ']') 518018334Speter p++; 518118334Speter 518290277Sobrien /* See if it's in the list. */ 518318334Speter for (len = p - name, sl = specs; sl; sl = sl->next) 518450599Sobrien if (sl->name_len == len && !strncmp (sl->name, name, len)) 518518334Speter { 518650599Sobrien name = *(sl->ptr_spec); 518750599Sobrien#ifdef DEBUG_SPECS 518852520Sobrien notice ("Processing spec %c%s%c, which is '%s'\n", 518952520Sobrien c, sl->name, (c == '(') ? ')' : ']', name); 519050599Sobrien#endif 519118334Speter break; 519218334Speter } 519318334Speter 519418334Speter if (sl) 519518334Speter { 519618334Speter if (c == '(') 519718334Speter { 519890277Sobrien value = do_spec_1 (name, 0, NULL); 519918334Speter if (value != 0) 520018334Speter return value; 520118334Speter } 520218334Speter else 520318334Speter { 5204132733Skan char *x = alloca (strlen (name) * 2 + 1); 520518334Speter char *buf = x; 520652520Sobrien const char *y = name; 520750599Sobrien int flag = 0; 520818334Speter 520918334Speter /* Copy all of NAME into BUF, but put __ after 521090277Sobrien every -D and at the end of each arg. */ 521118334Speter while (1) 521218334Speter { 521318334Speter if (! strncmp (y, "-D", 2)) 521418334Speter { 521518334Speter *x++ = '-'; 521618334Speter *x++ = 'D'; 521718334Speter *x++ = '_'; 521818334Speter *x++ = '_'; 521918334Speter y += 2; 522050599Sobrien flag = 1; 522150599Sobrien continue; 522218334Speter } 522390277Sobrien else if (flag 522490277Sobrien && (*y == ' ' || *y == '\t' || *y == '=' 522590277Sobrien || *y == '}' || *y == 0)) 522618334Speter { 522718334Speter *x++ = '_'; 522818334Speter *x++ = '_'; 522950599Sobrien flag = 0; 523018334Speter } 523190277Sobrien if (*y == 0) 523250599Sobrien break; 523318334Speter else 523418334Speter *x++ = *y++; 523518334Speter } 523618334Speter *x = 0; 523718334Speter 523890277Sobrien value = do_spec_1 (buf, 0, NULL); 523918334Speter if (value != 0) 524018334Speter return value; 524118334Speter } 524218334Speter } 524318334Speter 524418334Speter /* Discard the closing paren or bracket. */ 524518334Speter if (*p) 524618334Speter p++; 524718334Speter } 524818334Speter break; 524918334Speter 525018334Speter default: 525190277Sobrien error ("spec failure: unrecognized spec option '%c'", c); 525290277Sobrien break; 525318334Speter } 525418334Speter break; 525518334Speter 525618334Speter case '\\': 525718334Speter /* Backslash: treat next character as ordinary. */ 525818334Speter c = *p++; 525918334Speter 5260132733Skan /* Fall through. */ 526118334Speter default: 526218334Speter /* Ordinary character: put it into the current argument. */ 526318334Speter obstack_1grow (&obstack, c); 526418334Speter arg_going = 1; 526518334Speter } 526618334Speter 5267117413Skan /* End of string. If we are processing a spec function, we need to 5268117413Skan end any pending argument. */ 5269117413Skan if (processing_spec_function && arg_going) 5270117413Skan { 5271117413Skan obstack_1grow (&obstack, 0); 5272117413Skan string = obstack_finish (&obstack); 5273117413Skan if (this_is_library_file) 5274117413Skan string = find_file (string); 5275117413Skan store_arg (string, delete_this_arg, this_is_output_file); 5276117413Skan if (this_is_output_file) 5277117413Skan outfiles[input_file_number] = string; 5278117413Skan arg_going = 0; 5279117413Skan } 5280117413Skan 528190277Sobrien return 0; 528218334Speter} 528318334Speter 5284117413Skan/* Look up a spec function. */ 5285117413Skan 5286117413Skanstatic const struct spec_function * 5287132733Skanlookup_spec_function (const char *name) 5288117413Skan{ 5289117413Skan static const struct spec_function * const spec_function_tables[] = 5290117413Skan { 5291117413Skan static_spec_functions, 5292117413Skan lang_specific_spec_functions, 5293117413Skan }; 5294117413Skan const struct spec_function *sf; 5295117413Skan unsigned int i; 5296117413Skan 5297117413Skan for (i = 0; i < ARRAY_SIZE (spec_function_tables); i++) 5298117413Skan { 5299117413Skan for (sf = spec_function_tables[i]; sf->name != NULL; sf++) 5300117413Skan if (strcmp (sf->name, name) == 0) 5301117413Skan return sf; 5302117413Skan } 5303117413Skan 5304117413Skan return NULL; 5305117413Skan} 5306117413Skan 5307117413Skan/* Evaluate a spec function. */ 5308117413Skan 5309117413Skanstatic const char * 5310132733Skaneval_spec_function (const char *func, const char *args) 5311117413Skan{ 5312117413Skan const struct spec_function *sf; 5313117413Skan const char *funcval; 5314117413Skan 5315117413Skan /* Saved spec processing context. */ 5316117413Skan int save_argbuf_index; 5317117413Skan int save_argbuf_length; 5318117413Skan const char **save_argbuf; 5319117413Skan 5320117413Skan int save_arg_going; 5321117413Skan int save_delete_this_arg; 5322117413Skan int save_this_is_output_file; 5323117413Skan int save_this_is_library_file; 5324117413Skan int save_input_from_pipe; 5325117413Skan const char *save_suffix_subst; 5326117413Skan 5327117413Skan 5328117413Skan sf = lookup_spec_function (func); 5329117413Skan if (sf == NULL) 5330117413Skan fatal ("unknown spec function `%s'", func); 5331117413Skan 5332117413Skan /* Push the spec processing context. */ 5333117413Skan save_argbuf_index = argbuf_index; 5334117413Skan save_argbuf_length = argbuf_length; 5335117413Skan save_argbuf = argbuf; 5336117413Skan 5337117413Skan save_arg_going = arg_going; 5338117413Skan save_delete_this_arg = delete_this_arg; 5339117413Skan save_this_is_output_file = this_is_output_file; 5340117413Skan save_this_is_library_file = this_is_library_file; 5341117413Skan save_input_from_pipe = input_from_pipe; 5342117413Skan save_suffix_subst = suffix_subst; 5343117413Skan 5344117413Skan /* Create a new spec processing context, and build the function 5345117413Skan arguments. */ 5346117413Skan 5347117413Skan alloc_args (); 5348117413Skan if (do_spec_2 (args) < 0) 5349117413Skan fatal ("error in args to spec function `%s'", func); 5350117413Skan 5351117413Skan /* argbuf_index is an index for the next argument to be inserted, and 5352117413Skan so contains the count of the args already inserted. */ 5353117413Skan 5354117413Skan funcval = (*sf->func) (argbuf_index, argbuf); 5355117413Skan 5356117413Skan /* Pop the spec processing context. */ 5357117413Skan argbuf_index = save_argbuf_index; 5358117413Skan argbuf_length = save_argbuf_length; 5359117413Skan free (argbuf); 5360117413Skan argbuf = save_argbuf; 5361117413Skan 5362117413Skan arg_going = save_arg_going; 5363117413Skan delete_this_arg = save_delete_this_arg; 5364117413Skan this_is_output_file = save_this_is_output_file; 5365117413Skan this_is_library_file = save_this_is_library_file; 5366117413Skan input_from_pipe = save_input_from_pipe; 5367117413Skan suffix_subst = save_suffix_subst; 5368117413Skan 5369117413Skan return funcval; 5370117413Skan} 5371117413Skan 5372117413Skan/* Handle a spec function call of the form: 5373117413Skan 5374117413Skan %:function(args) 5375117413Skan 5376117413Skan ARGS is processed as a spec in a separate context and split into an 5377117413Skan argument vector in the normal fashion. The function returns a string 5378117413Skan containing a spec which we then process in the caller's context, or 5379117413Skan NULL if no processing is required. */ 5380117413Skan 5381117413Skanstatic const char * 5382132733Skanhandle_spec_function (const char *p) 5383117413Skan{ 5384117413Skan char *func, *args; 5385117413Skan const char *endp, *funcval; 5386117413Skan int count; 5387117413Skan 5388117413Skan processing_spec_function++; 5389117413Skan 5390117413Skan /* Get the function name. */ 5391117413Skan for (endp = p; *endp != '\0'; endp++) 5392117413Skan { 5393117413Skan if (*endp == '(') /* ) */ 5394117413Skan break; 5395117413Skan /* Only allow [A-Za-z0-9], -, and _ in function names. */ 5396117413Skan if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_')) 5397117413Skan fatal ("malformed spec function name"); 5398117413Skan } 5399117413Skan if (*endp != '(') /* ) */ 5400117413Skan fatal ("no arguments for spec function"); 5401117413Skan func = save_string (p, endp - p); 5402117413Skan p = ++endp; 5403117413Skan 5404117413Skan /* Get the arguments. */ 5405117413Skan for (count = 0; *endp != '\0'; endp++) 5406117413Skan { 5407117413Skan /* ( */ 5408117413Skan if (*endp == ')') 5409117413Skan { 5410117413Skan if (count == 0) 5411117413Skan break; 5412117413Skan count--; 5413117413Skan } 5414117413Skan else if (*endp == '(') /* ) */ 5415117413Skan count++; 5416117413Skan } 5417117413Skan /* ( */ 5418117413Skan if (*endp != ')') 5419117413Skan fatal ("malformed spec function arguments"); 5420117413Skan args = save_string (p, endp - p); 5421117413Skan p = ++endp; 5422117413Skan 5423117413Skan /* p now points to just past the end of the spec function expression. */ 5424117413Skan 5425117413Skan funcval = eval_spec_function (func, args); 5426117413Skan if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0) 5427117413Skan p = NULL; 5428117413Skan 5429117413Skan free (func); 5430117413Skan free (args); 5431117413Skan 5432117413Skan processing_spec_function--; 5433117413Skan 5434117413Skan return p; 5435117413Skan} 5436117413Skan 5437132733Skan/* Inline subroutine of handle_braces. Returns true if the current 5438132733Skan input suffix matches the atom bracketed by ATOM and END_ATOM. */ 5439132733Skanstatic inline bool 5440132733Skaninput_suffix_matches (const char *atom, const char *end_atom) 5441132733Skan{ 5442132733Skan return (input_suffix 5443132733Skan && !strncmp (input_suffix, atom, end_atom - atom) 5444132733Skan && input_suffix[end_atom - atom] == '\0'); 5445132733Skan} 544618334Speter 5447132733Skan/* Inline subroutine of handle_braces. Returns true if a switch 5448132733Skan matching the atom bracketed by ATOM and END_ATOM appeared on the 5449132733Skan command line. */ 5450132733Skanstatic inline bool 5451132733Skanswitch_matches (const char *atom, const char *end_atom, int starred) 545218334Speter{ 5453132733Skan int i; 5454132733Skan int len = end_atom - atom; 5455132733Skan int plen = starred ? len : -1; 545618334Speter 5457132733Skan for (i = 0; i < n_switches; i++) 5458132733Skan if (!strncmp (switches[i].part1, atom, len) 5459132733Skan && (starred || switches[i].part1[len] == '\0') 5460132733Skan && check_live_switch (i, plen)) 5461132733Skan return true; 546250599Sobrien 5463132733Skan return false; 5464132733Skan} 546518334Speter 5466132733Skan/* Inline subroutine of handle_braces. Mark all of the switches which 5467132733Skan match ATOM (extends to END_ATOM; STARRED indicates whether there 5468132733Skan was a star after the atom) for later processing. */ 5469132733Skanstatic inline void 5470132733Skanmark_matching_switches (const char *atom, const char *end_atom, int starred) 5471132733Skan{ 5472132733Skan int i; 5473132733Skan int len = end_atom - atom; 5474132733Skan int plen = starred ? len : -1; 547590277Sobrien 5476132733Skan for (i = 0; i < n_switches; i++) 5477132733Skan if (!strncmp (switches[i].part1, atom, len) 5478132733Skan && (starred || switches[i].part1[len] == '\0') 5479132733Skan && check_live_switch (i, plen)) 5480132733Skan switches[i].ordering = 1; 5481132733Skan} 548250599Sobrien 5483132733Skan/* Inline subroutine of handle_braces. Process all the currently 5484132733Skan marked switches through give_switch, and clear the marks. */ 5485132733Skanstatic inline void 5486132733Skanprocess_marked_switches (void) 5487132733Skan{ 5488132733Skan int i; 548918334Speter 5490132733Skan for (i = 0; i < n_switches; i++) 5491132733Skan if (switches[i].ordering == 1) 5492132733Skan { 5493132733Skan switches[i].ordering = 0; 5494132733Skan give_switch (i, 0); 5495132733Skan } 5496132733Skan} 549718334Speter 5498132733Skan/* Handle a %{ ... } construct. P points just inside the leading {. 5499132733Skan Returns a pointer one past the end of the brace block, or 0 5500132733Skan if we call do_spec_1 and that returns -1. */ 550118334Speter 5502132733Skanstatic const char * 5503132733Skanhandle_braces (const char *p) 5504132733Skan{ 5505132733Skan const char *atom, *end_atom; 5506132733Skan const char *d_atom = NULL, *d_end_atom = NULL; 550790277Sobrien 5508132733Skan bool a_is_suffix; 5509132733Skan bool a_is_starred; 5510132733Skan bool a_is_negated; 5511132733Skan bool a_matched; 551250599Sobrien 5513132733Skan bool a_must_be_last = false; 5514132733Skan bool ordered_set = false; 5515132733Skan bool disjunct_set = false; 5516132733Skan bool disj_matched = false; 5517132733Skan bool disj_starred = true; 5518132733Skan bool n_way_choice = false; 5519132733Skan bool n_way_matched = false; 552050599Sobrien 5521132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0) 5522132733Skan 5523132733Skan do 552418334Speter { 5525132733Skan if (a_must_be_last) 5526132733Skan abort (); 552750599Sobrien 5528132733Skan /* Scan one "atom" (S in the description above of %{}, possibly 5529132733Skan with !, ., or * modifiers). */ 5530132733Skan a_matched = a_is_suffix = a_is_starred = a_is_negated = false; 553190277Sobrien 5532132733Skan SKIP_WHITE(); 5533132733Skan if (*p == '!') 5534132733Skan p++, a_is_negated = true; 553518334Speter 5536132733Skan SKIP_WHITE(); 5537132733Skan if (*p == '.') 5538132733Skan p++, a_is_suffix = true; 553918334Speter 5540132733Skan atom = p; 5541132733Skan while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '=' 5542132733Skan || *p == ',' || *p == '.' || *p == '@') 5543132733Skan p++; 5544132733Skan end_atom = p; 554518334Speter 5546132733Skan if (*p == '*') 5547132733Skan p++, a_is_starred = 1; 554890277Sobrien 5549132733Skan SKIP_WHITE(); 5550132733Skan if (*p == '&' || *p == '}') 5551132733Skan { 5552132733Skan /* Substitute the switch(es) indicated by the current atom. */ 5553132733Skan ordered_set = true; 5554132733Skan if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix 5555132733Skan || atom == end_atom) 5556132733Skan abort (); 555718334Speter 5558132733Skan mark_matching_switches (atom, end_atom, a_is_starred); 5559132733Skan 5560132733Skan if (*p == '}') 5561132733Skan process_marked_switches (); 5562132733Skan } 5563132733Skan else if (*p == '|' || *p == ':') 556418334Speter { 5565132733Skan /* Substitute some text if the current atom appears as a switch 5566132733Skan or suffix. */ 5567132733Skan disjunct_set = true; 5568132733Skan if (ordered_set) 5569132733Skan abort (); 557018334Speter 5571132733Skan if (atom == end_atom) 557218334Speter { 5573132733Skan if (!n_way_choice || disj_matched || *p == '|' 5574132733Skan || a_is_negated || a_is_suffix || a_is_starred) 5575132733Skan abort (); 5576132733Skan 5577132733Skan /* An empty term may appear as the last choice of an 5578132733Skan N-way choice set; it means "otherwise". */ 5579132733Skan a_must_be_last = true; 5580132733Skan disj_matched = !n_way_matched; 5581132733Skan disj_starred = false; 558218334Speter } 5583132733Skan else 558418334Speter { 5585132733Skan if (a_is_suffix && a_is_starred) 5586132733Skan abort (); 558718334Speter 5588132733Skan if (!a_is_starred) 5589132733Skan disj_starred = false; 559018334Speter 5591132733Skan /* Don't bother testing this atom if we already have a 5592132733Skan match. */ 5593132733Skan if (!disj_matched && !n_way_matched) 5594132733Skan { 5595132733Skan if (a_is_suffix) 5596132733Skan a_matched = input_suffix_matches (atom, end_atom); 5597132733Skan else 5598132733Skan a_matched = switch_matches (atom, end_atom, a_is_starred); 559918334Speter 5600132733Skan if (a_matched != a_is_negated) 5601132733Skan { 5602132733Skan disj_matched = true; 5603132733Skan d_atom = atom; 5604132733Skan d_end_atom = end_atom; 5605132733Skan } 5606132733Skan } 560718334Speter } 560818334Speter 5609132733Skan if (*p == ':') 561018334Speter { 5611132733Skan /* Found the body, that is, the text to substitute if the 5612132733Skan current disjunction matches. */ 5613132733Skan p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred, 5614132733Skan disj_matched && !n_way_matched); 5615132733Skan if (p == 0) 5616132733Skan return 0; 561718334Speter 5618132733Skan /* If we have an N-way choice, reset state for the next 5619132733Skan disjunction. */ 5620132733Skan if (*p == ';') 562118334Speter { 5622132733Skan n_way_choice = true; 5623132733Skan n_way_matched |= disj_matched; 5624132733Skan disj_matched = false; 5625132733Skan disj_starred = true; 5626132733Skan d_atom = d_end_atom = NULL; 562718334Speter } 562818334Speter } 562918334Speter } 563018334Speter else 5631132733Skan abort (); 5632132733Skan } 5633132733Skan while (*p++ != '}'); 563418334Speter 5635132733Skan return p; 5636132733Skan 5637132733Skan#undef SKIP_WHITE 5638132733Skan} 5639132733Skan 5640132733Skan/* Subroutine of handle_braces. Scan and process a brace substitution body 5641132733Skan (X in the description of %{} syntax). P points one past the colon; 5642132733Skan ATOM and END_ATOM bracket the first atom which was found to be true 5643132733Skan (present) in the current disjunction; STARRED indicates whether all 5644132733Skan the atoms in the current disjunction were starred (for syntax validation); 5645132733Skan MATCHED indicates whether the disjunction matched or not, and therefore 5646132733Skan whether or not the body is to be processed through do_spec_1 or just 5647132733Skan skipped. Returns a pointer to the closing } or ;, or 0 if do_spec_1 5648132733Skan returns -1. */ 5649132733Skan 5650132733Skanstatic const char * 5651132733Skanprocess_brace_body (const char *p, const char *atom, const char *end_atom, 5652132733Skan int starred, int matched) 5653132733Skan{ 5654132733Skan const char *body, *end_body; 5655132733Skan unsigned int nesting_level; 5656132733Skan bool have_subst = false; 5657132733Skan 5658132733Skan /* Locate the closing } or ;, honoring nested braces. 5659132733Skan Trim trailing whitespace. */ 5660132733Skan body = p; 5661132733Skan nesting_level = 1; 5662132733Skan for (;;) 5663132733Skan { 5664132733Skan if (*p == '{') 5665132733Skan nesting_level++; 5666132733Skan else if (*p == '}') 566718334Speter { 5668132733Skan if (!--nesting_level) 5669132733Skan break; 567018334Speter } 5671132733Skan else if (*p == ';' && nesting_level == 1) 5672132733Skan break; 5673132733Skan else if (*p == '%' && p[1] == '*' && nesting_level == 1) 5674132733Skan have_subst = true; 5675132733Skan else if (*p == '\0') 5676132733Skan abort (); 5677132733Skan p++; 567818334Speter } 567918334Speter 5680132733Skan end_body = p; 5681132733Skan while (end_body[-1] == ' ' || end_body[-1] == '\t') 5682132733Skan end_body--; 568350599Sobrien 5684132733Skan if (have_subst && !starred) 5685132733Skan abort (); 5686132733Skan 5687132733Skan if (matched) 568890277Sobrien { 5689132733Skan /* Copy the substitution body to permanent storage and execute it. 5690132733Skan If have_subst is false, this is a simple matter of running the 5691132733Skan body through do_spec_1... */ 5692132733Skan char *string = save_string (body, end_body - body); 5693132733Skan if (!have_subst) 5694132733Skan { 5695132733Skan if (do_spec_1 (string, 0, NULL) < 0) 5696132733Skan return 0; 5697132733Skan } 5698132733Skan else 5699132733Skan { 5700132733Skan /* ... but if have_subst is true, we have to process the 5701132733Skan body once for each matching switch, with %* set to the 5702132733Skan variant part of the switch. */ 5703132733Skan unsigned int hard_match_len = end_atom - atom; 5704132733Skan int i; 570590277Sobrien 5706132733Skan for (i = 0; i < n_switches; i++) 5707132733Skan if (!strncmp (switches[i].part1, atom, hard_match_len) 5708132733Skan && check_live_switch (i, hard_match_len)) 5709132733Skan { 5710132733Skan if (do_spec_1 (string, 0, 5711132733Skan &switches[i].part1[hard_match_len]) < 0) 5712132733Skan return 0; 5713132733Skan /* Pass any arguments this switch has. */ 5714132733Skan give_switch (i, 1); 5715132733Skan suffix_subst = NULL; 5716132733Skan } 5717132733Skan } 571890277Sobrien } 571990277Sobrien 5720132733Skan return p; 572118334Speter} 572218334Speter 572318334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch 572418334Speter on the command line. PREFIX_LENGTH is the length of XXX in an {XXX*} 572518334Speter spec, or -1 if either exact match or %* is used. 572618334Speter 572718334Speter A -O switch is obsoleted by a later -O switch. A -f, -m, or -W switch 572818334Speter whose value does not begin with "no-" is obsoleted by the same value 572918334Speter with the "no-", similarly for a switch with the "no-" prefix. */ 573018334Speter 573118334Speterstatic int 5732132733Skancheck_live_switch (int switchnum, int prefix_length) 573318334Speter{ 573452520Sobrien const char *name = switches[switchnum].part1; 573518334Speter int i; 573618334Speter 573718334Speter /* In the common case of {<at-most-one-letter>*}, a negating 573818334Speter switch would always match, so ignore that case. We will just 573918334Speter send the conflicting switches to the compiler phase. */ 574018334Speter if (prefix_length >= 0 && prefix_length <= 1) 574118334Speter return 1; 574218334Speter 574318334Speter /* If we already processed this switch and determined if it was 574418334Speter live or not, return our past determination. */ 574518334Speter if (switches[switchnum].live_cond != 0) 574618334Speter return switches[switchnum].live_cond > 0; 574718334Speter 574818334Speter /* Now search for duplicate in a manner that depends on the name. */ 574918334Speter switch (*name) 575018334Speter { 575118334Speter case 'O': 575290277Sobrien for (i = switchnum + 1; i < n_switches; i++) 575390277Sobrien if (switches[i].part1[0] == 'O') 575490277Sobrien { 575590277Sobrien switches[switchnum].validated = 1; 575690277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 575790277Sobrien return 0; 575890277Sobrien } 575918334Speter break; 576018334Speter 576118334Speter case 'W': case 'f': case 'm': 576218334Speter if (! strncmp (name + 1, "no-", 3)) 576318334Speter { 576450599Sobrien /* We have Xno-YYY, search for XYYY. */ 576518334Speter for (i = switchnum + 1; i < n_switches; i++) 576618334Speter if (switches[i].part1[0] == name[0] 576718334Speter && ! strcmp (&switches[i].part1[1], &name[4])) 576890277Sobrien { 576990277Sobrien switches[switchnum].validated = 1; 577090277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 577190277Sobrien return 0; 577290277Sobrien } 577318334Speter } 577418334Speter else 577518334Speter { 577618334Speter /* We have XYYY, search for Xno-YYY. */ 577718334Speter for (i = switchnum + 1; i < n_switches; i++) 577818334Speter if (switches[i].part1[0] == name[0] 577918334Speter && switches[i].part1[1] == 'n' 578018334Speter && switches[i].part1[2] == 'o' 578118334Speter && switches[i].part1[3] == '-' 578218334Speter && !strcmp (&switches[i].part1[4], &name[1])) 578390277Sobrien { 578490277Sobrien switches[switchnum].validated = 1; 578590277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 578690277Sobrien return 0; 578790277Sobrien } 578818334Speter } 578918334Speter break; 579018334Speter } 579118334Speter 579218334Speter /* Otherwise the switch is live. */ 579390277Sobrien switches[switchnum].live_cond = SWITCH_LIVE; 579418334Speter return 1; 579518334Speter} 579618334Speter 579718334Speter/* Pass a switch to the current accumulating command 579818334Speter in the same form that we received it. 579918334Speter SWITCHNUM identifies the switch; it is an index into 580018334Speter the vector of switches gcc received, which is `switches'. 580118334Speter This cannot fail since it never finishes a command line. 580218334Speter 5803132733Skan If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. */ 580418334Speter 580518334Speterstatic void 5806132733Skangive_switch (int switchnum, int omit_first_word) 580718334Speter{ 580890277Sobrien if (switches[switchnum].live_cond == SWITCH_IGNORE) 580990277Sobrien return; 581090277Sobrien 581118334Speter if (!omit_first_word) 581218334Speter { 581390277Sobrien do_spec_1 ("-", 0, NULL); 581490277Sobrien do_spec_1 (switches[switchnum].part1, 1, NULL); 581518334Speter } 581650599Sobrien 581718334Speter if (switches[switchnum].args != 0) 581818334Speter { 581990277Sobrien const char **p; 582018334Speter for (p = switches[switchnum].args; *p; p++) 582118334Speter { 582290277Sobrien const char *arg = *p; 582390277Sobrien 5824132733Skan do_spec_1 (" ", 0, NULL); 582590277Sobrien if (suffix_subst) 582690277Sobrien { 582790277Sobrien unsigned length = strlen (arg); 582890277Sobrien int dot = 0; 582990277Sobrien 583090277Sobrien while (length-- && !IS_DIR_SEPARATOR (arg[length])) 583190277Sobrien if (arg[length] == '.') 583290277Sobrien { 583390277Sobrien ((char *)arg)[length] = 0; 583490277Sobrien dot = 1; 583590277Sobrien break; 583690277Sobrien } 583790277Sobrien do_spec_1 (arg, 1, NULL); 583890277Sobrien if (dot) 583990277Sobrien ((char *)arg)[length] = '.'; 584090277Sobrien do_spec_1 (suffix_subst, 1, NULL); 584190277Sobrien } 584290277Sobrien else 584390277Sobrien do_spec_1 (arg, 1, NULL); 584418334Speter } 584518334Speter } 584650599Sobrien 584790277Sobrien do_spec_1 (" ", 0, NULL); 584852520Sobrien switches[switchnum].validated = 1; 584918334Speter} 585018334Speter 585118334Speter/* Search for a file named NAME trying various prefixes including the 585218334Speter user's -B prefix and some standard ones. 585318334Speter Return the absolute file name found. If nothing is found, return NAME. */ 585418334Speter 585552520Sobrienstatic const char * 5856132733Skanfind_file (const char *name) 585718334Speter{ 585818334Speter char *newname; 585918334Speter 586018334Speter /* Try multilib_dir if it is defined. */ 5861104763Skan if (multilib_os_dir != NULL) 586218334Speter { 5863104763Skan newname = find_a_file (&startfile_prefixes, name, R_OK, 1); 586418334Speter 586518334Speter /* If we don't find it in the multi library dir, then fall 586618334Speter through and look for it in the normal places. */ 586718334Speter if (newname != NULL) 586818334Speter return newname; 586918334Speter } 587018334Speter 5871104763Skan newname = find_a_file (&startfile_prefixes, name, R_OK, 0); 587218334Speter return newname ? newname : name; 587318334Speter} 587418334Speter 587518334Speter/* Determine whether a directory exists. If LINKER, return 0 for 587618334Speter certain fixed names not needed by the linker. If not LINKER, it is 587718334Speter only important to return 0 if the host machine has a small ARG_MAX 587818334Speter limit. */ 587918334Speter 588018334Speterstatic int 5881132733Skanis_directory (const char *path1, const char *path2, int linker) 588218334Speter{ 588318334Speter int len1 = strlen (path1); 588418334Speter int len2 = strlen (path2); 5885132733Skan char *path = alloca (3 + len1 + len2); 588618334Speter char *cp; 588718334Speter struct stat st; 588818334Speter 588918334Speter#ifndef SMALL_ARG_MAX 589018334Speter if (! linker) 589118334Speter return 1; 589218334Speter#endif 589318334Speter 589418334Speter /* Construct the path from the two parts. Ensure the string ends with "/.". 589518334Speter The resulting path will be a directory even if the given path is a 589618334Speter symbolic link. */ 589752520Sobrien memcpy (path, path1, len1); 589852520Sobrien memcpy (path + len1, path2, len2); 589918334Speter cp = path + len1 + len2; 590052520Sobrien if (!IS_DIR_SEPARATOR (cp[-1])) 590118334Speter *cp++ = DIR_SEPARATOR; 590218334Speter *cp++ = '.'; 590318334Speter *cp = '\0'; 590418334Speter 590551232Sbde#ifndef FREEBSD_NATIVE 590618334Speter /* Exclude directories that the linker is known to search. */ 590718334Speter if (linker 590818334Speter && ((cp - path == 6 590990277Sobrien && strcmp (path, concat (dir_separator_str, "lib", 591090277Sobrien dir_separator_str, ".", NULL)) == 0) 591118334Speter || (cp - path == 10 591290277Sobrien && strcmp (path, concat (dir_separator_str, "usr", 591390277Sobrien dir_separator_str, "lib", 591490277Sobrien dir_separator_str, ".", NULL)) == 0))) 591518334Speter return 0; 591651232Sbde#endif /* FREEBSD_NATIVE */ 591718334Speter 591818334Speter return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode)); 591918334Speter} 592090277Sobrien 592190277Sobrien/* Set up the various global variables to indicate that we're processing 592290277Sobrien the input file named FILENAME. */ 592390277Sobrien 592490277Sobrienvoid 5925132733Skanset_input (const char *filename) 592690277Sobrien{ 592790277Sobrien const char *p; 592890277Sobrien 592990277Sobrien input_filename = filename; 593090277Sobrien input_filename_length = strlen (input_filename); 593190277Sobrien 593290277Sobrien input_basename = input_filename; 593390277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 593490277Sobrien /* Skip drive name so 'x:foo' is handled properly. */ 593590277Sobrien if (input_basename[1] == ':') 593690277Sobrien input_basename += 2; 593790277Sobrien#endif 593890277Sobrien for (p = input_basename; *p; p++) 593990277Sobrien if (IS_DIR_SEPARATOR (*p)) 594090277Sobrien input_basename = p + 1; 594190277Sobrien 594290277Sobrien /* Find a suffix starting with the last period, 594390277Sobrien and set basename_length to exclude that suffix. */ 594490277Sobrien basename_length = strlen (input_basename); 594590277Sobrien suffixed_basename_length = basename_length; 594690277Sobrien p = input_basename + basename_length; 594790277Sobrien while (p != input_basename && *p != '.') 594890277Sobrien --p; 594990277Sobrien if (*p == '.' && p != input_basename) 595090277Sobrien { 595190277Sobrien basename_length = p - input_basename; 595290277Sobrien input_suffix = p + 1; 595390277Sobrien } 595490277Sobrien else 595590277Sobrien input_suffix = ""; 5956117413Skan 595790277Sobrien /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then 595890277Sobrien we will need to do a stat on the input_filename. The 595990277Sobrien INPUT_STAT_SET signals that the stat is needed. */ 596090277Sobrien input_stat_set = 0; 596190277Sobrien} 596218334Speter 596318334Speter/* On fatal signals, delete all the temporary files. */ 596418334Speter 596518334Speterstatic void 5966132733Skanfatal_error (int signum) 596718334Speter{ 596818334Speter signal (signum, SIG_DFL); 596918334Speter delete_failure_queue (); 597018334Speter delete_temp_files (); 597118334Speter /* Get the same signal again, this time not handled, 597218334Speter so its normal effect occurs. */ 597318334Speter kill (getpid (), signum); 597418334Speter} 597518334Speter 5976132733Skanextern int main (int, const char **); 597790277Sobrien 597818334Speterint 5979132733Skanmain (int argc, const char **argv) 598018334Speter{ 598190277Sobrien size_t i; 598218334Speter int value; 598318334Speter int linker_was_run = 0; 5984132733Skan int num_linker_inputs = 0; 598518334Speter char *explicit_link_files; 598618334Speter char *specs_file; 598752520Sobrien const char *p; 598850599Sobrien struct user_specs *uptr; 598918334Speter 599018334Speter p = argv[0] + strlen (argv[0]); 599152520Sobrien while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) 599252520Sobrien --p; 599318334Speter programname = p; 599418334Speter 599590277Sobrien xmalloc_set_program_name (programname); 599690277Sobrien 599790277Sobrien#ifdef GCC_DRIVER_HOST_INITIALIZATION 599890277Sobrien /* Perform host dependent initialization when needed. */ 599990277Sobrien GCC_DRIVER_HOST_INITIALIZATION; 600052520Sobrien#endif 600152520Sobrien 600290277Sobrien gcc_init_libintl (); 600390277Sobrien 600418334Speter if (signal (SIGINT, SIG_IGN) != SIG_IGN) 600518334Speter signal (SIGINT, fatal_error); 600618334Speter#ifdef SIGHUP 600718334Speter if (signal (SIGHUP, SIG_IGN) != SIG_IGN) 600818334Speter signal (SIGHUP, fatal_error); 600918334Speter#endif 601018334Speter if (signal (SIGTERM, SIG_IGN) != SIG_IGN) 601118334Speter signal (SIGTERM, fatal_error); 601218334Speter#ifdef SIGPIPE 601318334Speter if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) 601418334Speter signal (SIGPIPE, fatal_error); 601518334Speter#endif 601690277Sobrien#ifdef SIGCHLD 601790277Sobrien /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will 601890277Sobrien receive the signal. A different setting is inheritable */ 601990277Sobrien signal (SIGCHLD, SIG_DFL); 602090277Sobrien#endif 602118334Speter 6022117413Skan /* Allocate the argument vector. */ 6023117413Skan alloc_args (); 602418334Speter 602518334Speter obstack_init (&obstack); 602618334Speter 602750599Sobrien /* Build multilib_select, et. al from the separate lines that make up each 602850599Sobrien multilib selection. */ 602950599Sobrien { 603090277Sobrien const char *const *q = multilib_raw; 603150599Sobrien int need_space; 603250599Sobrien 603350599Sobrien obstack_init (&multilib_obstack); 603450599Sobrien while ((p = *q++) != (char *) 0) 603550599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 603650599Sobrien 603750599Sobrien obstack_1grow (&multilib_obstack, 0); 603850599Sobrien multilib_select = obstack_finish (&multilib_obstack); 603950599Sobrien 604050599Sobrien q = multilib_matches_raw; 604150599Sobrien while ((p = *q++) != (char *) 0) 604250599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 604350599Sobrien 604450599Sobrien obstack_1grow (&multilib_obstack, 0); 604550599Sobrien multilib_matches = obstack_finish (&multilib_obstack); 604650599Sobrien 604790277Sobrien q = multilib_exclusions_raw; 604890277Sobrien while ((p = *q++) != (char *) 0) 604990277Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 605090277Sobrien 605190277Sobrien obstack_1grow (&multilib_obstack, 0); 605290277Sobrien multilib_exclusions = obstack_finish (&multilib_obstack); 605390277Sobrien 605450599Sobrien need_space = FALSE; 605590277Sobrien for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++) 605650599Sobrien { 605750599Sobrien if (need_space) 605850599Sobrien obstack_1grow (&multilib_obstack, ' '); 605950599Sobrien obstack_grow (&multilib_obstack, 606050599Sobrien multilib_defaults_raw[i], 606150599Sobrien strlen (multilib_defaults_raw[i])); 606250599Sobrien need_space = TRUE; 606350599Sobrien } 606450599Sobrien 606550599Sobrien obstack_1grow (&multilib_obstack, 0); 606650599Sobrien multilib_defaults = obstack_finish (&multilib_obstack); 606750599Sobrien } 606850599Sobrien 606918334Speter /* Set up to remember the pathname of gcc and any options 607018334Speter needed for collect. We use argv[0] instead of programname because 607118334Speter we need the complete pathname. */ 607218334Speter obstack_init (&collect_obstack); 607390277Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1); 607490277Sobrien obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1); 607518334Speter putenv (obstack_finish (&collect_obstack)); 607618334Speter 607718334Speter#ifdef INIT_ENVIRONMENT 607818334Speter /* Set up any other necessary machine specific environment variables. */ 607918334Speter putenv (INIT_ENVIRONMENT); 608018334Speter#endif 608118334Speter 608218334Speter /* Make a table of what switches there are (switches, n_switches). 608318334Speter Make a table of specified input files (infiles, n_infiles). 608418334Speter Decode switches that are handled locally. */ 608518334Speter 608618334Speter process_command (argc, argv); 608718334Speter 608818334Speter /* Initialize the vector of specs to just the default. 608918334Speter This means one element containing 0s, as a terminator. */ 609018334Speter 6091132733Skan compilers = xmalloc (sizeof default_compilers); 6092132733Skan memcpy (compilers, default_compilers, sizeof default_compilers); 609318334Speter n_compilers = n_default_compilers; 609418334Speter 609518334Speter /* Read specs from a file if there is one. */ 609618334Speter 609791561Sobrien#ifdef FREEBSD_NATIVE 609891561Sobrien just_machine_suffix = ""; 609991561Sobrien#else /* FREEBSD_NATIVE */ 610050599Sobrien machine_suffix = concat (spec_machine, dir_separator_str, 610190277Sobrien spec_version, dir_separator_str, NULL); 610290277Sobrien just_machine_suffix = concat (spec_machine, dir_separator_str, NULL); 610350599Sobrien#endif /* FREEBSD_NATIVE */ 610418334Speter 6105104763Skan specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, 0); 610618334Speter /* Read the specs file unless it is a default one. */ 610718334Speter if (specs_file != 0 && strcmp (specs_file, "specs")) 610850599Sobrien read_specs (specs_file, TRUE); 610950599Sobrien else 611050599Sobrien init_spec (); 611118334Speter 611250599Sobrien /* We need to check standard_exec_prefix/just_machine_suffix/specs 611390277Sobrien for any override of as, ld and libraries. */ 611497902Sobrien specs_file = (char *) alloca (strlen (FBSD_DATA_PREFIX) 611550599Sobrien + strlen (just_machine_suffix) 611650599Sobrien + sizeof ("specs")); 611750599Sobrien 611897902Sobrien strcpy (specs_file, FBSD_DATA_PREFIX); 611950599Sobrien strcat (specs_file, just_machine_suffix); 612050599Sobrien strcat (specs_file, "specs"); 612150599Sobrien if (access (specs_file, R_OK) == 0) 612250599Sobrien read_specs (specs_file, TRUE); 612390277Sobrien 6124132733Skan /* Process any configure-time defaults specified for the command line 6125132733Skan options, via OPTION_DEFAULT_SPECS. */ 6126132733Skan for (i = 0; i < ARRAY_SIZE (option_default_specs); i++) 6127132733Skan do_option_spec (option_default_specs[i].name, 6128132733Skan option_default_specs[i].spec); 6129132733Skan 6130132733Skan /* Process DRIVER_SELF_SPECS, adding any new options to the end 6131132733Skan of the command line. */ 6132132733Skan 6133132733Skan for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++) 6134132733Skan do_self_spec (driver_self_specs[i]); 6135132733Skan 6136132733Skan /* If not cross-compiling, look for executables in the standard 6137132733Skan places. */ 6138132733Skan if (*cross_compile == '0') 613918334Speter { 614090277Sobrien if (*md_exec_prefix) 614190277Sobrien { 614290277Sobrien add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 6143104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 614490277Sobrien } 6145132733Skan } 614618334Speter 6147132733Skan /* Process sysroot_suffix_spec. */ 6148132733Skan if (*sysroot_suffix_spec != 0 6149132733Skan && do_spec_2 (sysroot_suffix_spec) == 0) 6150132733Skan { 6151132733Skan if (argbuf_index > 1) 6152132733Skan error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC."); 6153132733Skan else if (argbuf_index == 1) 6154132733Skan target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]); 6155132733Skan } 6156132733Skan 6157132733Skan /* Process sysroot_hdrs_suffix_spec. */ 6158132733Skan if (*sysroot_hdrs_suffix_spec != 0 6159132733Skan && do_spec_2 (sysroot_hdrs_suffix_spec) == 0) 6160132733Skan { 6161132733Skan if (argbuf_index > 1) 6162132733Skan error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC."); 6163132733Skan else if (argbuf_index == 1) 6164132733Skan target_sysroot_hdrs_suffix = xstrdup (argbuf[argbuf_index -1]); 6165132733Skan } 6166132733Skan 6167132733Skan /* Look for startfiles in the standard places. */ 6168132733Skan if (*startfile_prefix_spec != 0 6169132733Skan && do_spec_2 (startfile_prefix_spec) == 0 6170132733Skan && do_spec_1 (" ", 0, NULL) == 0) 6171132733Skan { 6172132733Skan int ndx; 6173132733Skan for (ndx = 0; ndx < argbuf_index; ndx++) 6174132733Skan add_sysrooted_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS", 6175132733Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 6176132733Skan } 6177132733Skan /* We should eventually get rid of all these and stick to 6178132733Skan startfile_prefix_spec exclusively. */ 6179132733Skan else if (*cross_compile == '0' || target_system_root) 6180132733Skan { 6181132733Skan if (*md_exec_prefix) 6182132733Skan add_sysrooted_prefix (&startfile_prefixes, md_exec_prefix, "GCC", 6183132733Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 6184132733Skan 618590277Sobrien if (*md_startfile_prefix) 6186132733Skan add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix, 6187132733Skan "GCC", PREFIX_PRIORITY_LAST, 0, NULL, 1); 618818334Speter 618990277Sobrien if (*md_startfile_prefix_1) 6190132733Skan add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix_1, 6191132733Skan "GCC", PREFIX_PRIORITY_LAST, 0, NULL, 1); 619218334Speter 619318334Speter /* If standard_startfile_prefix is relative, base it on 619418334Speter standard_exec_prefix. This lets us move the installed tree 619518334Speter as a unit. If GCC_EXEC_PREFIX is defined, base 6196132733Skan standard_startfile_prefix on that as well. 6197132733Skan 6198132733Skan If the prefix is relative, only search it for native compilers; 6199132733Skan otherwise we will search a directory containing host libraries. */ 6200132733Skan if (IS_ABSOLUTE_PATH (standard_startfile_prefix)) 6201132733Skan add_sysrooted_prefix (&startfile_prefixes, 6202132733Skan standard_startfile_prefix, "BINUTILS", 6203132733Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 6204132733Skan else if (*cross_compile == '0') 620518334Speter { 620618334Speter if (gcc_exec_prefix) 620718334Speter add_prefix (&startfile_prefixes, 620850599Sobrien concat (gcc_exec_prefix, machine_suffix, 620990277Sobrien standard_startfile_prefix, NULL), 6210104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); 621118334Speter add_prefix (&startfile_prefixes, 621250599Sobrien concat (standard_exec_prefix, 621350599Sobrien machine_suffix, 621490277Sobrien standard_startfile_prefix, NULL), 6215104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); 621690277Sobrien } 621718334Speter 621818346Speter#ifndef FREEBSD_NATIVE 6219132733Skan add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_1, 6220132733Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); 6221132733Skan add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_2, 6222132733Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); 622391561Sobrien#endif /* not FREEBSD_NATIVE */ 622418334Speter#if 0 /* Can cause surprises, and one can use -B./ instead. */ 622590277Sobrien add_prefix (&startfile_prefixes, "./", NULL, 6226104763Skan PREFIX_PRIORITY_LAST, 1, NULL, 0); 622718334Speter#endif 622818334Speter } 622918334Speter 623052520Sobrien /* Process any user specified specs in the order given on the command 623152520Sobrien line. */ 623252520Sobrien for (uptr = user_specs_head; uptr; uptr = uptr->next) 623352520Sobrien { 6234104763Skan char *filename = find_a_file (&startfile_prefixes, uptr->filename, 6235104763Skan R_OK, 0); 623652520Sobrien read_specs (filename ? filename : uptr->filename, FALSE); 623752520Sobrien } 623852520Sobrien 623918334Speter /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */ 624018334Speter if (gcc_exec_prefix) 624190277Sobrien gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 624290277Sobrien spec_version, dir_separator_str, NULL); 624318334Speter 624418334Speter /* Now we have the specs. 624518334Speter Set the `valid' bits for switches that match anything in any spec. */ 624618334Speter 624718334Speter validate_all_switches (); 624818334Speter 624918334Speter /* Now that we have the switches and the specs, set 625018334Speter the subdirectory based on the options. */ 625118334Speter set_multilib_dir (); 625218334Speter 625318334Speter /* Warn about any switches that no pass was interested in. */ 625418334Speter 625590277Sobrien for (i = 0; (int) i < n_switches; i++) 625652520Sobrien if (! switches[i].validated) 625718334Speter error ("unrecognized option `-%s'", switches[i].part1); 625818334Speter 625918334Speter /* Obey some of the options. */ 626018334Speter 626118334Speter if (print_search_dirs) 626218334Speter { 626390277Sobrien printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix); 626490277Sobrien printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0)); 626590277Sobrien printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0)); 626690277Sobrien return (0); 626718334Speter } 626818334Speter 626918334Speter if (print_file_name) 627018334Speter { 627118334Speter printf ("%s\n", find_file (print_file_name)); 627290277Sobrien return (0); 627318334Speter } 627418334Speter 627518334Speter if (print_prog_name) 627618334Speter { 6277104763Skan char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0); 627818334Speter printf ("%s\n", (newname ? newname : print_prog_name)); 627990277Sobrien return (0); 628018334Speter } 628118334Speter 628218334Speter if (print_multi_lib) 628318334Speter { 628418334Speter print_multilib_info (); 628590277Sobrien return (0); 628618334Speter } 628718334Speter 628818334Speter if (print_multi_directory) 628918334Speter { 629018334Speter if (multilib_dir == NULL) 629118334Speter printf (".\n"); 629218334Speter else 629318334Speter printf ("%s\n", multilib_dir); 629490277Sobrien return (0); 629518334Speter } 629618334Speter 6297104763Skan if (print_multi_os_directory) 6298104763Skan { 6299104763Skan if (multilib_os_dir == NULL) 6300104763Skan printf (".\n"); 6301104763Skan else 6302104763Skan printf ("%s\n", multilib_os_dir); 6303104763Skan return (0); 6304104763Skan } 6305104763Skan 630690277Sobrien if (target_help_flag) 630790277Sobrien { 630890277Sobrien /* Print if any target specific options. */ 630990277Sobrien 631090277Sobrien /* We do not exit here. Instead we have created a fake input file 631190277Sobrien called 'target-dummy' which needs to be compiled, and we pass this 631290277Sobrien on to the various sub-processes, along with the --target-help 631390277Sobrien switch. */ 631490277Sobrien } 631590277Sobrien 631650599Sobrien if (print_help_list) 631750599Sobrien { 631850599Sobrien display_help (); 631950599Sobrien 632050599Sobrien if (! verbose_flag) 632150599Sobrien { 632290277Sobrien printf (_("\nFor bug reporting instructions, please see:\n")); 6323117413Skan printf ("%s.\n", bug_report_url); 632490277Sobrien 632590277Sobrien return (0); 632650599Sobrien } 632750599Sobrien 632850599Sobrien /* We do not exit here. Instead we have created a fake input file 632950599Sobrien called 'help-dummy' which needs to be compiled, and we pass this 633090277Sobrien on the various sub-processes, along with the --help switch. */ 633150599Sobrien } 633290277Sobrien 633318334Speter if (verbose_flag) 633418334Speter { 633550599Sobrien int n; 633690277Sobrien const char *thrmod; 633750599Sobrien 633890277Sobrien notice ("Configured with: %s\n", configuration_arguments); 633990277Sobrien 634090277Sobrien#ifdef THREAD_MODEL_SPEC 634190277Sobrien /* We could have defined THREAD_MODEL_SPEC to "%*" by default, 634290277Sobrien but there's no point in doing all this processing just to get 634390277Sobrien thread_model back. */ 634490277Sobrien obstack_init (&obstack); 634590277Sobrien do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); 634690277Sobrien obstack_1grow (&obstack, '\0'); 634790277Sobrien thrmod = obstack_finish (&obstack); 634890277Sobrien#else 634990277Sobrien thrmod = thread_model; 635090277Sobrien#endif 635190277Sobrien 635290277Sobrien notice ("Thread model: %s\n", thrmod); 635390277Sobrien 635450599Sobrien /* compiler_version is truncated at the first space when initialized 635550599Sobrien from version string, so truncate version_string at the first space 635650599Sobrien before comparing. */ 635750599Sobrien for (n = 0; version_string[n]; n++) 635850599Sobrien if (version_string[n] == ' ') 635950599Sobrien break; 636050599Sobrien 636150599Sobrien if (! strncmp (version_string, compiler_version, n) 636250599Sobrien && compiler_version[n] == 0) 636352520Sobrien notice ("gcc version %s\n", version_string); 636418334Speter else 636552520Sobrien notice ("gcc driver version %s executing gcc version %s\n", 636652520Sobrien version_string, compiler_version); 636718334Speter 636818334Speter if (n_infiles == 0) 636990277Sobrien return (0); 637018334Speter } 637118334Speter 637250599Sobrien if (n_infiles == added_libraries) 637318346Speter fatal ("No input files specified"); 637418334Speter 637518334Speter /* Make a place to record the compiler output file names 637618334Speter that correspond to the input files. */ 637718334Speter 637850599Sobrien i = n_infiles; 637950599Sobrien i += lang_specific_extra_outfiles; 6380132733Skan outfiles = xcalloc (i, sizeof (char *)); 638118334Speter 638218334Speter /* Record which files were specified explicitly as link input. */ 638318334Speter 638490277Sobrien explicit_link_files = xcalloc (1, n_infiles); 638518334Speter 6386132733Skan if (combine_inputs) 638718334Speter { 6388132733Skan int lang_n_infiles = 0; 6389132733Skan for (i = 0; (int) i < n_infiles; i++) 6390132733Skan { 6391132733Skan const char *name = infiles[i].name; 6392132733Skan struct compiler *compiler 6393132733Skan = lookup_compiler (name, strlen (name), infiles[i].language); 6394132733Skan if (compiler == NULL) 6395132733Skan error ("%s: linker input file unused because linking not done", 6396132733Skan name); 6397132733Skan else if (lang_n_infiles > 0 && compiler != input_file_compiler) 6398132733Skan fatal ("cannot specify -o with -c or -S and multiple languages"); 6399132733Skan else 6400132733Skan { 6401132733Skan lang_n_infiles++; 6402132733Skan input_file_compiler = compiler; 6403132733Skan } 6404132733Skan } 6405132733Skan } 6406132733Skan 6407132733Skan for (i = 0; (int) i < (combine_inputs ? 1 : n_infiles); i++) 6408132733Skan { 640918334Speter int this_file_error = 0; 641018334Speter 641118334Speter /* Tell do_spec what to substitute for %i. */ 641218334Speter 641318334Speter input_file_number = i; 641490277Sobrien set_input (infiles[i].name); 641518334Speter 641618334Speter /* Use the same thing in %o, unless cp->spec says otherwise. */ 641718334Speter 641818334Speter outfiles[i] = input_filename; 641918334Speter 642018334Speter /* Figure out which compiler from the file's suffix. */ 642118334Speter 6422132733Skan if (! combine_inputs) 6423132733Skan input_file_compiler 6424132733Skan = lookup_compiler (infiles[i].name, input_filename_length, 6425132733Skan infiles[i].language); 6426117413Skan 642790277Sobrien if (input_file_compiler) 642818334Speter { 642918334Speter /* Ok, we found an applicable compiler. Run its spec. */ 643018334Speter 643190277Sobrien if (input_file_compiler->spec[0] == '#') 643218334Speter { 643390277Sobrien error ("%s: %s compiler not installed on this system", 643490277Sobrien input_filename, &input_file_compiler->spec[1]); 643590277Sobrien this_file_error = 1; 643618334Speter } 643718334Speter else 643890277Sobrien { 643990277Sobrien value = do_spec (input_file_compiler->spec); 644090277Sobrien if (value < 0) 644190277Sobrien this_file_error = 1; 644290277Sobrien } 644318334Speter } 644418334Speter 644518334Speter /* If this file's name does not contain a recognized suffix, 644618334Speter record it as explicit linker input. */ 644718334Speter 644818334Speter else 644918334Speter explicit_link_files[i] = 1; 645018334Speter 645118334Speter /* Clear the delete-on-failure queue, deleting the files in it 645218334Speter if this compilation failed. */ 645318334Speter 645418334Speter if (this_file_error) 645518334Speter { 645618334Speter delete_failure_queue (); 645718334Speter error_count++; 645818334Speter } 645918334Speter /* If this compilation succeeded, don't delete those files later. */ 646018334Speter clear_failure_queue (); 646118334Speter } 646218334Speter 646390277Sobrien /* Reset the output file name to the first input file name, for use 646490277Sobrien with %b in LINK_SPEC on a target that prefers not to emit a.out 646590277Sobrien by default. */ 646690277Sobrien if (n_infiles > 0) 646790277Sobrien set_input (infiles[0].name); 646890277Sobrien 646952520Sobrien if (error_count == 0) 647052520Sobrien { 647152520Sobrien /* Make sure INPUT_FILE_NUMBER points to first available open 647252520Sobrien slot. */ 647352520Sobrien input_file_number = n_infiles; 647452520Sobrien if (lang_specific_pre_link ()) 647552520Sobrien error_count++; 647652520Sobrien } 647750599Sobrien 6478132733Skan /* Determine if there are any linker input files. */ 6479132733Skan num_linker_inputs = 0; 6480132733Skan for (i = 0; (int) i < n_infiles; i++) 6481132733Skan if (explicit_link_files[i] || outfiles[i] != NULL) 6482132733Skan num_linker_inputs++; 6483132733Skan 648418334Speter /* Run ld to link all the compiler output files. */ 648518334Speter 6486132733Skan if (num_linker_inputs > 0 && error_count == 0) 648718334Speter { 648818334Speter int tmp = execution_count; 648918334Speter 649090277Sobrien /* We'll use ld if we can't find collect2. */ 649150599Sobrien if (! strcmp (linker_name_spec, "collect2")) 649250599Sobrien { 6493104763Skan char *s = find_a_file (&exec_prefixes, "collect2", X_OK, 0); 649450599Sobrien if (s == NULL) 649550599Sobrien linker_name_spec = "ld"; 649650599Sobrien } 649718334Speter /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 649818334Speter for collect. */ 649990277Sobrien putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH"); 650090277Sobrien putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV); 650118334Speter 650218334Speter value = do_spec (link_command_spec); 650318334Speter if (value < 0) 650418334Speter error_count = 1; 650518334Speter linker_was_run = (tmp != execution_count); 650618334Speter } 650718334Speter 650818334Speter /* If options said don't run linker, 650918334Speter complain about input files to be given to the linker. */ 651018334Speter 651118334Speter if (! linker_was_run && error_count == 0) 651290277Sobrien for (i = 0; (int) i < n_infiles; i++) 651318334Speter if (explicit_link_files[i]) 651490277Sobrien error ("%s: linker input file unused because linking not done", 651518334Speter outfiles[i]); 651618334Speter 651718334Speter /* Delete some or all of the temporary files we made. */ 651818334Speter 651918334Speter if (error_count) 652018334Speter delete_failure_queue (); 652118334Speter delete_temp_files (); 652218334Speter 652350599Sobrien if (print_help_list) 652450599Sobrien { 652590277Sobrien printf (("\nFor bug reporting instructions, please see:\n")); 6526117413Skan printf ("%s\n", bug_report_url); 652750599Sobrien } 652890277Sobrien 652990277Sobrien return (signal_count != 0 ? 2 653090277Sobrien : error_count > 0 ? (pass_exit_codes ? greatest_status : 1) 653190277Sobrien : 0); 653218334Speter} 653318334Speter 653418334Speter/* Find the proper compilation spec for the file name NAME, 653518334Speter whose length is LENGTH. LANGUAGE is the specified language, 653650599Sobrien or 0 if this file is to be passed to the linker. */ 653718334Speter 653818334Speterstatic struct compiler * 6539132733Skanlookup_compiler (const char *name, size_t length, const char *language) 654018334Speter{ 654118334Speter struct compiler *cp; 654218334Speter 654390277Sobrien /* If this was specified by the user to be a linker input, indicate that. */ 654450599Sobrien if (language != 0 && language[0] == '*') 654550599Sobrien return 0; 654650599Sobrien 654750599Sobrien /* Otherwise, look for the language, if one is spec'd. */ 654818334Speter if (language != 0) 654918334Speter { 655018334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 655150599Sobrien if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language)) 655250599Sobrien return cp; 655350599Sobrien 655418334Speter error ("language %s not recognized", language); 655550599Sobrien return 0; 655618334Speter } 655718334Speter 655818334Speter /* Look for a suffix. */ 655918334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 656018334Speter { 656118334Speter if (/* The suffix `-' matches only the file name `-'. */ 656218334Speter (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 656350599Sobrien || (strlen (cp->suffix) < length 656450599Sobrien /* See if the suffix matches the end of NAME. */ 656550599Sobrien && !strcmp (cp->suffix, 656650599Sobrien name + length - strlen (cp->suffix)) 656750599Sobrien )) 6568117413Skan break; 656990277Sobrien } 657050599Sobrien 657190277Sobrien#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM) 657290277Sobrien /* look again, but case-insensitively this time. */ 657390277Sobrien if (cp < compilers) 657490277Sobrien for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 657590277Sobrien { 657690277Sobrien if (/* The suffix `-' matches only the file name `-'. */ 657790277Sobrien (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 657890277Sobrien || (strlen (cp->suffix) < length 657990277Sobrien /* See if the suffix matches the end of NAME. */ 658090277Sobrien && ((!strcmp (cp->suffix, 658190277Sobrien name + length - strlen (cp->suffix)) 658290277Sobrien || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) 658390277Sobrien && !strcasecmp (cp->suffix, 658490277Sobrien name + length - strlen (cp->suffix))) 658590277Sobrien )) 658690277Sobrien break; 658790277Sobrien } 658890277Sobrien#endif 658950599Sobrien 659090277Sobrien if (cp >= compilers) 659190277Sobrien { 659290277Sobrien if (cp->spec[0] != '@') 659390277Sobrien /* A non-alias entry: return it. */ 659490277Sobrien return cp; 659590277Sobrien 659690277Sobrien /* An alias entry maps a suffix to a language. 659790277Sobrien Search for the language; pass 0 for NAME and LENGTH 659890277Sobrien to avoid infinite recursion if language not found. */ 659990277Sobrien return lookup_compiler (NULL, 0, cp->spec + 1); 660018334Speter } 660118334Speter return 0; 660218334Speter} 660318334Speter 660418334Speterstatic char * 6605132733Skansave_string (const char *s, int len) 660618334Speter{ 660790277Sobrien char *result = xmalloc (len + 1); 660818334Speter 660990277Sobrien memcpy (result, s, len); 661018334Speter result[len] = 0; 661118334Speter return result; 661218334Speter} 661318334Speter 661490277Sobrienvoid 6615132733Skanpfatal_with_name (const char *name) 661618334Speter{ 661752520Sobrien perror_with_name (name); 661852520Sobrien delete_temp_files (); 661952520Sobrien exit (1); 662018334Speter} 662118334Speter 662218334Speterstatic void 6623132733Skanperror_with_name (const char *name) 662418334Speter{ 662552520Sobrien error ("%s: %s", name, xstrerror (errno)); 662618334Speter} 662718334Speter 662818334Speterstatic void 6629132733Skanpfatal_pexecute (const char *errmsg_fmt, const char *errmsg_arg) 663018334Speter{ 663150599Sobrien if (errmsg_arg) 663250599Sobrien { 663352520Sobrien int save_errno = errno; 663452520Sobrien 663550599Sobrien /* Space for trailing '\0' is in %s. */ 663650599Sobrien char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg)); 663750599Sobrien sprintf (msg, errmsg_fmt, errmsg_arg); 663850599Sobrien errmsg_fmt = msg; 663952520Sobrien 664052520Sobrien errno = save_errno; 664150599Sobrien } 664250599Sobrien 664352520Sobrien pfatal_with_name (errmsg_fmt); 664418334Speter} 664518334Speter 6646132733Skan/* Output an error message and exit. */ 664718334Speter 664818334Spetervoid 6649132733Skanfancy_abort (void) 665018334Speter{ 665190277Sobrien fatal ("internal gcc abort"); 665218334Speter} 665318334Speter 6654132733Skan/* Output an error message and exit. */ 665518334Speter 665652520Sobrienvoid 6657132733Skanfatal (const char *msgid, ...) 665818334Speter{ 6659132733Skan va_list ap; 666018334Speter 6661132733Skan va_start (ap, msgid); 6662132733Skan 666318334Speter fprintf (stderr, "%s: ", programname); 666452520Sobrien vfprintf (stderr, _(msgid), ap); 6665132733Skan va_end (ap); 666618334Speter fprintf (stderr, "\n"); 666718334Speter delete_temp_files (); 666818334Speter exit (1); 666918334Speter} 667018334Speter 667190277Sobrienvoid 6672132733Skanerror (const char *msgid, ...) 667318334Speter{ 6674132733Skan va_list ap; 667518334Speter 6676132733Skan va_start (ap, msgid); 667718334Speter fprintf (stderr, "%s: ", programname); 667852520Sobrien vfprintf (stderr, _(msgid), ap); 6679132733Skan va_end (ap); 668018334Speter 668118334Speter fprintf (stderr, "\n"); 668218334Speter} 668352520Sobrien 668452520Sobrienstatic void 6685132733Skannotice (const char *msgid, ...) 668652520Sobrien{ 6687132733Skan va_list ap; 668852520Sobrien 6689132733Skan va_start (ap, msgid); 669052520Sobrien vfprintf (stderr, _(msgid), ap); 6691132733Skan va_end (ap); 669252520Sobrien} 669318334Speter 6694132733Skanstatic inline void 6695132733Skanvalidate_switches_from_spec (const char *spec) 6696132733Skan{ 6697132733Skan const char *p = spec; 6698132733Skan char c; 6699132733Skan while ((c = *p++)) 6700132733Skan if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{'))) 6701132733Skan /* We have a switch spec. */ 6702132733Skan p = validate_switches (p + 1); 6703132733Skan} 6704132733Skan 670518334Speterstatic void 6706132733Skanvalidate_all_switches (void) 670718334Speter{ 670818334Speter struct compiler *comp; 670918334Speter struct spec_list *spec; 671018334Speter 671190277Sobrien for (comp = compilers; comp->spec; comp++) 6712132733Skan validate_switches_from_spec (comp->spec); 671318334Speter 671490277Sobrien /* Look through the linked list of specs read from the specs file. */ 671590277Sobrien for (spec = specs; spec; spec = spec->next) 6716132733Skan validate_switches_from_spec (*spec->ptr_spec); 671718334Speter 6718132733Skan validate_switches_from_spec (link_command_spec); 671918334Speter} 672018334Speter 672118334Speter/* Look at the switch-name that comes after START 672218334Speter and mark as valid all supplied switches that match it. */ 672318334Speter 6724132733Skanstatic const char * 6725132733Skanvalidate_switches (const char *start) 672618334Speter{ 672790277Sobrien const char *p = start; 6728132733Skan const char *atom; 6729132733Skan size_t len; 673090277Sobrien int i; 6731132733Skan bool suffix = false; 6732132733Skan bool starred = false; 673318334Speter 6734132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0) 673518334Speter 673690277Sobriennext_member: 6737132733Skan SKIP_WHITE (); 6738132733Skan 673918334Speter if (*p == '!') 6740132733Skan p++; 674118334Speter 6742132733Skan SKIP_WHITE (); 674318334Speter if (*p == '.') 6744132733Skan suffix = true, p++; 674518334Speter 6746132733Skan atom = p; 6747132733Skan while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '=' 6748132733Skan || *p == ',' || *p == '.' || *p == '@') 674990277Sobrien p++; 6750132733Skan len = p - atom; 675118334Speter 6752132733Skan if (*p == '*') 6753132733Skan starred = true, p++; 6754132733Skan 6755132733Skan SKIP_WHITE (); 6756132733Skan 6757132733Skan if (!suffix) 675818334Speter { 675918334Speter /* Mark all matching switches as valid. */ 676018334Speter for (i = 0; i < n_switches; i++) 6761132733Skan if (!strncmp (switches[i].part1, atom, len) 6762132733Skan && (starred || switches[i].part1[len] == 0)) 676352520Sobrien switches[i].validated = 1; 676418334Speter } 6765132733Skan 6766132733Skan if (*p) p++; 6767132733Skan if (*p && (p[-1] == '|' || p[-1] == '&')) 6768132733Skan goto next_member; 6769132733Skan 6770132733Skan if (*p && p[-1] == ':') 677118334Speter { 6772132733Skan while (*p && *p != ';' && *p != '}') 677318334Speter { 6774132733Skan if (*p == '%') 6775132733Skan { 6776132733Skan p++; 6777132733Skan if (*p == '{' || *p == '<') 6778132733Skan p = validate_switches (p+1); 6779132733Skan else if (p[0] == 'W' && p[1] == '{') 6780132733Skan p = validate_switches (p+2); 6781132733Skan } 6782132733Skan else 6783132733Skan p++; 678418334Speter } 6785132733Skan 6786132733Skan if (*p) p++; 6787132733Skan if (*p && p[-1] == ';') 6788132733Skan goto next_member; 678918334Speter } 679090277Sobrien 6791132733Skan return p; 6792132733Skan#undef SKIP_WHITE 679318334Speter} 679418334Speter 6795104763Skanstruct mdswitchstr 6796104763Skan{ 6797104763Skan const char *str; 6798104763Skan int len; 6799104763Skan}; 6800104763Skan 6801104763Skanstatic struct mdswitchstr *mdswitches; 6802104763Skanstatic int n_mdswitches; 6803104763Skan 680450599Sobrien/* Check whether a particular argument was used. The first time we 680550599Sobrien canonicalize the switches to keep only the ones we care about. */ 680618334Speter 680718334Speterstatic int 6808132733Skanused_arg (const char *p, int len) 680918334Speter{ 681090277Sobrien struct mswitchstr 681190277Sobrien { 681290277Sobrien const char *str; 681390277Sobrien const char *replace; 681450599Sobrien int len; 681550599Sobrien int rep_len; 681650599Sobrien }; 681718334Speter 681850599Sobrien static struct mswitchstr *mswitches; 681950599Sobrien static int n_mswitches; 682050599Sobrien int i, j; 682150599Sobrien 682250599Sobrien if (!mswitches) 682350599Sobrien { 682450599Sobrien struct mswitchstr *matches; 682590277Sobrien const char *q; 682650599Sobrien int cnt = 0; 682750599Sobrien 682890277Sobrien /* Break multilib_matches into the component strings of string 682990277Sobrien and replacement string. */ 683050599Sobrien for (q = multilib_matches; *q != '\0'; q++) 683150599Sobrien if (*q == ';') 683250599Sobrien cnt++; 683350599Sobrien 6834132733Skan matches = alloca ((sizeof (struct mswitchstr)) * cnt); 683550599Sobrien i = 0; 683650599Sobrien q = multilib_matches; 683750599Sobrien while (*q != '\0') 683850599Sobrien { 683950599Sobrien matches[i].str = q; 684050599Sobrien while (*q != ' ') 684150599Sobrien { 684250599Sobrien if (*q == '\0') 684350599Sobrien abort (); 684450599Sobrien q++; 684550599Sobrien } 684650599Sobrien matches[i].len = q - matches[i].str; 684750599Sobrien 684850599Sobrien matches[i].replace = ++q; 684950599Sobrien while (*q != ';' && *q != '\0') 685050599Sobrien { 685150599Sobrien if (*q == ' ') 685250599Sobrien abort (); 685350599Sobrien q++; 685450599Sobrien } 685550599Sobrien matches[i].rep_len = q - matches[i].replace; 685650599Sobrien i++; 685750599Sobrien if (*q == ';') 685890277Sobrien q++; 685950599Sobrien } 686050599Sobrien 686150599Sobrien /* Now build a list of the replacement string for switches that we care 686250599Sobrien about. Make sure we allocate at least one entry. This prevents 686350599Sobrien xmalloc from calling fatal, and prevents us from re-executing this 686450599Sobrien block of code. */ 686550599Sobrien mswitches 6866132733Skan = xmalloc (sizeof (struct mswitchstr) 6867104763Skan * (n_mdswitches + (n_switches ? n_switches : 1))); 686850599Sobrien for (i = 0; i < n_switches; i++) 686950599Sobrien { 687050599Sobrien int xlen = strlen (switches[i].part1); 687150599Sobrien for (j = 0; j < cnt; j++) 687290277Sobrien if (xlen == matches[j].len 687390277Sobrien && ! strncmp (switches[i].part1, matches[j].str, xlen)) 687450599Sobrien { 687550599Sobrien mswitches[n_mswitches].str = matches[j].replace; 687650599Sobrien mswitches[n_mswitches].len = matches[j].rep_len; 687790277Sobrien mswitches[n_mswitches].replace = (char *) 0; 687850599Sobrien mswitches[n_mswitches].rep_len = 0; 687950599Sobrien n_mswitches++; 688050599Sobrien break; 688150599Sobrien } 688250599Sobrien } 6883104763Skan 6884104763Skan /* Add MULTILIB_DEFAULTS switches too, as long as they were not present 6885104763Skan on the command line nor any options mutually incompatible with 6886104763Skan them. */ 6887104763Skan for (i = 0; i < n_mdswitches; i++) 6888104763Skan { 6889104763Skan const char *r; 6890104763Skan 6891104763Skan for (q = multilib_options; *q != '\0'; q++) 6892104763Skan { 6893104763Skan while (*q == ' ') 6894104763Skan q++; 6895104763Skan 6896104763Skan r = q; 6897104763Skan while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0 6898104763Skan || strchr (" /", q[mdswitches[i].len]) == NULL) 6899104763Skan { 6900104763Skan while (*q != ' ' && *q != '/' && *q != '\0') 6901104763Skan q++; 6902104763Skan if (*q != '/') 6903104763Skan break; 6904104763Skan q++; 6905104763Skan } 6906104763Skan 6907104763Skan if (*q != ' ' && *q != '\0') 6908104763Skan { 6909104763Skan while (*r != ' ' && *r != '\0') 6910104763Skan { 6911104763Skan q = r; 6912104763Skan while (*q != ' ' && *q != '/' && *q != '\0') 6913104763Skan q++; 6914104763Skan 6915104763Skan if (used_arg (r, q - r)) 6916104763Skan break; 6917104763Skan 6918104763Skan if (*q != '/') 6919104763Skan { 6920104763Skan mswitches[n_mswitches].str = mdswitches[i].str; 6921104763Skan mswitches[n_mswitches].len = mdswitches[i].len; 6922104763Skan mswitches[n_mswitches].replace = (char *) 0; 6923104763Skan mswitches[n_mswitches].rep_len = 0; 6924104763Skan n_mswitches++; 6925104763Skan break; 6926104763Skan } 6927104763Skan 6928104763Skan r = q + 1; 6929104763Skan } 6930104763Skan break; 6931104763Skan } 6932104763Skan } 6933104763Skan } 693450599Sobrien } 693550599Sobrien 693650599Sobrien for (i = 0; i < n_mswitches; i++) 693750599Sobrien if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len)) 693818334Speter return 1; 693950599Sobrien 694018334Speter return 0; 694118334Speter} 694218334Speter 694318334Speterstatic int 6944132733Skandefault_arg (const char *p, int len) 694518334Speter{ 6946104763Skan int i; 694718334Speter 6948104763Skan for (i = 0; i < n_mdswitches; i++) 6949104763Skan if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len)) 6950104763Skan return 1; 695118334Speter 695218334Speter return 0; 695318334Speter} 695418334Speter 695590277Sobrien/* Work out the subdirectory to use based on the options. The format of 695690277Sobrien multilib_select is a list of elements. Each element is a subdirectory 695790277Sobrien name followed by a list of options followed by a semicolon. The format 695890277Sobrien of multilib_exclusions is the same, but without the preceding 695990277Sobrien directory. First gcc will check the exclusions, if none of the options 696090277Sobrien beginning with an exclamation point are present, and all of the other 696190277Sobrien options are present, then we will ignore this completely. Passing 696290277Sobrien that, gcc will consider each multilib_select in turn using the same 696390277Sobrien rules for matching the options. If a match is found, that subdirectory 696490277Sobrien will be used. */ 696518334Speter 696618334Speterstatic void 6967132733Skanset_multilib_dir (void) 696818334Speter{ 696990277Sobrien const char *p; 697090277Sobrien unsigned int this_path_len; 697190277Sobrien const char *this_path, *this_arg; 6972104763Skan const char *start, *end; 697318334Speter int not_arg; 6974104763Skan int ok, ndfltok, first; 697518334Speter 6976104763Skan n_mdswitches = 0; 6977104763Skan start = multilib_defaults; 6978104763Skan while (*start == ' ' || *start == '\t') 6979104763Skan start++; 6980104763Skan while (*start != '\0') 6981104763Skan { 6982104763Skan n_mdswitches++; 6983104763Skan while (*start != ' ' && *start != '\t' && *start != '\0') 6984104763Skan start++; 6985104763Skan while (*start == ' ' || *start == '\t') 6986104763Skan start++; 6987104763Skan } 6988104763Skan 6989104763Skan if (n_mdswitches) 6990104763Skan { 6991104763Skan int i = 0; 6992104763Skan 6993132733Skan mdswitches = xmalloc (sizeof (struct mdswitchstr) * n_mdswitches); 6994104763Skan for (start = multilib_defaults; *start != '\0'; start = end + 1) 6995104763Skan { 6996104763Skan while (*start == ' ' || *start == '\t') 6997104763Skan start++; 6998104763Skan 6999104763Skan if (*start == '\0') 7000104763Skan break; 7001132733Skan 7002104763Skan for (end = start + 1; 7003104763Skan *end != ' ' && *end != '\t' && *end != '\0'; end++) 7004104763Skan ; 7005104763Skan 7006104763Skan obstack_grow (&multilib_obstack, start, end - start); 7007104763Skan obstack_1grow (&multilib_obstack, 0); 7008104763Skan mdswitches[i].str = obstack_finish (&multilib_obstack); 7009104763Skan mdswitches[i++].len = end - start; 7010104763Skan 7011104763Skan if (*end == '\0') 7012104763Skan break; 7013104763Skan } 7014104763Skan } 7015104763Skan 701690277Sobrien p = multilib_exclusions; 701718334Speter while (*p != '\0') 701818334Speter { 701918334Speter /* Ignore newlines. */ 702018334Speter if (*p == '\n') 702118334Speter { 702218334Speter ++p; 702318334Speter continue; 702418334Speter } 702518334Speter 702690277Sobrien /* Check the arguments. */ 702790277Sobrien ok = 1; 702890277Sobrien while (*p != ';') 702990277Sobrien { 703090277Sobrien if (*p == '\0') 703190277Sobrien abort (); 703290277Sobrien 703390277Sobrien if (! ok) 703490277Sobrien { 703590277Sobrien ++p; 703690277Sobrien continue; 703790277Sobrien } 703890277Sobrien 703990277Sobrien this_arg = p; 704090277Sobrien while (*p != ' ' && *p != ';') 704190277Sobrien { 704290277Sobrien if (*p == '\0') 704390277Sobrien abort (); 704490277Sobrien ++p; 704590277Sobrien } 704690277Sobrien 704790277Sobrien if (*this_arg != '!') 704890277Sobrien not_arg = 0; 704990277Sobrien else 705090277Sobrien { 705190277Sobrien not_arg = 1; 705290277Sobrien ++this_arg; 705390277Sobrien } 705490277Sobrien 705590277Sobrien ok = used_arg (this_arg, p - this_arg); 705690277Sobrien if (not_arg) 705790277Sobrien ok = ! ok; 705890277Sobrien 705990277Sobrien if (*p == ' ') 706090277Sobrien ++p; 706190277Sobrien } 706290277Sobrien 706390277Sobrien if (ok) 706490277Sobrien return; 706590277Sobrien 706690277Sobrien ++p; 706790277Sobrien } 706890277Sobrien 7069104763Skan first = 1; 707090277Sobrien p = multilib_select; 707190277Sobrien while (*p != '\0') 707290277Sobrien { 707390277Sobrien /* Ignore newlines. */ 707490277Sobrien if (*p == '\n') 707590277Sobrien { 707690277Sobrien ++p; 707790277Sobrien continue; 707890277Sobrien } 707990277Sobrien 708018334Speter /* Get the initial path. */ 708118334Speter this_path = p; 708218334Speter while (*p != ' ') 708318334Speter { 708418334Speter if (*p == '\0') 708518334Speter abort (); 708618334Speter ++p; 708718334Speter } 708818334Speter this_path_len = p - this_path; 708918334Speter 709018334Speter /* Check the arguments. */ 709118334Speter ok = 1; 7092104763Skan ndfltok = 1; 709318334Speter ++p; 709418334Speter while (*p != ';') 709518334Speter { 709618334Speter if (*p == '\0') 709718334Speter abort (); 709818334Speter 709918334Speter if (! ok) 710018334Speter { 710118334Speter ++p; 710218334Speter continue; 710318334Speter } 710418334Speter 710518334Speter this_arg = p; 710618334Speter while (*p != ' ' && *p != ';') 710718334Speter { 710818334Speter if (*p == '\0') 710918334Speter abort (); 711018334Speter ++p; 711118334Speter } 711218334Speter 711318334Speter if (*this_arg != '!') 711418334Speter not_arg = 0; 711518334Speter else 711618334Speter { 711718334Speter not_arg = 1; 711818334Speter ++this_arg; 711918334Speter } 712018334Speter 712118334Speter /* If this is a default argument, we can just ignore it. 712218334Speter This is true even if this_arg begins with '!'. Beginning 712318334Speter with '!' does not mean that this argument is necessarily 712418334Speter inappropriate for this library: it merely means that 712518334Speter there is a more specific library which uses this 712618334Speter argument. If this argument is a default, we need not 712718334Speter consider that more specific library. */ 7128104763Skan ok = used_arg (this_arg, p - this_arg); 7129104763Skan if (not_arg) 7130104763Skan ok = ! ok; 713118334Speter 7132104763Skan if (! ok) 7133104763Skan ndfltok = 0; 7134104763Skan 7135104763Skan if (default_arg (this_arg, p - this_arg)) 7136104763Skan ok = 1; 7137104763Skan 713818334Speter if (*p == ' ') 713918334Speter ++p; 714018334Speter } 714118334Speter 7142104763Skan if (ok && first) 714318334Speter { 714418334Speter if (this_path_len != 1 714518334Speter || this_path[0] != '.') 714618334Speter { 714790277Sobrien char *new_multilib_dir = xmalloc (this_path_len + 1); 7148104763Skan char *q; 7149104763Skan 715052520Sobrien strncpy (new_multilib_dir, this_path, this_path_len); 715152520Sobrien new_multilib_dir[this_path_len] = '\0'; 7152104763Skan q = strchr (new_multilib_dir, ':'); 7153104763Skan if (q != NULL) 7154104763Skan *q = '\0'; 715552520Sobrien multilib_dir = new_multilib_dir; 715618334Speter } 7157104763Skan first = 0; 715818334Speter } 715918334Speter 7160104763Skan if (ndfltok) 7161104763Skan { 7162104763Skan const char *q = this_path, *end = this_path + this_path_len; 7163104763Skan 7164104763Skan while (q < end && *q != ':') 7165104763Skan q++; 7166104763Skan if (q < end) 7167104763Skan { 7168104763Skan char *new_multilib_os_dir = xmalloc (end - q); 7169104763Skan memcpy (new_multilib_os_dir, q + 1, end - q - 1); 7170104763Skan new_multilib_os_dir[end - q - 1] = '\0'; 7171104763Skan multilib_os_dir = new_multilib_os_dir; 7172104763Skan break; 7173104763Skan } 7174104763Skan } 7175104763Skan 717618334Speter ++p; 717790277Sobrien } 7178104763Skan 7179104763Skan if (multilib_dir == NULL && multilib_os_dir != NULL 7180104763Skan && strcmp (multilib_os_dir, ".") == 0) 7181104763Skan { 7182104763Skan free ((char *) multilib_os_dir); 7183104763Skan multilib_os_dir = NULL; 7184104763Skan } 7185104763Skan else if (multilib_dir != NULL && multilib_os_dir == NULL) 7186104763Skan multilib_os_dir = multilib_dir; 718718334Speter} 718818334Speter 718918334Speter/* Print out the multiple library subdirectory selection 719018334Speter information. This prints out a series of lines. Each line looks 719118334Speter like SUBDIRECTORY;@OPTION@OPTION, with as many options as is 719218334Speter required. Only the desired options are printed out, the negative 719318334Speter matches. The options are print without a leading dash. There are 719418334Speter no spaces to make it easy to use the information in the shell. 719518334Speter Each subdirectory is printed only once. This assumes the ordering 719690277Sobrien generated by the genmultilib script. Also, we leave out ones that match 719790277Sobrien the exclusions. */ 719818334Speter 719918334Speterstatic void 7200132733Skanprint_multilib_info (void) 720118334Speter{ 720290277Sobrien const char *p = multilib_select; 720390277Sobrien const char *last_path = 0, *this_path; 720418334Speter int skip; 720590277Sobrien unsigned int last_path_len = 0; 720618334Speter 720718334Speter while (*p != '\0') 720818334Speter { 720990277Sobrien skip = 0; 721018334Speter /* Ignore newlines. */ 721118334Speter if (*p == '\n') 721218334Speter { 721318334Speter ++p; 721418334Speter continue; 721518334Speter } 721618334Speter 721718334Speter /* Get the initial path. */ 721818334Speter this_path = p; 721918334Speter while (*p != ' ') 722018334Speter { 722118334Speter if (*p == '\0') 722218334Speter abort (); 722318334Speter ++p; 722418334Speter } 722518334Speter 7226104763Skan /* When --disable-multilib was used but target defines 7227104763Skan MULTILIB_OSDIRNAMES, entries starting with .: are there just 7228104763Skan to find multilib_os_dir, so skip them from output. */ 7229104763Skan if (this_path[0] == '.' && this_path[1] == ':') 7230104763Skan skip = 1; 7231104763Skan 723290277Sobrien /* Check for matches with the multilib_exclusions. We don't bother 723390277Sobrien with the '!' in either list. If any of the exclusion rules match 723490277Sobrien all of its options with the select rule, we skip it. */ 723590277Sobrien { 723690277Sobrien const char *e = multilib_exclusions; 723790277Sobrien const char *this_arg; 723818334Speter 723990277Sobrien while (*e != '\0') 724090277Sobrien { 724190277Sobrien int m = 1; 724290277Sobrien /* Ignore newlines. */ 724390277Sobrien if (*e == '\n') 724490277Sobrien { 724590277Sobrien ++e; 724690277Sobrien continue; 724790277Sobrien } 724818334Speter 724990277Sobrien /* Check the arguments. */ 725090277Sobrien while (*e != ';') 725190277Sobrien { 725290277Sobrien const char *q; 725390277Sobrien int mp = 0; 725490277Sobrien 725590277Sobrien if (*e == '\0') 725690277Sobrien abort (); 725790277Sobrien 725890277Sobrien if (! m) 725990277Sobrien { 726090277Sobrien ++e; 726190277Sobrien continue; 726290277Sobrien } 726390277Sobrien 726490277Sobrien this_arg = e; 726590277Sobrien 726690277Sobrien while (*e != ' ' && *e != ';') 726790277Sobrien { 726890277Sobrien if (*e == '\0') 726990277Sobrien abort (); 727090277Sobrien ++e; 727190277Sobrien } 727290277Sobrien 727390277Sobrien q = p + 1; 727490277Sobrien while (*q != ';') 727590277Sobrien { 727690277Sobrien const char *arg; 727790277Sobrien int len = e - this_arg; 727890277Sobrien 727990277Sobrien if (*q == '\0') 728090277Sobrien abort (); 728190277Sobrien 728290277Sobrien arg = q; 728390277Sobrien 728490277Sobrien while (*q != ' ' && *q != ';') 728590277Sobrien { 728690277Sobrien if (*q == '\0') 728790277Sobrien abort (); 728890277Sobrien ++q; 728990277Sobrien } 729090277Sobrien 729190277Sobrien if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) || 729290277Sobrien default_arg (this_arg, e - this_arg)) 729390277Sobrien { 729490277Sobrien mp = 1; 729590277Sobrien break; 729690277Sobrien } 729790277Sobrien 729890277Sobrien if (*q == ' ') 729990277Sobrien ++q; 730090277Sobrien } 730190277Sobrien 730290277Sobrien if (! mp) 730390277Sobrien m = 0; 730490277Sobrien 730590277Sobrien if (*e == ' ') 730690277Sobrien ++e; 730790277Sobrien } 730890277Sobrien 730990277Sobrien if (m) 731090277Sobrien { 731190277Sobrien skip = 1; 731290277Sobrien break; 731390277Sobrien } 731490277Sobrien 731590277Sobrien if (*e != '\0') 731690277Sobrien ++e; 731790277Sobrien } 731890277Sobrien } 731990277Sobrien 732090277Sobrien if (! skip) 732190277Sobrien { 732290277Sobrien /* If this is a duplicate, skip it. */ 732390277Sobrien skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len 732490277Sobrien && ! strncmp (last_path, this_path, last_path_len)); 732590277Sobrien 732690277Sobrien last_path = this_path; 732790277Sobrien last_path_len = p - this_path; 732890277Sobrien } 732990277Sobrien 733018334Speter /* If this directory requires any default arguments, we can skip 733118334Speter it. We will already have printed a directory identical to 733218334Speter this one which does not require that default argument. */ 733318334Speter if (! skip) 733418334Speter { 733590277Sobrien const char *q; 733618334Speter 733718334Speter q = p + 1; 733818334Speter while (*q != ';') 733918334Speter { 734090277Sobrien const char *arg; 734118334Speter 734218334Speter if (*q == '\0') 734318334Speter abort (); 734418334Speter 734518334Speter if (*q == '!') 734618334Speter arg = NULL; 734718334Speter else 734818334Speter arg = q; 734918334Speter 735018334Speter while (*q != ' ' && *q != ';') 735118334Speter { 735218334Speter if (*q == '\0') 735318334Speter abort (); 735418334Speter ++q; 735518334Speter } 735618334Speter 735718334Speter if (arg != NULL 735818334Speter && default_arg (arg, q - arg)) 735918334Speter { 736018334Speter skip = 1; 736118334Speter break; 736218334Speter } 736318334Speter 736418334Speter if (*q == ' ') 736518334Speter ++q; 736618334Speter } 736718334Speter } 736818334Speter 736918334Speter if (! skip) 737018334Speter { 737190277Sobrien const char *p1; 737218334Speter 7373104763Skan for (p1 = last_path; p1 < p && *p1 != ':'; p1++) 737418334Speter putchar (*p1); 737518334Speter putchar (';'); 737618334Speter } 737718334Speter 737818334Speter ++p; 737918334Speter while (*p != ';') 738018334Speter { 738118334Speter int use_arg; 738218334Speter 738318334Speter if (*p == '\0') 738418334Speter abort (); 738518334Speter 738618334Speter if (skip) 738718334Speter { 738818334Speter ++p; 738918334Speter continue; 739018334Speter } 739118334Speter 739218334Speter use_arg = *p != '!'; 739318334Speter 739418334Speter if (use_arg) 739518334Speter putchar ('@'); 739618334Speter 739718334Speter while (*p != ' ' && *p != ';') 739818334Speter { 739918334Speter if (*p == '\0') 740018334Speter abort (); 740118334Speter if (use_arg) 740218334Speter putchar (*p); 740318334Speter ++p; 740418334Speter } 740518334Speter 740618334Speter if (*p == ' ') 740718334Speter ++p; 740818334Speter } 740918334Speter 741018334Speter if (! skip) 741150599Sobrien { 741290277Sobrien /* If there are extra options, print them now. */ 741350599Sobrien if (multilib_extra && *multilib_extra) 741450599Sobrien { 741550599Sobrien int print_at = TRUE; 741690277Sobrien const char *q; 741718334Speter 741850599Sobrien for (q = multilib_extra; *q != '\0'; q++) 741950599Sobrien { 742050599Sobrien if (*q == ' ') 742150599Sobrien print_at = TRUE; 742250599Sobrien else 742350599Sobrien { 742450599Sobrien if (print_at) 742550599Sobrien putchar ('@'); 742650599Sobrien putchar (*q); 742750599Sobrien print_at = FALSE; 742850599Sobrien } 742950599Sobrien } 743050599Sobrien } 743190277Sobrien 743250599Sobrien putchar ('\n'); 743350599Sobrien } 743450599Sobrien 743518334Speter ++p; 743618334Speter } 743718334Speter} 7438117413Skan 7439117413Skan/* if-exists built-in spec function. 7440117413Skan 7441117413Skan Checks to see if the file specified by the absolute pathname in 7442117413Skan ARGS exists. Returns that pathname if found. 7443117413Skan 7444117413Skan The usual use for this function is to check for a library file 7445117413Skan (whose name has been expanded with %s). */ 7446117413Skan 7447117413Skanstatic const char * 7448132733Skanif_exists_spec_function (int argc, const char **argv) 7449117413Skan{ 7450117413Skan /* Must have only one argument. */ 7451132733Skan if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK)) 7452117413Skan return argv[0]; 7453117413Skan 7454117413Skan return NULL; 7455117413Skan} 7456117413Skan 7457117413Skan/* if-exists-else built-in spec function. 7458117413Skan 7459117413Skan This is like if-exists, but takes an additional argument which 7460117413Skan is returned if the first argument does not exist. */ 7461117413Skan 7462117413Skanstatic const char * 7463132733Skanif_exists_else_spec_function (int argc, const char **argv) 7464117413Skan{ 7465117413Skan /* Must have exactly two arguments. */ 7466117413Skan if (argc != 2) 7467117413Skan return NULL; 7468117413Skan 7469132733Skan if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK)) 7470117413Skan return argv[0]; 7471117413Skan 7472117413Skan return argv[1]; 7473117413Skan} 7474