gcc.c revision 161660
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. 4161660Skan 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, 5161660Skan Inc. 618334Speter 790277SobrienThis file is part of GCC. 818334Speter 990277SobrienGCC is free software; you can redistribute it and/or modify it under 1090277Sobrienthe terms of the GNU General Public License as published by the Free 1190277SobrienSoftware Foundation; either version 2, or (at your option) any later 1290277Sobrienversion. 1318334Speter 1490277SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1590277SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1690277SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1790277Sobrienfor more details. 1818334Speter 1918334SpeterYou should have received a copy of the GNU General Public License 2090277Sobrienalong with GCC; see the file COPYING. If not, write to the Free 2190277SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2290277Sobrien02111-1307, USA. 2318334Speter 2418334SpeterThis paragraph is here to try to keep Sun CC from dying. 2518334SpeterThe number of chars here seems crucial!!!! */ 2618334Speter 2751232Sbde/* $FreeBSD: head/contrib/gcc/gcc.c 161660 2006-08-26 21:37:21Z kan $ */ 2851232Sbde 2918334Speter/* This program is the user interface to the C compiler and possibly to 3018334Speterother compilers. It is used because compilation is a complicated procedure 3118334Speterwhich involves running several programs and passing temporary files between 3218334Speterthem, forwarding the users switches to those programs selectively, 3318334Speterand deleting the temporary files at the end. 3418334Speter 3518334SpeterCC recognizes how to compile each input file by suffixes in the file names. 3618334SpeterOnce it knows which kind of compilation to perform, the procedure for 3718334Spetercompilation is specified by a string called a "spec". */ 3890277Sobrien 3990277Sobrien/* A Short Introduction to Adding a Command-Line Option. 4090277Sobrien 4190277Sobrien Before adding a command-line option, consider if it is really 4290277Sobrien necessary. Each additional command-line option adds complexity and 4390277Sobrien is difficult to remove in subsequent versions. 4490277Sobrien 4590277Sobrien In the following, consider adding the command-line argument 4690277Sobrien `--bar'. 4790277Sobrien 4890277Sobrien 1. Each command-line option is specified in the specs file. The 4990277Sobrien notation is described below in the comment entitled "The Specs 5090277Sobrien Language". Read it. 5190277Sobrien 5290277Sobrien 2. In this file, add an entry to "option_map" equating the long 5390277Sobrien `--' argument version and any shorter, single letter version. Read 5490277Sobrien the comments in the declaration of "struct option_map" for an 5590277Sobrien explanation. Do not omit the first `-'. 5690277Sobrien 5790277Sobrien 3. Look in the "specs" file to determine which program or option 5890277Sobrien list should be given the argument, e.g., "cc1_options". Add the 5990277Sobrien appropriate syntax for the shorter option version to the 6090277Sobrien corresponding "const char *" entry in this file. Omit the first 6190277Sobrien `-' from the option. For example, use `-bar', rather than `--bar'. 6290277Sobrien 6390277Sobrien 4. If the argument takes an argument, e.g., `--baz argument1', 6490277Sobrien modify either DEFAULT_SWITCH_TAKES_ARG or 6590277Sobrien DEFAULT_WORD_SWITCH_TAKES_ARG in this file. Omit the first `-' 6690277Sobrien from `--baz'. 6790277Sobrien 6890277Sobrien 5. Document the option in this file's display_help(). If the 6990277Sobrien option is passed to a subprogram, modify its corresponding 7090277Sobrien function, e.g., cppinit.c:print_help() or toplev.c:display_help(), 7190277Sobrien instead. 7290277Sobrien 7390277Sobrien 6. Compile and test. Make sure that your new specs file is being 7490277Sobrien read. For example, use a debugger to investigate the value of 7590277Sobrien "specs_file" in main(). */ 7690277Sobrien 7750599Sobrien#include "config.h" 7850599Sobrien#include "system.h" 79132733Skan#include "coretypes.h" 80132733Skan#include "multilib.h" /* before tm.h */ 81132733Skan#include "tm.h" 8250599Sobrien#include <signal.h> 8390277Sobrien#if ! defined( SIGCHLD ) && defined( SIGCLD ) 8490277Sobrien# define SIGCHLD SIGCLD 8590277Sobrien#endif 8650599Sobrien#include "obstack.h" 8752520Sobrien#include "intl.h" 8852520Sobrien#include "prefix.h" 8990277Sobrien#include "gcc.h" 9090277Sobrien#include "flags.h" 9118334Speter 9290277Sobrien#ifdef HAVE_SYS_RESOURCE_H 9390277Sobrien#include <sys/resource.h> 9418334Speter#endif 9590277Sobrien#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE 96132733Skanextern int getrusage (int, struct rusage *); 9790277Sobrien#endif 9818334Speter 9990277Sobrien/* By default there is no special suffix for target executables. */ 10090277Sobrien/* FIXME: when autoconf is fixed, remove the host check - dj */ 10190277Sobrien#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX) 10290277Sobrien#define HAVE_TARGET_EXECUTABLE_SUFFIX 10318334Speter#endif 10418334Speter 10590277Sobrien/* By default there is no special suffix for host executables. */ 10690277Sobrien#ifdef HOST_EXECUTABLE_SUFFIX 10790277Sobrien#define HAVE_HOST_EXECUTABLE_SUFFIX 10818334Speter#else 10990277Sobrien#define HOST_EXECUTABLE_SUFFIX "" 11018334Speter#endif 11118334Speter 11290277Sobrien/* By default, the suffix for target object files is ".o". */ 11390277Sobrien#ifdef TARGET_OBJECT_SUFFIX 11490277Sobrien#define HAVE_TARGET_OBJECT_SUFFIX 11590277Sobrien#else 11690277Sobrien#define TARGET_OBJECT_SUFFIX ".o" 11718334Speter#endif 11818334Speter 11990277Sobrienstatic const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; 12052520Sobrien 12190277Sobrien/* Most every one is fine with LIBRARY_PATH. For some, it conflicts. */ 12290277Sobrien#ifndef LIBRARY_PATH_ENV 12390277Sobrien#define LIBRARY_PATH_ENV "LIBRARY_PATH" 12490277Sobrien#endif 12590277Sobrien 12650599Sobrien#ifndef HAVE_KILL 12750599Sobrien#define kill(p,s) raise(s) 12818334Speter#endif 12918334Speter 13018334Speter/* If a stage of compilation returns an exit status >= 1, 13118334Speter compilation of that file ceases. */ 13218334Speter 13318334Speter#define MIN_FATAL_STATUS 1 13418334Speter 13590277Sobrien/* Flag set by cppspec.c to 1. */ 13690277Sobrienint is_cpp_driver; 13790277Sobrien 13890277Sobrien/* Flag saying to pass the greatest exit code returned by a sub-process 13990277Sobrien to the calling program. */ 14090277Sobrienstatic int pass_exit_codes; 14190277Sobrien 14290277Sobrien/* Definition of string containing the arguments given to configure. */ 14390277Sobrien#include "configargs.h" 14490277Sobrien 14518334Speter/* Flag saying to print the directories gcc will search through looking for 14618334Speter programs, libraries, etc. */ 14718334Speter 14818334Speterstatic int print_search_dirs; 14918334Speter 15018334Speter/* Flag saying to print the full filename of this file 15118334Speter as found through our usual search mechanism. */ 15218334Speter 15352520Sobrienstatic const char *print_file_name = NULL; 15418334Speter 15550599Sobrien/* As print_file_name, but search for executable file. */ 15618334Speter 15752520Sobrienstatic const char *print_prog_name = NULL; 15818334Speter 15918334Speter/* Flag saying to print the relative path we'd use to 16018334Speter find libgcc.a given the current compiler flags. */ 16118334Speter 16218334Speterstatic int print_multi_directory; 16318334Speter 164104763Skan/* Flag saying to print the relative path we'd use to 165104763Skan find OS libraries given the current compiler flags. */ 166104763Skan 167104763Skanstatic int print_multi_os_directory; 168104763Skan 16918334Speter/* Flag saying to print the list of subdirectories and 17018334Speter compiler flags used to select them in a standard form. */ 17118334Speter 17218334Speterstatic int print_multi_lib; 17318334Speter 17450599Sobrien/* Flag saying to print the command line options understood by gcc and its 17550599Sobrien sub-processes. */ 17650599Sobrien 17750599Sobrienstatic int print_help_list; 17850599Sobrien 17918334Speter/* Flag indicating whether we should print the command and arguments */ 18018334Speter 18118334Speterstatic int verbose_flag; 18218334Speter 18390277Sobrien/* Flag indicating whether we should ONLY print the command and 18490277Sobrien arguments (like verbose_flag) without executing the command. 18590277Sobrien Displayed arguments are quoted so that the generated command 18690277Sobrien line is suitable for execution. This is intended for use in 18790277Sobrien shell scripts to capture the driver-generated command line. */ 18890277Sobrienstatic int verbose_only_flag; 18990277Sobrien 19090277Sobrien/* Flag indicating to print target specific command line options. */ 19190277Sobrien 19290277Sobrienstatic int target_help_flag; 19390277Sobrien 19490277Sobrien/* Flag indicating whether we should report subprocess execution times 19590277Sobrien (if this is supported by the system - see pexecute.c). */ 19690277Sobrien 19790277Sobrienstatic int report_times; 19890277Sobrien 199132733Skan/* Nonzero means place this string before uses of /, so that include 200132733Skan and library files can be found in an alternate location. */ 201132733Skan 202132733Skan#ifdef TARGET_SYSTEM_ROOT 203132733Skanstatic const char *target_system_root = TARGET_SYSTEM_ROOT; 204132733Skan#else 205132733Skanstatic const char *target_system_root = 0; 206132733Skan#endif 207132733Skan 208132733Skan/* Nonzero means pass the updated target_system_root to the compiler. */ 209132733Skan 210132733Skanstatic int target_system_root_changed; 211132733Skan 212132733Skan/* Nonzero means append this string to target_system_root. */ 213132733Skan 214132733Skanstatic const char *target_sysroot_suffix = 0; 215132733Skan 216132733Skan/* Nonzero means append this string to target_system_root for headers. */ 217132733Skan 218132733Skanstatic const char *target_sysroot_hdrs_suffix = 0; 219132733Skan 22018334Speter/* Nonzero means write "temp" files in source directory 22118334Speter and use the source file's name in them, and don't delete them. */ 22218334Speter 22318334Speterstatic int save_temps_flag; 22418334Speter 225132733Skan/* Nonzero means use pipes to communicate between subprocesses. 226132733Skan Overridden by either of the above two flags. */ 227132733Skan 228132733Skanstatic int use_pipes; 229132733Skan 23018334Speter/* The compiler version. */ 23118334Speter 23290277Sobrienstatic const char *compiler_version; 23318334Speter 23418334Speter/* The target version specified with -V */ 23518334Speter 236117413Skanstatic const char *const spec_version = DEFAULT_TARGET_VERSION; 23718334Speter 23818334Speter/* The target machine specified with -b. */ 23918334Speter 24052520Sobrienstatic const char *spec_machine = DEFAULT_TARGET_MACHINE; 24118334Speter 24218334Speter/* Nonzero if cross-compiling. 24318334Speter When -b is used, the value comes from the `specs' file. */ 24418334Speter 24518334Speter#ifdef CROSS_COMPILE 24690277Sobrienstatic const char *cross_compile = "1"; 24718334Speter#else 24890277Sobrienstatic const char *cross_compile = "0"; 24918334Speter#endif 25018334Speter 25190277Sobrien#ifdef MODIFY_TARGET_NAME 25290277Sobrien 25390277Sobrien/* Information on how to alter the target name based on a command-line 25490277Sobrien switch. The only case we support now is simply appending or deleting a 25590277Sobrien string to or from the end of the first part of the configuration name. */ 25690277Sobrien 25790277Sobrienstatic const struct modify_target 25890277Sobrien{ 25990277Sobrien const char *const sw; 26090277Sobrien const enum add_del {ADD, DELETE} add_del; 26190277Sobrien const char *const str; 26290277Sobrien} 26390277Sobrienmodify_target[] = MODIFY_TARGET_NAME; 26490277Sobrien#endif 265117413Skan 26618334Speter/* The number of errors that have occurred; the link phase will not be 267117413Skan run if this is nonzero. */ 26818334Speterstatic int error_count = 0; 26918334Speter 27090277Sobrien/* Greatest exit code of sub-processes that has been encountered up to 27190277Sobrien now. */ 27290277Sobrienstatic int greatest_status = 1; 27390277Sobrien 27418334Speter/* This is the obstack which we use to allocate many strings. */ 27518334Speter 27618334Speterstatic struct obstack obstack; 27718334Speter 27818334Speter/* This is the obstack to build an environment variable to pass to 27918334Speter collect2 that describes all of the relevant switches of what to 28018334Speter pass the compiler in building the list of pointers to constructors 28118334Speter and destructors. */ 28218334Speter 28318334Speterstatic struct obstack collect_obstack; 28418334Speter 28590277Sobrien/* These structs are used to collect resource usage information for 28690277Sobrien subprocesses. */ 28790277Sobrien#ifdef HAVE_GETRUSAGE 28890277Sobrienstatic struct rusage rus, prus; 28990277Sobrien#endif 29018334Speter 29118334Speter/* Forward declaration for prototypes. */ 29218334Speterstruct path_prefix; 29318334Speter 294132733Skanstatic void init_spec (void); 295132733Skanstatic void store_arg (const char *, int, int); 296132733Skanstatic char *load_specs (const char *); 297132733Skanstatic void read_specs (const char *, int); 298132733Skanstatic void set_spec (const char *, const char *); 299132733Skanstatic struct compiler *lookup_compiler (const char *, size_t, const char *); 300132733Skanstatic char *build_search_list (struct path_prefix *, const char *, int); 301132733Skanstatic void putenv_from_prefixes (struct path_prefix *, const char *); 302132733Skanstatic int access_check (const char *, int); 303132733Skanstatic char *find_a_file (struct path_prefix *, const char *, int, int); 304132733Skanstatic void add_prefix (struct path_prefix *, const char *, const char *, 305132733Skan int, int, int *, int); 306132733Skanstatic void add_sysrooted_prefix (struct path_prefix *, const char *, 307132733Skan const char *, int, int, int *, int); 308132733Skanstatic void translate_options (int *, const char *const **); 309132733Skanstatic char *skip_whitespace (char *); 310132733Skanstatic void delete_if_ordinary (const char *); 311132733Skanstatic void delete_temp_files (void); 312132733Skanstatic void delete_failure_queue (void); 313132733Skanstatic void clear_failure_queue (void); 314132733Skanstatic int check_live_switch (int, int); 315132733Skanstatic const char *handle_braces (const char *); 316132733Skanstatic inline bool input_suffix_matches (const char *, const char *); 317132733Skanstatic inline bool switch_matches (const char *, const char *, int); 318132733Skanstatic inline void mark_matching_switches (const char *, const char *, int); 319132733Skanstatic inline void process_marked_switches (void); 320132733Skanstatic const char *process_brace_body (const char *, const char *, const char *, int, int); 321132733Skanstatic const struct spec_function *lookup_spec_function (const char *); 322132733Skanstatic const char *eval_spec_function (const char *, const char *); 323132733Skanstatic const char *handle_spec_function (const char *); 324132733Skanstatic char *save_string (const char *, int); 325132733Skanstatic void set_collect_gcc_options (void); 326132733Skanstatic int do_spec_1 (const char *, int, const char *); 327132733Skanstatic int do_spec_2 (const char *); 328132733Skanstatic void do_option_spec (const char *, const char *); 329132733Skanstatic void do_self_spec (const char *); 330132733Skanstatic const char *find_file (const char *); 331132733Skanstatic int is_directory (const char *, const char *, int); 332132733Skanstatic const char *validate_switches (const char *); 333132733Skanstatic void validate_all_switches (void); 334132733Skanstatic inline void validate_switches_from_spec (const char *); 335132733Skanstatic void give_switch (int, int); 336132733Skanstatic int used_arg (const char *, int); 337132733Skanstatic int default_arg (const char *, int); 338132733Skanstatic void set_multilib_dir (void); 339132733Skanstatic void print_multilib_info (void); 340132733Skanstatic void perror_with_name (const char *); 341132733Skanstatic void pfatal_pexecute (const char *, const char *) ATTRIBUTE_NORETURN; 342132733Skanstatic void notice (const char *, ...) ATTRIBUTE_PRINTF_1; 343132733Skanstatic void display_help (void); 344132733Skanstatic void add_preprocessor_option (const char *, int); 345132733Skanstatic void add_assembler_option (const char *, int); 346132733Skanstatic void add_linker_option (const char *, int); 347132733Skanstatic void process_command (int, const char **); 348132733Skanstatic int execute (void); 349132733Skanstatic void alloc_args (void); 350132733Skanstatic void clear_args (void); 351132733Skanstatic void fatal_error (int); 35290277Sobrien#ifdef ENABLE_SHARED_LIBGCC 353132733Skanstatic void init_gcc_specs (struct obstack *, const char *, const char *, 354132733Skan const char *); 35590277Sobrien#endif 35690277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 357132733Skanstatic const char *convert_filename (const char *, int, int); 35890277Sobrien#endif 359117413Skan 360132733Skanstatic const char *if_exists_spec_function (int, const char **); 361132733Skanstatic const char *if_exists_else_spec_function (int, const char **); 36290277Sobrien 36390277Sobrien/* The Specs Language 36418334Speter 36590277SobrienSpecs are strings containing lines, each of which (if not blank) 36618334Speteris made up of a program name, and arguments separated by spaces. 36718334SpeterThe program name must be exact and start from root, since no path 36818334Speteris searched and it is unreliable to depend on the current working directory. 36918334SpeterRedirection of input or output is not supported; the subprograms must 37018334Speteraccept filenames saying what files to read and write. 37118334Speter 37218334SpeterIn addition, the specs can contain %-sequences to substitute variable text 37318334Speteror for conditional text. Here is a table of all defined %-sequences. 37418334SpeterNote that spaces are not generated automatically around the results of 37518334Speterexpanding these sequences; therefore, you can concatenate them together 37618334Speteror with constant text in a single argument. 37718334Speter 37818334Speter %% substitute one % into the program name or argument. 37918334Speter %i substitute the name of the input file being processed. 38018334Speter %b substitute the basename of the input file being processed. 38118334Speter This is the substring up to (and not including) the last period 38218334Speter and not including the directory. 38390277Sobrien %B same as %b, but include the file suffix (text after the last period). 38450599Sobrien %gSUFFIX 38550599Sobrien substitute a file name that has suffix SUFFIX and is chosen 38650599Sobrien once per compilation, and mark the argument a la %d. To reduce 38750599Sobrien exposure to denial-of-service attacks, the file name is now 38850599Sobrien chosen in a way that is hard to predict even when previously 38950599Sobrien chosen file names are known. For example, `%g.s ... %g.o ... %g.s' 39050599Sobrien might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'. SUFFIX matches 39190277Sobrien the regexp "[.A-Za-z]*%O"; "%O" is treated exactly as if it 39290277Sobrien had been pre-processed. Previously, %g was simply substituted 39390277Sobrien with a file name chosen once per compilation, without regard 39490277Sobrien to any appended suffix (which was therefore treated just like 39590277Sobrien ordinary text), making such attacks more likely to succeed. 396132733Skan %|SUFFIX 397132733Skan like %g, but if -pipe is in effect, expands simply to "-". 398132733Skan %mSUFFIX 399132733Skan like %g, but if -pipe is in effect, expands to nothing. (We have both 400132733Skan %| and %m to accommodate differences between system assemblers; see 401132733Skan the AS_NEEDS_DASH_FOR_PIPED_INPUT target macro.) 40250599Sobrien %uSUFFIX 40350599Sobrien like %g, but generates a new temporary file name even if %uSUFFIX 40450599Sobrien was already seen. 40550599Sobrien %USUFFIX 40650599Sobrien substitutes the last file name generated with %uSUFFIX, generating a 40750599Sobrien new one if there is no such last file name. In the absence of any 40850599Sobrien %uSUFFIX, this is just like %gSUFFIX, except they don't share 40950599Sobrien the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s' 41050599Sobrien would involve the generation of two distinct file names, one 41150599Sobrien for each `%g.s' and another for each `%U.s'. Previously, %U was 41250599Sobrien simply substituted with a file name chosen for the previous %u, 41350599Sobrien without regard to any appended suffix. 41490277Sobrien %jSUFFIX 41590277Sobrien substitutes the name of the HOST_BIT_BUCKET, if any, and if it is 41690277Sobrien writable, and if save-temps is off; otherwise, substitute the name 41790277Sobrien of a temporary file, just like %u. This temporary file is not 41890277Sobrien meant for communication between processes, but rather as a junk 41990277Sobrien disposal mechanism. 42090277Sobrien %.SUFFIX 42190277Sobrien substitutes .SUFFIX for the suffixes of a matched switch's args when 42290277Sobrien it is subsequently output with %*. SUFFIX is terminated by the next 42390277Sobrien space or %. 42418334Speter %d marks the argument containing or following the %d as a 42518334Speter temporary file name, so that that file will be deleted if CC exits 42618334Speter successfully. Unlike %g, this contributes no text to the argument. 42718334Speter %w marks the argument containing or following the %w as the 42818334Speter "output file" of this compilation. This puts the argument 42918334Speter into the sequence of arguments that %o will substitute later. 430132733Skan %V indicates that this compilation produces no "output file". 43118334Speter %W{...} 43218334Speter like %{...} but mark last argument supplied within 43318334Speter as a file to be deleted on failure. 43418334Speter %o substitutes the names of all the output files, with spaces 43518334Speter automatically placed around them. You should write spaces 43618334Speter around the %o as well or the results are undefined. 43718334Speter %o is for use in the specs for running the linker. 43818334Speter Input files whose names have no recognized suffix are not compiled 43918334Speter at all, but they are included among the output files, so they will 44018334Speter be linked. 44150599Sobrien %O substitutes the suffix for object files. Note that this is 44290277Sobrien handled specially when it immediately follows %g, %u, or %U 44390277Sobrien (with or without a suffix argument) because of the need for 44490277Sobrien those to form complete file names. The handling is such that 44590277Sobrien %O is treated exactly as if it had already been substituted, 44690277Sobrien except that %g, %u, and %U do not currently support additional 44790277Sobrien SUFFIX characters following %O as they would following, for 44890277Sobrien example, `.o'. 449132733Skan %I Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot 450132733Skan (made from TARGET_SYSTEM_ROOT), and -isystem (made from COMPILER_PATH 451132733Skan and -B options) as necessary. 45218334Speter %s current argument is the name of a library or startup file of some sort. 45318334Speter Search for that file in a standard list of directories 45418334Speter and substitute the full name found. 45518334Speter %eSTR Print STR as an error message. STR is terminated by a newline. 45618334Speter Use this when inconsistent options are detected. 457117413Skan %nSTR Print STR as a notice. STR is terminated by a newline. 45818334Speter %x{OPTION} Accumulate an option for %X. 45918334Speter %X Output the accumulated linker options specified by compilations. 46018334Speter %Y Output the accumulated assembler options specified by compilations. 46118334Speter %Z Output the accumulated preprocessor options specified by compilations. 46218334Speter %a process ASM_SPEC as a spec. 46318334Speter This allows config.h to specify part of the spec for running as. 46418334Speter %A process ASM_FINAL_SPEC as a spec. A capital A is actually 46518334Speter used here. This can be used to run a post-processor after the 46650599Sobrien assembler has done its job. 46718334Speter %D Dump out a -L option for each directory in startfile_prefixes. 46818334Speter If multilib_dir is set, extra entries are generated with it affixed. 46918334Speter %l process LINK_SPEC as a spec. 47018334Speter %L process LIB_SPEC as a spec. 47118334Speter %G process LIBGCC_SPEC as a spec. 47290277Sobrien %M output multilib_dir with directory separators replaced with "_"; 47390277Sobrien if multilib_dir is not set or is ".", output "". 47418334Speter %S process STARTFILE_SPEC as a spec. A capital S is actually used here. 47518334Speter %E process ENDFILE_SPEC as a spec. A capital E is actually used here. 47690277Sobrien %C process CPP_SPEC as a spec. 47718334Speter %1 process CC1_SPEC as a spec. 47818334Speter %2 process CC1PLUS_SPEC as a spec. 47918334Speter %* substitute the variable part of a matched option. (See below.) 48018334Speter Note that each comma in the substituted string is replaced by 48118334Speter a single space. 482132733Skan %<S remove all occurrences of -S from the command line. 483132733Skan Note - this command is position dependent. % commands in the 484132733Skan spec string before this one will see -S, % commands in the 485132733Skan spec string after this one will not. 486132733Skan %<S* remove all occurrences of all switches beginning with -S from the 487132733Skan command line. 488117413Skan %:function(args) 489117413Skan Call the named function FUNCTION, passing it ARGS. ARGS is 490117413Skan first processed as a nested spec string, then split into an 491117413Skan argument vector in the usual fashion. The function returns 492117413Skan a string which is processed as if it had appeared literally 493117413Skan as part of the current spec. 49418334Speter %{S} substitutes the -S switch, if that switch was given to CC. 49518334Speter If that switch was not specified, this substitutes nothing. 49618334Speter Here S is a metasyntactic variable. 49718334Speter %{S*} substitutes all the switches specified to CC whose names start 49890277Sobrien with -S. This is used for -o, -I, etc; switches that take 49918334Speter arguments. CC considers `-o foo' as being one switch whose 50018334Speter name starts with `o'. %{o*} would substitute this text, 50118334Speter including the space; thus, two arguments would be generated. 50290277Sobrien %{S*&T*} likewise, but preserve order of S and T options (the order 503132733Skan of S and T in the spec is not significant). Can be any number 504132733Skan of ampersand-separated variables; for each the wild card is 505132733Skan optional. Useful for CPP as %{D*&U*&A*}. 506132733Skan 507132733Skan %{S:X} substitutes X, if the -S switch was given to CC. 508132733Skan %{!S:X} substitutes X, if the -S switch was NOT given to CC. 509132733Skan %{S*:X} substitutes X if one or more switches whose names start 510132733Skan with -S was given to CC. Normally X is substituted only 511132733Skan once, no matter how many such switches appeared. However, 512132733Skan if %* appears somewhere in X, then X will be substituted 513132733Skan once for each matching switch, with the %* replaced by the 514132733Skan part of that switch that matched the '*'. 515132733Skan %{.S:X} substitutes X, if processing a file with suffix S. 516132733Skan %{!.S:X} substitutes X, if NOT processing a file with suffix S. 517132733Skan 518132733Skan %{S|T:X} substitutes X if either -S or -T was given to CC. This may be 519132733Skan combined with !, ., and * as above binding stronger than the OR. 520132733Skan If %* appears in X, all of the alternatives must be starred, and 521132733Skan only the first matching alternative is substituted. 522132733Skan %{S:X; if S was given to CC, substitutes X; 523132733Skan T:Y; else if T was given to CC, substitutes Y; 524132733Skan :D} else substitutes D. There can be as many clauses as you need. 525132733Skan This may be combined with ., !, |, and * as above. 526132733Skan 52718334Speter %(Spec) processes a specification defined in a specs file as *Spec: 52818334Speter %[Spec] as above, but put __ around -D arguments 52918334Speter 530132733SkanThe conditional text X in a %{S:X} or similar construct may contain 53118334Speterother nested % constructs or spaces, or even newlines. They are 532132733Skanprocessed as usual, as described above. Trailing white space in X is 533132733Skanignored. White space may also appear anywhere on the left side of the 534132733Skancolon in these constructs, except between . or * and the corresponding 535132733Skanword. 53618334Speter 53718334SpeterThe -O, -f, -m, and -W switches are handled specifically in these 53818334Speterconstructs. If another value of -O or the negated form of a -f, -m, or 53918334Speter-W switch is found later in the command line, the earlier switch 54018334Spetervalue is ignored, except with {S*} where S is just one letter; this 54118334Speterpasses all matching options. 54218334Speter 54350599SobrienThe character | at the beginning of the predicate text is used to indicate 54450599Sobrienthat a command should be piped to the following command, but only if -pipe 54550599Sobrienis specified. 54618334Speter 54718334SpeterNote that it is built into CC which switches take arguments and which 54818334Speterdo not. You might think it would be useful to generalize this to 54918334Speterallow each compiler's spec to say which switches take arguments. But 55018334Speterthis cannot be done in a consistent fashion. CC cannot even decide 55118334Speterwhich input files have been specified without knowing which switches 55218334Spetertake arguments, and it must know which input files to compile in order 55318334Speterto tell which compilers to run. 55418334Speter 55518334SpeterCC also knows implicitly that arguments starting in `-l' are to be 55618334Spetertreated as compiler output files, and passed to the linker in their 55718334Speterproper position among the other output files. */ 55818334Speter 55996285Sobrien/* Define the macros used for specs %a, %l, %L, %S, %C, %1. */ 56018334Speter 56118334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler 56218334Speter or extra switch-translations. */ 56318334Speter#ifndef ASM_SPEC 56418334Speter#define ASM_SPEC "" 56518334Speter#endif 56618334Speter 56718334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after 56818334Speter the assembler has run. */ 56918334Speter#ifndef ASM_FINAL_SPEC 57018334Speter#define ASM_FINAL_SPEC "" 57118334Speter#endif 57218334Speter 57318334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor 57418334Speter or extra switch-translations. */ 57518334Speter#ifndef CPP_SPEC 57618334Speter#define CPP_SPEC "" 57718334Speter#endif 57818334Speter 57918334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus 58018334Speter or extra switch-translations. */ 58118334Speter#ifndef CC1_SPEC 58218334Speter#define CC1_SPEC "" 58318334Speter#endif 58418334Speter 58518334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus 58618334Speter or extra switch-translations. */ 58718334Speter#ifndef CC1PLUS_SPEC 58818334Speter#define CC1PLUS_SPEC "" 58918334Speter#endif 59018334Speter 59118334Speter/* config.h can define LINK_SPEC to provide extra args to the linker 59218334Speter or extra switch-translations. */ 59318334Speter#ifndef LINK_SPEC 59418334Speter#define LINK_SPEC "" 59518334Speter#endif 59618334Speter 59718334Speter/* config.h can define LIB_SPEC to override the default libraries. */ 59818334Speter#ifndef LIB_SPEC 59918334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}" 60018334Speter#endif 60118334Speter 60218334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is 60318334Speter included. */ 60418334Speter#ifndef LIBGCC_SPEC 60518334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1) 60618334Speter/* Have gcc do the search for libgcc.a. */ 60750599Sobrien#define LIBGCC_SPEC "libgcc.a%s" 60818334Speter#else 60950599Sobrien#define LIBGCC_SPEC "-lgcc" 61018334Speter#endif 61118334Speter#endif 61218334Speter 61318334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files. */ 61418334Speter#ifndef STARTFILE_SPEC 61518334Speter#define STARTFILE_SPEC \ 61618334Speter "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}" 61718334Speter#endif 61818334Speter 61950599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options 62050599Sobrien require spaces between the option and the argument. */ 62118334Speter#ifndef SWITCHES_NEED_SPACES 62218334Speter#define SWITCHES_NEED_SPACES "" 62318334Speter#endif 62418334Speter 62518334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files. */ 62618334Speter#ifndef ENDFILE_SPEC 62718334Speter#define ENDFILE_SPEC "" 62818334Speter#endif 62918334Speter 63050599Sobrien#ifndef LINKER_NAME 63150599Sobrien#define LINKER_NAME "collect2" 63218334Speter#endif 63318334Speter 63490277Sobrien/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g' 63590277Sobrien to the assembler. */ 63690277Sobrien#ifndef ASM_DEBUG_SPEC 63790277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \ 63890277Sobrien && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) 63990277Sobrien# define ASM_DEBUG_SPEC \ 64090277Sobrien (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \ 64190277Sobrien ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" \ 64290277Sobrien : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}") 64390277Sobrien# else 64490277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) 64590277Sobrien# define ASM_DEBUG_SPEC "%{g*:--gstabs}" 64690277Sobrien# endif 64790277Sobrien# if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) 64890277Sobrien# define ASM_DEBUG_SPEC "%{g*:--gdwarf2}" 64990277Sobrien# endif 65090277Sobrien# endif 65190277Sobrien#endif 65290277Sobrien#ifndef ASM_DEBUG_SPEC 65390277Sobrien# define ASM_DEBUG_SPEC "" 65490277Sobrien#endif 65518334Speter 65690277Sobrien/* Here is the spec for running the linker, after compiling all files. */ 65790277Sobrien 65896285Sobrien/* This is overridable by the target in case they need to specify the 65996285Sobrien -lgcc and -lc order specially, yet not require them to override all 66096285Sobrien of LINK_COMMAND_SPEC. */ 66196285Sobrien#ifndef LINK_GCC_C_SEQUENCE_SPEC 66296285Sobrien#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G" 66396285Sobrien#endif 66496285Sobrien 665132733Skan#ifndef LINK_PIE_SPEC 666132733Skan#ifdef HAVE_LD_PIE 667132733Skan#define LINK_PIE_SPEC "%{pie:-pie} " 668132733Skan#else 669132733Skan#define LINK_PIE_SPEC "%{pie:} " 670132733Skan#endif 671132733Skan#endif 672132733Skan 67390277Sobrien/* -u* was put back because both BSD and SysV seem to support it. */ 67490277Sobrien/* %{static:} simply prevents an error message if the target machine 67590277Sobrien doesn't handle -static. */ 67690277Sobrien/* We want %{T*} after %{L*} and %D so that it can be used to specify linker 67790277Sobrien scripts which exist in user specified directories, or in standard 67890277Sobrien directories. */ 67990277Sobrien#ifndef LINK_COMMAND_SPEC 68090277Sobrien#define LINK_COMMAND_SPEC "\ 68190277Sobrien%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ 682132733Skan %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\ 683132733Skan %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ 684132733Skan %{static:} %{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate:-lgcov}\ 685132733Skan %{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\ 68690277Sobrien %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}" 68790277Sobrien#endif 68890277Sobrien 68990277Sobrien#ifndef LINK_LIBGCC_SPEC 69090277Sobrien# ifdef LINK_LIBGCC_SPECIAL 69190277Sobrien/* Don't generate -L options for startfile prefix list. */ 69290277Sobrien# define LINK_LIBGCC_SPEC "" 69390277Sobrien# else 69490277Sobrien/* Do generate them. */ 69590277Sobrien# define LINK_LIBGCC_SPEC "%D" 69690277Sobrien# endif 69790277Sobrien#endif 69890277Sobrien 699117413Skan#ifndef STARTFILE_PREFIX_SPEC 700117413Skan# define STARTFILE_PREFIX_SPEC "" 701117413Skan#endif 702117413Skan 703132733Skan#ifndef SYSROOT_SUFFIX_SPEC 704132733Skan# define SYSROOT_SUFFIX_SPEC "" 705132733Skan#endif 706132733Skan 707132733Skan#ifndef SYSROOT_HEADERS_SUFFIX_SPEC 708132733Skan# define SYSROOT_HEADERS_SUFFIX_SPEC "" 709132733Skan#endif 710132733Skan 711117413Skanstatic const char *asm_debug; 71290277Sobrienstatic const char *cpp_spec = CPP_SPEC; 71390277Sobrienstatic const char *cc1_spec = CC1_SPEC; 71490277Sobrienstatic const char *cc1plus_spec = CC1PLUS_SPEC; 71596285Sobrienstatic const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC; 71690277Sobrienstatic const char *asm_spec = ASM_SPEC; 71790277Sobrienstatic const char *asm_final_spec = ASM_FINAL_SPEC; 71890277Sobrienstatic const char *link_spec = LINK_SPEC; 71990277Sobrienstatic const char *lib_spec = LIB_SPEC; 72090277Sobrienstatic const char *libgcc_spec = LIBGCC_SPEC; 72190277Sobrienstatic const char *endfile_spec = ENDFILE_SPEC; 72290277Sobrienstatic const char *startfile_spec = STARTFILE_SPEC; 72390277Sobrienstatic const char *switches_need_spaces = SWITCHES_NEED_SPACES; 72490277Sobrienstatic const char *linker_name_spec = LINKER_NAME; 72590277Sobrienstatic const char *link_command_spec = LINK_COMMAND_SPEC; 72690277Sobrienstatic const char *link_libgcc_spec = LINK_LIBGCC_SPEC; 727117413Skanstatic const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC; 728132733Skanstatic const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC; 729132733Skanstatic const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC; 73090277Sobrien 73190277Sobrien/* Standard options to cpp, cc1, and as, to reduce duplication in specs. 73290277Sobrien There should be no need to override these in target dependent files, 73390277Sobrien but we need to copy them to the specs file so that newer versions 73490277Sobrien of the GCC driver can correctly drive older tool chains with the 73590277Sobrien appropriate -B options. */ 73690277Sobrien 737117413Skan/* When cpplib handles traditional preprocessing, get rid of this, and 738117413Skan call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so 739117413Skan that we default the front end language better. */ 74090277Sobrienstatic const char *trad_capable_cpp = 741117413Skan"cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}"; 74290277Sobrien 743107594Sobrien/* We don't wrap .d files in %W{} since a missing .d file, and 744107594Sobrien therefore no dependency entry, confuses make into thinking a .o 745107594Sobrien file that happens to exist is up-to-date. */ 74690277Sobrienstatic const char *cpp_unique_options = 747132733Skan"%{C|CC:%{!E:%eGCC does not support -C or -CC without -E}}\ 748117413Skan %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*} %{P} %I\ 749107594Sobrien %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\ 750107594Sobrien %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\ 751107594Sobrien %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\ 75296285Sobrien %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\ 753146908Skan %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\ 75496285Sobrien %{E|M|MM:%W{o*}}"; 75590277Sobrien 75690277Sobrien/* This contains cpp options which are common with cc1_options and are passed 757117413Skan only when preprocessing only to avoid duplication. We pass the cc1 spec 758117413Skan options to the preprocessor so that it the cc1 spec may manipulate 759117413Skan options used to set target flags. Those special target flags settings may 760117413Skan in turn cause preprocessor symbols to be defined specially. */ 76190277Sobrienstatic const char *cpp_options = 762146908Skan"%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\ 763146908Skan %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\ 764146908Skan %{undef}"; 76590277Sobrien 766117413Skan/* This contains cpp options which are not passed when the preprocessor 767117413Skan output will be used by another program. */ 768117413Skanstatic const char *cpp_debug_options = "%{d*}"; 769117413Skan 77090277Sobrien/* NB: This is shared amongst all front-ends. */ 77190277Sobrienstatic const char *cc1_options = 77290277Sobrien"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 77390277Sobrien %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\ 774132733Skan %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}}\ 775146908Skan %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\ 776117413Skan %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\ 77790277Sobrien %{Qn:-fno-ident} %{--help:--help}\ 77890277Sobrien %{--target-help:--target-help}\ 77990277Sobrien %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\ 78090277Sobrien %{fsyntax-only:-o %j} %{-param*}"; 78190277Sobrien 78290277Sobrienstatic const char *asm_options = 78390277Sobrien"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}"; 78490277Sobrien 78590277Sobrienstatic const char *invoke_as = 786132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT 787132733Skan"%{!S:-o %|.s |\n as %(asm_options) %|.s %A }"; 788132733Skan#else 789132733Skan"%{!S:-o %|.s |\n as %(asm_options) %m.s %A }"; 790132733Skan#endif 79190277Sobrien 79250599Sobrien/* Some compilers have limits on line lengths, and the multilib_select 79350599Sobrien and/or multilib_matches strings can be very long, so we build them at 79450599Sobrien run time. */ 79550599Sobrienstatic struct obstack multilib_obstack; 79690277Sobrienstatic const char *multilib_select; 79790277Sobrienstatic const char *multilib_matches; 79890277Sobrienstatic const char *multilib_defaults; 79990277Sobrienstatic const char *multilib_exclusions; 80050599Sobrien 80150599Sobrien/* Check whether a particular argument is a default argument. */ 80250599Sobrien 80350599Sobrien#ifndef MULTILIB_DEFAULTS 80450599Sobrien#define MULTILIB_DEFAULTS { "" } 80550599Sobrien#endif 80650599Sobrien 80790277Sobrienstatic const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS; 80850599Sobrien 809117413Skan#ifndef DRIVER_SELF_SPECS 810117413Skan#define DRIVER_SELF_SPECS "" 811117413Skan#endif 812117413Skan 813117413Skanstatic const char *const driver_self_specs[] = { DRIVER_SELF_SPECS }; 814117413Skan 815132733Skan#ifndef OPTION_DEFAULT_SPECS 816132733Skan#define OPTION_DEFAULT_SPECS { "", "" } 817132733Skan#endif 818132733Skan 819132733Skanstruct default_spec 820132733Skan{ 821132733Skan const char *name; 822132733Skan const char *spec; 823132733Skan}; 824132733Skan 825132733Skanstatic const struct default_spec 826132733Skan option_default_specs[] = { OPTION_DEFAULT_SPECS }; 827132733Skan 82890277Sobrienstruct user_specs 82990277Sobrien{ 83050599Sobrien struct user_specs *next; 83152520Sobrien const char *filename; 83250599Sobrien}; 83350599Sobrien 83450599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail; 83550599Sobrien 83650599Sobrien#ifndef SWITCH_TAKES_ARG 83750599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR) 83818334Speter#endif 83918334Speter 84018334Speter#ifndef WORD_SWITCH_TAKES_ARG 84118334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR) 84218334Speter#endif 84318334Speter 84490277Sobrien#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX 84550599Sobrien/* This defines which switches stop a full compilation. */ 84650599Sobrien#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \ 84750599Sobrien ((CHAR) == 'c' || (CHAR) == 'S') 84850599Sobrien 84950599Sobrien#ifndef SWITCH_CURTAILS_COMPILATION 85050599Sobrien#define SWITCH_CURTAILS_COMPILATION(CHAR) \ 85150599Sobrien DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) 85250599Sobrien#endif 85350599Sobrien#endif 85450599Sobrien 85518334Speter/* Record the mapping from file suffixes for compilation specs. */ 85618334Speter 85718334Speterstruct compiler 85818334Speter{ 85952520Sobrien const char *suffix; /* Use this compiler for input files 86018334Speter whose names end in this suffix. */ 86118334Speter 86290277Sobrien const char *spec; /* To use this compiler, run this spec. */ 86390277Sobrien 86490277Sobrien const char *cpp_spec; /* If non-NULL, substitute this spec 86590277Sobrien for `%C', rather than the usual 86690277Sobrien cpp_spec. */ 86718334Speter}; 86818334Speter 86918334Speter/* Pointer to a vector of `struct compiler' that gives the spec for 87018334Speter compiling a file, based on its suffix. 87118334Speter A file that does not end in any of these suffixes will be passed 87218334Speter unchanged to the loader and nothing else will be done to it. 87318334Speter 87418334Speter An entry containing two 0s is used to terminate the vector. 87518334Speter 87618334Speter If multiple entries match a file, the last matching one is used. */ 87718334Speter 87818334Speterstatic struct compiler *compilers; 87918334Speter 88018334Speter/* Number of entries in `compilers', not counting the null terminator. */ 88118334Speter 88218334Speterstatic int n_compilers; 88318334Speter 88418334Speter/* The default list of file name suffixes and their compilation specs. */ 88518334Speter 88690277Sobrienstatic const struct compiler default_compilers[] = 88718334Speter{ 88850599Sobrien /* Add lists of suffixes of known languages here. If those languages 88950599Sobrien were not present when we built the driver, we will hit these copies 89050599Sobrien and be given a more meaningful error than "file not used since 89150599Sobrien linking is not done". */ 89290277Sobrien {".m", "#Objective-C", 0}, {".mi", "#Objective-C", 0}, 89390277Sobrien {".cc", "#C++", 0}, {".cxx", "#C++", 0}, {".cpp", "#C++", 0}, 89490277Sobrien {".cp", "#C++", 0}, {".c++", "#C++", 0}, {".C", "#C++", 0}, 895132733Skan {".CPP", "#C++", 0}, {".ii", "#C++", 0}, 89690277Sobrien {".ads", "#Ada", 0}, {".adb", "#Ada", 0}, 89790277Sobrien {".f", "#Fortran", 0}, {".for", "#Fortran", 0}, {".fpp", "#Fortran", 0}, 89890277Sobrien {".F", "#Fortran", 0}, {".FOR", "#Fortran", 0}, {".FPP", "#Fortran", 0}, 89990277Sobrien {".r", "#Ratfor", 0}, 90090277Sobrien {".p", "#Pascal", 0}, {".pas", "#Pascal", 0}, 90190277Sobrien {".java", "#Java", 0}, {".class", "#Java", 0}, 90290277Sobrien {".zip", "#Java", 0}, {".jar", "#Java", 0}, 90350599Sobrien /* Next come the entries for C. */ 90490277Sobrien {".c", "@c", 0}, 90518334Speter {"@c", 90690277Sobrien /* cc1 has an integrated ISO C preprocessor. We should invoke the 907117413Skan external preprocessor if -save-temps is given. */ 908117413Skan "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\ 90990277Sobrien %{!E:%{!M:%{!MM:\ 910117413Skan %{traditional|ftraditional:\ 911117413Skan%eGNU C no longer supports -traditional without -E}\ 912117413Skan %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ 913132733Skan %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\ 914132733Skan cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \ 915132733Skan %(cc1_options)}\ 916117413Skan %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\ 917117413Skan cc1 %(cpp_unique_options) %(cc1_options)}}}\ 91890277Sobrien %{!fsyntax-only:%(invoke_as)}}}}", 0}, 91918334Speter {"-", 920146908Skan "%{!E:%e-E or -x required when input is from standard input}\ 921117413Skan %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0}, 92290277Sobrien {".h", "@c-header", 0}, 92318334Speter {"@c-header", 924132733Skan /* cc1 has an integrated ISO C preprocessor. We should invoke the 925132733Skan external preprocessor if -save-temps is given. */ 926132733Skan "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\ 927132733Skan %{!E:%{!M:%{!MM:\ 928132733Skan %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ 929132733Skan %(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\ 930132733Skan cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \ 931132733Skan %(cc1_options)\ 932132733Skan -o %g.s %{!o*:--output-pch=%i.gch}\ 933132733Skan %W{o*:--output-pch=%*}%V}\ 934132733Skan %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\ 935132733Skan cc1 %(cpp_unique_options) %(cc1_options)\ 936132733Skan -o %g.s %{!o*:--output-pch=%i.gch}\ 937132733Skan %W{o*:--output-pch=%*}%V}}}}}}", 0}, 93890277Sobrien {".i", "@cpp-output", 0}, 93918334Speter {"@cpp-output", 94090277Sobrien "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0}, 94190277Sobrien {".s", "@assembler", 0}, 94218334Speter {"@assembler", 94390277Sobrien "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0}, 94490277Sobrien {".S", "@assembler-with-cpp", 0}, 94518334Speter {"@assembler-with-cpp", 946132733Skan#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT 94790277Sobrien "%(trad_capable_cpp) -lang-asm %(cpp_options)\ 948117413Skan %{E|M|MM:%(cpp_debug_options)}\ 949132733Skan %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\ 950132733Skan as %(asm_debug) %(asm_options) %|.s %A }}}}" 951132733Skan#else 952132733Skan "%(trad_capable_cpp) -lang-asm %(cpp_options)\ 953132733Skan %{E|M|MM:%(cpp_debug_options)}\ 954132733Skan %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\ 955132733Skan as %(asm_debug) %(asm_options) %m.s %A }}}}" 956132733Skan#endif 957132733Skan , 0}, 958132733Skan 95918334Speter#include "specs.h" 960132733Skan /* Mark end of table. */ 96190277Sobrien {0, 0, 0} 96218334Speter}; 96318334Speter 96418334Speter/* Number of elements in default_compilers, not counting the terminator. */ 96518334Speter 966117413Skanstatic const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1; 96718334Speter 96818334Speter/* A vector of options to give to the linker. 96918334Speter These options are accumulated by %x, 97018334Speter and substituted into the linker command with %X. */ 97118334Speterstatic int n_linker_options; 97218334Speterstatic char **linker_options; 97318334Speter 97418334Speter/* A vector of options to give to the assembler. 97518334Speter These options are accumulated by -Wa, 97618334Speter and substituted into the assembler command with %Y. */ 97718334Speterstatic int n_assembler_options; 97818334Speterstatic char **assembler_options; 97918334Speter 98018334Speter/* A vector of options to give to the preprocessor. 98118334Speter These options are accumulated by -Wp, 98218334Speter and substituted into the preprocessor command with %Z. */ 98318334Speterstatic int n_preprocessor_options; 98418334Speterstatic char **preprocessor_options; 98518334Speter 98618334Speter/* Define how to map long options into short ones. */ 98718334Speter 98818334Speter/* This structure describes one mapping. */ 98918334Speterstruct option_map 99018334Speter{ 99118334Speter /* The long option's name. */ 99290277Sobrien const char *const name; 99318334Speter /* The equivalent short option. */ 99490277Sobrien const char *const equivalent; 99518334Speter /* Argument info. A string of flag chars; NULL equals no options. 99618334Speter a => argument required. 99718334Speter o => argument optional. 99818334Speter j => join argument to equivalent, making one word. 99918334Speter * => require other text after NAME as an argument. */ 100090277Sobrien const char *const arg_info; 100118334Speter}; 100218334Speter 100318334Speter/* This is the table of mappings. Mappings are tried sequentially 100418334Speter for each option encountered; the first one that matches, wins. */ 100518334Speter 100690277Sobrienstatic const struct option_map option_map[] = 100718334Speter { 100818334Speter {"--all-warnings", "-Wall", 0}, 100918334Speter {"--ansi", "-ansi", 0}, 101018334Speter {"--assemble", "-S", 0}, 101118334Speter {"--assert", "-A", "a"}, 101252520Sobrien {"--classpath", "-fclasspath=", "aj"}, 101396285Sobrien {"--bootclasspath", "-fbootclasspath=", "aj"}, 101496285Sobrien {"--CLASSPATH", "-fclasspath=", "aj"}, 101518334Speter {"--comments", "-C", 0}, 1016117413Skan {"--comments-in-macros", "-CC", 0}, 101718334Speter {"--compile", "-c", 0}, 101818334Speter {"--debug", "-g", "oj"}, 101950599Sobrien {"--define-macro", "-D", "aj"}, 102018334Speter {"--dependencies", "-M", 0}, 102118334Speter {"--dump", "-d", "a"}, 102218334Speter {"--dumpbase", "-dumpbase", "a"}, 102318334Speter {"--entry", "-e", 0}, 102418334Speter {"--extra-warnings", "-W", 0}, 102518334Speter {"--for-assembler", "-Wa", "a"}, 102618334Speter {"--for-linker", "-Xlinker", "a"}, 102718334Speter {"--force-link", "-u", "a"}, 102818334Speter {"--imacros", "-imacros", "a"}, 102918334Speter {"--include", "-include", "a"}, 103018334Speter {"--include-barrier", "-I-", 0}, 103150599Sobrien {"--include-directory", "-I", "aj"}, 103218334Speter {"--include-directory-after", "-idirafter", "a"}, 103318334Speter {"--include-prefix", "-iprefix", "a"}, 103418334Speter {"--include-with-prefix", "-iwithprefix", "a"}, 103518334Speter {"--include-with-prefix-before", "-iwithprefixbefore", "a"}, 103618334Speter {"--include-with-prefix-after", "-iwithprefix", "a"}, 103718334Speter {"--language", "-x", "a"}, 103818334Speter {"--library-directory", "-L", "a"}, 103918334Speter {"--machine", "-m", "aj"}, 104018334Speter {"--machine-", "-m", "*j"}, 104196285Sobrien {"--no-integrated-cpp", "-no-integrated-cpp", 0}, 104218334Speter {"--no-line-commands", "-P", 0}, 104318334Speter {"--no-precompiled-includes", "-noprecomp", 0}, 104418334Speter {"--no-standard-includes", "-nostdinc", 0}, 104518334Speter {"--no-standard-libraries", "-nostdlib", 0}, 104618334Speter {"--no-warnings", "-w", 0}, 104718334Speter {"--optimize", "-O", "oj"}, 104818334Speter {"--output", "-o", "a"}, 104952520Sobrien {"--output-class-directory", "-foutput-class-dir=", "ja"}, 105090277Sobrien {"--param", "--param", "a"}, 105118334Speter {"--pedantic", "-pedantic", 0}, 105218334Speter {"--pedantic-errors", "-pedantic-errors", 0}, 1053132733Skan {"--pie", "-pie", 0}, 105418334Speter {"--pipe", "-pipe", 0}, 105518334Speter {"--prefix", "-B", "a"}, 105618334Speter {"--preprocess", "-E", 0}, 105718334Speter {"--print-search-dirs", "-print-search-dirs", 0}, 105818334Speter {"--print-file-name", "-print-file-name=", "aj"}, 105918334Speter {"--print-libgcc-file-name", "-print-libgcc-file-name", 0}, 106018334Speter {"--print-missing-file-dependencies", "-MG", 0}, 106118334Speter {"--print-multi-lib", "-print-multi-lib", 0}, 106218334Speter {"--print-multi-directory", "-print-multi-directory", 0}, 1063104763Skan {"--print-multi-os-directory", "-print-multi-os-directory", 0}, 106418334Speter {"--print-prog-name", "-print-prog-name=", "aj"}, 106518334Speter {"--profile", "-p", 0}, 106618334Speter {"--profile-blocks", "-a", 0}, 106718334Speter {"--quiet", "-q", 0}, 106896285Sobrien {"--resource", "-fcompile-resource=", "aj"}, 106918334Speter {"--save-temps", "-save-temps", 0}, 107018334Speter {"--shared", "-shared", 0}, 107118334Speter {"--silent", "-q", 0}, 107250599Sobrien {"--specs", "-specs=", "aj"}, 107318334Speter {"--static", "-static", 0}, 107452520Sobrien {"--std", "-std=", "aj"}, 107518334Speter {"--symbolic", "-symbolic", 0}, 107690277Sobrien {"--time", "-time", 0}, 107718334Speter {"--trace-includes", "-H", 0}, 107818334Speter {"--traditional", "-traditional", 0}, 107918334Speter {"--traditional-cpp", "-traditional-cpp", 0}, 108018334Speter {"--trigraphs", "-trigraphs", 0}, 108150599Sobrien {"--undefine-macro", "-U", "aj"}, 108218334Speter {"--user-dependencies", "-MM", 0}, 108318334Speter {"--verbose", "-v", 0}, 108418334Speter {"--warn-", "-W", "*j"}, 108518334Speter {"--write-dependencies", "-MD", 0}, 108618334Speter {"--write-user-dependencies", "-MMD", 0}, 108718334Speter {"--", "-f", "*j"} 108818334Speter }; 108918334Speter 109090277Sobrien 109190277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE 109290277Sobrienstatic const struct { 109390277Sobrien const char *const option_found; 109490277Sobrien const char *const replacements; 109590277Sobrien} target_option_translations[] = 109690277Sobrien{ 109790277Sobrien TARGET_OPTION_TRANSLATE_TABLE, 109890277Sobrien { 0, 0 } 109990277Sobrien}; 110090277Sobrien#endif 110190277Sobrien 110218334Speter/* Translate the options described by *ARGCP and *ARGVP. 110318334Speter Make a new vector and store it back in *ARGVP, 110418334Speter and store its length in *ARGVC. */ 110518334Speter 110618334Speterstatic void 1107132733Skantranslate_options (int *argcp, const char *const **argvp) 110818334Speter{ 110952520Sobrien int i; 111018334Speter int argc = *argcp; 111190277Sobrien const char *const *argv = *argvp; 111290277Sobrien int newvsize = (argc + 2) * 2 * sizeof (const char *); 1113132733Skan const char **newv = xmalloc (newvsize); 111418334Speter int newindex = 0; 111518334Speter 111618334Speter i = 0; 111718334Speter newv[newindex++] = argv[i++]; 111818334Speter 111918334Speter while (i < argc) 112018334Speter { 112190277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE 112290277Sobrien int tott_idx; 112390277Sobrien 112490277Sobrien for (tott_idx = 0; 112590277Sobrien target_option_translations[tott_idx].option_found; 112690277Sobrien tott_idx++) 112790277Sobrien { 112890277Sobrien if (strcmp (target_option_translations[tott_idx].option_found, 112990277Sobrien argv[i]) == 0) 113090277Sobrien { 113190277Sobrien int spaces = 1; 113290277Sobrien const char *sp; 113390277Sobrien char *np; 113490277Sobrien 113590277Sobrien for (sp = target_option_translations[tott_idx].replacements; 113690277Sobrien *sp; sp++) 113790277Sobrien { 113890277Sobrien if (*sp == ' ') 113990277Sobrien spaces ++; 114090277Sobrien } 114190277Sobrien 114290277Sobrien newvsize += spaces * sizeof (const char *); 1143132733Skan newv = xrealloc (newv, newvsize); 114490277Sobrien 114590277Sobrien sp = target_option_translations[tott_idx].replacements; 114690277Sobrien np = xstrdup (sp); 114790277Sobrien 114890277Sobrien while (1) 114990277Sobrien { 115090277Sobrien while (*np == ' ') 115190277Sobrien np++; 115290277Sobrien if (*np == 0) 115390277Sobrien break; 115490277Sobrien newv[newindex++] = np; 115590277Sobrien while (*np != ' ' && *np) 115690277Sobrien np++; 115790277Sobrien if (*np == 0) 115890277Sobrien break; 115990277Sobrien *np++ = 0; 116090277Sobrien } 116190277Sobrien 116290277Sobrien i ++; 116390277Sobrien break; 116490277Sobrien } 116590277Sobrien } 116690277Sobrien if (target_option_translations[tott_idx].option_found) 116790277Sobrien continue; 116890277Sobrien#endif 116990277Sobrien 117018334Speter /* Translate -- options. */ 117118334Speter if (argv[i][0] == '-' && argv[i][1] == '-') 117218334Speter { 117352520Sobrien size_t j; 117418334Speter /* Find a mapping that applies to this option. */ 117590277Sobrien for (j = 0; j < ARRAY_SIZE (option_map); j++) 117618334Speter { 117750599Sobrien size_t optlen = strlen (option_map[j].name); 117850599Sobrien size_t arglen = strlen (argv[i]); 117950599Sobrien size_t complen = arglen > optlen ? optlen : arglen; 118052520Sobrien const char *arginfo = option_map[j].arg_info; 118118334Speter 118218334Speter if (arginfo == 0) 118318334Speter arginfo = ""; 118418334Speter 118518334Speter if (!strncmp (argv[i], option_map[j].name, complen)) 118618334Speter { 118752520Sobrien const char *arg = 0; 118818334Speter 118918334Speter if (arglen < optlen) 119018334Speter { 119152520Sobrien size_t k; 119290277Sobrien for (k = j + 1; k < ARRAY_SIZE (option_map); k++) 119318334Speter if (strlen (option_map[k].name) >= arglen 119418334Speter && !strncmp (argv[i], option_map[k].name, arglen)) 119518334Speter { 119690277Sobrien error ("ambiguous abbreviation %s", argv[i]); 119718334Speter break; 119818334Speter } 119918334Speter 120090277Sobrien if (k != ARRAY_SIZE (option_map)) 120118334Speter break; 120218334Speter } 120318334Speter 120418334Speter if (arglen > optlen) 120518334Speter { 120618334Speter /* If the option has an argument, accept that. */ 120718334Speter if (argv[i][optlen] == '=') 120818334Speter arg = argv[i] + optlen + 1; 120918334Speter 121018334Speter /* If this mapping requires extra text at end of name, 121118334Speter accept that as "argument". */ 121290277Sobrien else if (strchr (arginfo, '*') != 0) 121318334Speter arg = argv[i] + optlen; 121418334Speter 121518334Speter /* Otherwise, extra text at end means mismatch. 121618334Speter Try other mappings. */ 121718334Speter else 121818334Speter continue; 121918334Speter } 122018334Speter 122190277Sobrien else if (strchr (arginfo, '*') != 0) 122218334Speter { 122390277Sobrien error ("incomplete `%s' option", option_map[j].name); 122418334Speter break; 122518334Speter } 122618334Speter 122718334Speter /* Handle arguments. */ 122890277Sobrien if (strchr (arginfo, 'a') != 0) 122918334Speter { 123018334Speter if (arg == 0) 123118334Speter { 123218334Speter if (i + 1 == argc) 123318334Speter { 123490277Sobrien error ("missing argument to `%s' option", 123518334Speter option_map[j].name); 123618334Speter break; 123718334Speter } 123818334Speter 123918334Speter arg = argv[++i]; 124018334Speter } 124118334Speter } 124290277Sobrien else if (strchr (arginfo, '*') != 0) 124318334Speter ; 124490277Sobrien else if (strchr (arginfo, 'o') == 0) 124518334Speter { 124618334Speter if (arg != 0) 124790277Sobrien error ("extraneous argument to `%s' option", 124818334Speter option_map[j].name); 124918334Speter arg = 0; 125018334Speter } 125118334Speter 125218334Speter /* Store the translation as one argv elt or as two. */ 125390277Sobrien if (arg != 0 && strchr (arginfo, 'j') != 0) 125450599Sobrien newv[newindex++] = concat (option_map[j].equivalent, arg, 125590277Sobrien NULL); 125618334Speter else if (arg != 0) 125718334Speter { 125818334Speter newv[newindex++] = option_map[j].equivalent; 125918334Speter newv[newindex++] = arg; 126018334Speter } 126118334Speter else 126218334Speter newv[newindex++] = option_map[j].equivalent; 126318334Speter 126418334Speter break; 126518334Speter } 126618334Speter } 126718334Speter i++; 126818334Speter } 126918334Speter 127018334Speter /* Handle old-fashioned options--just copy them through, 127118334Speter with their arguments. */ 127218334Speter else if (argv[i][0] == '-') 127318334Speter { 127452520Sobrien const char *p = argv[i] + 1; 127518334Speter int c = *p; 127618334Speter int nskip = 1; 127718334Speter 127818334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 127918334Speter nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0); 128018334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 128118334Speter nskip += WORD_SWITCH_TAKES_ARG (p); 1282117413Skan else if ((c == 'B' || c == 'b' || c == 'x') 128318334Speter && p[1] == 0) 128418334Speter nskip += 1; 128518334Speter else if (! strcmp (p, "Xlinker")) 128618334Speter nskip += 1; 1287132733Skan else if (! strcmp (p, "Xpreprocessor")) 1288132733Skan nskip += 1; 1289132733Skan else if (! strcmp (p, "Xassembler")) 1290132733Skan nskip += 1; 129118334Speter 129218334Speter /* Watch out for an option at the end of the command line that 129318334Speter is missing arguments, and avoid skipping past the end of the 129418334Speter command line. */ 129518334Speter if (nskip + i > argc) 129618334Speter nskip = argc - i; 129718334Speter 129818334Speter while (nskip > 0) 129918334Speter { 130018334Speter newv[newindex++] = argv[i++]; 130118334Speter nskip--; 130218334Speter } 130318334Speter } 130418334Speter else 130518334Speter /* Ordinary operands, or +e options. */ 130618334Speter newv[newindex++] = argv[i++]; 130718334Speter } 130818334Speter 130918334Speter newv[newindex] = 0; 131018334Speter 131118334Speter *argvp = newv; 131218334Speter *argcp = newindex; 131318334Speter} 131418334Speter 131518334Speterstatic char * 1316132733Skanskip_whitespace (char *p) 131718334Speter{ 131818334Speter while (1) 131918334Speter { 132018334Speter /* A fully-blank line is a delimiter in the SPEC file and shouldn't 132118334Speter be considered whitespace. */ 132218334Speter if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n') 132318334Speter return p + 1; 132418334Speter else if (*p == '\n' || *p == ' ' || *p == '\t') 132518334Speter p++; 132618334Speter else if (*p == '#') 132718334Speter { 132890277Sobrien while (*p != '\n') 132990277Sobrien p++; 133018334Speter p++; 133118334Speter } 133218334Speter else 133318334Speter break; 133418334Speter } 133518334Speter 133618334Speter return p; 133718334Speter} 133890277Sobrien/* Structures to keep track of prefixes to try when looking for files. */ 133990277Sobrien 134090277Sobrienstruct prefix_list 134190277Sobrien{ 134290277Sobrien const char *prefix; /* String to prepend to the path. */ 134390277Sobrien struct prefix_list *next; /* Next in linked list. */ 134490277Sobrien int require_machine_suffix; /* Don't use without machine_suffix. */ 134590277Sobrien /* 2 means try both machine_suffix and just_machine_suffix. */ 134690277Sobrien int *used_flag_ptr; /* 1 if a file was found with this prefix. */ 1347104763Skan int priority; /* Sort key - priority within list. */ 1348104763Skan int os_multilib; /* 1 if OS multilib scheme should be used, 1349104763Skan 0 for GCC multilib scheme. */ 135090277Sobrien}; 135190277Sobrien 135290277Sobrienstruct path_prefix 135390277Sobrien{ 135490277Sobrien struct prefix_list *plist; /* List of prefixes to try */ 135590277Sobrien int max_len; /* Max length of a prefix in PLIST */ 135690277Sobrien const char *name; /* Name of this list (used in config stuff) */ 135790277Sobrien}; 135890277Sobrien 135990277Sobrien/* List of prefixes to try when looking for executables. */ 136090277Sobrien 136190277Sobrienstatic struct path_prefix exec_prefixes = { 0, 0, "exec" }; 136290277Sobrien 136390277Sobrien/* List of prefixes to try when looking for startup (crt0) files. */ 136490277Sobrien 136590277Sobrienstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" }; 136690277Sobrien 136790277Sobrien/* List of prefixes to try when looking for include files. */ 136890277Sobrien 136990277Sobrienstatic struct path_prefix include_prefixes = { 0, 0, "include" }; 137090277Sobrien 137190277Sobrien/* Suffix to attach to directories searched for commands. 137290277Sobrien This looks like `MACHINE/VERSION/'. */ 137390277Sobrien 137490277Sobrienstatic const char *machine_suffix = 0; 137590277Sobrien 137690277Sobrien/* Suffix to attach to directories searched for commands. 137790277Sobrien This is just `MACHINE/'. */ 137890277Sobrien 137990277Sobrienstatic const char *just_machine_suffix = 0; 138090277Sobrien 138190277Sobrien/* Adjusted value of GCC_EXEC_PREFIX envvar. */ 138290277Sobrien 138390277Sobrienstatic const char *gcc_exec_prefix; 138490277Sobrien 1385132733Skan/* Adjusted value of standard_libexec_prefix. */ 1386132733Skan 1387132733Skanstatic const char *gcc_libexec_prefix; 1388132733Skan 138990277Sobrien/* Default prefixes to attach to command names. */ 139090277Sobrien 139190277Sobrien#ifdef CROSS_COMPILE /* Don't use these prefixes for a cross compiler. */ 139290277Sobrien#undef MD_EXEC_PREFIX 139390277Sobrien#undef MD_STARTFILE_PREFIX 139490277Sobrien#undef MD_STARTFILE_PREFIX_1 139590277Sobrien#endif 139690277Sobrien 139790277Sobrien/* If no prefixes defined, use the null string, which will disable them. */ 139890277Sobrien#ifndef MD_EXEC_PREFIX 139990277Sobrien#define MD_EXEC_PREFIX "" 140090277Sobrien#endif 140190277Sobrien#ifndef MD_STARTFILE_PREFIX 140290277Sobrien#define MD_STARTFILE_PREFIX "" 140390277Sobrien#endif 140490277Sobrien#ifndef MD_STARTFILE_PREFIX_1 140590277Sobrien#define MD_STARTFILE_PREFIX_1 "" 140690277Sobrien#endif 140790277Sobrien 140890277Sobrienstatic const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX; 1409132733Skanstatic const char *const standard_exec_prefix_1 = "/usr/libexec/gcc/"; 1410132733Skanstatic const char *const standard_exec_prefix_2 = "/usr/lib/gcc/"; 141190277Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX; 141290277Sobrien 141390277Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX; 141490277Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1; 141590277Sobrienstatic const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; 141690277Sobrienstatic const char *const standard_startfile_prefix_1 = "/lib/"; 141790277Sobrienstatic const char *const standard_startfile_prefix_2 = "/usr/lib/"; 141890277Sobrien 141990277Sobrienstatic const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX; 142090277Sobrienstatic const char *tooldir_prefix; 142190277Sobrien 142296736Sru#ifndef FREEBSD_NATIVE 142390277Sobrienstatic const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX; 142496736Sru#endif /* not FREEBSD_NATIVE */ 142590277Sobrien 1426132733Skanstatic const char *standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX; 1427132733Skan 142890277Sobrien/* Subdirectory to use for locating libraries. Set by 142990277Sobrien set_multilib_dir based on the compilation options. */ 143090277Sobrien 143190277Sobrienstatic const char *multilib_dir; 1432104763Skan 1433104763Skan/* Subdirectory to use for locating libraries in OS conventions. Set by 1434104763Skan set_multilib_dir based on the compilation options. */ 1435104763Skan 1436104763Skanstatic const char *multilib_os_dir; 143718334Speter 143850599Sobrien/* Structure to keep track of the specs that have been defined so far. 143950599Sobrien These are accessed using %(specname) or %[specname] in a compiler 144050599Sobrien or link spec. */ 144118334Speter 144218334Speterstruct spec_list 144318334Speter{ 144450599Sobrien /* The following 2 fields must be first */ 144550599Sobrien /* to allow EXTRA_SPECS to be initialized */ 144690277Sobrien const char *name; /* name of the spec. */ 144790277Sobrien const char *ptr; /* available ptr if no static pointer */ 144850599Sobrien 144950599Sobrien /* The following fields are not initialized */ 145050599Sobrien /* by EXTRA_SPECS */ 145190277Sobrien const char **ptr_spec; /* pointer to the spec itself. */ 145250599Sobrien struct spec_list *next; /* Next spec in linked list. */ 145350599Sobrien int name_len; /* length of the name */ 145450599Sobrien int alloc_p; /* whether string was allocated */ 145518334Speter}; 145618334Speter 145750599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \ 145890277Sobrien{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 } 145918334Speter 146090277Sobrien/* List of statically defined specs. */ 146190277Sobrienstatic struct spec_list static_specs[] = 146290277Sobrien{ 146350599Sobrien INIT_STATIC_SPEC ("asm", &asm_spec), 146490277Sobrien INIT_STATIC_SPEC ("asm_debug", &asm_debug), 146550599Sobrien INIT_STATIC_SPEC ("asm_final", &asm_final_spec), 146690277Sobrien INIT_STATIC_SPEC ("asm_options", &asm_options), 146790277Sobrien INIT_STATIC_SPEC ("invoke_as", &invoke_as), 146850599Sobrien INIT_STATIC_SPEC ("cpp", &cpp_spec), 146990277Sobrien INIT_STATIC_SPEC ("cpp_options", &cpp_options), 1470117413Skan INIT_STATIC_SPEC ("cpp_debug_options", &cpp_debug_options), 147190277Sobrien INIT_STATIC_SPEC ("cpp_unique_options", &cpp_unique_options), 147290277Sobrien INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp), 147350599Sobrien INIT_STATIC_SPEC ("cc1", &cc1_spec), 147490277Sobrien INIT_STATIC_SPEC ("cc1_options", &cc1_options), 147550599Sobrien INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec), 147696285Sobrien INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec), 147750599Sobrien INIT_STATIC_SPEC ("endfile", &endfile_spec), 147850599Sobrien INIT_STATIC_SPEC ("link", &link_spec), 147950599Sobrien INIT_STATIC_SPEC ("lib", &lib_spec), 148050599Sobrien INIT_STATIC_SPEC ("libgcc", &libgcc_spec), 148150599Sobrien INIT_STATIC_SPEC ("startfile", &startfile_spec), 148250599Sobrien INIT_STATIC_SPEC ("switches_need_spaces", &switches_need_spaces), 148350599Sobrien INIT_STATIC_SPEC ("cross_compile", &cross_compile), 148450599Sobrien INIT_STATIC_SPEC ("version", &compiler_version), 148550599Sobrien INIT_STATIC_SPEC ("multilib", &multilib_select), 148650599Sobrien INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults), 148750599Sobrien INIT_STATIC_SPEC ("multilib_extra", &multilib_extra), 148850599Sobrien INIT_STATIC_SPEC ("multilib_matches", &multilib_matches), 148990277Sobrien INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions), 1490104763Skan INIT_STATIC_SPEC ("multilib_options", &multilib_options), 149150599Sobrien INIT_STATIC_SPEC ("linker", &linker_name_spec), 149290277Sobrien INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec), 149390277Sobrien INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix), 149490277Sobrien INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix), 149590277Sobrien INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1), 1496117413Skan INIT_STATIC_SPEC ("startfile_prefix_spec", &startfile_prefix_spec), 1497132733Skan INIT_STATIC_SPEC ("sysroot_suffix_spec", &sysroot_suffix_spec), 1498132733Skan INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec", &sysroot_hdrs_suffix_spec), 149950599Sobrien}; 150050599Sobrien 150150599Sobrien#ifdef EXTRA_SPECS /* additional specs needed */ 150252520Sobrien/* Structure to keep track of just the first two args of a spec_list. 150390277Sobrien That is all that the EXTRA_SPECS macro gives us. */ 150452520Sobrienstruct spec_list_1 150552520Sobrien{ 150690277Sobrien const char *const name; 150790277Sobrien const char *const ptr; 150852520Sobrien}; 150952520Sobrien 151090277Sobrienstatic const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS }; 151190277Sobrienstatic struct spec_list *extra_specs = (struct spec_list *) 0; 151250599Sobrien#endif 151350599Sobrien 151450599Sobrien/* List of dynamically allocates specs that have been defined so far. */ 151550599Sobrien 151690277Sobrienstatic struct spec_list *specs = (struct spec_list *) 0; 151790277Sobrien 1518117413Skan/* List of static spec functions. */ 1519117413Skan 1520117413Skanstatic const struct spec_function static_spec_functions[] = 1521117413Skan{ 1522117413Skan { "if-exists", if_exists_spec_function }, 1523117413Skan { "if-exists-else", if_exists_else_spec_function }, 1524117413Skan { 0, 0 } 1525117413Skan}; 1526117413Skan 1527117413Skanstatic int processing_spec_function; 1528117413Skan 152990277Sobrien/* Add appropriate libgcc specs to OBSTACK, taking into account 153090277Sobrien various permutations of -shared-libgcc, -shared, and such. */ 153150599Sobrien 153290277Sobrien#ifdef ENABLE_SHARED_LIBGCC 153390277Sobrienstatic void 1534132733Skaninit_gcc_specs (struct obstack *obstack, const char *shared_name, 1535132733Skan const char *static_name, const char *eh_name) 153690277Sobrien{ 153796285Sobrien char *buf; 153890277Sobrien 153996285Sobrien buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name, 154096285Sobrien "}%{!static:%{!static-libgcc:", 1541132733Skan#ifdef HAVE_LD_AS_NEEDED 1542132733Skan "%{!shared-libgcc:", static_name, 1543132733Skan " --as-needed ", shared_name, " --no-as-needed}" 1544132733Skan "%{shared-libgcc:", shared_name, "%{!shared: ", static_name, 1545132733Skan "}", 1546132733Skan#else 154796285Sobrien "%{!shared:%{!shared-libgcc:", static_name, " ", 154896285Sobrien eh_name, "}%{shared-libgcc:", shared_name, " ", 154996285Sobrien static_name, "}}%{shared:", 155090277Sobrien#ifdef LINK_EH_SPEC 155196285Sobrien "%{shared-libgcc:", shared_name, 155296285Sobrien "}%{!shared-libgcc:", static_name, "}", 155390277Sobrien#else 155496285Sobrien shared_name, 155590277Sobrien#endif 1556132733Skan#endif 155796285Sobrien "}}}", NULL); 155896285Sobrien 155996285Sobrien obstack_grow (obstack, buf, strlen (buf)); 156096285Sobrien free (buf); 156190277Sobrien} 156290277Sobrien#endif /* ENABLE_SHARED_LIBGCC */ 156390277Sobrien 156450599Sobrien/* Initialize the specs lookup routines. */ 156550599Sobrien 156650599Sobrienstatic void 1567132733Skaninit_spec (void) 156850599Sobrien{ 156990277Sobrien struct spec_list *next = (struct spec_list *) 0; 157090277Sobrien struct spec_list *sl = (struct spec_list *) 0; 157150599Sobrien int i; 157250599Sobrien 157350599Sobrien if (specs) 157490277Sobrien return; /* Already initialized. */ 157550599Sobrien 157650599Sobrien if (verbose_flag) 157790277Sobrien notice ("Using built-in specs.\n"); 157850599Sobrien 157950599Sobrien#ifdef EXTRA_SPECS 1580132733Skan extra_specs = xcalloc (sizeof (struct spec_list), 1581132733Skan ARRAY_SIZE (extra_specs_1)); 158290277Sobrien 158390277Sobrien for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--) 158450599Sobrien { 158550599Sobrien sl = &extra_specs[i]; 158652520Sobrien sl->name = extra_specs_1[i].name; 158752520Sobrien sl->ptr = extra_specs_1[i].ptr; 158850599Sobrien sl->next = next; 158950599Sobrien sl->name_len = strlen (sl->name); 159050599Sobrien sl->ptr_spec = &sl->ptr; 159150599Sobrien next = sl; 159250599Sobrien } 159350599Sobrien#endif 159450599Sobrien 1595117413Skan /* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes 1596117413Skan on ?: in file-scope variable initializations. */ 1597117413Skan asm_debug = ASM_DEBUG_SPEC; 1598117413Skan 159990277Sobrien for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) 160050599Sobrien { 160150599Sobrien sl = &static_specs[i]; 160250599Sobrien sl->next = next; 160350599Sobrien next = sl; 160450599Sobrien } 160550599Sobrien 160690277Sobrien#ifdef ENABLE_SHARED_LIBGCC 160790277Sobrien /* ??? If neither -shared-libgcc nor --static-libgcc was 160890277Sobrien seen, then we should be making an educated guess. Some proposed 160990277Sobrien heuristics for ELF include: 161090277Sobrien 161190277Sobrien (1) If "-Wl,--export-dynamic", then it's a fair bet that the 161290277Sobrien program will be doing dynamic loading, which will likely 161390277Sobrien need the shared libgcc. 161490277Sobrien 161590277Sobrien (2) If "-ldl", then it's also a fair bet that we're doing 161690277Sobrien dynamic loading. 161790277Sobrien 161890277Sobrien (3) For each ET_DYN we're linking against (either through -lfoo 161990277Sobrien or /some/path/foo.so), check to see whether it or one of 162090277Sobrien its dependencies depends on a shared libgcc. 162190277Sobrien 162290277Sobrien (4) If "-shared" 162390277Sobrien 162490277Sobrien If the runtime is fixed to look for program headers instead 162590277Sobrien of calling __register_frame_info at all, for each object, 162690277Sobrien use the shared libgcc if any EH symbol referenced. 162790277Sobrien 162890277Sobrien If crtstuff is fixed to not invoke __register_frame_info 162990277Sobrien automatically, for each object, use the shared libgcc if 163090277Sobrien any non-empty unwind section found. 163190277Sobrien 163290277Sobrien Doing any of this probably requires invoking an external program to 163390277Sobrien do the actual object file scanning. */ 163490277Sobrien { 163590277Sobrien const char *p = libgcc_spec; 163690277Sobrien int in_sep = 1; 1637117413Skan 163890277Sobrien /* Transform the extant libgcc_spec into one that uses the shared libgcc 163990277Sobrien when given the proper command line arguments. */ 164090277Sobrien while (*p) 164190277Sobrien { 1642117413Skan if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0) 164390277Sobrien { 164490277Sobrien init_gcc_specs (&obstack, 164590277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB 164690277Sobrien "-lgcc_s" 164790277Sobrien#else 164890277Sobrien "-lgcc_s%M" 164990277Sobrien#endif 1650146908Skan#ifdef USE_LIBUNWIND_EXCEPTIONS 1651146908Skan " -lunwind" 1652146908Skan#endif 1653132733Skan , 1654132733Skan "-lgcc", 1655132733Skan "-lgcc_eh" 1656122197Skan#ifdef USE_LIBUNWIND_EXCEPTIONS 1657146908Skan# ifdef HAVE_LD_STATIC_DYNAMIC 1658146908Skan " %{!static:-Bstatic} -lunwind %{!static:-Bdynamic}" 1659146908Skan# else 1660122197Skan " -lunwind" 1661146908Skan# endif 1662122197Skan#endif 1663132733Skan ); 1664132733Skan 166590277Sobrien p += 5; 166690277Sobrien in_sep = 0; 166790277Sobrien } 166890277Sobrien else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0) 166990277Sobrien { 167090277Sobrien /* Ug. We don't know shared library extensions. Hope that 167190277Sobrien systems that use this form don't do shared libraries. */ 167290277Sobrien init_gcc_specs (&obstack, 167390277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB 167490277Sobrien "-lgcc_s" 167590277Sobrien#else 167690277Sobrien "-lgcc_s%M" 167790277Sobrien#endif 167890277Sobrien , 167990277Sobrien "libgcc.a%s", 1680132733Skan "libgcc_eh.a%s" 1681132733Skan#ifdef USE_LIBUNWIND_EXCEPTIONS 1682132733Skan " -lunwind" 1683132733Skan#endif 1684132733Skan ); 168590277Sobrien p += 10; 168690277Sobrien in_sep = 0; 168790277Sobrien } 168890277Sobrien else 168990277Sobrien { 169090277Sobrien obstack_1grow (&obstack, *p); 169190277Sobrien in_sep = (*p == ' '); 169290277Sobrien p += 1; 169390277Sobrien } 169490277Sobrien } 169590277Sobrien 169690277Sobrien obstack_1grow (&obstack, '\0'); 169790277Sobrien libgcc_spec = obstack_finish (&obstack); 169890277Sobrien } 169990277Sobrien#endif 170090277Sobrien#ifdef USE_AS_TRADITIONAL_FORMAT 170190277Sobrien /* Prepend "--traditional-format" to whatever asm_spec we had before. */ 170290277Sobrien { 170390277Sobrien static const char tf[] = "--traditional-format "; 170490277Sobrien obstack_grow (&obstack, tf, sizeof(tf) - 1); 170590277Sobrien obstack_grow0 (&obstack, asm_spec, strlen (asm_spec)); 170690277Sobrien asm_spec = obstack_finish (&obstack); 170790277Sobrien } 170890277Sobrien#endif 170990277Sobrien#ifdef LINK_EH_SPEC 171090277Sobrien /* Prepend LINK_EH_SPEC to whatever link_spec we had before. */ 171190277Sobrien obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1); 171290277Sobrien obstack_grow0 (&obstack, link_spec, strlen (link_spec)); 171390277Sobrien link_spec = obstack_finish (&obstack); 171490277Sobrien#endif 171590277Sobrien 171650599Sobrien specs = sl; 171750599Sobrien} 171850599Sobrien 171918334Speter/* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is 172018334Speter removed; If the spec starts with a + then SPEC is added to the end of the 172150599Sobrien current spec. */ 172218334Speter 172318334Speterstatic void 1724132733Skanset_spec (const char *name, const char *spec) 172518334Speter{ 172618334Speter struct spec_list *sl; 172790277Sobrien const char *old_spec; 172850599Sobrien int name_len = strlen (name); 172950599Sobrien int i; 173018334Speter 173190277Sobrien /* If this is the first call, initialize the statically allocated specs. */ 173250599Sobrien if (!specs) 173350599Sobrien { 173490277Sobrien struct spec_list *next = (struct spec_list *) 0; 173590277Sobrien for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) 173650599Sobrien { 173750599Sobrien sl = &static_specs[i]; 173850599Sobrien sl->next = next; 173950599Sobrien next = sl; 174050599Sobrien } 174150599Sobrien specs = sl; 174250599Sobrien } 174350599Sobrien 174490277Sobrien /* See if the spec already exists. */ 174518334Speter for (sl = specs; sl; sl = sl->next) 174650599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, name)) 174718334Speter break; 174818334Speter 174918334Speter if (!sl) 175018334Speter { 175190277Sobrien /* Not found - make it. */ 1752132733Skan sl = xmalloc (sizeof (struct spec_list)); 175390277Sobrien sl->name = xstrdup (name); 175450599Sobrien sl->name_len = name_len; 175550599Sobrien sl->ptr_spec = &sl->ptr; 175650599Sobrien sl->alloc_p = 0; 175750599Sobrien *(sl->ptr_spec) = ""; 175818334Speter sl->next = specs; 175918334Speter specs = sl; 176018334Speter } 176118334Speter 176250599Sobrien old_spec = *(sl->ptr_spec); 176352520Sobrien *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1])) 176490277Sobrien ? concat (old_spec, spec + 1, NULL) 176590277Sobrien : xstrdup (spec)); 176618334Speter 176750599Sobrien#ifdef DEBUG_SPECS 176850599Sobrien if (verbose_flag) 176952520Sobrien notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec)); 177050599Sobrien#endif 177150599Sobrien 177290277Sobrien /* Free the old spec. */ 177350599Sobrien if (old_spec && sl->alloc_p) 1774132733Skan free ((void *) old_spec); 177550599Sobrien 177650599Sobrien sl->alloc_p = 1; 177718334Speter} 177818334Speter 177918334Speter/* Accumulate a command (program name and args), and run it. */ 178018334Speter 178118334Speter/* Vector of pointers to arguments in the current line of specifications. */ 178218334Speter 178390277Sobrienstatic const char **argbuf; 178418334Speter 178518334Speter/* Number of elements allocated in argbuf. */ 178618334Speter 178718334Speterstatic int argbuf_length; 178818334Speter 178918334Speter/* Number of elements in argbuf currently in use (containing args). */ 179018334Speter 179118334Speterstatic int argbuf_index; 179218334Speter 179390277Sobrien/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated 179490277Sobrien temp file. If the HOST_BIT_BUCKET is used for %j, no entry is made for 179590277Sobrien it here. */ 179650599Sobrien 179718334Speterstatic struct temp_name { 179852520Sobrien const char *suffix; /* suffix associated with the code. */ 179918334Speter int length; /* strlen (suffix). */ 180018334Speter int unique; /* Indicates whether %g or %u/%U was used. */ 180152520Sobrien const char *filename; /* associated filename. */ 180218334Speter int filename_length; /* strlen (filename). */ 180318334Speter struct temp_name *next; 180418334Speter} *temp_names; 180518334Speter 180618334Speter/* Number of commands executed so far. */ 180718334Speter 180818334Speterstatic int execution_count; 180918334Speter 181018334Speter/* Number of commands that exited with a signal. */ 181118334Speter 181218334Speterstatic int signal_count; 181318334Speter 181418334Speter/* Name with which this program was invoked. */ 181518334Speter 181652520Sobrienstatic const char *programname; 181718334Speter 1818117413Skan/* Allocate the argument vector. */ 1819117413Skan 1820117413Skanstatic void 1821132733Skanalloc_args (void) 1822117413Skan{ 1823117413Skan argbuf_length = 10; 1824132733Skan argbuf = xmalloc (argbuf_length * sizeof (const char *)); 1825117413Skan} 1826117413Skan 182718334Speter/* Clear out the vector of arguments (after a command is executed). */ 182818334Speter 182918334Speterstatic void 1830132733Skanclear_args (void) 183118334Speter{ 183218334Speter argbuf_index = 0; 183318334Speter} 183418334Speter 183518334Speter/* Add one argument to the vector at the end. 183618334Speter This is done when a space is seen or at the end of the line. 183718334Speter If DELETE_ALWAYS is nonzero, the arg is a filename 183818334Speter and the file should be deleted eventually. 183918334Speter If DELETE_FAILURE is nonzero, the arg is a filename 184018334Speter and the file should be deleted if this compilation fails. */ 184118334Speter 184218334Speterstatic void 1843132733Skanstore_arg (const char *arg, int delete_always, int delete_failure) 184418334Speter{ 184518334Speter if (argbuf_index + 1 == argbuf_length) 1846132733Skan argbuf = xrealloc (argbuf, (argbuf_length *= 2) * sizeof (const char *)); 184718334Speter 184818334Speter argbuf[argbuf_index++] = arg; 184918334Speter argbuf[argbuf_index] = 0; 185018334Speter 185118334Speter if (delete_always || delete_failure) 185218334Speter record_temp_file (arg, delete_always, delete_failure); 185318334Speter} 185418334Speter 185590277Sobrien/* Load specs from a file name named FILENAME, replacing occurrences of 185690277Sobrien various different types of line-endings, \r\n, \n\r and just \r, with 185790277Sobrien a single \n. */ 185850599Sobrien 185990277Sobrienstatic char * 1860132733Skanload_specs (const char *filename) 186150599Sobrien{ 186250599Sobrien int desc; 186350599Sobrien int readlen; 186450599Sobrien struct stat statbuf; 186550599Sobrien char *buffer; 186690277Sobrien char *buffer_p; 186790277Sobrien char *specs; 186890277Sobrien char *specs_p; 186950599Sobrien 187050599Sobrien if (verbose_flag) 187152520Sobrien notice ("Reading specs from %s\n", filename); 187250599Sobrien 187350599Sobrien /* Open and stat the file. */ 187450599Sobrien desc = open (filename, O_RDONLY, 0); 187550599Sobrien if (desc < 0) 187650599Sobrien pfatal_with_name (filename); 187750599Sobrien if (stat (filename, &statbuf) < 0) 187850599Sobrien pfatal_with_name (filename); 187950599Sobrien 188050599Sobrien /* Read contents of file into BUFFER. */ 188150599Sobrien buffer = xmalloc ((unsigned) statbuf.st_size + 1); 188250599Sobrien readlen = read (desc, buffer, (unsigned) statbuf.st_size); 188350599Sobrien if (readlen < 0) 188450599Sobrien pfatal_with_name (filename); 188550599Sobrien buffer[readlen] = 0; 188650599Sobrien close (desc); 188750599Sobrien 188890277Sobrien specs = xmalloc (readlen + 1); 188990277Sobrien specs_p = specs; 189090277Sobrien for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++) 189190277Sobrien { 189290277Sobrien int skip = 0; 189390277Sobrien char c = *buffer_p; 189490277Sobrien if (c == '\r') 189590277Sobrien { 189690277Sobrien if (buffer_p > buffer && *(buffer_p - 1) == '\n') /* \n\r */ 189790277Sobrien skip = 1; 189890277Sobrien else if (*(buffer_p + 1) == '\n') /* \r\n */ 189990277Sobrien skip = 1; 190090277Sobrien else /* \r */ 190190277Sobrien c = '\n'; 190290277Sobrien } 190390277Sobrien if (! skip) 190490277Sobrien *specs_p++ = c; 190590277Sobrien } 190690277Sobrien *specs_p = '\0'; 190790277Sobrien 190890277Sobrien free (buffer); 190990277Sobrien return (specs); 191090277Sobrien} 191190277Sobrien 191290277Sobrien/* Read compilation specs from a file named FILENAME, 191390277Sobrien replacing the default ones. 191490277Sobrien 191590277Sobrien A suffix which starts with `*' is a definition for 191690277Sobrien one of the machine-specific sub-specs. The "suffix" should be 191796285Sobrien *asm, *cc1, *cpp, *link, *startfile, etc. 191890277Sobrien The corresponding spec is stored in asm_spec, etc., 191990277Sobrien rather than in the `compilers' vector. 192090277Sobrien 192190277Sobrien Anything invalid in the file is a fatal error. */ 192290277Sobrien 192390277Sobrienstatic void 1924132733Skanread_specs (const char *filename, int main_p) 192590277Sobrien{ 192690277Sobrien char *buffer; 192790277Sobrien char *p; 192890277Sobrien 192990277Sobrien buffer = load_specs (filename); 193090277Sobrien 193150599Sobrien /* Scan BUFFER for specs, putting them in the vector. */ 193250599Sobrien p = buffer; 193350599Sobrien while (1) 193450599Sobrien { 193550599Sobrien char *suffix; 193650599Sobrien char *spec; 193750599Sobrien char *in, *out, *p1, *p2, *p3; 193850599Sobrien 193950599Sobrien /* Advance P in BUFFER to the next nonblank nocomment line. */ 194050599Sobrien p = skip_whitespace (p); 194150599Sobrien if (*p == 0) 194250599Sobrien break; 194350599Sobrien 194450599Sobrien /* Is this a special command that starts with '%'? */ 194550599Sobrien /* Don't allow this for the main specs file, since it would 194650599Sobrien encourage people to overwrite it. */ 194750599Sobrien if (*p == '%' && !main_p) 194850599Sobrien { 194950599Sobrien p1 = p; 195050599Sobrien while (*p && *p != '\n') 195150599Sobrien p++; 195250599Sobrien 195390277Sobrien /* Skip '\n'. */ 195490277Sobrien p++; 195550599Sobrien 195690277Sobrien if (!strncmp (p1, "%include", sizeof ("%include") - 1) 195750599Sobrien && (p1[sizeof "%include" - 1] == ' ' 195850599Sobrien || p1[sizeof "%include" - 1] == '\t')) 195950599Sobrien { 196050599Sobrien char *new_filename; 196150599Sobrien 196250599Sobrien p1 += sizeof ("%include"); 196350599Sobrien while (*p1 == ' ' || *p1 == '\t') 196450599Sobrien p1++; 196550599Sobrien 196650599Sobrien if (*p1++ != '<' || p[-2] != '>') 196752520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 196852520Sobrien (long) (p1 - buffer + 1)); 196950599Sobrien 197050599Sobrien p[-2] = '\0'; 1971104763Skan new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0); 197250599Sobrien read_specs (new_filename ? new_filename : p1, FALSE); 197350599Sobrien continue; 197450599Sobrien } 197550599Sobrien else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1) 197650599Sobrien && (p1[sizeof "%include_noerr" - 1] == ' ' 197750599Sobrien || p1[sizeof "%include_noerr" - 1] == '\t')) 197850599Sobrien { 197950599Sobrien char *new_filename; 198050599Sobrien 198150599Sobrien p1 += sizeof "%include_noerr"; 198290277Sobrien while (*p1 == ' ' || *p1 == '\t') 198390277Sobrien p1++; 198450599Sobrien 198550599Sobrien if (*p1++ != '<' || p[-2] != '>') 198652520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 198752520Sobrien (long) (p1 - buffer + 1)); 198850599Sobrien 198950599Sobrien p[-2] = '\0'; 1990104763Skan new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0); 199150599Sobrien if (new_filename) 199250599Sobrien read_specs (new_filename, FALSE); 199350599Sobrien else if (verbose_flag) 199490277Sobrien notice ("could not find specs file %s\n", p1); 199550599Sobrien continue; 199650599Sobrien } 199750599Sobrien else if (!strncmp (p1, "%rename", sizeof "%rename" - 1) 199850599Sobrien && (p1[sizeof "%rename" - 1] == ' ' 199950599Sobrien || p1[sizeof "%rename" - 1] == '\t')) 200050599Sobrien { 200150599Sobrien int name_len; 200250599Sobrien struct spec_list *sl; 2003117413Skan struct spec_list *newsl; 200450599Sobrien 2005117413Skan /* Get original name. */ 200650599Sobrien p1 += sizeof "%rename"; 200750599Sobrien while (*p1 == ' ' || *p1 == '\t') 200850599Sobrien p1++; 200950599Sobrien 201090277Sobrien if (! ISALPHA ((unsigned char) *p1)) 201152520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 201252520Sobrien (long) (p1 - buffer)); 201350599Sobrien 201450599Sobrien p2 = p1; 201590277Sobrien while (*p2 && !ISSPACE ((unsigned char) *p2)) 201650599Sobrien p2++; 201750599Sobrien 201850599Sobrien if (*p2 != ' ' && *p2 != '\t') 201952520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 202052520Sobrien (long) (p2 - buffer)); 202150599Sobrien 202250599Sobrien name_len = p2 - p1; 202350599Sobrien *p2++ = '\0'; 202450599Sobrien while (*p2 == ' ' || *p2 == '\t') 202550599Sobrien p2++; 202650599Sobrien 202790277Sobrien if (! ISALPHA ((unsigned char) *p2)) 202852520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 202952520Sobrien (long) (p2 - buffer)); 203050599Sobrien 203190277Sobrien /* Get new spec name. */ 203250599Sobrien p3 = p2; 203390277Sobrien while (*p3 && !ISSPACE ((unsigned char) *p3)) 203450599Sobrien p3++; 203550599Sobrien 203690277Sobrien if (p3 != p - 1) 203752520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 203852520Sobrien (long) (p3 - buffer)); 203950599Sobrien *p3 = '\0'; 204050599Sobrien 204150599Sobrien for (sl = specs; sl; sl = sl->next) 204250599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, p1)) 204350599Sobrien break; 204450599Sobrien 204550599Sobrien if (!sl) 204650599Sobrien fatal ("specs %s spec was not found to be renamed", p1); 204750599Sobrien 204850599Sobrien if (strcmp (p1, p2) == 0) 204950599Sobrien continue; 205050599Sobrien 2051117413Skan for (newsl = specs; newsl; newsl = newsl->next) 2052117413Skan if (strcmp (newsl->name, p2) == 0) 2053117413Skan fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'", 2054117413Skan filename, p1, p2); 2055117413Skan 205650599Sobrien if (verbose_flag) 205750599Sobrien { 205852520Sobrien notice ("rename spec %s to %s\n", p1, p2); 205950599Sobrien#ifdef DEBUG_SPECS 206052520Sobrien notice ("spec is '%s'\n\n", *(sl->ptr_spec)); 206150599Sobrien#endif 206250599Sobrien } 206350599Sobrien 206450599Sobrien set_spec (p2, *(sl->ptr_spec)); 206550599Sobrien if (sl->alloc_p) 2066132733Skan free ((void *) *(sl->ptr_spec)); 206750599Sobrien 206850599Sobrien *(sl->ptr_spec) = ""; 206950599Sobrien sl->alloc_p = 0; 207050599Sobrien continue; 207150599Sobrien } 207250599Sobrien else 207352520Sobrien fatal ("specs unknown %% command after %ld characters", 207452520Sobrien (long) (p1 - buffer)); 207550599Sobrien } 207650599Sobrien 207750599Sobrien /* Find the colon that should end the suffix. */ 207850599Sobrien p1 = p; 207950599Sobrien while (*p1 && *p1 != ':' && *p1 != '\n') 208050599Sobrien p1++; 208150599Sobrien 208250599Sobrien /* The colon shouldn't be missing. */ 208350599Sobrien if (*p1 != ':') 208452520Sobrien fatal ("specs file malformed after %ld characters", 208552520Sobrien (long) (p1 - buffer)); 208650599Sobrien 208750599Sobrien /* Skip back over trailing whitespace. */ 208850599Sobrien p2 = p1; 208950599Sobrien while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) 209050599Sobrien p2--; 209150599Sobrien 209250599Sobrien /* Copy the suffix to a string. */ 209350599Sobrien suffix = save_string (p, p2 - p); 209450599Sobrien /* Find the next line. */ 209550599Sobrien p = skip_whitespace (p1 + 1); 209650599Sobrien if (p[1] == 0) 209752520Sobrien fatal ("specs file malformed after %ld characters", 209852520Sobrien (long) (p - buffer)); 209950599Sobrien 210050599Sobrien p1 = p; 210150599Sobrien /* Find next blank line or end of string. */ 210250599Sobrien while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0'))) 210350599Sobrien p1++; 210450599Sobrien 210550599Sobrien /* Specs end at the blank line and do not include the newline. */ 210650599Sobrien spec = save_string (p, p1 - p); 210750599Sobrien p = p1; 210850599Sobrien 210950599Sobrien /* Delete backslash-newline sequences from the spec. */ 211050599Sobrien in = spec; 211150599Sobrien out = spec; 211250599Sobrien while (*in != 0) 211350599Sobrien { 211450599Sobrien if (in[0] == '\\' && in[1] == '\n') 211550599Sobrien in += 2; 211650599Sobrien else if (in[0] == '#') 211750599Sobrien while (*in && *in != '\n') 211850599Sobrien in++; 211950599Sobrien 212050599Sobrien else 212150599Sobrien *out++ = *in++; 212250599Sobrien } 212350599Sobrien *out = 0; 212450599Sobrien 212550599Sobrien if (suffix[0] == '*') 212650599Sobrien { 212750599Sobrien if (! strcmp (suffix, "*link_command")) 212850599Sobrien link_command_spec = spec; 212950599Sobrien else 213050599Sobrien set_spec (suffix + 1, spec); 213150599Sobrien } 213250599Sobrien else 213350599Sobrien { 213450599Sobrien /* Add this pair to the vector. */ 213550599Sobrien compilers 2136132733Skan = xrealloc (compilers, 2137132733Skan (n_compilers + 2) * sizeof (struct compiler)); 213850599Sobrien 213950599Sobrien compilers[n_compilers].suffix = suffix; 214090277Sobrien compilers[n_compilers].spec = spec; 214150599Sobrien n_compilers++; 214290277Sobrien memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]); 214350599Sobrien } 214450599Sobrien 214550599Sobrien if (*suffix == 0) 214650599Sobrien link_command_spec = spec; 214750599Sobrien } 214850599Sobrien 214950599Sobrien if (link_command_spec == 0) 215050599Sobrien fatal ("spec file has no spec for linking"); 215150599Sobrien} 215250599Sobrien 215318334Speter/* Record the names of temporary files we tell compilers to write, 215418334Speter and delete them at the end of the run. */ 215518334Speter 215618334Speter/* This is the common prefix we use to make temp file names. 215718334Speter It is chosen once for each run of this program. 215890277Sobrien It is substituted into a spec by %g or %j. 215918334Speter Thus, all temp file names contain this prefix. 216018334Speter In practice, all temp file names start with this prefix. 216118334Speter 216218334Speter This prefix comes from the envvar TMPDIR if it is defined; 216318334Speter otherwise, from the P_tmpdir macro if that is defined; 216450599Sobrien otherwise, in /usr/tmp or /tmp; 216550599Sobrien or finally the current directory if all else fails. */ 216618334Speter 216752520Sobrienstatic const char *temp_filename; 216818334Speter 216918334Speter/* Length of the prefix. */ 217018334Speter 217118334Speterstatic int temp_filename_length; 217218334Speter 217318334Speter/* Define the list of temporary files to delete. */ 217418334Speter 217518334Speterstruct temp_file 217618334Speter{ 217752520Sobrien const char *name; 217818334Speter struct temp_file *next; 217918334Speter}; 218018334Speter 218118334Speter/* Queue of files to delete on success or failure of compilation. */ 218218334Speterstatic struct temp_file *always_delete_queue; 218318334Speter/* Queue of files to delete on failure of compilation. */ 218418334Speterstatic struct temp_file *failure_delete_queue; 218518334Speter 218618334Speter/* Record FILENAME as a file to be deleted automatically. 218718334Speter ALWAYS_DELETE nonzero means delete it if all compilation succeeds; 218818334Speter otherwise delete it in any case. 218918334Speter FAIL_DELETE nonzero means delete it if a compilation step fails; 219018334Speter otherwise delete it in any case. */ 219118334Speter 219290277Sobrienvoid 2193132733Skanrecord_temp_file (const char *filename, int always_delete, int fail_delete) 219418334Speter{ 219590277Sobrien char *const name = xstrdup (filename); 219618334Speter 219718334Speter if (always_delete) 219818334Speter { 219990277Sobrien struct temp_file *temp; 220018334Speter for (temp = always_delete_queue; temp; temp = temp->next) 220118334Speter if (! strcmp (name, temp->name)) 220218334Speter goto already1; 220350599Sobrien 2204132733Skan temp = xmalloc (sizeof (struct temp_file)); 220518334Speter temp->next = always_delete_queue; 220618334Speter temp->name = name; 220718334Speter always_delete_queue = temp; 220850599Sobrien 220918334Speter already1:; 221018334Speter } 221118334Speter 221218334Speter if (fail_delete) 221318334Speter { 221490277Sobrien struct temp_file *temp; 221518334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 221618334Speter if (! strcmp (name, temp->name)) 221718334Speter goto already2; 221850599Sobrien 2219132733Skan temp = xmalloc (sizeof (struct temp_file)); 222018334Speter temp->next = failure_delete_queue; 222118334Speter temp->name = name; 222218334Speter failure_delete_queue = temp; 222350599Sobrien 222418334Speter already2:; 222518334Speter } 222618334Speter} 222718334Speter 222818334Speter/* Delete all the temporary files whose names we previously recorded. */ 222918334Speter 223018334Speterstatic void 2231132733Skandelete_if_ordinary (const char *name) 223218334Speter{ 223318334Speter struct stat st; 223418334Speter#ifdef DEBUG 223518334Speter int i, c; 223618334Speter 223718334Speter printf ("Delete %s? (y or n) ", name); 223818334Speter fflush (stdout); 223918334Speter i = getchar (); 224018334Speter if (i != '\n') 224150599Sobrien while ((c = getchar ()) != '\n' && c != EOF) 224250599Sobrien ; 224350599Sobrien 224418334Speter if (i == 'y' || i == 'Y') 224518334Speter#endif /* DEBUG */ 224618334Speter if (stat (name, &st) >= 0 && S_ISREG (st.st_mode)) 224718334Speter if (unlink (name) < 0) 224818334Speter if (verbose_flag) 224918334Speter perror_with_name (name); 225018334Speter} 225118334Speter 225218334Speterstatic void 2253132733Skandelete_temp_files (void) 225418334Speter{ 225590277Sobrien struct temp_file *temp; 225618334Speter 225718334Speter for (temp = always_delete_queue; temp; temp = temp->next) 225818334Speter delete_if_ordinary (temp->name); 225918334Speter always_delete_queue = 0; 226018334Speter} 226118334Speter 226218334Speter/* Delete all the files to be deleted on error. */ 226318334Speter 226418334Speterstatic void 2265132733Skandelete_failure_queue (void) 226618334Speter{ 226790277Sobrien struct temp_file *temp; 226818334Speter 226918334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 227018334Speter delete_if_ordinary (temp->name); 227118334Speter} 227218334Speter 227318334Speterstatic void 2274132733Skanclear_failure_queue (void) 227518334Speter{ 227618334Speter failure_delete_queue = 0; 227718334Speter} 227818334Speter 227918334Speter/* Build a list of search directories from PATHS. 228018334Speter PREFIX is a string to prepend to the list. 2281117413Skan If CHECK_DIR_P is nonzero we ensure the directory exists. 228218334Speter This is used mostly by putenv_from_prefixes so we use `collect_obstack'. 228318334Speter It is also used by the --print-search-dirs flag. */ 228418334Speter 228518334Speterstatic char * 2286132733Skanbuild_search_list (struct path_prefix *paths, const char *prefix, 2287132733Skan int check_dir_p) 228818334Speter{ 228918334Speter int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0; 229018334Speter int just_suffix_len 229118334Speter = (just_machine_suffix) ? strlen (just_machine_suffix) : 0; 229218334Speter int first_time = TRUE; 229318334Speter struct prefix_list *pprefix; 229418334Speter 229518334Speter obstack_grow (&collect_obstack, prefix, strlen (prefix)); 229690277Sobrien obstack_1grow (&collect_obstack, '='); 229718334Speter 229818334Speter for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next) 229918334Speter { 230018334Speter int len = strlen (pprefix->prefix); 230118334Speter 230218334Speter if (machine_suffix 230350599Sobrien && (! check_dir_p 230418334Speter || is_directory (pprefix->prefix, machine_suffix, 0))) 230518334Speter { 230618334Speter if (!first_time) 230718334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 230890277Sobrien 230918334Speter first_time = FALSE; 231018334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 231118334Speter obstack_grow (&collect_obstack, machine_suffix, suffix_len); 231218334Speter } 231318334Speter 231418334Speter if (just_machine_suffix 231518334Speter && pprefix->require_machine_suffix == 2 231650599Sobrien && (! check_dir_p 231718334Speter || is_directory (pprefix->prefix, just_machine_suffix, 0))) 231818334Speter { 231950599Sobrien if (! first_time) 232018334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 232190277Sobrien 232218334Speter first_time = FALSE; 232318334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 232418334Speter obstack_grow (&collect_obstack, just_machine_suffix, 232518334Speter just_suffix_len); 232618334Speter } 232718334Speter 232850599Sobrien if (! pprefix->require_machine_suffix) 232918334Speter { 233050599Sobrien if (! first_time) 233118334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 233218334Speter 233318334Speter first_time = FALSE; 233418334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 233518334Speter } 233618334Speter } 233750599Sobrien 233818334Speter obstack_1grow (&collect_obstack, '\0'); 233918334Speter return obstack_finish (&collect_obstack); 234018334Speter} 234118334Speter 234250599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 234350599Sobrien for collect. */ 234418334Speter 234518334Speterstatic void 2346132733Skanputenv_from_prefixes (struct path_prefix *paths, const char *env_var) 234718334Speter{ 234818334Speter putenv (build_search_list (paths, env_var, 1)); 234918334Speter} 235018334Speter 235190277Sobrien/* Check whether NAME can be accessed in MODE. This is like access, 235290277Sobrien except that it never considers directories to be executable. */ 235390277Sobrien 235490277Sobrienstatic int 2355132733Skanaccess_check (const char *name, int mode) 235690277Sobrien{ 235790277Sobrien if (mode == X_OK) 235890277Sobrien { 235990277Sobrien struct stat st; 236090277Sobrien 236190277Sobrien if (stat (name, &st) < 0 236290277Sobrien || S_ISDIR (st.st_mode)) 236390277Sobrien return -1; 236490277Sobrien } 236590277Sobrien 236690277Sobrien return access (name, mode); 236790277Sobrien} 236890277Sobrien 236918334Speter/* Search for NAME using the prefix list PREFIXES. MODE is passed to 237018334Speter access to check permissions. 237150599Sobrien Return 0 if not found, otherwise return its name, allocated with malloc. */ 237218334Speter 237318334Speterstatic char * 2374132733Skanfind_a_file (struct path_prefix *pprefix, const char *name, int mode, 2375132733Skan int multilib) 237618334Speter{ 237718334Speter char *temp; 237890277Sobrien const char *const file_suffix = 237990277Sobrien ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : ""); 238018334Speter struct prefix_list *pl; 238118334Speter int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1; 2382104763Skan const char *multilib_name, *multilib_os_name; 238318334Speter 238452520Sobrien#ifdef DEFAULT_ASSEMBLER 238590277Sobrien if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) 238690277Sobrien return xstrdup (DEFAULT_ASSEMBLER); 238752520Sobrien#endif 238852520Sobrien 238952520Sobrien#ifdef DEFAULT_LINKER 239090277Sobrien if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) 239190277Sobrien return xstrdup (DEFAULT_LINKER); 239252520Sobrien#endif 239352520Sobrien 239418334Speter if (machine_suffix) 239518334Speter len += strlen (machine_suffix); 239618334Speter 2397104763Skan multilib_name = name; 2398104763Skan multilib_os_name = name; 2399104763Skan if (multilib && multilib_os_dir) 2400104763Skan { 2401104763Skan int len1 = multilib_dir ? strlen (multilib_dir) + 1 : 0; 2402104763Skan int len2 = strlen (multilib_os_dir) + 1; 2403104763Skan 2404104763Skan len += len1 > len2 ? len1 : len2; 2405104763Skan if (multilib_dir) 2406104763Skan multilib_name = ACONCAT ((multilib_dir, dir_separator_str, name, 2407104763Skan NULL)); 2408104763Skan if (strcmp (multilib_os_dir, ".") != 0) 2409104763Skan multilib_os_name = ACONCAT ((multilib_os_dir, dir_separator_str, name, 2410104763Skan NULL)); 2411104763Skan } 2412104763Skan 241318334Speter temp = xmalloc (len); 241418334Speter 241518334Speter /* Determine the filename to execute (special case for absolute paths). */ 241618334Speter 2417132733Skan if (IS_ABSOLUTE_PATH (name)) 241818334Speter { 241952520Sobrien if (access (name, mode) == 0) 242018334Speter { 242118334Speter strcpy (temp, name); 242218334Speter return temp; 242318334Speter } 242418334Speter } 242518334Speter else 242618334Speter for (pl = pprefix->plist; pl; pl = pl->next) 242718334Speter { 2428104763Skan const char *this_name 2429104763Skan = pl->os_multilib ? multilib_os_name : multilib_name; 2430104763Skan 243118334Speter if (machine_suffix) 243218334Speter { 243318334Speter /* Some systems have a suffix for executable files. 243418334Speter So try appending that first. */ 243518334Speter if (file_suffix[0] != 0) 243618334Speter { 243718334Speter strcpy (temp, pl->prefix); 243818334Speter strcat (temp, machine_suffix); 2439104763Skan strcat (temp, multilib_name); 244018334Speter strcat (temp, file_suffix); 244190277Sobrien if (access_check (temp, mode) == 0) 244218334Speter { 244318334Speter if (pl->used_flag_ptr != 0) 244418334Speter *pl->used_flag_ptr = 1; 244518334Speter return temp; 244618334Speter } 244718334Speter } 244818334Speter 2449104763Skan /* Now try just the multilib_name. */ 245018334Speter strcpy (temp, pl->prefix); 245118334Speter strcat (temp, machine_suffix); 2452104763Skan strcat (temp, multilib_name); 245390277Sobrien if (access_check (temp, mode) == 0) 245418334Speter { 245518334Speter if (pl->used_flag_ptr != 0) 245618334Speter *pl->used_flag_ptr = 1; 245718334Speter return temp; 245818334Speter } 245918334Speter } 246018334Speter 246118334Speter /* Certain prefixes are tried with just the machine type, 246218334Speter not the version. This is used for finding as, ld, etc. */ 246318334Speter if (just_machine_suffix && pl->require_machine_suffix == 2) 246418334Speter { 246518334Speter /* Some systems have a suffix for executable files. 246618334Speter So try appending that first. */ 246718334Speter if (file_suffix[0] != 0) 246818334Speter { 246918334Speter strcpy (temp, pl->prefix); 247018334Speter strcat (temp, just_machine_suffix); 2471104763Skan strcat (temp, multilib_name); 247218334Speter strcat (temp, file_suffix); 247390277Sobrien if (access_check (temp, mode) == 0) 247418334Speter { 247518334Speter if (pl->used_flag_ptr != 0) 247618334Speter *pl->used_flag_ptr = 1; 247718334Speter return temp; 247818334Speter } 247918334Speter } 248018334Speter 248118334Speter strcpy (temp, pl->prefix); 248218334Speter strcat (temp, just_machine_suffix); 2483104763Skan strcat (temp, multilib_name); 248490277Sobrien if (access_check (temp, mode) == 0) 248518334Speter { 248618334Speter if (pl->used_flag_ptr != 0) 248718334Speter *pl->used_flag_ptr = 1; 248818334Speter return temp; 248918334Speter } 249018334Speter } 249118334Speter 249218334Speter /* Certain prefixes can't be used without the machine suffix 249318334Speter when the machine or version is explicitly specified. */ 249450599Sobrien if (! pl->require_machine_suffix) 249518334Speter { 249618334Speter /* Some systems have a suffix for executable files. 249718334Speter So try appending that first. */ 249818334Speter if (file_suffix[0] != 0) 249918334Speter { 250018334Speter strcpy (temp, pl->prefix); 2501104763Skan strcat (temp, this_name); 250218334Speter strcat (temp, file_suffix); 250390277Sobrien if (access_check (temp, mode) == 0) 250418334Speter { 250518334Speter if (pl->used_flag_ptr != 0) 250618334Speter *pl->used_flag_ptr = 1; 250718334Speter return temp; 250818334Speter } 250918334Speter } 251018334Speter 251118334Speter strcpy (temp, pl->prefix); 2512104763Skan strcat (temp, this_name); 251390277Sobrien if (access_check (temp, mode) == 0) 251418334Speter { 251518334Speter if (pl->used_flag_ptr != 0) 251618334Speter *pl->used_flag_ptr = 1; 251718334Speter return temp; 251818334Speter } 251918334Speter } 252018334Speter } 252118334Speter 252218334Speter free (temp); 252318334Speter return 0; 252418334Speter} 252518334Speter 252690277Sobrien/* Ranking of prefixes in the sort list. -B prefixes are put before 252790277Sobrien all others. */ 252818334Speter 252990277Sobrienenum path_prefix_priority 253090277Sobrien{ 253190277Sobrien PREFIX_PRIORITY_B_OPT, 253290277Sobrien PREFIX_PRIORITY_LAST 253390277Sobrien}; 253490277Sobrien 2535132733Skan/* Add an entry for PREFIX in PLIST. The PLIST is kept in ascending 253690277Sobrien order according to PRIORITY. Within each PRIORITY, new entries are 253790277Sobrien appended. 253890277Sobrien 253918334Speter If WARN is nonzero, we will warn if no file is found 254018334Speter through this prefix. WARN should point to an int 254118334Speter which will be set to 1 if this entry is used. 254218334Speter 254350599Sobrien COMPONENT is the value to be passed to update_path. 254450599Sobrien 254518334Speter REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without 254618334Speter the complete value of machine_suffix. 254718334Speter 2 means try both machine_suffix and just_machine_suffix. */ 254818334Speter 254918334Speterstatic void 2550132733Skanadd_prefix (struct path_prefix *pprefix, const char *prefix, 2551132733Skan const char *component, /* enum prefix_priority */ int priority, 2552132733Skan int require_machine_suffix, int *warn, int os_multilib) 255318334Speter{ 255418334Speter struct prefix_list *pl, **prev; 255518334Speter int len; 255618334Speter 255790277Sobrien for (prev = &pprefix->plist; 255890277Sobrien (*prev) != NULL && (*prev)->priority <= priority; 255990277Sobrien prev = &(*prev)->next) 256090277Sobrien ; 256118334Speter 2562132733Skan /* Keep track of the longest prefix. */ 256318334Speter 256450599Sobrien prefix = update_path (prefix, component); 256518334Speter len = strlen (prefix); 256618334Speter if (len > pprefix->max_len) 256718334Speter pprefix->max_len = len; 256818334Speter 2569132733Skan pl = xmalloc (sizeof (struct prefix_list)); 257090277Sobrien pl->prefix = prefix; 257118334Speter pl->require_machine_suffix = require_machine_suffix; 257218334Speter pl->used_flag_ptr = warn; 257390277Sobrien pl->priority = priority; 2574104763Skan pl->os_multilib = os_multilib; 257518334Speter if (warn) 257618334Speter *warn = 0; 257718334Speter 2578132733Skan /* Insert after PREV. */ 257990277Sobrien pl->next = (*prev); 258090277Sobrien (*prev) = pl; 258118334Speter} 2582132733Skan 2583132733Skan/* Same as add_prefix, but prepending target_system_root to prefix. */ 2584132733Skanstatic void 2585132733Skanadd_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix, 2586132733Skan const char *component, 2587132733Skan /* enum prefix_priority */ int priority, 2588132733Skan int require_machine_suffix, int *warn, int os_multilib) 2589132733Skan{ 2590132733Skan if (!IS_ABSOLUTE_PATH (prefix)) 2591132733Skan abort (); 2592132733Skan 2593132733Skan if (target_system_root) 2594132733Skan { 2595132733Skan if (target_sysroot_suffix) 2596132733Skan prefix = concat (target_sysroot_suffix, prefix, NULL); 2597132733Skan prefix = concat (target_system_root, prefix, NULL); 2598132733Skan 2599132733Skan /* We have to override this because GCC's notion of sysroot 2600132733Skan moves along with GCC. */ 2601132733Skan component = "GCC"; 2602132733Skan } 2603132733Skan 2604132733Skan add_prefix (pprefix, prefix, component, priority, 2605132733Skan require_machine_suffix, warn, os_multilib); 2606132733Skan} 260718334Speter 260818334Speter/* Execute the command specified by the arguments on the current line of spec. 260918334Speter When using pipes, this includes several piped-together commands 261018334Speter with `|' between them. 261118334Speter 261218334Speter Return 0 if successful, -1 if failed. */ 261318334Speter 261418334Speterstatic int 2615132733Skanexecute (void) 261618334Speter{ 261718334Speter int i; 261818334Speter int n_commands; /* # of command. */ 261918334Speter char *string; 262018334Speter struct command 262190277Sobrien { 262290277Sobrien const char *prog; /* program name. */ 262390277Sobrien const char **argv; /* vector of args. */ 262490277Sobrien int pid; /* pid of process for this command. */ 262590277Sobrien }; 262618334Speter 262718334Speter struct command *commands; /* each command buffer with above info. */ 262818334Speter 2629117413Skan if (processing_spec_function) 2630117413Skan abort (); 2631117413Skan 263218334Speter /* Count # of piped commands. */ 263318334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 263418334Speter if (strcmp (argbuf[i], "|") == 0) 263518334Speter n_commands++; 263618334Speter 263718334Speter /* Get storage for each command. */ 2638132733Skan commands = alloca (n_commands * sizeof (struct command)); 263918334Speter 264018334Speter /* Split argbuf into its separate piped processes, 264118334Speter and record info about each one. 264218334Speter Also search for the programs that are to be run. */ 264318334Speter 264418334Speter commands[0].prog = argbuf[0]; /* first command. */ 264518334Speter commands[0].argv = &argbuf[0]; 2646104763Skan string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, 0); 264750599Sobrien 264818334Speter if (string) 264918334Speter commands[0].argv[0] = string; 265018334Speter 265118334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 265218334Speter if (strcmp (argbuf[i], "|") == 0) 265318334Speter { /* each command. */ 265452520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS) 265590277Sobrien fatal ("-pipe not supported"); 265618334Speter#endif 265718334Speter argbuf[i] = 0; /* termination of command args. */ 265818334Speter commands[n_commands].prog = argbuf[i + 1]; 265918334Speter commands[n_commands].argv = &argbuf[i + 1]; 2660104763Skan string = find_a_file (&exec_prefixes, commands[n_commands].prog, 2661104763Skan X_OK, 0); 266218334Speter if (string) 266318334Speter commands[n_commands].argv[0] = string; 266418334Speter n_commands++; 266518334Speter } 266618334Speter 266718334Speter argbuf[argbuf_index] = 0; 266818334Speter 266918334Speter /* If -v, print what we are about to do, and maybe query. */ 267018334Speter 267118334Speter if (verbose_flag) 267218334Speter { 267350599Sobrien /* For help listings, put a blank line between sub-processes. */ 267450599Sobrien if (print_help_list) 267550599Sobrien fputc ('\n', stderr); 267690277Sobrien 267718334Speter /* Print each piped command as a separate line. */ 267890277Sobrien for (i = 0; i < n_commands; i++) 267918334Speter { 268090277Sobrien const char *const *j; 268118334Speter 2682117413Skan if (verbose_only_flag) 2683117413Skan { 268490277Sobrien for (j = commands[i].argv; *j; j++) 268590277Sobrien { 268690277Sobrien const char *p; 268790277Sobrien fprintf (stderr, " \""); 268890277Sobrien for (p = *j; *p; ++p) 268990277Sobrien { 269090277Sobrien if (*p == '"' || *p == '\\' || *p == '$') 269190277Sobrien fputc ('\\', stderr); 269290277Sobrien fputc (*p, stderr); 269390277Sobrien } 269490277Sobrien fputc ('"', stderr); 269590277Sobrien } 2696117413Skan } 2697117413Skan else 269890277Sobrien for (j = commands[i].argv; *j; j++) 269990277Sobrien fprintf (stderr, " %s", *j); 270018334Speter 270118334Speter /* Print a pipe symbol after all but the last command. */ 270218334Speter if (i + 1 != n_commands) 270318334Speter fprintf (stderr, " |"); 270418334Speter fprintf (stderr, "\n"); 270518334Speter } 270618334Speter fflush (stderr); 270790277Sobrien if (verbose_only_flag != 0) 2708132733Skan { 2709132733Skan /* verbose_only_flag should act as if the spec was 2710132733Skan executed, so increment execution_count before 2711132733Skan returning. This prevents spurious warnings about 2712132733Skan unused linker input files, etc. */ 2713132733Skan execution_count++; 2714132733Skan return 0; 2715132733Skan } 271618334Speter#ifdef DEBUG 271752520Sobrien notice ("\nGo ahead? (y or n) "); 271818334Speter fflush (stderr); 271918334Speter i = getchar (); 272018334Speter if (i != '\n') 272150599Sobrien while (getchar () != '\n') 272250599Sobrien ; 272350599Sobrien 272418334Speter if (i != 'y' && i != 'Y') 272518334Speter return 0; 272618334Speter#endif /* DEBUG */ 272718334Speter } 272818334Speter 2729117413Skan#ifdef ENABLE_VALGRIND_CHECKING 2730132733Skan /* Run the each command through valgrind. To simplify prepending the 2731117413Skan path to valgrind and the option "-q" (for quiet operation unless 2732117413Skan something triggers), we allocate a separate argv array. */ 2733117413Skan 2734117413Skan for (i = 0; i < n_commands; i++) 2735117413Skan { 2736117413Skan const char **argv; 2737117413Skan int argc; 2738117413Skan int j; 2739117413Skan 2740117413Skan for (argc = 0; commands[i].argv[argc] != NULL; argc++) 2741117413Skan ; 2742117413Skan 2743117413Skan argv = alloca ((argc + 3) * sizeof (char *)); 2744117413Skan 2745117413Skan argv[0] = VALGRIND_PATH; 2746117413Skan argv[1] = "-q"; 2747117413Skan for (j = 2; j < argc + 2; j++) 2748117413Skan argv[j] = commands[i].argv[j - 2]; 2749117413Skan argv[j] = NULL; 2750117413Skan 2751117413Skan commands[i].argv = argv; 2752117413Skan commands[i].prog = argv[0]; 2753117413Skan } 2754117413Skan#endif 2755117413Skan 275618334Speter /* Run each piped subprocess. */ 275718334Speter 275818334Speter for (i = 0; i < n_commands; i++) 275918334Speter { 276050599Sobrien char *errmsg_fmt, *errmsg_arg; 276190277Sobrien const char *string = commands[i].argv[0]; 276218334Speter 276390277Sobrien /* For some bizarre reason, the second argument of execvp() is 276490277Sobrien char *const *, not const char *const *. */ 276590277Sobrien commands[i].pid = pexecute (string, (char *const *) commands[i].argv, 276650599Sobrien programname, temp_filename, 276750599Sobrien &errmsg_fmt, &errmsg_arg, 276850599Sobrien ((i == 0 ? PEXECUTE_FIRST : 0) 276950599Sobrien | (i + 1 == n_commands ? PEXECUTE_LAST : 0) 277050599Sobrien | (string == commands[i].prog 277150599Sobrien ? PEXECUTE_SEARCH : 0) 277250599Sobrien | (verbose_flag ? PEXECUTE_VERBOSE : 0))); 277318334Speter 277450599Sobrien if (commands[i].pid == -1) 277550599Sobrien pfatal_pexecute (errmsg_fmt, errmsg_arg); 277650599Sobrien 277718334Speter if (string != commands[i].prog) 2778132733Skan free ((void *) string); 277918334Speter } 278018334Speter 278118334Speter execution_count++; 278218334Speter 278318334Speter /* Wait for all the subprocesses to finish. 278418334Speter We don't care what order they finish in; 278518334Speter we know that N_COMMANDS waits will get them all. 278618334Speter Ignore subprocesses that we don't know about, 278718334Speter since they can be spawned by the process that exec'ed us. */ 278818334Speter 278918334Speter { 279018334Speter int ret_code = 0; 279190277Sobrien#ifdef HAVE_GETRUSAGE 279290277Sobrien struct timeval d; 279390277Sobrien double ut = 0.0, st = 0.0; 279490277Sobrien#endif 279518334Speter 279690277Sobrien for (i = 0; i < n_commands;) 279718334Speter { 279818334Speter int j; 279918334Speter int status; 280018334Speter int pid; 280118334Speter 280250599Sobrien pid = pwait (commands[i].pid, &status, 0); 280318334Speter if (pid < 0) 280418334Speter abort (); 280518334Speter 280690277Sobrien#ifdef HAVE_GETRUSAGE 280790277Sobrien if (report_times) 280890277Sobrien { 280990277Sobrien /* getrusage returns the total resource usage of all children 281090277Sobrien up to now. Copy the previous values into prus, get the 281190277Sobrien current statistics, then take the difference. */ 281290277Sobrien 281390277Sobrien prus = rus; 281490277Sobrien getrusage (RUSAGE_CHILDREN, &rus); 281590277Sobrien d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec; 281690277Sobrien d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec; 281790277Sobrien ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6; 281890277Sobrien 281990277Sobrien d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec; 282090277Sobrien d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec; 282190277Sobrien st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6; 282290277Sobrien } 282390277Sobrien#endif 282490277Sobrien 282518334Speter for (j = 0; j < n_commands; j++) 282618334Speter if (commands[j].pid == pid) 282718334Speter { 282818334Speter i++; 282990277Sobrien if (WIFSIGNALED (status)) 283018334Speter { 283190277Sobrien#ifdef SIGPIPE 283290277Sobrien /* SIGPIPE is a special case. It happens in -pipe mode 283390277Sobrien when the compiler dies before the preprocessor is 283490277Sobrien done, or the assembler dies before the compiler is 283590277Sobrien done. There's generally been an error already, and 283690277Sobrien this is just fallout. So don't generate another error 283790277Sobrien unless we would otherwise have succeeded. */ 283890277Sobrien if (WTERMSIG (status) == SIGPIPE 283990277Sobrien && (signal_count || greatest_status >= MIN_FATAL_STATUS)) 284090277Sobrien ; 284190277Sobrien else 284290277Sobrien#endif 284390277Sobrien fatal ("\ 284490277SobrienInternal error: %s (program %s)\n\ 284590277SobrienPlease submit a full bug report.\n\ 284690277SobrienSee %s for instructions.", 284790277Sobrien strsignal (WTERMSIG (status)), commands[j].prog, 2848117413Skan bug_report_url); 284990277Sobrien signal_count++; 285090277Sobrien ret_code = -1; 285118334Speter } 285290277Sobrien else if (WIFEXITED (status) 285390277Sobrien && WEXITSTATUS (status) >= MIN_FATAL_STATUS) 285490277Sobrien { 285590277Sobrien if (WEXITSTATUS (status) > greatest_status) 285690277Sobrien greatest_status = WEXITSTATUS (status); 285790277Sobrien ret_code = -1; 285890277Sobrien } 285990277Sobrien#ifdef HAVE_GETRUSAGE 286090277Sobrien if (report_times && ut + st != 0) 286190277Sobrien notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st); 286290277Sobrien#endif 286318334Speter break; 286418334Speter } 286518334Speter } 286618334Speter return ret_code; 286718334Speter } 286818334Speter} 286918334Speter 287018334Speter/* Find all the switches given to us 287118334Speter and make a vector describing them. 287218334Speter The elements of the vector are strings, one per switch given. 287318334Speter If a switch uses following arguments, then the `part1' field 287418334Speter is the switch itself and the `args' field 287518334Speter is a null-terminated vector containing the following arguments. 287690277Sobrien The `live_cond' field is: 287790277Sobrien 0 when initialized 287890277Sobrien 1 if the switch is true in a conditional spec, 287990277Sobrien -1 if false (overridden by a later switch) 2880132733Skan -2 if this switch should be ignored (used in %<S) 288152520Sobrien The `validated' field is nonzero if any spec has looked at this switch; 288218334Speter if it remains zero at the end of the run, it must be meaningless. */ 288318334Speter 288490277Sobrien#define SWITCH_OK 0 288590277Sobrien#define SWITCH_FALSE -1 288690277Sobrien#define SWITCH_IGNORE -2 288790277Sobrien#define SWITCH_LIVE 1 288890277Sobrien 288918334Speterstruct switchstr 289018334Speter{ 289152520Sobrien const char *part1; 289290277Sobrien const char **args; 289318334Speter int live_cond; 289490277Sobrien unsigned char validated; 289590277Sobrien unsigned char ordering; 289618334Speter}; 289718334Speter 289818334Speterstatic struct switchstr *switches; 289918334Speter 290018334Speterstatic int n_switches; 290118334Speter 290218334Speterstruct infile 290318334Speter{ 290452520Sobrien const char *name; 290552520Sobrien const char *language; 290618334Speter}; 290718334Speter 290818334Speter/* Also a vector of input files specified. */ 290918334Speter 291018334Speterstatic struct infile *infiles; 291118334Speter 291290277Sobrienint n_infiles; 291318334Speter 2914132733Skan/* True if multiple input files are being compiled to a single 2915132733Skan assembly file. */ 2916132733Skan 2917132733Skanstatic bool combine_inputs; 2918132733Skan 291952520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that 292050599Sobrien we can tell if there were any user supplied any files or libraries. */ 292150599Sobrien 292250599Sobrienstatic int added_libraries; 292350599Sobrien 292418334Speter/* And a vector of corresponding output files is made up later. */ 292518334Speter 292690277Sobrienconst char **outfiles; 292718334Speter 292850599Sobrien/* Used to track if none of the -B paths are used. */ 292950599Sobrienstatic int warn_B; 293050599Sobrien 293150599Sobrien/* Gives value to pass as "warn" to add_prefix for standard prefixes. */ 293250599Sobrienstatic int *warn_std_ptr = 0; 293350599Sobrien 293490277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 293550599Sobrien 293650599Sobrien/* Convert NAME to a new name if it is the standard suffix. DO_EXE 293790277Sobrien is true if we should look for an executable suffix. DO_OBJ 293890277Sobrien is true if we should look for an object suffix. */ 293950599Sobrien 294090277Sobrienstatic const char * 2941132733Skanconvert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED, 2942132733Skan int do_obj ATTRIBUTE_UNUSED) 294350599Sobrien{ 294490277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 294550599Sobrien int i; 294690277Sobrien#endif 294752520Sobrien int len; 294850599Sobrien 294952520Sobrien if (name == NULL) 295052520Sobrien return NULL; 295190277Sobrien 295252520Sobrien len = strlen (name); 295352520Sobrien 295490277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX 295590277Sobrien /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj". */ 295690277Sobrien if (do_obj && len > 2 295750599Sobrien && name[len - 2] == '.' 295850599Sobrien && name[len - 1] == 'o') 295950599Sobrien { 296050599Sobrien obstack_grow (&obstack, name, len - 2); 296190277Sobrien obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); 296250599Sobrien name = obstack_finish (&obstack); 296350599Sobrien } 296450599Sobrien#endif 296550599Sobrien 296690277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 296750599Sobrien /* If there is no filetype, make it the executable suffix (which includes 296850599Sobrien the "."). But don't get confused if we have just "-o". */ 296990277Sobrien if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-')) 297050599Sobrien return name; 297150599Sobrien 297250599Sobrien for (i = len - 1; i >= 0; i--) 297352520Sobrien if (IS_DIR_SEPARATOR (name[i])) 297450599Sobrien break; 297550599Sobrien 297650599Sobrien for (i++; i < len; i++) 297750599Sobrien if (name[i] == '.') 297850599Sobrien return name; 297950599Sobrien 298050599Sobrien obstack_grow (&obstack, name, len); 298190277Sobrien obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX, 298290277Sobrien strlen (TARGET_EXECUTABLE_SUFFIX)); 298350599Sobrien name = obstack_finish (&obstack); 298450599Sobrien#endif 298550599Sobrien 298650599Sobrien return name; 298750599Sobrien} 298850599Sobrien#endif 298950599Sobrien 299050599Sobrien/* Display the command line switches accepted by gcc. */ 299150599Sobrienstatic void 2992132733Skandisplay_help (void) 299350599Sobrien{ 299490277Sobrien printf (_("Usage: %s [options] file...\n"), programname); 299590277Sobrien fputs (_("Options:\n"), stdout); 299650599Sobrien 299790277Sobrien fputs (_(" -pass-exit-codes Exit with highest error code from a phase\n"), stdout); 299890277Sobrien fputs (_(" --help Display this information\n"), stdout); 299990277Sobrien fputs (_(" --target-help Display target specific command line options\n"), stdout); 300050599Sobrien if (! verbose_flag) 300190277Sobrien fputs (_(" (Use '-v --help' to display command line options of sub-processes)\n"), stdout); 300290277Sobrien fputs (_(" -dumpspecs Display all of the built in spec strings\n"), stdout); 300390277Sobrien fputs (_(" -dumpversion Display the version of the compiler\n"), stdout); 300490277Sobrien fputs (_(" -dumpmachine Display the compiler's target processor\n"), stdout); 300590277Sobrien fputs (_(" -print-search-dirs Display the directories in the compiler's search path\n"), stdout); 300690277Sobrien fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library\n"), stdout); 300790277Sobrien fputs (_(" -print-file-name=<lib> Display the full path to library <lib>\n"), stdout); 300890277Sobrien fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>\n"), stdout); 300990277Sobrien fputs (_(" -print-multi-directory Display the root directory for versions of libgcc\n"), stdout); 301090277Sobrien fputs (_("\ 301190277Sobrien -print-multi-lib Display the mapping between command line options and\n\ 301290277Sobrien multiple library search directories\n"), stdout); 3013104763Skan fputs (_(" -print-multi-os-directory Display the relative path to OS libraries\n"), stdout); 301490277Sobrien fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler\n"), stdout); 301590277Sobrien fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout); 301690277Sobrien fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker\n"), stdout); 3017132733Skan fputs (_(" -Xassembler <arg> Pass <arg> on to the assembler\n"), stdout); 3018132733Skan fputs (_(" -Xpreprocessor <arg> Pass <arg> on to the preprocessor\n"), stdout); 301990277Sobrien fputs (_(" -Xlinker <arg> Pass <arg> on to the linker\n"), stdout); 302090277Sobrien fputs (_(" -save-temps Do not delete intermediate files\n"), stdout); 302190277Sobrien fputs (_(" -pipe Use pipes rather than intermediate files\n"), stdout); 302290277Sobrien fputs (_(" -time Time the execution of each subprocess\n"), stdout); 302390277Sobrien fputs (_(" -specs=<file> Override built-in specs with the contents of <file>\n"), stdout); 302490277Sobrien fputs (_(" -std=<standard> Assume that the input sources are for <standard>\n"), stdout); 302590277Sobrien fputs (_(" -B <directory> Add <directory> to the compiler's search paths\n"), stdout); 302690277Sobrien fputs (_(" -b <machine> Run gcc for target <machine>, if installed\n"), stdout); 302790277Sobrien fputs (_(" -V <version> Run gcc version number <version>, if installed\n"), stdout); 302890277Sobrien fputs (_(" -v Display the programs invoked by the compiler\n"), stdout); 302990277Sobrien fputs (_(" -### Like -v but options quoted and commands not executed\n"), stdout); 303090277Sobrien fputs (_(" -E Preprocess only; do not compile, assemble or link\n"), stdout); 303190277Sobrien fputs (_(" -S Compile only; do not assemble or link\n"), stdout); 303290277Sobrien fputs (_(" -c Compile and assemble, but do not link\n"), stdout); 303390277Sobrien fputs (_(" -o <file> Place the output into <file>\n"), stdout); 303490277Sobrien fputs (_("\ 303590277Sobrien -x <language> Specify the language of the following input files\n\ 3036117413Skan Permissible languages include: c c++ assembler none\n\ 303790277Sobrien 'none' means revert to the default behavior of\n\ 303890277Sobrien guessing the language based on the file's extension\n\ 303990277Sobrien"), stdout); 304050599Sobrien 304190277Sobrien printf (_("\ 304290277Sobrien\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\ 304390277Sobrien passed on to the various sub-processes invoked by %s. In order to pass\n\ 304490277Sobrien other options on to these processes the -W<letter> options must be used.\n\ 304590277Sobrien"), programname); 304650599Sobrien 304750599Sobrien /* The rest of the options are displayed by invocations of the various 304850599Sobrien sub-processes. */ 304950599Sobrien} 305050599Sobrien 305190277Sobrienstatic void 3052132733Skanadd_preprocessor_option (const char *option, int len) 305390277Sobrien{ 305452520Sobrien n_preprocessor_options++; 305590277Sobrien 305652520Sobrien if (! preprocessor_options) 3057132733Skan preprocessor_options = xmalloc (n_preprocessor_options * sizeof (char *)); 305852520Sobrien else 3059132733Skan preprocessor_options = xrealloc (preprocessor_options, 3060132733Skan n_preprocessor_options * sizeof (char *)); 306190277Sobrien 306252520Sobrien preprocessor_options [n_preprocessor_options - 1] = 306352520Sobrien save_string (option, len); 306450599Sobrien} 306590277Sobrien 306690277Sobrienstatic void 3067132733Skanadd_assembler_option (const char *option, int len) 306852520Sobrien{ 306952520Sobrien n_assembler_options++; 307052520Sobrien 307152520Sobrien if (! assembler_options) 3072132733Skan assembler_options = xmalloc (n_assembler_options * sizeof (char *)); 307352520Sobrien else 3074132733Skan assembler_options = xrealloc (assembler_options, 3075132733Skan n_assembler_options * sizeof (char *)); 307652520Sobrien 307752520Sobrien assembler_options [n_assembler_options - 1] = save_string (option, len); 307850599Sobrien} 307990277Sobrien 308090277Sobrienstatic void 3081132733Skanadd_linker_option (const char *option, int len) 308252520Sobrien{ 308352520Sobrien n_linker_options++; 308452520Sobrien 308552520Sobrien if (! linker_options) 3086132733Skan linker_options = xmalloc (n_linker_options * sizeof (char *)); 308752520Sobrien else 3088132733Skan linker_options = xrealloc (linker_options, 3089132733Skan n_linker_options * sizeof (char *)); 309052520Sobrien 309152520Sobrien linker_options [n_linker_options - 1] = save_string (option, len); 309250599Sobrien} 309350599Sobrien 309418334Speter/* Create the vector `switches' and its contents. 309518334Speter Store its length in `n_switches'. */ 309618334Speter 309718334Speterstatic void 3098132733Skanprocess_command (int argc, const char **argv) 309918334Speter{ 310090277Sobrien int i; 310152520Sobrien const char *temp; 310252520Sobrien char *temp1; 310390277Sobrien const char *spec_lang = 0; 310418334Speter int last_language_n_infiles; 310550599Sobrien int have_c = 0; 310650599Sobrien int have_o = 0; 310750599Sobrien int lang_n_infiles = 0; 310890277Sobrien#ifdef MODIFY_TARGET_NAME 310990277Sobrien int is_modify_target_name; 311090277Sobrien int j; 311190277Sobrien#endif 311218334Speter 3113117413Skan GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX"); 311418334Speter 311518334Speter n_switches = 0; 311618334Speter n_infiles = 0; 311750599Sobrien added_libraries = 0; 311818334Speter 311918334Speter /* Figure compiler version from version string. */ 312018334Speter 312190277Sobrien compiler_version = temp1 = xstrdup (version_string); 312290277Sobrien 312352520Sobrien for (; *temp1; ++temp1) 312418334Speter { 312552520Sobrien if (*temp1 == ' ') 312618334Speter { 312752520Sobrien *temp1 = '\0'; 312818334Speter break; 312918334Speter } 313018334Speter } 313118334Speter 3132117413Skan /* If there is a -V or -b option (or both), process it now, before 3133117413Skan trying to interpret the rest of the command line. */ 3134117413Skan if (argc > 1 && argv[1][0] == '-' 3135117413Skan && (argv[1][1] == 'V' || argv[1][1] == 'b')) 3136117413Skan { 3137117413Skan const char *new_version = DEFAULT_TARGET_VERSION; 3138117413Skan const char *new_machine = DEFAULT_TARGET_MACHINE; 3139117413Skan const char *progname = argv[0]; 3140117413Skan char **new_argv; 3141117413Skan char *new_argv0; 3142117413Skan int baselen; 3143132733Skan 3144117413Skan while (argc > 1 && argv[1][0] == '-' 3145117413Skan && (argv[1][1] == 'V' || argv[1][1] == 'b')) 3146117413Skan { 3147117413Skan char opt = argv[1][1]; 3148117413Skan const char *arg; 3149117413Skan if (argv[1][2] != '\0') 3150117413Skan { 3151117413Skan arg = argv[1] + 2; 3152117413Skan argc -= 1; 3153117413Skan argv += 1; 3154117413Skan } 3155117413Skan else if (argc > 2) 3156117413Skan { 3157117413Skan arg = argv[2]; 3158117413Skan argc -= 2; 3159117413Skan argv += 2; 3160117413Skan } 3161117413Skan else 3162117413Skan fatal ("`-%c' option must have argument", opt); 3163117413Skan if (opt == 'V') 3164117413Skan new_version = arg; 3165117413Skan else 3166117413Skan new_machine = arg; 3167117413Skan } 3168117413Skan 3169117413Skan for (baselen = strlen (progname); baselen > 0; baselen--) 3170117413Skan if (IS_DIR_SEPARATOR (progname[baselen-1])) 3171117413Skan break; 3172132733Skan new_argv0 = xmemdup (progname, baselen, 3173117413Skan baselen + concat_length (new_version, new_machine, 3174117413Skan "-gcc-", NULL) + 1); 3175117413Skan strcpy (new_argv0 + baselen, new_machine); 3176117413Skan strcat (new_argv0, "-gcc-"); 3177117413Skan strcat (new_argv0, new_version); 3178117413Skan 3179117413Skan new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]), 3180117413Skan (argc + 1) * sizeof (argv[0])); 3181117413Skan new_argv[0] = new_argv0; 3182117413Skan 3183117413Skan execvp (new_argv0, new_argv); 3184117413Skan fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno)); 3185117413Skan } 3186117413Skan 318790277Sobrien /* Set up the default search paths. If there is no GCC_EXEC_PREFIX, 318890277Sobrien see if we can create it from the pathname specified in argv[0]. */ 318918334Speter 3190132733Skan gcc_libexec_prefix = standard_libexec_prefix; 319196736Sru#ifndef FREEBSD_NATIVE 319290277Sobrien#ifndef VMS 319390277Sobrien /* FIXME: make_relative_prefix doesn't yet work for VMS. */ 319490277Sobrien if (!gcc_exec_prefix) 319590277Sobrien { 319690277Sobrien gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix, 319790277Sobrien standard_exec_prefix); 3198132733Skan gcc_libexec_prefix = make_relative_prefix (argv[0], 3199132733Skan standard_bindir_prefix, 3200132733Skan standard_libexec_prefix); 320190277Sobrien if (gcc_exec_prefix) 320290277Sobrien putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL)); 320390277Sobrien } 3204132733Skan else 3205132733Skan gcc_libexec_prefix = make_relative_prefix (gcc_exec_prefix, 3206132733Skan standard_exec_prefix, 3207132733Skan standard_libexec_prefix); 3208132733Skan#else 320990277Sobrien#endif 321096736Sru#endif /* not FREEBSD_NATIVE */ 321190277Sobrien 321218334Speter if (gcc_exec_prefix) 321318334Speter { 321450599Sobrien int len = strlen (gcc_exec_prefix); 321590277Sobrien 3216132733Skan if (len > (int) sizeof ("/lib/gcc/") - 1 321752520Sobrien && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1]))) 321850599Sobrien { 3219132733Skan temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1; 322052520Sobrien if (IS_DIR_SEPARATOR (*temp) 322190277Sobrien && strncmp (temp + 1, "lib", 3) == 0 322252520Sobrien && IS_DIR_SEPARATOR (temp[4]) 3223132733Skan && strncmp (temp + 5, "gcc", 3) == 0) 3224132733Skan len -= sizeof ("/lib/gcc/") - 1; 322550599Sobrien } 322650599Sobrien 322750599Sobrien set_std_prefix (gcc_exec_prefix, len); 3228132733Skan add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC", 3229104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 323090277Sobrien add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 3231104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 323218334Speter } 323318334Speter 323418334Speter /* COMPILER_PATH and LIBRARY_PATH have values 323518334Speter that are lists of directory names with colons. */ 323618334Speter 3237117413Skan GET_ENVIRONMENT (temp, "COMPILER_PATH"); 323818334Speter if (temp) 323918334Speter { 324052520Sobrien const char *startp, *endp; 3241132733Skan char *nstore = alloca (strlen (temp) + 3); 324218334Speter 324318334Speter startp = endp = temp; 324418334Speter while (1) 324518334Speter { 324618334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 324718334Speter { 324890277Sobrien strncpy (nstore, startp, endp - startp); 324918334Speter if (endp == startp) 325090277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 325152520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 325218334Speter { 325390277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 325490277Sobrien nstore[endp - startp + 1] = 0; 325518334Speter } 325618334Speter else 325790277Sobrien nstore[endp - startp] = 0; 325890277Sobrien add_prefix (&exec_prefixes, nstore, 0, 3259104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 326050599Sobrien add_prefix (&include_prefixes, 326190277Sobrien concat (nstore, "include", NULL), 3262104763Skan 0, PREFIX_PRIORITY_LAST, 0, NULL, 0); 326318334Speter if (*endp == 0) 326418334Speter break; 326518334Speter endp = startp = endp + 1; 326618334Speter } 326718334Speter else 326818334Speter endp++; 326918334Speter } 327018334Speter } 327118334Speter 3272117413Skan GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV); 327391651Sobrien if (temp && *cross_compile == '0') 327418334Speter { 327552520Sobrien const char *startp, *endp; 3276132733Skan char *nstore = alloca (strlen (temp) + 3); 327718334Speter 327818334Speter startp = endp = temp; 327918334Speter while (1) 328018334Speter { 328118334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 328218334Speter { 328390277Sobrien strncpy (nstore, startp, endp - startp); 328418334Speter if (endp == startp) 328590277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 328652520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 328718334Speter { 328890277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 328990277Sobrien nstore[endp - startp + 1] = 0; 329018334Speter } 329118334Speter else 329290277Sobrien nstore[endp - startp] = 0; 329390277Sobrien add_prefix (&startfile_prefixes, nstore, NULL, 3294104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 329518334Speter if (*endp == 0) 329618334Speter break; 329718334Speter endp = startp = endp + 1; 329818334Speter } 329918334Speter else 330018334Speter endp++; 330118334Speter } 330218334Speter } 330318334Speter 330418334Speter /* Use LPATH like LIBRARY_PATH (for the CMU build program). */ 3305117413Skan GET_ENVIRONMENT (temp, "LPATH"); 330650599Sobrien if (temp && *cross_compile == '0') 330718334Speter { 330852520Sobrien const char *startp, *endp; 3309132733Skan char *nstore = alloca (strlen (temp) + 3); 331018334Speter 331118334Speter startp = endp = temp; 331218334Speter while (1) 331318334Speter { 331418334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 331518334Speter { 331690277Sobrien strncpy (nstore, startp, endp - startp); 331718334Speter if (endp == startp) 331890277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 331952520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 332018334Speter { 332190277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 332290277Sobrien nstore[endp - startp + 1] = 0; 332318334Speter } 332418334Speter else 332590277Sobrien nstore[endp - startp] = 0; 332690277Sobrien add_prefix (&startfile_prefixes, nstore, NULL, 3327104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 332818334Speter if (*endp == 0) 332918334Speter break; 333018334Speter endp = startp = endp + 1; 333118334Speter } 333218334Speter else 333318334Speter endp++; 333418334Speter } 333518334Speter } 333618334Speter 333777389Sobrien /* Options specified as if they appeared on the command line. */ 333877389Sobrien temp = getenv ("GCC_OPTIONS"); 333977389Sobrien if ((temp) && (strlen (temp) > 0)) 334077389Sobrien { 334177389Sobrien int len; 334277389Sobrien int optc = 1; 334377389Sobrien int new_argc; 3344110024Sobrien const char **new_argv; 334577389Sobrien char *envopts; 334677389Sobrien 334777389Sobrien while (isspace (*temp)) 334877389Sobrien temp++; 334977389Sobrien len = strlen (temp); 335077389Sobrien envopts = (char *) xmalloc (len + 1); 335177389Sobrien strcpy (envopts, temp); 335277389Sobrien 335377389Sobrien for (i = 0; i < (len - 1); i++) 335477389Sobrien if ((isspace (envopts[i])) && ! (isspace (envopts[i+1]))) 335577389Sobrien optc++; 335677389Sobrien 3357110024Sobrien new_argv = (const char **) alloca ((optc + argc) * sizeof(char *)); 335877389Sobrien 335977389Sobrien for (i = 0, new_argc = 1; new_argc <= optc; new_argc++) 336077389Sobrien { 336177389Sobrien while (isspace (envopts[i])) 336277389Sobrien i++; 336377389Sobrien new_argv[new_argc] = envopts + i; 336477389Sobrien while (!isspace (envopts[i]) && (envopts[i] != '\0')) 336577389Sobrien i++; 336677389Sobrien envopts[i++] = '\0'; 336777389Sobrien } 336877389Sobrien for (i = 1; i < argc; i++) 336977389Sobrien new_argv[new_argc++] = argv[i]; 337077389Sobrien 337177389Sobrien argv = new_argv; 337277389Sobrien argc = new_argc; 337377389Sobrien } 337477389Sobrien 337518334Speter /* Convert new-style -- options to old-style. */ 3376132733Skan translate_options (&argc, (const char *const **) &argv); 337718334Speter 337850599Sobrien /* Do language-specific adjustment/addition of flags. */ 3379132733Skan lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries); 338050599Sobrien 338118334Speter /* Scan argv twice. Here, the first time, just count how many switches 338218334Speter there will be in their vector, and how many input files in theirs. 338318334Speter Here we also parse the switches that cc itself uses (e.g. -v). */ 338418334Speter 338518334Speter for (i = 1; i < argc; i++) 338618334Speter { 338718334Speter if (! strcmp (argv[i], "-dumpspecs")) 338818334Speter { 338950599Sobrien struct spec_list *sl; 339050599Sobrien init_spec (); 339150599Sobrien for (sl = specs; sl; sl = sl->next) 339250599Sobrien printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec)); 339390277Sobrien if (link_command_spec) 339490277Sobrien printf ("*link_command:\n%s\n\n", link_command_spec); 339518334Speter exit (0); 339618334Speter } 339718334Speter else if (! strcmp (argv[i], "-dumpversion")) 339818334Speter { 339950599Sobrien printf ("%s\n", spec_version); 340018334Speter exit (0); 340118334Speter } 340218334Speter else if (! strcmp (argv[i], "-dumpmachine")) 340318334Speter { 340418334Speter printf ("%s\n", spec_machine); 340590277Sobrien exit (0); 340618334Speter } 340790277Sobrien else if (strcmp (argv[i], "-fversion") == 0) 340890277Sobrien { 340990277Sobrien /* translate_options () has turned --version into -fversion. */ 341090277Sobrien printf (_("%s (GCC) %s\n"), programname, version_string); 3411161660Skan printf ("Copyright %s 2006 Free Software Foundation, Inc.\n", 3412132733Skan _("(C)")); 341390277Sobrien fputs (_("This is free software; see the source for copying conditions. There is NO\n\ 341490277Sobrienwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"), 341590277Sobrien stdout); 341690277Sobrien exit (0); 341790277Sobrien } 341850599Sobrien else if (strcmp (argv[i], "-fhelp") == 0) 341950599Sobrien { 342050599Sobrien /* translate_options () has turned --help into -fhelp. */ 342150599Sobrien print_help_list = 1; 342250599Sobrien 342350599Sobrien /* We will be passing a dummy file on to the sub-processes. */ 342450599Sobrien n_infiles++; 342550599Sobrien n_switches++; 342690277Sobrien 342790277Sobrien /* CPP driver cannot obtain switch from cc1_options. */ 342890277Sobrien if (is_cpp_driver) 342990277Sobrien add_preprocessor_option ("--help", 6); 343050599Sobrien add_assembler_option ("--help", 6); 343150599Sobrien add_linker_option ("--help", 6); 343250599Sobrien } 343390277Sobrien else if (strcmp (argv[i], "-ftarget-help") == 0) 3434117413Skan { 3435117413Skan /* translate_options() has turned --target-help into -ftarget-help. */ 3436117413Skan target_help_flag = 1; 343790277Sobrien 3438117413Skan /* We will be passing a dummy file on to the sub-processes. */ 3439117413Skan n_infiles++; 3440117413Skan n_switches++; 344190277Sobrien 344290277Sobrien /* CPP driver cannot obtain switch from cc1_options. */ 344390277Sobrien if (is_cpp_driver) 344490277Sobrien add_preprocessor_option ("--target-help", 13); 3445117413Skan add_assembler_option ("--target-help", 13); 3446117413Skan add_linker_option ("--target-help", 13); 3447117413Skan } 344890277Sobrien else if (! strcmp (argv[i], "-pass-exit-codes")) 344990277Sobrien { 345090277Sobrien pass_exit_codes = 1; 345190277Sobrien n_switches++; 345290277Sobrien } 345318334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 345418334Speter print_search_dirs = 1; 345518334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 345618334Speter print_file_name = "libgcc.a"; 345718334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 345818334Speter print_file_name = argv[i] + 17; 345918334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 346018334Speter print_prog_name = argv[i] + 17; 346118334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 346218334Speter print_multi_lib = 1; 346318334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 346418334Speter print_multi_directory = 1; 3465104763Skan else if (! strcmp (argv[i], "-print-multi-os-directory")) 3466104763Skan print_multi_os_directory = 1; 346718334Speter else if (! strncmp (argv[i], "-Wa,", 4)) 346818334Speter { 346918334Speter int prev, j; 347018334Speter /* Pass the rest of this option to the assembler. */ 347118334Speter 347218334Speter /* Split the argument at commas. */ 347318334Speter prev = 4; 347418334Speter for (j = 4; argv[i][j]; j++) 347518334Speter if (argv[i][j] == ',') 347618334Speter { 347750599Sobrien add_assembler_option (argv[i] + prev, j - prev); 347818334Speter prev = j + 1; 347918334Speter } 348090277Sobrien 348118334Speter /* Record the part after the last comma. */ 348250599Sobrien add_assembler_option (argv[i] + prev, j - prev); 348318334Speter } 348418334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 348518334Speter { 348618334Speter int prev, j; 348718334Speter /* Pass the rest of this option to the preprocessor. */ 348818334Speter 348918334Speter /* Split the argument at commas. */ 349018334Speter prev = 4; 349118334Speter for (j = 4; argv[i][j]; j++) 349218334Speter if (argv[i][j] == ',') 349318334Speter { 349450599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 349518334Speter prev = j + 1; 349618334Speter } 349790277Sobrien 349818334Speter /* Record the part after the last comma. */ 349950599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 350018334Speter } 350118334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 350218334Speter /* The +e options to the C++ front-end. */ 350318334Speter n_switches++; 350418334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 350518334Speter { 350618334Speter int j; 350718334Speter /* Split the argument at commas. */ 350818334Speter for (j = 3; argv[i][j]; j++) 350918334Speter n_infiles += (argv[i][j] == ','); 351018334Speter } 351118334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 351218334Speter { 351318334Speter if (i + 1 == argc) 351418334Speter fatal ("argument to `-Xlinker' is missing"); 351518334Speter 351618334Speter n_infiles++; 351718334Speter i++; 351818334Speter } 3519132733Skan else if (strcmp (argv[i], "-Xpreprocessor") == 0) 3520132733Skan { 3521132733Skan if (i + 1 == argc) 3522132733Skan fatal ("argument to `-Xpreprocessor' is missing"); 3523132733Skan 3524132733Skan add_preprocessor_option (argv[i+1], strlen (argv[i+1])); 3525132733Skan } 3526132733Skan else if (strcmp (argv[i], "-Xassembler") == 0) 3527132733Skan { 3528132733Skan if (i + 1 == argc) 3529132733Skan fatal ("argument to `-Xassembler' is missing"); 3530132733Skan 3531132733Skan add_assembler_option (argv[i+1], strlen (argv[i+1])); 3532132733Skan } 353377389Sobrien else if (strcmp (argv[i], "-l") == 0) 353477389Sobrien { 353577389Sobrien if (i + 1 == argc) 353677389Sobrien fatal ("argument to `-l' is missing"); 353777389Sobrien 353877389Sobrien n_infiles++; 353977389Sobrien i++; 354077389Sobrien } 354118334Speter else if (strncmp (argv[i], "-l", 2) == 0) 354218334Speter n_infiles++; 354350599Sobrien else if (strcmp (argv[i], "-save-temps") == 0) 354450599Sobrien { 354550599Sobrien save_temps_flag = 1; 354650599Sobrien n_switches++; 354750599Sobrien } 354850599Sobrien else if (strcmp (argv[i], "-specs") == 0) 354950599Sobrien { 3550132733Skan struct user_specs *user = xmalloc (sizeof (struct user_specs)); 355150599Sobrien if (++i >= argc) 355250599Sobrien fatal ("argument to `-specs' is missing"); 355350599Sobrien 355490277Sobrien user->next = (struct user_specs *) 0; 355550599Sobrien user->filename = argv[i]; 355650599Sobrien if (user_specs_tail) 355750599Sobrien user_specs_tail->next = user; 355850599Sobrien else 355950599Sobrien user_specs_head = user; 356050599Sobrien user_specs_tail = user; 356150599Sobrien } 356250599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 356350599Sobrien { 3564132733Skan struct user_specs *user = xmalloc (sizeof (struct user_specs)); 356550599Sobrien if (strlen (argv[i]) == 7) 356650599Sobrien fatal ("argument to `-specs=' is missing"); 356750599Sobrien 356890277Sobrien user->next = (struct user_specs *) 0; 356990277Sobrien user->filename = argv[i] + 7; 357050599Sobrien if (user_specs_tail) 357150599Sobrien user_specs_tail->next = user; 357250599Sobrien else 357350599Sobrien user_specs_head = user; 357450599Sobrien user_specs_tail = user; 357550599Sobrien } 357690277Sobrien else if (strcmp (argv[i], "-time") == 0) 357790277Sobrien report_times = 1; 3578132733Skan else if (strcmp (argv[i], "-pipe") == 0) 3579132733Skan { 3580132733Skan /* -pipe has to go into the switches array as well as 3581132733Skan setting a flag. */ 3582132733Skan use_pipes = 1; 3583132733Skan n_switches++; 3584132733Skan } 358590277Sobrien else if (strcmp (argv[i], "-###") == 0) 358690277Sobrien { 358790277Sobrien /* This is similar to -v except that there is no execution 358890277Sobrien of the commands and the echoed arguments are quoted. It 358990277Sobrien is intended for use in shell scripts to capture the 359090277Sobrien driver-generated command line. */ 359190277Sobrien verbose_only_flag++; 359290277Sobrien verbose_flag++; 359390277Sobrien } 359418334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 359518334Speter { 359690277Sobrien const char *p = &argv[i][1]; 359790277Sobrien int c = *p; 359818334Speter 359918334Speter switch (c) 360018334Speter { 360118334Speter case 'b': 3602117413Skan case 'V': 3603117413Skan fatal ("`-%c' must come at the start of the command line", c); 360418334Speter break; 360518334Speter 360618334Speter case 'B': 360718334Speter { 360890277Sobrien const char *value; 360990277Sobrien int len; 361090277Sobrien 361118334Speter if (p[1] == 0 && i + 1 == argc) 361218334Speter fatal ("argument to `-B' is missing"); 361318334Speter if (p[1] == 0) 361418334Speter value = argv[++i]; 361518334Speter else 361618334Speter value = p + 1; 361718334Speter 361890277Sobrien len = strlen (value); 361990277Sobrien 362090277Sobrien /* Catch the case where the user has forgotten to append a 362190277Sobrien directory separator to the path. Note, they may be using 362290277Sobrien -B to add an executable name prefix, eg "i386-elf-", in 362390277Sobrien order to distinguish between multiple installations of 362490277Sobrien GCC in the same directory. Hence we must check to see 362590277Sobrien if appending a directory separator actually makes a 362690277Sobrien valid directory name. */ 362790277Sobrien if (! IS_DIR_SEPARATOR (value [len - 1]) 362890277Sobrien && is_directory (value, "", 0)) 362990277Sobrien { 363090277Sobrien char *tmp = xmalloc (len + 2); 363190277Sobrien strcpy (tmp, value); 363290277Sobrien tmp[len] = DIR_SEPARATOR; 363390277Sobrien tmp[++ len] = 0; 363490277Sobrien value = tmp; 363590277Sobrien } 3636117413Skan 363790277Sobrien /* As a kludge, if the arg is "[foo/]stageN/", just 363890277Sobrien add "[foo/]include" to the include prefix. */ 363990277Sobrien if ((len == 7 364090277Sobrien || (len > 7 364190277Sobrien && (IS_DIR_SEPARATOR (value[len - 8])))) 364290277Sobrien && strncmp (value + len - 7, "stage", 5) == 0 364390277Sobrien && ISDIGIT (value[len - 2]) 364490277Sobrien && (IS_DIR_SEPARATOR (value[len - 1]))) 364590277Sobrien { 364690277Sobrien if (len == 7) 364790277Sobrien add_prefix (&include_prefixes, "include", NULL, 3648104763Skan PREFIX_PRIORITY_B_OPT, 0, NULL, 0); 364990277Sobrien else 365090277Sobrien { 365190277Sobrien char * string = xmalloc (len + 1); 365290277Sobrien 365390277Sobrien strncpy (string, value, len - 7); 365490277Sobrien strcpy (string + len - 7, "include"); 365590277Sobrien add_prefix (&include_prefixes, string, NULL, 3656104763Skan PREFIX_PRIORITY_B_OPT, 0, NULL, 0); 365790277Sobrien } 365890277Sobrien } 365990277Sobrien 366090277Sobrien add_prefix (&exec_prefixes, value, NULL, 3661104763Skan PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0); 366290277Sobrien add_prefix (&startfile_prefixes, value, NULL, 3663104763Skan PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0); 366490277Sobrien add_prefix (&include_prefixes, concat (value, "include", NULL), 3665104763Skan NULL, PREFIX_PRIORITY_B_OPT, 0, NULL, 0); 366690277Sobrien n_switches++; 366718334Speter } 366818334Speter break; 366918334Speter 367018334Speter case 'v': /* Print our subcommands and print versions. */ 367118334Speter n_switches++; 367218334Speter /* If they do anything other than exactly `-v', don't set 367318334Speter verbose_flag; rather, continue on to give the error. */ 367418334Speter if (p[1] != 0) 367518334Speter break; 367618334Speter verbose_flag++; 367718334Speter break; 367818334Speter 367950599Sobrien case 'S': 368050599Sobrien case 'c': 368150599Sobrien if (p[1] == 0) 368218334Speter { 368350599Sobrien have_c = 1; 368418334Speter n_switches++; 368518334Speter break; 368618334Speter } 368750599Sobrien goto normal_switch; 368850599Sobrien 368950599Sobrien case 'o': 369050599Sobrien have_o = 1; 369190277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 369250599Sobrien if (! have_c) 369350599Sobrien { 369450599Sobrien int skip; 369590277Sobrien 369650599Sobrien /* Forward scan, just in case -S or -c is specified 369750599Sobrien after -o. */ 369850599Sobrien int j = i + 1; 369950599Sobrien if (p[1] == 0) 370050599Sobrien ++j; 370150599Sobrien while (j < argc) 370250599Sobrien { 370350599Sobrien if (argv[j][0] == '-') 370450599Sobrien { 370550599Sobrien if (SWITCH_CURTAILS_COMPILATION (argv[j][1]) 370650599Sobrien && argv[j][2] == 0) 370750599Sobrien { 370850599Sobrien have_c = 1; 370950599Sobrien break; 371050599Sobrien } 371190277Sobrien else if ((skip = SWITCH_TAKES_ARG (argv[j][1]))) 371250599Sobrien j += skip - (argv[j][2] != 0); 371390277Sobrien else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1))) 371450599Sobrien j += skip; 371550599Sobrien } 371650599Sobrien j++; 371750599Sobrien } 371850599Sobrien } 371950599Sobrien#endif 372090277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX) 372150599Sobrien if (p[1] == 0) 372290277Sobrien argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0); 372350599Sobrien else 372490277Sobrien argv[i] = convert_filename (argv[i], ! have_c, 0); 372550599Sobrien#endif 372650599Sobrien goto normal_switch; 372750599Sobrien 372818334Speter default: 372950599Sobrien normal_switch: 373090277Sobrien 373190277Sobrien#ifdef MODIFY_TARGET_NAME 373290277Sobrien is_modify_target_name = 0; 373390277Sobrien 3734117413Skan for (j = 0; j < ARRAY_SIZE (modify_target); j++) 373590277Sobrien if (! strcmp (argv[i], modify_target[j].sw)) 373690277Sobrien { 3737132733Skan char *new_name = xmalloc (strlen (modify_target[j].str) 3738132733Skan + strlen (spec_machine)); 373990277Sobrien const char *p, *r; 374090277Sobrien char *q; 374190277Sobrien int made_addition = 0; 374290277Sobrien 374390277Sobrien is_modify_target_name = 1; 374490277Sobrien for (p = spec_machine, q = new_name; *p != 0; ) 374590277Sobrien { 374690277Sobrien if (modify_target[j].add_del == DELETE 374790277Sobrien && (! strncmp (q, modify_target[j].str, 374890277Sobrien strlen (modify_target[j].str)))) 374990277Sobrien p += strlen (modify_target[j].str); 375090277Sobrien else if (modify_target[j].add_del == ADD 375190277Sobrien && ! made_addition && *p == '-') 375290277Sobrien { 375390277Sobrien for (r = modify_target[j].str; *r != 0; ) 375490277Sobrien *q++ = *r++; 375590277Sobrien made_addition = 1; 375690277Sobrien } 375790277Sobrien 375890277Sobrien *q++ = *p++; 375990277Sobrien } 376090277Sobrien 376190277Sobrien spec_machine = new_name; 376290277Sobrien } 376390277Sobrien 376490277Sobrien if (is_modify_target_name) 376590277Sobrien break; 3766117413Skan#endif 376790277Sobrien 376818334Speter n_switches++; 376918334Speter 377018334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 377118334Speter i += SWITCH_TAKES_ARG (c) - (p[1] != 0); 377218334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 377318334Speter i += WORD_SWITCH_TAKES_ARG (p); 377418334Speter } 377518334Speter } 377618334Speter else 377750599Sobrien { 377850599Sobrien n_infiles++; 377950599Sobrien lang_n_infiles++; 378050599Sobrien } 378118334Speter } 378218334Speter 3783132733Skan combine_inputs = (have_c && have_o && lang_n_infiles > 1); 378450599Sobrien 3785132733Skan if ((save_temps_flag || report_times) && use_pipes) 3786132733Skan { 3787132733Skan /* -save-temps overrides -pipe, so that temp files are produced */ 3788132733Skan if (save_temps_flag) 3789132733Skan error ("warning: -pipe ignored because -save-temps specified"); 3790132733Skan /* -time overrides -pipe because we can't get correct stats when 3791132733Skan multiple children are running at once. */ 3792132733Skan else if (report_times) 3793132733Skan error ("warning: -pipe ignored because -time specified"); 3794132733Skan 3795132733Skan use_pipes = 0; 3796132733Skan } 3797132733Skan 379818334Speter /* Set up the search paths before we go looking for config files. */ 379918334Speter 380018334Speter /* These come before the md prefixes so that we will find gcc's subcommands 380118334Speter (such as cpp) rather than those of the host system. */ 380218334Speter /* Use 2 as fourth arg meaning try just the machine as a suffix, 380318334Speter as well as trying the machine and the version. */ 380418346Speter#ifdef FREEBSD_NATIVE 3805104953Sobrien add_prefix (&exec_prefixes, PREFIX"/bin/", "BINUTILS", 3806122632Skan PREFIX_PRIORITY_LAST, 0, warn_std_ptr, 0); 380791561Sobrien#endif /* FREEBSD_NATIVE */ 380818334Speter#ifndef OS2 3809132733Skan add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC", 3810104763Skan PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); 3811132733Skan add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS", 3812132733Skan PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); 3813132733Skan#ifndef FREEBSD_NATIVE 381450599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", 3815104763Skan PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); 381650599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS", 3817104763Skan PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); 3818132733Skan add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS", 3819132733Skan PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); 3820132733Skan#endif /* FREEBSD_NATIVE */ 382118334Speter#endif 382218334Speter 382391578Sobrien#ifndef FREEBSD_NATIVE 382450599Sobrien add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", 3825104763Skan PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); 3826132733Skan add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS", 3827104763Skan PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); 382891561Sobrien#endif /* not FREEBSD_NATIVE */ 382918334Speter 383090277Sobrien tooldir_prefix = concat (tooldir_base_prefix, spec_machine, 383190277Sobrien dir_separator_str, NULL); 383218334Speter 383318334Speter /* If tooldir is relative, base it on exec_prefixes. A relative 383418334Speter tooldir lets us move the installed tree as a unit. 383518334Speter 383618334Speter If GCC_EXEC_PREFIX is defined, then we want to add two relative 383718334Speter directories, so that we can search both the user specified directory 383818334Speter and the standard place. */ 383918334Speter 3840132733Skan if (!IS_ABSOLUTE_PATH (tooldir_prefix)) 384118334Speter { 384218334Speter if (gcc_exec_prefix) 384318334Speter { 384418334Speter char *gcc_exec_tooldir_prefix 384550599Sobrien = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 384690277Sobrien spec_version, dir_separator_str, tooldir_prefix, NULL); 384718334Speter 384818334Speter add_prefix (&exec_prefixes, 384990277Sobrien concat (gcc_exec_tooldir_prefix, "bin", 385090277Sobrien dir_separator_str, NULL), 3851104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 0); 385218334Speter add_prefix (&startfile_prefixes, 385390277Sobrien concat (gcc_exec_tooldir_prefix, "lib", 385490277Sobrien dir_separator_str, NULL), 3855104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); 385618334Speter } 385718334Speter 385850599Sobrien tooldir_prefix = concat (standard_exec_prefix, spec_machine, 385990277Sobrien dir_separator_str, spec_version, 386090277Sobrien dir_separator_str, tooldir_prefix, NULL); 386118334Speter } 386218334Speter 386318346Speter#ifndef FREEBSD_NATIVE 386490277Sobrien add_prefix (&exec_prefixes, 386590277Sobrien concat (tooldir_prefix, "bin", dir_separator_str, NULL), 3866104763Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 0); 386718334Speter add_prefix (&startfile_prefixes, 386890277Sobrien concat (tooldir_prefix, "lib", dir_separator_str, NULL), 3869104763Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); 3870132733Skan 3871132733Skan#if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS) 3872132733Skan /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix, 3873132733Skan then consider it to relocate with the rest of the GCC installation 3874132733Skan if GCC_EXEC_PREFIX is set. 3875132733Skan ``make_relative_prefix'' is not compiled for VMS, so don't call it. */ 3876132733Skan if (target_system_root && gcc_exec_prefix) 3877132733Skan { 3878132733Skan char *tmp_prefix = make_relative_prefix (argv[0], 3879132733Skan standard_bindir_prefix, 3880132733Skan target_system_root); 3881132733Skan if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0) 3882132733Skan { 3883132733Skan target_system_root = tmp_prefix; 3884132733Skan target_system_root_changed = 1; 3885132733Skan } 3886132733Skan } 3887132733Skan#endif 388818346Speter#endif /* FREEBSD_NATIVE */ 388918334Speter 389018334Speter /* More prefixes are enabled in main, after we read the specs file 389118334Speter and determine whether this is cross-compilation or not. */ 389218334Speter 389318334Speter /* Then create the space for the vectors and scan again. */ 389418334Speter 3895132733Skan switches = xmalloc ((n_switches + 1) * sizeof (struct switchstr)); 3896132733Skan infiles = xmalloc ((n_infiles + 1) * sizeof (struct infile)); 389718334Speter n_switches = 0; 389818334Speter n_infiles = 0; 389918334Speter last_language_n_infiles = -1; 390018334Speter 390118334Speter /* This, time, copy the text of each switch and store a pointer 390218334Speter to the copy in the vector of switches. 390318334Speter Store all the infiles in their vector. */ 390418334Speter 390518334Speter for (i = 1; i < argc; i++) 390618334Speter { 390718334Speter /* Just skip the switches that were handled by the preceding loop. */ 390890277Sobrien#ifdef MODIFY_TARGET_NAME 390990277Sobrien is_modify_target_name = 0; 391090277Sobrien 3911117413Skan for (j = 0; j < ARRAY_SIZE (modify_target); j++) 391290277Sobrien if (! strcmp (argv[i], modify_target[j].sw)) 391390277Sobrien is_modify_target_name = 1; 391490277Sobrien 391590277Sobrien if (is_modify_target_name) 391690277Sobrien ; 391790277Sobrien else 391890277Sobrien#endif 391918334Speter if (! strncmp (argv[i], "-Wa,", 4)) 392018334Speter ; 392118334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 392218334Speter ; 392390277Sobrien else if (! strcmp (argv[i], "-pass-exit-codes")) 392490277Sobrien ; 392518334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 392618334Speter ; 392718334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 392818334Speter ; 392918334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 393018334Speter ; 393118334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 393218334Speter ; 393318334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 393418334Speter ; 393518334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 393618334Speter ; 3937104763Skan else if (! strcmp (argv[i], "-print-multi-os-directory")) 3938104763Skan ; 393990277Sobrien else if (! strcmp (argv[i], "-ftarget-help")) 394090277Sobrien ; 394190277Sobrien else if (! strcmp (argv[i], "-fhelp")) 394290277Sobrien ; 394318334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 394418334Speter { 394518334Speter /* Compensate for the +e options to the C++ front-end; 394618334Speter they're there simply for cfront call-compatibility. We do 394718334Speter some magic in default_compilers to pass them down properly. 394818334Speter Note we deliberately start at the `+' here, to avoid passing 394918334Speter -e0 or -e1 down into the linker. */ 395018334Speter switches[n_switches].part1 = &argv[i][0]; 395118334Speter switches[n_switches].args = 0; 395290277Sobrien switches[n_switches].live_cond = SWITCH_OK; 395352520Sobrien switches[n_switches].validated = 0; 395418334Speter n_switches++; 395518334Speter } 395618334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 395718334Speter { 395818334Speter int prev, j; 395918334Speter /* Split the argument at commas. */ 396018334Speter prev = 4; 396118334Speter for (j = 4; argv[i][j]; j++) 396218334Speter if (argv[i][j] == ',') 396318334Speter { 396450599Sobrien infiles[n_infiles].language = "*"; 396518334Speter infiles[n_infiles++].name 396618334Speter = save_string (argv[i] + prev, j - prev); 396718334Speter prev = j + 1; 396818334Speter } 396918334Speter /* Record the part after the last comma. */ 397050599Sobrien infiles[n_infiles].language = "*"; 397118334Speter infiles[n_infiles++].name = argv[i] + prev; 397218334Speter } 397318334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 397418334Speter { 397550599Sobrien infiles[n_infiles].language = "*"; 397618334Speter infiles[n_infiles++].name = argv[++i]; 397718334Speter } 3978132733Skan else if (strcmp (argv[i], "-Xassembler") == 0) 3979132733Skan { 3980132733Skan infiles[n_infiles].language = "*"; 3981132733Skan infiles[n_infiles++].name = argv[++i]; 3982132733Skan } 3983132733Skan else if (strcmp (argv[i], "-Xpreprocessor") == 0) 3984132733Skan { 3985132733Skan infiles[n_infiles].language = "*"; 3986132733Skan infiles[n_infiles++].name = argv[++i]; 3987132733Skan } 398877389Sobrien else if (strcmp (argv[i], "-l") == 0) 398977389Sobrien { /* POSIX allows separation of -l and the lib arg; 399077389Sobrien canonicalize by concatenating -l with its arg */ 399177389Sobrien infiles[n_infiles].language = "*"; 399277389Sobrien infiles[n_infiles++].name = concat ("-l", argv[++i], NULL); 399377389Sobrien } 399418334Speter else if (strncmp (argv[i], "-l", 2) == 0) 399518334Speter { 399650599Sobrien infiles[n_infiles].language = "*"; 399718334Speter infiles[n_infiles++].name = argv[i]; 399818334Speter } 399950599Sobrien else if (strcmp (argv[i], "-specs") == 0) 400050599Sobrien i++; 400150599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 400250599Sobrien ; 400390277Sobrien else if (strcmp (argv[i], "-time") == 0) 400490277Sobrien ; 400590277Sobrien else if (strcmp (argv[i], "-###") == 0) 400690277Sobrien ; 400718334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 400818334Speter { 400990277Sobrien const char *p = &argv[i][1]; 401090277Sobrien int c = *p; 401118334Speter 401218334Speter if (c == 'x') 401318334Speter { 401418334Speter if (p[1] == 0 && i + 1 == argc) 401518334Speter fatal ("argument to `-x' is missing"); 401618334Speter if (p[1] == 0) 401718334Speter spec_lang = argv[++i]; 401818334Speter else 401918334Speter spec_lang = p + 1; 402018334Speter if (! strcmp (spec_lang, "none")) 402118334Speter /* Suppress the warning if -xnone comes after the last input 402218334Speter file, because alternate command interfaces like g++ might 402318334Speter find it useful to place -xnone after each input file. */ 402418334Speter spec_lang = 0; 402518334Speter else 402618334Speter last_language_n_infiles = n_infiles; 402718334Speter continue; 402818334Speter } 402918334Speter switches[n_switches].part1 = p; 403018334Speter /* Deal with option arguments in separate argv elements. */ 403118334Speter if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) 403218334Speter || WORD_SWITCH_TAKES_ARG (p)) 403318334Speter { 403418334Speter int j = 0; 403518334Speter int n_args = WORD_SWITCH_TAKES_ARG (p); 403618334Speter 403718334Speter if (n_args == 0) 403818334Speter { 403918334Speter /* Count only the option arguments in separate argv elements. */ 404018334Speter n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); 404118334Speter } 404218334Speter if (i + n_args >= argc) 404318334Speter fatal ("argument to `-%s' is missing", p); 404418334Speter switches[n_switches].args 4045132733Skan = xmalloc ((n_args + 1) * sizeof(const char *)); 404618334Speter while (j < n_args) 404718334Speter switches[n_switches].args[j++] = argv[++i]; 404818334Speter /* Null-terminate the vector. */ 404918334Speter switches[n_switches].args[j] = 0; 405018334Speter } 405190277Sobrien else if (strchr (switches_need_spaces, c)) 405218334Speter { 405350599Sobrien /* On some systems, ld cannot handle some options without 405450599Sobrien a space. So split the option from its argument. */ 4055132733Skan char *part1 = xmalloc (2); 405650599Sobrien part1[0] = c; 405750599Sobrien part1[1] = '\0'; 405890277Sobrien 405950599Sobrien switches[n_switches].part1 = part1; 4060132733Skan switches[n_switches].args = xmalloc (2 * sizeof (const char *)); 406190277Sobrien switches[n_switches].args[0] = xstrdup (p+1); 406218334Speter switches[n_switches].args[1] = 0; 406318334Speter } 406418334Speter else 406518334Speter switches[n_switches].args = 0; 406618334Speter 406790277Sobrien switches[n_switches].live_cond = SWITCH_OK; 406852520Sobrien switches[n_switches].validated = 0; 406990277Sobrien switches[n_switches].ordering = 0; 4070132733Skan /* These are always valid, since gcc.c itself understands them. */ 407190277Sobrien if (!strcmp (p, "save-temps") 407290277Sobrien || !strcmp (p, "static-libgcc") 4073132733Skan || !strcmp (p, "shared-libgcc") 4074132733Skan || !strcmp (p, "pipe")) 407552520Sobrien switches[n_switches].validated = 1; 407690277Sobrien else 407790277Sobrien { 407890277Sobrien char ch = switches[n_switches].part1[0]; 4079117413Skan if (ch == 'B') 408090277Sobrien switches[n_switches].validated = 1; 408190277Sobrien } 408218334Speter n_switches++; 408318334Speter } 408418334Speter else 408518334Speter { 408690277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX 408790277Sobrien argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK)); 408818334Speter#endif 408918334Speter 409090277Sobrien if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0) 409118334Speter { 409218334Speter perror_with_name (argv[i]); 409318334Speter error_count++; 409418334Speter } 409518334Speter else 409618334Speter { 409718334Speter infiles[n_infiles].language = spec_lang; 409818334Speter infiles[n_infiles++].name = argv[i]; 409918334Speter } 410018334Speter } 410118334Speter } 410218334Speter 410318334Speter if (n_infiles == last_language_n_infiles && spec_lang != 0) 410490277Sobrien error ("warning: `-x %s' after last input file has no effect", spec_lang); 410518334Speter 410690277Sobrien /* Ensure we only invoke each subprocess once. */ 410790277Sobrien if (target_help_flag || print_help_list) 410890277Sobrien { 410990277Sobrien n_infiles = 1; 411090277Sobrien 411190277Sobrien /* Create a dummy input file, so that we can pass --target-help on to 411290277Sobrien the various sub-processes. */ 411390277Sobrien infiles[0].language = "c"; 411490277Sobrien infiles[0].name = "help-dummy"; 411590277Sobrien 411690277Sobrien if (target_help_flag) 411790277Sobrien { 411890277Sobrien switches[n_switches].part1 = "--target-help"; 411990277Sobrien switches[n_switches].args = 0; 412090277Sobrien switches[n_switches].live_cond = SWITCH_OK; 412190277Sobrien switches[n_switches].validated = 0; 412290277Sobrien 412390277Sobrien n_switches++; 412490277Sobrien } 412590277Sobrien 412690277Sobrien if (print_help_list) 412790277Sobrien { 412890277Sobrien switches[n_switches].part1 = "--help"; 412990277Sobrien switches[n_switches].args = 0; 413090277Sobrien switches[n_switches].live_cond = SWITCH_OK; 413190277Sobrien switches[n_switches].validated = 0; 413290277Sobrien 413390277Sobrien n_switches++; 413490277Sobrien } 413590277Sobrien } 413690277Sobrien 413718334Speter switches[n_switches].part1 = 0; 413818334Speter infiles[n_infiles].name = 0; 413918334Speter} 414090277Sobrien 4141132733Skan/* Store switches not filtered out by %<S in spec in COLLECT_GCC_OPTIONS 414290277Sobrien and place that in the environment. */ 414390277Sobrien 414490277Sobrienstatic void 4145132733Skanset_collect_gcc_options (void) 414690277Sobrien{ 414790277Sobrien int i; 414890277Sobrien int first_time; 414990277Sobrien 415090277Sobrien /* Build COLLECT_GCC_OPTIONS to have all of the options specified to 415190277Sobrien the compiler. */ 415290277Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=", 415390277Sobrien sizeof ("COLLECT_GCC_OPTIONS=") - 1); 415490277Sobrien 415590277Sobrien first_time = TRUE; 415690277Sobrien for (i = 0; (int) i < n_switches; i++) 415790277Sobrien { 415890277Sobrien const char *const *args; 415990277Sobrien const char *p, *q; 416090277Sobrien if (!first_time) 416190277Sobrien obstack_grow (&collect_obstack, " ", 1); 416290277Sobrien 416390277Sobrien first_time = FALSE; 416490277Sobrien 416590277Sobrien /* Ignore elided switches. */ 416690277Sobrien if (switches[i].live_cond == SWITCH_IGNORE) 416790277Sobrien continue; 416890277Sobrien 416990277Sobrien obstack_grow (&collect_obstack, "'-", 2); 417090277Sobrien q = switches[i].part1; 417190277Sobrien while ((p = strchr (q, '\''))) 417290277Sobrien { 417390277Sobrien obstack_grow (&collect_obstack, q, p - q); 417490277Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 417590277Sobrien q = ++p; 417690277Sobrien } 417790277Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 417890277Sobrien obstack_grow (&collect_obstack, "'", 1); 417990277Sobrien 418090277Sobrien for (args = switches[i].args; args && *args; args++) 418190277Sobrien { 418290277Sobrien obstack_grow (&collect_obstack, " '", 2); 418390277Sobrien q = *args; 418490277Sobrien while ((p = strchr (q, '\''))) 418590277Sobrien { 418690277Sobrien obstack_grow (&collect_obstack, q, p - q); 418790277Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 418890277Sobrien q = ++p; 418990277Sobrien } 419090277Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 419190277Sobrien obstack_grow (&collect_obstack, "'", 1); 419290277Sobrien } 419390277Sobrien } 419490277Sobrien obstack_grow (&collect_obstack, "\0", 1); 419590277Sobrien putenv (obstack_finish (&collect_obstack)); 419690277Sobrien} 419718334Speter 419818334Speter/* Process a spec string, accumulating and running commands. */ 419918334Speter 420018334Speter/* These variables describe the input file name. 420118334Speter input_file_number is the index on outfiles of this file, 420218334Speter so that the output file name can be stored for later use by %o. 420318334Speter input_basename is the start of the part of the input file 420418334Speter sans all directory names, and basename_length is the number 420518334Speter of characters starting there excluding the suffix .c or whatever. */ 420618334Speter 4207132733Skanstatic const char *input_filename; 420818334Speterstatic int input_file_number; 420950599Sobriensize_t input_filename_length; 421018334Speterstatic int basename_length; 421190277Sobrienstatic int suffixed_basename_length; 421252520Sobrienstatic const char *input_basename; 421352520Sobrienstatic const char *input_suffix; 421490277Sobrienstatic struct stat input_stat; 421590277Sobrienstatic int input_stat_set; 421618334Speter 421790277Sobrien/* The compiler used to process the current input file. */ 421890277Sobrienstatic struct compiler *input_file_compiler; 421990277Sobrien 422018334Speter/* These are variables used within do_spec and do_spec_1. */ 422118334Speter 422218334Speter/* Nonzero if an arg has been started and not yet terminated 422318334Speter (with space, tab or newline). */ 422418334Speterstatic int arg_going; 422518334Speter 422618334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated 422718334Speter is a temporary file name. */ 422818334Speterstatic int delete_this_arg; 422918334Speter 423018334Speter/* Nonzero means %w has been seen; the next arg to be terminated 423118334Speter is the output file name of this compilation. */ 423218334Speterstatic int this_is_output_file; 423318334Speter 423418334Speter/* Nonzero means %s has been seen; the next arg to be terminated 423518334Speter is the name of a library file and we should try the standard 423618334Speter search dirs for it. */ 423718334Speterstatic int this_is_library_file; 423818334Speter 423918334Speter/* Nonzero means that the input of this command is coming from a pipe. */ 424018334Speterstatic int input_from_pipe; 424118334Speter 424290277Sobrien/* Nonnull means substitute this for any suffix when outputting a switches 424390277Sobrien arguments. */ 424490277Sobrienstatic const char *suffix_subst; 424590277Sobrien 424618334Speter/* Process the spec SPEC and run the commands specified therein. 424718334Speter Returns 0 if the spec is successfully processed; -1 if failed. */ 424818334Speter 424950599Sobrienint 4250132733Skando_spec (const char *spec) 425118334Speter{ 425218334Speter int value; 425318334Speter 4254117413Skan value = do_spec_2 (spec); 425518334Speter 425618334Speter /* Force out any unfinished command. 425718334Speter If -pipe, this forces out the last command if it ended in `|'. */ 425818334Speter if (value == 0) 425918334Speter { 426018334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 426118334Speter argbuf_index--; 426218334Speter 426390277Sobrien set_collect_gcc_options (); 426490277Sobrien 426518334Speter if (argbuf_index > 0) 426618334Speter value = execute (); 426718334Speter } 426818334Speter 426918334Speter return value; 427018334Speter} 427118334Speter 4272117413Skanstatic int 4273132733Skando_spec_2 (const char *spec) 4274117413Skan{ 4275132733Skan const char *string; 4276132733Skan int result; 4277132733Skan 4278117413Skan clear_args (); 4279117413Skan arg_going = 0; 4280117413Skan delete_this_arg = 0; 4281117413Skan this_is_output_file = 0; 4282117413Skan this_is_library_file = 0; 4283117413Skan input_from_pipe = 0; 4284117413Skan suffix_subst = NULL; 4285117413Skan 4286132733Skan result = do_spec_1 (spec, 0, NULL); 4287132733Skan 4288132733Skan /* End any pending argument. */ 4289132733Skan if (arg_going) 4290132733Skan { 4291132733Skan obstack_1grow (&obstack, 0); 4292132733Skan string = obstack_finish (&obstack); 4293132733Skan if (this_is_library_file) 4294132733Skan string = find_file (string); 4295132733Skan store_arg (string, delete_this_arg, this_is_output_file); 4296132733Skan if (this_is_output_file) 4297132733Skan outfiles[input_file_number] = string; 4298132733Skan arg_going = 0; 4299132733Skan } 4300132733Skan 4301132733Skan return result; 4302117413Skan} 4303117413Skan 4304117413Skan 4305117413Skan/* Process the given spec string and add any new options to the end 4306117413Skan of the switches/n_switches array. */ 4307117413Skan 4308117413Skanstatic void 4309132733Skando_option_spec (const char *name, const char *spec) 4310117413Skan{ 4311132733Skan unsigned int i, value_count, value_len; 4312132733Skan const char *p, *q, *value; 4313132733Skan char *tmp_spec, *tmp_spec_p; 4314132733Skan 4315132733Skan if (configure_default_options[0].name == NULL) 4316132733Skan return; 4317132733Skan 4318132733Skan for (i = 0; i < ARRAY_SIZE (configure_default_options); i++) 4319132733Skan if (strcmp (configure_default_options[i].name, name) == 0) 4320132733Skan break; 4321132733Skan if (i == ARRAY_SIZE (configure_default_options)) 4322132733Skan return; 4323132733Skan 4324132733Skan value = configure_default_options[i].value; 4325132733Skan value_len = strlen (value); 4326132733Skan 4327132733Skan /* Compute the size of the final spec. */ 4328132733Skan value_count = 0; 4329132733Skan p = spec; 4330132733Skan while ((p = strstr (p, "%(VALUE)")) != NULL) 4331132733Skan { 4332132733Skan p ++; 4333132733Skan value_count ++; 4334132733Skan } 4335132733Skan 4336132733Skan /* Replace each %(VALUE) by the specified value. */ 4337132733Skan tmp_spec = alloca (strlen (spec) + 1 4338132733Skan + value_count * (value_len - strlen ("%(VALUE)"))); 4339132733Skan tmp_spec_p = tmp_spec; 4340132733Skan q = spec; 4341132733Skan while ((p = strstr (q, "%(VALUE)")) != NULL) 4342132733Skan { 4343132733Skan memcpy (tmp_spec_p, q, p - q); 4344132733Skan tmp_spec_p = tmp_spec_p + (p - q); 4345132733Skan memcpy (tmp_spec_p, value, value_len); 4346132733Skan tmp_spec_p += value_len; 4347132733Skan q = p + strlen ("%(VALUE)"); 4348132733Skan } 4349132733Skan strcpy (tmp_spec_p, q); 4350132733Skan 4351132733Skan do_self_spec (tmp_spec); 4352132733Skan} 4353132733Skan 4354132733Skan/* Process the given spec string and add any new options to the end 4355132733Skan of the switches/n_switches array. */ 4356132733Skan 4357132733Skanstatic void 4358132733Skando_self_spec (const char *spec) 4359132733Skan{ 4360117413Skan do_spec_2 (spec); 4361117413Skan do_spec_1 (" ", 0, NULL); 4362117413Skan 4363117413Skan if (argbuf_index > 0) 4364117413Skan { 4365117413Skan int i, first; 4366117413Skan 4367117413Skan first = n_switches; 4368117413Skan n_switches += argbuf_index; 4369117413Skan switches = xrealloc (switches, 4370117413Skan sizeof (struct switchstr) * (n_switches + 1)); 4371117413Skan 4372117413Skan switches[n_switches] = switches[first]; 4373117413Skan for (i = 0; i < argbuf_index; i++) 4374117413Skan { 4375117413Skan struct switchstr *sw; 4376117413Skan 4377117413Skan /* Each switch should start with '-'. */ 4378117413Skan if (argbuf[i][0] != '-') 4379117413Skan abort (); 4380117413Skan 4381117413Skan sw = &switches[i + first]; 4382117413Skan sw->part1 = &argbuf[i][1]; 4383117413Skan sw->args = 0; 4384117413Skan sw->live_cond = SWITCH_OK; 4385117413Skan sw->validated = 0; 4386117413Skan sw->ordering = 0; 4387117413Skan } 4388117413Skan } 4389117413Skan} 4390117413Skan 439118334Speter/* Process the sub-spec SPEC as a portion of a larger spec. 439218334Speter This is like processing a whole spec except that we do 439318334Speter not initialize at the beginning and we do not supply a 439418334Speter newline by default at the end. 439518334Speter INSWITCH nonzero means don't process %-sequences in SPEC; 439618334Speter in this case, % is treated as an ordinary character. 439718334Speter This is used while substituting switches. 439818334Speter INSWITCH nonzero also causes SPC not to terminate an argument. 439918334Speter 440018334Speter Value is zero unless a line was finished 440118334Speter and the command on that line reported an error. */ 440218334Speter 440318334Speterstatic int 4404132733Skando_spec_1 (const char *spec, int inswitch, const char *soft_matched_part) 440518334Speter{ 440690277Sobrien const char *p = spec; 440790277Sobrien int c; 440818334Speter int i; 440952520Sobrien const char *string; 441018334Speter int value; 441118334Speter 441250599Sobrien while ((c = *p++)) 441318334Speter /* If substituting a switch, treat all chars like letters. 441418334Speter Otherwise, NL, SPC, TAB and % are special. */ 441518334Speter switch (inswitch ? 'a' : c) 441618334Speter { 441718334Speter case '\n': 441818334Speter /* End of line: finish any pending argument, 441918334Speter then run the pending command if one has been started. */ 442018334Speter if (arg_going) 442118334Speter { 442218334Speter obstack_1grow (&obstack, 0); 442318334Speter string = obstack_finish (&obstack); 442418334Speter if (this_is_library_file) 442518334Speter string = find_file (string); 442618334Speter store_arg (string, delete_this_arg, this_is_output_file); 442718334Speter if (this_is_output_file) 442818334Speter outfiles[input_file_number] = string; 442918334Speter } 443018334Speter arg_going = 0; 443118334Speter 443218334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 443318334Speter { 443418334Speter /* A `|' before the newline means use a pipe here, 443518334Speter but only if -pipe was specified. 443618334Speter Otherwise, execute now and don't pass the `|' as an arg. */ 4437132733Skan if (use_pipes) 443818334Speter { 443918334Speter input_from_pipe = 1; 444018334Speter break; 444118334Speter } 444218334Speter else 444318334Speter argbuf_index--; 444418334Speter } 444518334Speter 444690277Sobrien set_collect_gcc_options (); 444790277Sobrien 444818334Speter if (argbuf_index > 0) 444918334Speter { 445018334Speter value = execute (); 445118334Speter if (value) 445218334Speter return value; 445318334Speter } 445418334Speter /* Reinitialize for a new command, and for a new argument. */ 445518334Speter clear_args (); 445618334Speter arg_going = 0; 445718334Speter delete_this_arg = 0; 445818334Speter this_is_output_file = 0; 445918334Speter this_is_library_file = 0; 446018334Speter input_from_pipe = 0; 446118334Speter break; 446218334Speter 446318334Speter case '|': 446418334Speter /* End any pending argument. */ 446518334Speter if (arg_going) 446618334Speter { 446718334Speter obstack_1grow (&obstack, 0); 446818334Speter string = obstack_finish (&obstack); 446918334Speter if (this_is_library_file) 447018334Speter string = find_file (string); 447118334Speter store_arg (string, delete_this_arg, this_is_output_file); 447218334Speter if (this_is_output_file) 447318334Speter outfiles[input_file_number] = string; 447418334Speter } 447518334Speter 447618334Speter /* Use pipe */ 447718334Speter obstack_1grow (&obstack, c); 447818334Speter arg_going = 1; 447918334Speter break; 448018334Speter 448118334Speter case '\t': 448218334Speter case ' ': 448318334Speter /* Space or tab ends an argument if one is pending. */ 448418334Speter if (arg_going) 448518334Speter { 448618334Speter obstack_1grow (&obstack, 0); 448718334Speter string = obstack_finish (&obstack); 448818334Speter if (this_is_library_file) 448918334Speter string = find_file (string); 449018334Speter store_arg (string, delete_this_arg, this_is_output_file); 449118334Speter if (this_is_output_file) 449218334Speter outfiles[input_file_number] = string; 449318334Speter } 449418334Speter /* Reinitialize for a new argument. */ 449518334Speter arg_going = 0; 449618334Speter delete_this_arg = 0; 449718334Speter this_is_output_file = 0; 449818334Speter this_is_library_file = 0; 449918334Speter break; 450018334Speter 450118334Speter case '%': 450218334Speter switch (c = *p++) 450318334Speter { 450418334Speter case 0: 450590277Sobrien fatal ("invalid specification! Bug in cc"); 450618334Speter 450718334Speter case 'b': 450818334Speter obstack_grow (&obstack, input_basename, basename_length); 450918334Speter arg_going = 1; 451018334Speter break; 451118334Speter 451290277Sobrien case 'B': 451390277Sobrien obstack_grow (&obstack, input_basename, suffixed_basename_length); 451490277Sobrien arg_going = 1; 451590277Sobrien break; 451690277Sobrien 451718334Speter case 'd': 451818334Speter delete_this_arg = 2; 451918334Speter break; 452018334Speter 452118334Speter /* Dump out the directories specified with LIBRARY_PATH, 452218334Speter followed by the absolute directories 452318334Speter that we search for startfiles. */ 452418334Speter case 'D': 452518334Speter { 452618334Speter struct prefix_list *pl = startfile_prefixes.plist; 452750599Sobrien size_t bufsize = 100; 4528132733Skan char *buffer = xmalloc (bufsize); 452918334Speter int idx; 453018334Speter 453118334Speter for (; pl; pl = pl->next) 453218334Speter { 453318334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR 453418334Speter /* Used on systems which record the specified -L dirs 453518334Speter and use them to search for dynamic linking. */ 453618334Speter /* Relative directories always come from -B, 453718334Speter and it is better not to use them for searching 453890277Sobrien at run time. In particular, stage1 loses. */ 4539132733Skan if (!IS_ABSOLUTE_PATH (pl->prefix)) 454018334Speter continue; 454118334Speter#endif 454218334Speter /* Try subdirectory if there is one. */ 4543104763Skan if (multilib_dir != NULL 4544104763Skan || (pl->os_multilib && multilib_os_dir != NULL)) 454518334Speter { 4546104763Skan const char *multi_dir; 4547104763Skan 4548104763Skan multi_dir = pl->os_multilib ? multilib_os_dir 4549104763Skan : multilib_dir; 4550104763Skan if (machine_suffix && multilib_dir) 455118334Speter { 455218334Speter if (strlen (pl->prefix) + strlen (machine_suffix) 455318334Speter >= bufsize) 455418334Speter bufsize = (strlen (pl->prefix) 455518334Speter + strlen (machine_suffix)) * 2 + 1; 4556132733Skan buffer = xrealloc (buffer, bufsize); 455718334Speter strcpy (buffer, pl->prefix); 455818334Speter strcat (buffer, machine_suffix); 455918334Speter if (is_directory (buffer, multilib_dir, 1)) 456018334Speter { 456190277Sobrien do_spec_1 ("-L", 0, NULL); 456218334Speter#ifdef SPACE_AFTER_L_OPTION 456390277Sobrien do_spec_1 (" ", 0, NULL); 456418334Speter#endif 456590277Sobrien do_spec_1 (buffer, 1, NULL); 456690277Sobrien do_spec_1 (multilib_dir, 1, NULL); 456718334Speter /* Make this a separate argument. */ 456890277Sobrien do_spec_1 (" ", 0, NULL); 456918334Speter } 457018334Speter } 457118334Speter if (!pl->require_machine_suffix) 457218334Speter { 4573104763Skan if (is_directory (pl->prefix, multi_dir, 1)) 457418334Speter { 457590277Sobrien do_spec_1 ("-L", 0, NULL); 457618334Speter#ifdef SPACE_AFTER_L_OPTION 457790277Sobrien do_spec_1 (" ", 0, NULL); 457818334Speter#endif 457990277Sobrien do_spec_1 (pl->prefix, 1, NULL); 4580104763Skan do_spec_1 (multi_dir, 1, NULL); 458118334Speter /* Make this a separate argument. */ 458290277Sobrien do_spec_1 (" ", 0, NULL); 458318334Speter } 458418334Speter } 458518334Speter } 458618334Speter if (machine_suffix) 458718334Speter { 458818334Speter if (is_directory (pl->prefix, machine_suffix, 1)) 458918334Speter { 459090277Sobrien do_spec_1 ("-L", 0, NULL); 459118334Speter#ifdef SPACE_AFTER_L_OPTION 459290277Sobrien do_spec_1 (" ", 0, NULL); 459318334Speter#endif 459490277Sobrien do_spec_1 (pl->prefix, 1, NULL); 459518334Speter /* Remove slash from machine_suffix. */ 459618334Speter if (strlen (machine_suffix) >= bufsize) 459718334Speter bufsize = strlen (machine_suffix) * 2 + 1; 4598132733Skan buffer = xrealloc (buffer, bufsize); 459918334Speter strcpy (buffer, machine_suffix); 460018334Speter idx = strlen (buffer); 460152520Sobrien if (IS_DIR_SEPARATOR (buffer[idx - 1])) 460218334Speter buffer[idx - 1] = 0; 460390277Sobrien do_spec_1 (buffer, 1, NULL); 460418334Speter /* Make this a separate argument. */ 460590277Sobrien do_spec_1 (" ", 0, NULL); 460618334Speter } 460718334Speter } 460818334Speter if (!pl->require_machine_suffix) 460918334Speter { 461018334Speter if (is_directory (pl->prefix, "", 1)) 461118334Speter { 461290277Sobrien do_spec_1 ("-L", 0, NULL); 461318334Speter#ifdef SPACE_AFTER_L_OPTION 461490277Sobrien do_spec_1 (" ", 0, NULL); 461518334Speter#endif 461618334Speter /* Remove slash from pl->prefix. */ 461718334Speter if (strlen (pl->prefix) >= bufsize) 461818334Speter bufsize = strlen (pl->prefix) * 2 + 1; 4619132733Skan buffer = xrealloc (buffer, bufsize); 462018334Speter strcpy (buffer, pl->prefix); 462118334Speter idx = strlen (buffer); 462252520Sobrien if (IS_DIR_SEPARATOR (buffer[idx - 1])) 462318334Speter buffer[idx - 1] = 0; 462490277Sobrien do_spec_1 (buffer, 1, NULL); 462518334Speter /* Make this a separate argument. */ 462690277Sobrien do_spec_1 (" ", 0, NULL); 462718334Speter } 462818334Speter } 462918334Speter } 463018334Speter free (buffer); 463118334Speter } 463218334Speter break; 463318334Speter 463418334Speter case 'e': 463552520Sobrien /* %efoo means report an error with `foo' as error message 463618334Speter and don't execute any more commands for this file. */ 463718334Speter { 463852520Sobrien const char *q = p; 463918334Speter char *buf; 464090277Sobrien while (*p != 0 && *p != '\n') 464190277Sobrien p++; 4642132733Skan buf = alloca (p - q + 1); 464318334Speter strncpy (buf, q, p - q); 464418334Speter buf[p - q] = 0; 464590277Sobrien error ("%s", buf); 464618334Speter return -1; 464718334Speter } 464818334Speter break; 464990277Sobrien case 'n': 4650117413Skan /* %nfoo means report a notice with `foo' on stderr. */ 465190277Sobrien { 465290277Sobrien const char *q = p; 465390277Sobrien char *buf; 465490277Sobrien while (*p != 0 && *p != '\n') 465590277Sobrien p++; 4656132733Skan buf = alloca (p - q + 1); 465790277Sobrien strncpy (buf, q, p - q); 465890277Sobrien buf[p - q] = 0; 465990277Sobrien notice ("%s\n", buf); 466090277Sobrien if (*p) 466190277Sobrien p++; 466290277Sobrien } 466390277Sobrien break; 466418334Speter 466590277Sobrien case 'j': 466690277Sobrien { 466790277Sobrien struct stat st; 466890277Sobrien 4669132733Skan /* If save_temps_flag is off, and the HOST_BIT_BUCKET is 4670132733Skan defined, and it is not a directory, and it is 4671132733Skan writable, use it. Otherwise, treat this like any 4672132733Skan other temporary file. */ 467390277Sobrien 467490277Sobrien if ((!save_temps_flag) 467590277Sobrien && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode)) 467690277Sobrien && (access (HOST_BIT_BUCKET, W_OK) == 0)) 467790277Sobrien { 467890277Sobrien obstack_grow (&obstack, HOST_BIT_BUCKET, 467990277Sobrien strlen (HOST_BIT_BUCKET)); 468090277Sobrien delete_this_arg = 0; 468190277Sobrien arg_going = 1; 468290277Sobrien break; 468390277Sobrien } 468490277Sobrien } 4685132733Skan goto create_temp_file; 4686132733Skan case '|': 4687132733Skan if (use_pipes) 4688132733Skan { 4689132733Skan obstack_1grow (&obstack, '-'); 4690132733Skan delete_this_arg = 0; 4691132733Skan arg_going = 1; 4692132733Skan 4693132733Skan /* consume suffix */ 4694132733Skan while (*p == '.' || ISALPHA ((unsigned char) *p)) 4695132733Skan p++; 4696132733Skan if (p[0] == '%' && p[1] == 'O') 4697132733Skan p += 2; 4698132733Skan 4699132733Skan break; 4700132733Skan } 4701132733Skan goto create_temp_file; 4702132733Skan case 'm': 4703132733Skan if (use_pipes) 4704132733Skan { 4705132733Skan /* consume suffix */ 4706132733Skan while (*p == '.' || ISALPHA ((unsigned char) *p)) 4707132733Skan p++; 4708132733Skan if (p[0] == '%' && p[1] == 'O') 4709132733Skan p += 2; 4710132733Skan 4711132733Skan break; 4712132733Skan } 4713132733Skan goto create_temp_file; 471418334Speter case 'g': 471518334Speter case 'u': 471618334Speter case 'U': 4717132733Skan create_temp_file: 471818334Speter { 471918334Speter struct temp_name *t; 472050599Sobrien int suffix_length; 472152520Sobrien const char *suffix = p; 472290277Sobrien char *saved_suffix = NULL; 472318334Speter 472490277Sobrien while (*p == '.' || ISALPHA ((unsigned char) *p)) 472590277Sobrien p++; 472690277Sobrien suffix_length = p - suffix; 472750599Sobrien if (p[0] == '%' && p[1] == 'O') 472850599Sobrien { 472950599Sobrien p += 2; 473050599Sobrien /* We don't support extra suffix characters after %O. */ 473190277Sobrien if (*p == '.' || ISALPHA ((unsigned char) *p)) 473250599Sobrien abort (); 473390277Sobrien if (suffix_length == 0) 473490277Sobrien suffix = TARGET_OBJECT_SUFFIX; 473590277Sobrien else 473690277Sobrien { 473790277Sobrien saved_suffix 4738132733Skan = xmalloc (suffix_length 4739132733Skan + strlen (TARGET_OBJECT_SUFFIX)); 474090277Sobrien strncpy (saved_suffix, suffix, suffix_length); 474190277Sobrien strcpy (saved_suffix + suffix_length, 474290277Sobrien TARGET_OBJECT_SUFFIX); 474390277Sobrien } 474490277Sobrien suffix_length += strlen (TARGET_OBJECT_SUFFIX); 474550599Sobrien } 4746117413Skan 474790277Sobrien /* If the input_filename has the same suffix specified 474890277Sobrien for the %g, %u, or %U, and -save-temps is specified, 474990277Sobrien we could end up using that file as an intermediate 475090277Sobrien thus clobbering the user's source file (.e.g., 475190277Sobrien gcc -save-temps foo.s would clobber foo.s with the 475290277Sobrien output of cpp0). So check for this condition and 475390277Sobrien generate a temp file as the intermediate. */ 4754117413Skan 475590277Sobrien if (save_temps_flag) 475650599Sobrien { 475790277Sobrien temp_filename_length = basename_length + suffix_length; 475890277Sobrien temp_filename = alloca (temp_filename_length + 1); 475990277Sobrien strncpy ((char *) temp_filename, input_basename, basename_length); 476090277Sobrien strncpy ((char *) temp_filename + basename_length, suffix, 4761132733Skan suffix_length); 476290277Sobrien *((char *) temp_filename + temp_filename_length) = '\0'; 476390277Sobrien if (strcmp (temp_filename, input_filename) != 0) 476490277Sobrien { 4765132733Skan struct stat st_temp; 4766117413Skan 4767132733Skan /* Note, set_input() resets input_stat_set to 0. */ 4768132733Skan if (input_stat_set == 0) 4769132733Skan { 4770132733Skan input_stat_set = stat (input_filename, &input_stat); 4771132733Skan if (input_stat_set >= 0) 4772132733Skan input_stat_set = 1; 4773132733Skan } 4774117413Skan 4775132733Skan /* If we have the stat for the input_filename 4776132733Skan and we can do the stat for the temp_filename 4777132733Skan then the they could still refer to the same 4778132733Skan file if st_dev/st_ino's are the same. */ 4779117413Skan 478090277Sobrien if (input_stat_set != 1 478190277Sobrien || stat (temp_filename, &st_temp) < 0 478290277Sobrien || input_stat.st_dev != st_temp.st_dev 478390277Sobrien || input_stat.st_ino != st_temp.st_ino) 4784117413Skan { 478590277Sobrien temp_filename = save_string (temp_filename, 478690277Sobrien temp_filename_length + 1); 478790277Sobrien obstack_grow (&obstack, temp_filename, 4788132733Skan temp_filename_length); 478990277Sobrien arg_going = 1; 4790117413Skan delete_this_arg = 0; 479190277Sobrien break; 479290277Sobrien } 479390277Sobrien } 479450599Sobrien } 479550599Sobrien 479618334Speter /* See if we already have an association of %g/%u/%U and 479718334Speter suffix. */ 479818334Speter for (t = temp_names; t; t = t->next) 479950599Sobrien if (t->length == suffix_length 480050599Sobrien && strncmp (t->suffix, suffix, suffix_length) == 0 4801132733Skan && t->unique == (c == 'u' || c == 'U' || c == 'j')) 480218334Speter break; 480318334Speter 480490277Sobrien /* Make a new association if needed. %u and %j 480590277Sobrien require one. */ 480690277Sobrien if (t == 0 || c == 'u' || c == 'j') 480718334Speter { 480818334Speter if (t == 0) 480918334Speter { 4810132733Skan t = xmalloc (sizeof (struct temp_name)); 481118334Speter t->next = temp_names; 481218334Speter temp_names = t; 481318334Speter } 481450599Sobrien t->length = suffix_length; 481590277Sobrien if (saved_suffix) 481690277Sobrien { 481790277Sobrien t->suffix = saved_suffix; 481890277Sobrien saved_suffix = NULL; 481990277Sobrien } 482090277Sobrien else 482190277Sobrien t->suffix = save_string (suffix, suffix_length); 4822132733Skan t->unique = (c == 'u' || c == 'U' || c == 'j'); 482350599Sobrien temp_filename = make_temp_file (t->suffix); 482450599Sobrien temp_filename_length = strlen (temp_filename); 482518334Speter t->filename = temp_filename; 482618334Speter t->filename_length = temp_filename_length; 482718334Speter } 482818334Speter 482990277Sobrien if (saved_suffix) 483090277Sobrien free (saved_suffix); 483190277Sobrien 483218334Speter obstack_grow (&obstack, t->filename, t->filename_length); 483318334Speter delete_this_arg = 1; 483418334Speter } 483518334Speter arg_going = 1; 483618334Speter break; 483718334Speter 483818334Speter case 'i': 4839132733Skan if (combine_inputs) 4840132733Skan { 4841132733Skan for (i = 0; (int) i < n_infiles; i++) 4842132733Skan store_arg (infiles[i].name, 0, 0); 4843132733Skan } 4844132733Skan else 4845132733Skan { 4846132733Skan obstack_grow (&obstack, input_filename, input_filename_length); 4847132733Skan arg_going = 1; 4848132733Skan } 484918334Speter break; 485018334Speter 485118334Speter case 'I': 485218334Speter { 485318334Speter struct prefix_list *pl = include_prefixes.plist; 485418334Speter 485518334Speter if (gcc_exec_prefix) 485618334Speter { 485790277Sobrien do_spec_1 ("-iprefix", 1, NULL); 485818334Speter /* Make this a separate argument. */ 485990277Sobrien do_spec_1 (" ", 0, NULL); 486090277Sobrien do_spec_1 (gcc_exec_prefix, 1, NULL); 486190277Sobrien do_spec_1 (" ", 0, NULL); 486218334Speter } 486318334Speter 4864132733Skan if (target_system_root_changed || 4865132733Skan (target_system_root && target_sysroot_hdrs_suffix)) 4866132733Skan { 4867132733Skan do_spec_1 ("-isysroot", 1, NULL); 4868132733Skan /* Make this a separate argument. */ 4869132733Skan do_spec_1 (" ", 0, NULL); 4870132733Skan do_spec_1 (target_system_root, 1, NULL); 4871132733Skan if (target_sysroot_hdrs_suffix) 4872132733Skan do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL); 4873132733Skan do_spec_1 (" ", 0, NULL); 4874132733Skan } 4875132733Skan 487618334Speter for (; pl; pl = pl->next) 487718334Speter { 487890277Sobrien do_spec_1 ("-isystem", 1, NULL); 487918334Speter /* Make this a separate argument. */ 488090277Sobrien do_spec_1 (" ", 0, NULL); 488190277Sobrien do_spec_1 (pl->prefix, 1, NULL); 488290277Sobrien do_spec_1 (" ", 0, NULL); 488318334Speter } 488418334Speter } 488518334Speter break; 488618334Speter 488718334Speter case 'o': 488852520Sobrien { 488952520Sobrien int max = n_infiles; 489052520Sobrien max += lang_specific_extra_outfiles; 489118334Speter 489252520Sobrien for (i = 0; i < max; i++) 489352520Sobrien if (outfiles[i]) 489452520Sobrien store_arg (outfiles[i], 0, 0); 489552520Sobrien break; 489652520Sobrien } 489752520Sobrien 489818334Speter case 'O': 489990277Sobrien obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); 490018334Speter arg_going = 1; 490118334Speter break; 490218334Speter 490318334Speter case 's': 490418334Speter this_is_library_file = 1; 490518334Speter break; 490618334Speter 4907132733Skan case 'V': 4908132733Skan outfiles[input_file_number] = NULL; 4909132733Skan break; 4910132733Skan 491118334Speter case 'w': 491218334Speter this_is_output_file = 1; 491318334Speter break; 491418334Speter 491518334Speter case 'W': 491618334Speter { 491750599Sobrien int cur_index = argbuf_index; 491818334Speter /* Handle the {...} following the %W. */ 491918334Speter if (*p != '{') 492018334Speter abort (); 492118334Speter p = handle_braces (p + 1); 492218334Speter if (p == 0) 492318334Speter return -1; 4924132733Skan /* End any pending argument. */ 4925132733Skan if (arg_going) 4926132733Skan { 4927132733Skan obstack_1grow (&obstack, 0); 4928132733Skan string = obstack_finish (&obstack); 4929132733Skan if (this_is_library_file) 4930132733Skan string = find_file (string); 4931132733Skan store_arg (string, delete_this_arg, this_is_output_file); 4932132733Skan if (this_is_output_file) 4933132733Skan outfiles[input_file_number] = string; 4934132733Skan arg_going = 0; 4935132733Skan } 493618334Speter /* If any args were output, mark the last one for deletion 493718334Speter on failure. */ 493850599Sobrien if (argbuf_index != cur_index) 493918334Speter record_temp_file (argbuf[argbuf_index - 1], 0, 1); 494018334Speter break; 494118334Speter } 494218334Speter 494318334Speter /* %x{OPTION} records OPTION for %X to output. */ 494418334Speter case 'x': 494518334Speter { 494652520Sobrien const char *p1 = p; 494718334Speter char *string; 494818334Speter 494918334Speter /* Skip past the option value and make a copy. */ 495018334Speter if (*p != '{') 495118334Speter abort (); 495218334Speter while (*p++ != '}') 495318334Speter ; 495418334Speter string = save_string (p1 + 1, p - p1 - 2); 495518334Speter 495618334Speter /* See if we already recorded this option. */ 495718334Speter for (i = 0; i < n_linker_options; i++) 495818334Speter if (! strcmp (string, linker_options[i])) 495918334Speter { 496018334Speter free (string); 496118334Speter return 0; 496218334Speter } 496318334Speter 496418334Speter /* This option is new; add it. */ 496550599Sobrien add_linker_option (string, strlen (string)); 496618334Speter } 496718334Speter break; 496818334Speter 496918334Speter /* Dump out the options accumulated previously using %x. */ 497018334Speter case 'X': 497118334Speter for (i = 0; i < n_linker_options; i++) 497218334Speter { 497390277Sobrien do_spec_1 (linker_options[i], 1, NULL); 497418334Speter /* Make each accumulated option a separate argument. */ 497590277Sobrien do_spec_1 (" ", 0, NULL); 497618334Speter } 497718334Speter break; 497818334Speter 497918334Speter /* Dump out the options accumulated previously using -Wa,. */ 498018334Speter case 'Y': 498118334Speter for (i = 0; i < n_assembler_options; i++) 498218334Speter { 498390277Sobrien do_spec_1 (assembler_options[i], 1, NULL); 498418334Speter /* Make each accumulated option a separate argument. */ 498590277Sobrien do_spec_1 (" ", 0, NULL); 498618334Speter } 498718334Speter break; 498818334Speter 498918334Speter /* Dump out the options accumulated previously using -Wp,. */ 499018334Speter case 'Z': 499118334Speter for (i = 0; i < n_preprocessor_options; i++) 499218334Speter { 499390277Sobrien do_spec_1 (preprocessor_options[i], 1, NULL); 499418334Speter /* Make each accumulated option a separate argument. */ 499590277Sobrien do_spec_1 (" ", 0, NULL); 499618334Speter } 499718334Speter break; 499818334Speter 499918334Speter /* Here are digits and numbers that just process 500018334Speter a certain constant string as a spec. */ 500118334Speter 500218334Speter case '1': 500390277Sobrien value = do_spec_1 (cc1_spec, 0, NULL); 500418334Speter if (value != 0) 500518334Speter return value; 500618334Speter break; 500718334Speter 500818334Speter case '2': 500990277Sobrien value = do_spec_1 (cc1plus_spec, 0, NULL); 501018334Speter if (value != 0) 501118334Speter return value; 501218334Speter break; 501318334Speter 501418334Speter case 'a': 501590277Sobrien value = do_spec_1 (asm_spec, 0, NULL); 501618334Speter if (value != 0) 501718334Speter return value; 501818334Speter break; 501918334Speter 502018334Speter case 'A': 502190277Sobrien value = do_spec_1 (asm_final_spec, 0, NULL); 502218334Speter if (value != 0) 502318334Speter return value; 502418334Speter break; 502518334Speter 502618334Speter case 'C': 502790277Sobrien { 502890277Sobrien const char *const spec 5029117413Skan = (input_file_compiler->cpp_spec 5030117413Skan ? input_file_compiler->cpp_spec 503190277Sobrien : cpp_spec); 503290277Sobrien value = do_spec_1 (spec, 0, NULL); 503390277Sobrien if (value != 0) 503490277Sobrien return value; 503590277Sobrien } 503618334Speter break; 503718334Speter 503818334Speter case 'E': 503990277Sobrien value = do_spec_1 (endfile_spec, 0, NULL); 504018334Speter if (value != 0) 504118334Speter return value; 504218334Speter break; 504318334Speter 504418334Speter case 'l': 504590277Sobrien value = do_spec_1 (link_spec, 0, NULL); 504618334Speter if (value != 0) 504718334Speter return value; 504818334Speter break; 504918334Speter 505018334Speter case 'L': 505190277Sobrien value = do_spec_1 (lib_spec, 0, NULL); 505218334Speter if (value != 0) 505318334Speter return value; 505418334Speter break; 505518334Speter 505618334Speter case 'G': 505790277Sobrien value = do_spec_1 (libgcc_spec, 0, NULL); 505818334Speter if (value != 0) 505918334Speter return value; 506018334Speter break; 506118334Speter 506290277Sobrien case 'M': 506390277Sobrien if (multilib_dir && strcmp (multilib_dir, ".") != 0) 506490277Sobrien { 506590277Sobrien char *p; 506690277Sobrien const char *q; 506790277Sobrien size_t len; 506890277Sobrien 506990277Sobrien len = strlen (multilib_dir); 507090277Sobrien obstack_blank (&obstack, len + 1); 507190277Sobrien p = obstack_next_free (&obstack) - (len + 1); 507290277Sobrien 507390277Sobrien *p++ = '_'; 507490277Sobrien for (q = multilib_dir; *q ; ++q, ++p) 507590277Sobrien *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q); 507690277Sobrien } 507790277Sobrien break; 507890277Sobrien 5079132733Skan case 'R': 5080132733Skan /* We assume there is a directory 5081132733Skan separator at the end of this string. */ 5082132733Skan if (target_system_root) 5083132733Skan { 5084132733Skan obstack_grow (&obstack, target_system_root, 5085132733Skan strlen (target_system_root)); 5086132733Skan if (target_sysroot_suffix) 5087132733Skan obstack_grow (&obstack, target_sysroot_suffix, 5088132733Skan strlen (target_sysroot_suffix)); 5089132733Skan } 509018334Speter break; 509118334Speter 509218334Speter case 'S': 509390277Sobrien value = do_spec_1 (startfile_spec, 0, NULL); 509418334Speter if (value != 0) 509518334Speter return value; 509618334Speter break; 509718334Speter 509818334Speter /* Here we define characters other than letters and digits. */ 509918334Speter 510018334Speter case '{': 510118334Speter p = handle_braces (p); 510218334Speter if (p == 0) 510318334Speter return -1; 510418334Speter break; 510518334Speter 5106117413Skan case ':': 5107117413Skan p = handle_spec_function (p); 5108117413Skan if (p == 0) 5109117413Skan return -1; 5110117413Skan break; 5111117413Skan 511218334Speter case '%': 511318334Speter obstack_1grow (&obstack, '%'); 511418334Speter break; 511518334Speter 5116117413Skan case '.': 5117117413Skan { 5118117413Skan unsigned len = 0; 511990277Sobrien 5120117413Skan while (p[len] && p[len] != ' ' && p[len] != '%') 5121117413Skan len++; 5122117413Skan suffix_subst = save_string (p - 1, len + 1); 5123117413Skan p += len; 5124117413Skan } 512590277Sobrien break; 5126117413Skan 5127132733Skan /* Henceforth ignore the option(s) matching the pattern 5128132733Skan after the %<. */ 5129132733Skan case '<': 5130132733Skan { 5131132733Skan unsigned len = 0; 5132132733Skan int have_wildcard = 0; 5133132733Skan int i; 5134132733Skan 5135132733Skan while (p[len] && p[len] != ' ' && p[len] != '\t') 5136132733Skan len++; 5137132733Skan 5138132733Skan if (p[len-1] == '*') 5139132733Skan have_wildcard = 1; 5140132733Skan 5141132733Skan for (i = 0; i < n_switches; i++) 5142132733Skan if (!strncmp (switches[i].part1, p, len - have_wildcard) 5143132733Skan && (have_wildcard || switches[i].part1[len] == '\0')) 5144132733Skan { 5145132733Skan switches[i].live_cond = SWITCH_IGNORE; 5146132733Skan switches[i].validated = 1; 5147132733Skan } 5148132733Skan 5149132733Skan p += len; 5150132733Skan } 5151132733Skan break; 5152132733Skan 515318334Speter case '*': 515490277Sobrien if (soft_matched_part) 515590277Sobrien { 515690277Sobrien do_spec_1 (soft_matched_part, 1, NULL); 515790277Sobrien do_spec_1 (" ", 0, NULL); 515890277Sobrien } 515990277Sobrien else 516090277Sobrien /* Catch the case where a spec string contains something like 516190277Sobrien '%{foo:%*}'. ie there is no * in the pattern on the left 516290277Sobrien hand side of the :. */ 516390277Sobrien error ("spec failure: '%%*' has not been initialized by pattern match"); 516418334Speter break; 516518334Speter 516618334Speter /* Process a string found as the value of a spec given by name. 516718334Speter This feature allows individual machine descriptions 516818334Speter to add and use their own specs. 516918334Speter %[...] modifies -D options the way %P does; 517018334Speter %(...) uses the spec unmodified. */ 517150599Sobrien case '[': 517290277Sobrien error ("warning: use of obsolete %%[ operator in specs"); 517318334Speter case '(': 517418334Speter { 517552520Sobrien const char *name = p; 517618334Speter struct spec_list *sl; 517718334Speter int len; 517818334Speter 517918334Speter /* The string after the S/P is the name of a spec that is to be 518050599Sobrien processed. */ 518118334Speter while (*p && *p != ')' && *p != ']') 518218334Speter p++; 518318334Speter 518490277Sobrien /* See if it's in the list. */ 518518334Speter for (len = p - name, sl = specs; sl; sl = sl->next) 518650599Sobrien if (sl->name_len == len && !strncmp (sl->name, name, len)) 518718334Speter { 518850599Sobrien name = *(sl->ptr_spec); 518950599Sobrien#ifdef DEBUG_SPECS 519052520Sobrien notice ("Processing spec %c%s%c, which is '%s'\n", 519152520Sobrien c, sl->name, (c == '(') ? ')' : ']', name); 519250599Sobrien#endif 519318334Speter break; 519418334Speter } 519518334Speter 519618334Speter if (sl) 519718334Speter { 519818334Speter if (c == '(') 519918334Speter { 520090277Sobrien value = do_spec_1 (name, 0, NULL); 520118334Speter if (value != 0) 520218334Speter return value; 520318334Speter } 520418334Speter else 520518334Speter { 5206132733Skan char *x = alloca (strlen (name) * 2 + 1); 520718334Speter char *buf = x; 520852520Sobrien const char *y = name; 520950599Sobrien int flag = 0; 521018334Speter 521118334Speter /* Copy all of NAME into BUF, but put __ after 521290277Sobrien every -D and at the end of each arg. */ 521318334Speter while (1) 521418334Speter { 521518334Speter if (! strncmp (y, "-D", 2)) 521618334Speter { 521718334Speter *x++ = '-'; 521818334Speter *x++ = 'D'; 521918334Speter *x++ = '_'; 522018334Speter *x++ = '_'; 522118334Speter y += 2; 522250599Sobrien flag = 1; 522350599Sobrien continue; 522418334Speter } 522590277Sobrien else if (flag 522690277Sobrien && (*y == ' ' || *y == '\t' || *y == '=' 522790277Sobrien || *y == '}' || *y == 0)) 522818334Speter { 522918334Speter *x++ = '_'; 523018334Speter *x++ = '_'; 523150599Sobrien flag = 0; 523218334Speter } 523390277Sobrien if (*y == 0) 523450599Sobrien break; 523518334Speter else 523618334Speter *x++ = *y++; 523718334Speter } 523818334Speter *x = 0; 523918334Speter 524090277Sobrien value = do_spec_1 (buf, 0, NULL); 524118334Speter if (value != 0) 524218334Speter return value; 524318334Speter } 524418334Speter } 524518334Speter 524618334Speter /* Discard the closing paren or bracket. */ 524718334Speter if (*p) 524818334Speter p++; 524918334Speter } 525018334Speter break; 525118334Speter 525218334Speter default: 525390277Sobrien error ("spec failure: unrecognized spec option '%c'", c); 525490277Sobrien break; 525518334Speter } 525618334Speter break; 525718334Speter 525818334Speter case '\\': 525918334Speter /* Backslash: treat next character as ordinary. */ 526018334Speter c = *p++; 526118334Speter 5262132733Skan /* Fall through. */ 526318334Speter default: 526418334Speter /* Ordinary character: put it into the current argument. */ 526518334Speter obstack_1grow (&obstack, c); 526618334Speter arg_going = 1; 526718334Speter } 526818334Speter 5269117413Skan /* End of string. If we are processing a spec function, we need to 5270117413Skan end any pending argument. */ 5271117413Skan if (processing_spec_function && arg_going) 5272117413Skan { 5273117413Skan obstack_1grow (&obstack, 0); 5274117413Skan string = obstack_finish (&obstack); 5275117413Skan if (this_is_library_file) 5276117413Skan string = find_file (string); 5277117413Skan store_arg (string, delete_this_arg, this_is_output_file); 5278117413Skan if (this_is_output_file) 5279117413Skan outfiles[input_file_number] = string; 5280117413Skan arg_going = 0; 5281117413Skan } 5282117413Skan 528390277Sobrien return 0; 528418334Speter} 528518334Speter 5286117413Skan/* Look up a spec function. */ 5287117413Skan 5288117413Skanstatic const struct spec_function * 5289132733Skanlookup_spec_function (const char *name) 5290117413Skan{ 5291117413Skan static const struct spec_function * const spec_function_tables[] = 5292117413Skan { 5293117413Skan static_spec_functions, 5294117413Skan lang_specific_spec_functions, 5295117413Skan }; 5296117413Skan const struct spec_function *sf; 5297117413Skan unsigned int i; 5298117413Skan 5299117413Skan for (i = 0; i < ARRAY_SIZE (spec_function_tables); i++) 5300117413Skan { 5301117413Skan for (sf = spec_function_tables[i]; sf->name != NULL; sf++) 5302117413Skan if (strcmp (sf->name, name) == 0) 5303117413Skan return sf; 5304117413Skan } 5305117413Skan 5306117413Skan return NULL; 5307117413Skan} 5308117413Skan 5309117413Skan/* Evaluate a spec function. */ 5310117413Skan 5311117413Skanstatic const char * 5312132733Skaneval_spec_function (const char *func, const char *args) 5313117413Skan{ 5314117413Skan const struct spec_function *sf; 5315117413Skan const char *funcval; 5316117413Skan 5317117413Skan /* Saved spec processing context. */ 5318117413Skan int save_argbuf_index; 5319117413Skan int save_argbuf_length; 5320117413Skan const char **save_argbuf; 5321117413Skan 5322117413Skan int save_arg_going; 5323117413Skan int save_delete_this_arg; 5324117413Skan int save_this_is_output_file; 5325117413Skan int save_this_is_library_file; 5326117413Skan int save_input_from_pipe; 5327117413Skan const char *save_suffix_subst; 5328117413Skan 5329117413Skan 5330117413Skan sf = lookup_spec_function (func); 5331117413Skan if (sf == NULL) 5332117413Skan fatal ("unknown spec function `%s'", func); 5333117413Skan 5334117413Skan /* Push the spec processing context. */ 5335117413Skan save_argbuf_index = argbuf_index; 5336117413Skan save_argbuf_length = argbuf_length; 5337117413Skan save_argbuf = argbuf; 5338117413Skan 5339117413Skan save_arg_going = arg_going; 5340117413Skan save_delete_this_arg = delete_this_arg; 5341117413Skan save_this_is_output_file = this_is_output_file; 5342117413Skan save_this_is_library_file = this_is_library_file; 5343117413Skan save_input_from_pipe = input_from_pipe; 5344117413Skan save_suffix_subst = suffix_subst; 5345117413Skan 5346117413Skan /* Create a new spec processing context, and build the function 5347117413Skan arguments. */ 5348117413Skan 5349117413Skan alloc_args (); 5350117413Skan if (do_spec_2 (args) < 0) 5351117413Skan fatal ("error in args to spec function `%s'", func); 5352117413Skan 5353117413Skan /* argbuf_index is an index for the next argument to be inserted, and 5354117413Skan so contains the count of the args already inserted. */ 5355117413Skan 5356117413Skan funcval = (*sf->func) (argbuf_index, argbuf); 5357117413Skan 5358117413Skan /* Pop the spec processing context. */ 5359117413Skan argbuf_index = save_argbuf_index; 5360117413Skan argbuf_length = save_argbuf_length; 5361117413Skan free (argbuf); 5362117413Skan argbuf = save_argbuf; 5363117413Skan 5364117413Skan arg_going = save_arg_going; 5365117413Skan delete_this_arg = save_delete_this_arg; 5366117413Skan this_is_output_file = save_this_is_output_file; 5367117413Skan this_is_library_file = save_this_is_library_file; 5368117413Skan input_from_pipe = save_input_from_pipe; 5369117413Skan suffix_subst = save_suffix_subst; 5370117413Skan 5371117413Skan return funcval; 5372117413Skan} 5373117413Skan 5374117413Skan/* Handle a spec function call of the form: 5375117413Skan 5376117413Skan %:function(args) 5377117413Skan 5378117413Skan ARGS is processed as a spec in a separate context and split into an 5379117413Skan argument vector in the normal fashion. The function returns a string 5380117413Skan containing a spec which we then process in the caller's context, or 5381117413Skan NULL if no processing is required. */ 5382117413Skan 5383117413Skanstatic const char * 5384132733Skanhandle_spec_function (const char *p) 5385117413Skan{ 5386117413Skan char *func, *args; 5387117413Skan const char *endp, *funcval; 5388117413Skan int count; 5389117413Skan 5390117413Skan processing_spec_function++; 5391117413Skan 5392117413Skan /* Get the function name. */ 5393117413Skan for (endp = p; *endp != '\0'; endp++) 5394117413Skan { 5395117413Skan if (*endp == '(') /* ) */ 5396117413Skan break; 5397117413Skan /* Only allow [A-Za-z0-9], -, and _ in function names. */ 5398117413Skan if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_')) 5399117413Skan fatal ("malformed spec function name"); 5400117413Skan } 5401117413Skan if (*endp != '(') /* ) */ 5402117413Skan fatal ("no arguments for spec function"); 5403117413Skan func = save_string (p, endp - p); 5404117413Skan p = ++endp; 5405117413Skan 5406117413Skan /* Get the arguments. */ 5407117413Skan for (count = 0; *endp != '\0'; endp++) 5408117413Skan { 5409117413Skan /* ( */ 5410117413Skan if (*endp == ')') 5411117413Skan { 5412117413Skan if (count == 0) 5413117413Skan break; 5414117413Skan count--; 5415117413Skan } 5416117413Skan else if (*endp == '(') /* ) */ 5417117413Skan count++; 5418117413Skan } 5419117413Skan /* ( */ 5420117413Skan if (*endp != ')') 5421117413Skan fatal ("malformed spec function arguments"); 5422117413Skan args = save_string (p, endp - p); 5423117413Skan p = ++endp; 5424117413Skan 5425117413Skan /* p now points to just past the end of the spec function expression. */ 5426117413Skan 5427117413Skan funcval = eval_spec_function (func, args); 5428117413Skan if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0) 5429117413Skan p = NULL; 5430117413Skan 5431117413Skan free (func); 5432117413Skan free (args); 5433117413Skan 5434117413Skan processing_spec_function--; 5435117413Skan 5436117413Skan return p; 5437117413Skan} 5438117413Skan 5439132733Skan/* Inline subroutine of handle_braces. Returns true if the current 5440132733Skan input suffix matches the atom bracketed by ATOM and END_ATOM. */ 5441132733Skanstatic inline bool 5442132733Skaninput_suffix_matches (const char *atom, const char *end_atom) 5443132733Skan{ 5444132733Skan return (input_suffix 5445132733Skan && !strncmp (input_suffix, atom, end_atom - atom) 5446132733Skan && input_suffix[end_atom - atom] == '\0'); 5447132733Skan} 544818334Speter 5449132733Skan/* Inline subroutine of handle_braces. Returns true if a switch 5450132733Skan matching the atom bracketed by ATOM and END_ATOM appeared on the 5451132733Skan command line. */ 5452132733Skanstatic inline bool 5453132733Skanswitch_matches (const char *atom, const char *end_atom, int starred) 545418334Speter{ 5455132733Skan int i; 5456132733Skan int len = end_atom - atom; 5457132733Skan int plen = starred ? len : -1; 545818334Speter 5459132733Skan for (i = 0; i < n_switches; i++) 5460132733Skan if (!strncmp (switches[i].part1, atom, len) 5461132733Skan && (starred || switches[i].part1[len] == '\0') 5462132733Skan && check_live_switch (i, plen)) 5463132733Skan return true; 546450599Sobrien 5465132733Skan return false; 5466132733Skan} 546718334Speter 5468132733Skan/* Inline subroutine of handle_braces. Mark all of the switches which 5469132733Skan match ATOM (extends to END_ATOM; STARRED indicates whether there 5470132733Skan was a star after the atom) for later processing. */ 5471132733Skanstatic inline void 5472132733Skanmark_matching_switches (const char *atom, const char *end_atom, int starred) 5473132733Skan{ 5474132733Skan int i; 5475132733Skan int len = end_atom - atom; 5476132733Skan int plen = starred ? len : -1; 547790277Sobrien 5478132733Skan for (i = 0; i < n_switches; i++) 5479132733Skan if (!strncmp (switches[i].part1, atom, len) 5480132733Skan && (starred || switches[i].part1[len] == '\0') 5481132733Skan && check_live_switch (i, plen)) 5482132733Skan switches[i].ordering = 1; 5483132733Skan} 548450599Sobrien 5485132733Skan/* Inline subroutine of handle_braces. Process all the currently 5486132733Skan marked switches through give_switch, and clear the marks. */ 5487132733Skanstatic inline void 5488132733Skanprocess_marked_switches (void) 5489132733Skan{ 5490132733Skan int i; 549118334Speter 5492132733Skan for (i = 0; i < n_switches; i++) 5493132733Skan if (switches[i].ordering == 1) 5494132733Skan { 5495132733Skan switches[i].ordering = 0; 5496132733Skan give_switch (i, 0); 5497132733Skan } 5498132733Skan} 549918334Speter 5500132733Skan/* Handle a %{ ... } construct. P points just inside the leading {. 5501132733Skan Returns a pointer one past the end of the brace block, or 0 5502132733Skan if we call do_spec_1 and that returns -1. */ 550318334Speter 5504132733Skanstatic const char * 5505132733Skanhandle_braces (const char *p) 5506132733Skan{ 5507132733Skan const char *atom, *end_atom; 5508132733Skan const char *d_atom = NULL, *d_end_atom = NULL; 550990277Sobrien 5510132733Skan bool a_is_suffix; 5511132733Skan bool a_is_starred; 5512132733Skan bool a_is_negated; 5513132733Skan bool a_matched; 551450599Sobrien 5515132733Skan bool a_must_be_last = false; 5516132733Skan bool ordered_set = false; 5517132733Skan bool disjunct_set = false; 5518132733Skan bool disj_matched = false; 5519132733Skan bool disj_starred = true; 5520132733Skan bool n_way_choice = false; 5521132733Skan bool n_way_matched = false; 552250599Sobrien 5523132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0) 5524132733Skan 5525132733Skan do 552618334Speter { 5527132733Skan if (a_must_be_last) 5528132733Skan abort (); 552950599Sobrien 5530132733Skan /* Scan one "atom" (S in the description above of %{}, possibly 5531132733Skan with !, ., or * modifiers). */ 5532132733Skan a_matched = a_is_suffix = a_is_starred = a_is_negated = false; 553390277Sobrien 5534132733Skan SKIP_WHITE(); 5535132733Skan if (*p == '!') 5536132733Skan p++, a_is_negated = true; 553718334Speter 5538132733Skan SKIP_WHITE(); 5539132733Skan if (*p == '.') 5540132733Skan p++, a_is_suffix = true; 554118334Speter 5542132733Skan atom = p; 5543132733Skan while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '=' 5544132733Skan || *p == ',' || *p == '.' || *p == '@') 5545132733Skan p++; 5546132733Skan end_atom = p; 554718334Speter 5548132733Skan if (*p == '*') 5549132733Skan p++, a_is_starred = 1; 555090277Sobrien 5551132733Skan SKIP_WHITE(); 5552132733Skan if (*p == '&' || *p == '}') 5553132733Skan { 5554132733Skan /* Substitute the switch(es) indicated by the current atom. */ 5555132733Skan ordered_set = true; 5556132733Skan if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix 5557132733Skan || atom == end_atom) 5558132733Skan abort (); 555918334Speter 5560132733Skan mark_matching_switches (atom, end_atom, a_is_starred); 5561132733Skan 5562132733Skan if (*p == '}') 5563132733Skan process_marked_switches (); 5564132733Skan } 5565132733Skan else if (*p == '|' || *p == ':') 556618334Speter { 5567132733Skan /* Substitute some text if the current atom appears as a switch 5568132733Skan or suffix. */ 5569132733Skan disjunct_set = true; 5570132733Skan if (ordered_set) 5571132733Skan abort (); 557218334Speter 5573132733Skan if (atom == end_atom) 557418334Speter { 5575132733Skan if (!n_way_choice || disj_matched || *p == '|' 5576132733Skan || a_is_negated || a_is_suffix || a_is_starred) 5577132733Skan abort (); 5578132733Skan 5579132733Skan /* An empty term may appear as the last choice of an 5580132733Skan N-way choice set; it means "otherwise". */ 5581132733Skan a_must_be_last = true; 5582132733Skan disj_matched = !n_way_matched; 5583132733Skan disj_starred = false; 558418334Speter } 5585132733Skan else 558618334Speter { 5587132733Skan if (a_is_suffix && a_is_starred) 5588132733Skan abort (); 558918334Speter 5590132733Skan if (!a_is_starred) 5591132733Skan disj_starred = false; 559218334Speter 5593132733Skan /* Don't bother testing this atom if we already have a 5594132733Skan match. */ 5595132733Skan if (!disj_matched && !n_way_matched) 5596132733Skan { 5597132733Skan if (a_is_suffix) 5598132733Skan a_matched = input_suffix_matches (atom, end_atom); 5599132733Skan else 5600132733Skan a_matched = switch_matches (atom, end_atom, a_is_starred); 560118334Speter 5602132733Skan if (a_matched != a_is_negated) 5603132733Skan { 5604132733Skan disj_matched = true; 5605132733Skan d_atom = atom; 5606132733Skan d_end_atom = end_atom; 5607132733Skan } 5608132733Skan } 560918334Speter } 561018334Speter 5611132733Skan if (*p == ':') 561218334Speter { 5613132733Skan /* Found the body, that is, the text to substitute if the 5614132733Skan current disjunction matches. */ 5615132733Skan p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred, 5616132733Skan disj_matched && !n_way_matched); 5617132733Skan if (p == 0) 5618132733Skan return 0; 561918334Speter 5620132733Skan /* If we have an N-way choice, reset state for the next 5621132733Skan disjunction. */ 5622132733Skan if (*p == ';') 562318334Speter { 5624132733Skan n_way_choice = true; 5625132733Skan n_way_matched |= disj_matched; 5626132733Skan disj_matched = false; 5627132733Skan disj_starred = true; 5628132733Skan d_atom = d_end_atom = NULL; 562918334Speter } 563018334Speter } 563118334Speter } 563218334Speter else 5633132733Skan abort (); 5634132733Skan } 5635132733Skan while (*p++ != '}'); 563618334Speter 5637132733Skan return p; 5638132733Skan 5639132733Skan#undef SKIP_WHITE 5640132733Skan} 5641132733Skan 5642132733Skan/* Subroutine of handle_braces. Scan and process a brace substitution body 5643132733Skan (X in the description of %{} syntax). P points one past the colon; 5644132733Skan ATOM and END_ATOM bracket the first atom which was found to be true 5645132733Skan (present) in the current disjunction; STARRED indicates whether all 5646132733Skan the atoms in the current disjunction were starred (for syntax validation); 5647132733Skan MATCHED indicates whether the disjunction matched or not, and therefore 5648132733Skan whether or not the body is to be processed through do_spec_1 or just 5649132733Skan skipped. Returns a pointer to the closing } or ;, or 0 if do_spec_1 5650132733Skan returns -1. */ 5651132733Skan 5652132733Skanstatic const char * 5653132733Skanprocess_brace_body (const char *p, const char *atom, const char *end_atom, 5654132733Skan int starred, int matched) 5655132733Skan{ 5656132733Skan const char *body, *end_body; 5657132733Skan unsigned int nesting_level; 5658132733Skan bool have_subst = false; 5659132733Skan 5660132733Skan /* Locate the closing } or ;, honoring nested braces. 5661132733Skan Trim trailing whitespace. */ 5662132733Skan body = p; 5663132733Skan nesting_level = 1; 5664132733Skan for (;;) 5665132733Skan { 5666132733Skan if (*p == '{') 5667132733Skan nesting_level++; 5668132733Skan else if (*p == '}') 566918334Speter { 5670132733Skan if (!--nesting_level) 5671132733Skan break; 567218334Speter } 5673132733Skan else if (*p == ';' && nesting_level == 1) 5674132733Skan break; 5675132733Skan else if (*p == '%' && p[1] == '*' && nesting_level == 1) 5676132733Skan have_subst = true; 5677132733Skan else if (*p == '\0') 5678132733Skan abort (); 5679132733Skan p++; 568018334Speter } 568118334Speter 5682132733Skan end_body = p; 5683132733Skan while (end_body[-1] == ' ' || end_body[-1] == '\t') 5684132733Skan end_body--; 568550599Sobrien 5686132733Skan if (have_subst && !starred) 5687132733Skan abort (); 5688132733Skan 5689132733Skan if (matched) 569090277Sobrien { 5691132733Skan /* Copy the substitution body to permanent storage and execute it. 5692132733Skan If have_subst is false, this is a simple matter of running the 5693132733Skan body through do_spec_1... */ 5694132733Skan char *string = save_string (body, end_body - body); 5695132733Skan if (!have_subst) 5696132733Skan { 5697132733Skan if (do_spec_1 (string, 0, NULL) < 0) 5698132733Skan return 0; 5699132733Skan } 5700132733Skan else 5701132733Skan { 5702132733Skan /* ... but if have_subst is true, we have to process the 5703132733Skan body once for each matching switch, with %* set to the 5704132733Skan variant part of the switch. */ 5705132733Skan unsigned int hard_match_len = end_atom - atom; 5706132733Skan int i; 570790277Sobrien 5708132733Skan for (i = 0; i < n_switches; i++) 5709132733Skan if (!strncmp (switches[i].part1, atom, hard_match_len) 5710132733Skan && check_live_switch (i, hard_match_len)) 5711132733Skan { 5712132733Skan if (do_spec_1 (string, 0, 5713132733Skan &switches[i].part1[hard_match_len]) < 0) 5714132733Skan return 0; 5715132733Skan /* Pass any arguments this switch has. */ 5716132733Skan give_switch (i, 1); 5717132733Skan suffix_subst = NULL; 5718132733Skan } 5719132733Skan } 572090277Sobrien } 572190277Sobrien 5722132733Skan return p; 572318334Speter} 572418334Speter 572518334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch 572618334Speter on the command line. PREFIX_LENGTH is the length of XXX in an {XXX*} 572718334Speter spec, or -1 if either exact match or %* is used. 572818334Speter 572918334Speter A -O switch is obsoleted by a later -O switch. A -f, -m, or -W switch 573018334Speter whose value does not begin with "no-" is obsoleted by the same value 573118334Speter with the "no-", similarly for a switch with the "no-" prefix. */ 573218334Speter 573318334Speterstatic int 5734132733Skancheck_live_switch (int switchnum, int prefix_length) 573518334Speter{ 573652520Sobrien const char *name = switches[switchnum].part1; 573718334Speter int i; 573818334Speter 573918334Speter /* In the common case of {<at-most-one-letter>*}, a negating 574018334Speter switch would always match, so ignore that case. We will just 574118334Speter send the conflicting switches to the compiler phase. */ 574218334Speter if (prefix_length >= 0 && prefix_length <= 1) 574318334Speter return 1; 574418334Speter 574518334Speter /* If we already processed this switch and determined if it was 574618334Speter live or not, return our past determination. */ 574718334Speter if (switches[switchnum].live_cond != 0) 574818334Speter return switches[switchnum].live_cond > 0; 574918334Speter 575018334Speter /* Now search for duplicate in a manner that depends on the name. */ 575118334Speter switch (*name) 575218334Speter { 575318334Speter case 'O': 575490277Sobrien for (i = switchnum + 1; i < n_switches; i++) 575590277Sobrien if (switches[i].part1[0] == 'O') 575690277Sobrien { 575790277Sobrien switches[switchnum].validated = 1; 575890277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 575990277Sobrien return 0; 576090277Sobrien } 576118334Speter break; 576218334Speter 576318334Speter case 'W': case 'f': case 'm': 576418334Speter if (! strncmp (name + 1, "no-", 3)) 576518334Speter { 576650599Sobrien /* We have Xno-YYY, search for XYYY. */ 576718334Speter for (i = switchnum + 1; i < n_switches; i++) 576818334Speter if (switches[i].part1[0] == name[0] 576918334Speter && ! strcmp (&switches[i].part1[1], &name[4])) 577090277Sobrien { 577190277Sobrien switches[switchnum].validated = 1; 577290277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 577390277Sobrien return 0; 577490277Sobrien } 577518334Speter } 577618334Speter else 577718334Speter { 577818334Speter /* We have XYYY, search for Xno-YYY. */ 577918334Speter for (i = switchnum + 1; i < n_switches; i++) 578018334Speter if (switches[i].part1[0] == name[0] 578118334Speter && switches[i].part1[1] == 'n' 578218334Speter && switches[i].part1[2] == 'o' 578318334Speter && switches[i].part1[3] == '-' 578418334Speter && !strcmp (&switches[i].part1[4], &name[1])) 578590277Sobrien { 578690277Sobrien switches[switchnum].validated = 1; 578790277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 578890277Sobrien return 0; 578990277Sobrien } 579018334Speter } 579118334Speter break; 579218334Speter } 579318334Speter 579418334Speter /* Otherwise the switch is live. */ 579590277Sobrien switches[switchnum].live_cond = SWITCH_LIVE; 579618334Speter return 1; 579718334Speter} 579818334Speter 579918334Speter/* Pass a switch to the current accumulating command 580018334Speter in the same form that we received it. 580118334Speter SWITCHNUM identifies the switch; it is an index into 580218334Speter the vector of switches gcc received, which is `switches'. 580318334Speter This cannot fail since it never finishes a command line. 580418334Speter 5805132733Skan If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. */ 580618334Speter 580718334Speterstatic void 5808132733Skangive_switch (int switchnum, int omit_first_word) 580918334Speter{ 581090277Sobrien if (switches[switchnum].live_cond == SWITCH_IGNORE) 581190277Sobrien return; 581290277Sobrien 581318334Speter if (!omit_first_word) 581418334Speter { 581590277Sobrien do_spec_1 ("-", 0, NULL); 581690277Sobrien do_spec_1 (switches[switchnum].part1, 1, NULL); 581718334Speter } 581850599Sobrien 581918334Speter if (switches[switchnum].args != 0) 582018334Speter { 582190277Sobrien const char **p; 582218334Speter for (p = switches[switchnum].args; *p; p++) 582318334Speter { 582490277Sobrien const char *arg = *p; 582590277Sobrien 5826132733Skan do_spec_1 (" ", 0, NULL); 582790277Sobrien if (suffix_subst) 582890277Sobrien { 582990277Sobrien unsigned length = strlen (arg); 583090277Sobrien int dot = 0; 583190277Sobrien 583290277Sobrien while (length-- && !IS_DIR_SEPARATOR (arg[length])) 583390277Sobrien if (arg[length] == '.') 583490277Sobrien { 583590277Sobrien ((char *)arg)[length] = 0; 583690277Sobrien dot = 1; 583790277Sobrien break; 583890277Sobrien } 583990277Sobrien do_spec_1 (arg, 1, NULL); 584090277Sobrien if (dot) 584190277Sobrien ((char *)arg)[length] = '.'; 584290277Sobrien do_spec_1 (suffix_subst, 1, NULL); 584390277Sobrien } 584490277Sobrien else 584590277Sobrien do_spec_1 (arg, 1, NULL); 584618334Speter } 584718334Speter } 584850599Sobrien 584990277Sobrien do_spec_1 (" ", 0, NULL); 585052520Sobrien switches[switchnum].validated = 1; 585118334Speter} 585218334Speter 585318334Speter/* Search for a file named NAME trying various prefixes including the 585418334Speter user's -B prefix and some standard ones. 585518334Speter Return the absolute file name found. If nothing is found, return NAME. */ 585618334Speter 585752520Sobrienstatic const char * 5858132733Skanfind_file (const char *name) 585918334Speter{ 586018334Speter char *newname; 586118334Speter 586218334Speter /* Try multilib_dir if it is defined. */ 5863104763Skan if (multilib_os_dir != NULL) 586418334Speter { 5865104763Skan newname = find_a_file (&startfile_prefixes, name, R_OK, 1); 586618334Speter 586718334Speter /* If we don't find it in the multi library dir, then fall 586818334Speter through and look for it in the normal places. */ 586918334Speter if (newname != NULL) 587018334Speter return newname; 587118334Speter } 587218334Speter 5873104763Skan newname = find_a_file (&startfile_prefixes, name, R_OK, 0); 587418334Speter return newname ? newname : name; 587518334Speter} 587618334Speter 587718334Speter/* Determine whether a directory exists. If LINKER, return 0 for 587818334Speter certain fixed names not needed by the linker. If not LINKER, it is 587918334Speter only important to return 0 if the host machine has a small ARG_MAX 588018334Speter limit. */ 588118334Speter 588218334Speterstatic int 5883132733Skanis_directory (const char *path1, const char *path2, int linker) 588418334Speter{ 588518334Speter int len1 = strlen (path1); 588618334Speter int len2 = strlen (path2); 5887132733Skan char *path = alloca (3 + len1 + len2); 588818334Speter char *cp; 588918334Speter struct stat st; 589018334Speter 589118334Speter#ifndef SMALL_ARG_MAX 589218334Speter if (! linker) 589318334Speter return 1; 589418334Speter#endif 589518334Speter 589618334Speter /* Construct the path from the two parts. Ensure the string ends with "/.". 589718334Speter The resulting path will be a directory even if the given path is a 589818334Speter symbolic link. */ 589952520Sobrien memcpy (path, path1, len1); 590052520Sobrien memcpy (path + len1, path2, len2); 590118334Speter cp = path + len1 + len2; 590252520Sobrien if (!IS_DIR_SEPARATOR (cp[-1])) 590318334Speter *cp++ = DIR_SEPARATOR; 590418334Speter *cp++ = '.'; 590518334Speter *cp = '\0'; 590618334Speter 590751232Sbde#ifndef FREEBSD_NATIVE 590818334Speter /* Exclude directories that the linker is known to search. */ 590918334Speter if (linker 591018334Speter && ((cp - path == 6 591190277Sobrien && strcmp (path, concat (dir_separator_str, "lib", 591290277Sobrien dir_separator_str, ".", NULL)) == 0) 591318334Speter || (cp - path == 10 591490277Sobrien && strcmp (path, concat (dir_separator_str, "usr", 591590277Sobrien dir_separator_str, "lib", 591690277Sobrien dir_separator_str, ".", NULL)) == 0))) 591718334Speter return 0; 591851232Sbde#endif /* FREEBSD_NATIVE */ 591918334Speter 592018334Speter return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode)); 592118334Speter} 592290277Sobrien 592390277Sobrien/* Set up the various global variables to indicate that we're processing 592490277Sobrien the input file named FILENAME. */ 592590277Sobrien 592690277Sobrienvoid 5927132733Skanset_input (const char *filename) 592890277Sobrien{ 592990277Sobrien const char *p; 593090277Sobrien 593190277Sobrien input_filename = filename; 593290277Sobrien input_filename_length = strlen (input_filename); 593390277Sobrien 593490277Sobrien input_basename = input_filename; 593590277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 593690277Sobrien /* Skip drive name so 'x:foo' is handled properly. */ 593790277Sobrien if (input_basename[1] == ':') 593890277Sobrien input_basename += 2; 593990277Sobrien#endif 594090277Sobrien for (p = input_basename; *p; p++) 594190277Sobrien if (IS_DIR_SEPARATOR (*p)) 594290277Sobrien input_basename = p + 1; 594390277Sobrien 594490277Sobrien /* Find a suffix starting with the last period, 594590277Sobrien and set basename_length to exclude that suffix. */ 594690277Sobrien basename_length = strlen (input_basename); 594790277Sobrien suffixed_basename_length = basename_length; 594890277Sobrien p = input_basename + basename_length; 594990277Sobrien while (p != input_basename && *p != '.') 595090277Sobrien --p; 595190277Sobrien if (*p == '.' && p != input_basename) 595290277Sobrien { 595390277Sobrien basename_length = p - input_basename; 595490277Sobrien input_suffix = p + 1; 595590277Sobrien } 595690277Sobrien else 595790277Sobrien input_suffix = ""; 5958117413Skan 595990277Sobrien /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then 596090277Sobrien we will need to do a stat on the input_filename. The 596190277Sobrien INPUT_STAT_SET signals that the stat is needed. */ 596290277Sobrien input_stat_set = 0; 596390277Sobrien} 596418334Speter 596518334Speter/* On fatal signals, delete all the temporary files. */ 596618334Speter 596718334Speterstatic void 5968132733Skanfatal_error (int signum) 596918334Speter{ 597018334Speter signal (signum, SIG_DFL); 597118334Speter delete_failure_queue (); 597218334Speter delete_temp_files (); 597318334Speter /* Get the same signal again, this time not handled, 597418334Speter so its normal effect occurs. */ 597518334Speter kill (getpid (), signum); 597618334Speter} 597718334Speter 5978132733Skanextern int main (int, const char **); 597990277Sobrien 598018334Speterint 5981132733Skanmain (int argc, const char **argv) 598218334Speter{ 598390277Sobrien size_t i; 598418334Speter int value; 598518334Speter int linker_was_run = 0; 5986132733Skan int num_linker_inputs = 0; 598718334Speter char *explicit_link_files; 598818334Speter char *specs_file; 598952520Sobrien const char *p; 599050599Sobrien struct user_specs *uptr; 599118334Speter 599218334Speter p = argv[0] + strlen (argv[0]); 599352520Sobrien while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) 599452520Sobrien --p; 599518334Speter programname = p; 599618334Speter 599790277Sobrien xmalloc_set_program_name (programname); 599890277Sobrien 599990277Sobrien#ifdef GCC_DRIVER_HOST_INITIALIZATION 600090277Sobrien /* Perform host dependent initialization when needed. */ 600190277Sobrien GCC_DRIVER_HOST_INITIALIZATION; 600252520Sobrien#endif 600352520Sobrien 600490277Sobrien gcc_init_libintl (); 600590277Sobrien 600618334Speter if (signal (SIGINT, SIG_IGN) != SIG_IGN) 600718334Speter signal (SIGINT, fatal_error); 600818334Speter#ifdef SIGHUP 600918334Speter if (signal (SIGHUP, SIG_IGN) != SIG_IGN) 601018334Speter signal (SIGHUP, fatal_error); 601118334Speter#endif 601218334Speter if (signal (SIGTERM, SIG_IGN) != SIG_IGN) 601318334Speter signal (SIGTERM, fatal_error); 601418334Speter#ifdef SIGPIPE 601518334Speter if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) 601618334Speter signal (SIGPIPE, fatal_error); 601718334Speter#endif 601890277Sobrien#ifdef SIGCHLD 601990277Sobrien /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will 602090277Sobrien receive the signal. A different setting is inheritable */ 602190277Sobrien signal (SIGCHLD, SIG_DFL); 602290277Sobrien#endif 602318334Speter 6024117413Skan /* Allocate the argument vector. */ 6025117413Skan alloc_args (); 602618334Speter 602718334Speter obstack_init (&obstack); 602818334Speter 602950599Sobrien /* Build multilib_select, et. al from the separate lines that make up each 603050599Sobrien multilib selection. */ 603150599Sobrien { 603290277Sobrien const char *const *q = multilib_raw; 603350599Sobrien int need_space; 603450599Sobrien 603550599Sobrien obstack_init (&multilib_obstack); 603650599Sobrien while ((p = *q++) != (char *) 0) 603750599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 603850599Sobrien 603950599Sobrien obstack_1grow (&multilib_obstack, 0); 604050599Sobrien multilib_select = obstack_finish (&multilib_obstack); 604150599Sobrien 604250599Sobrien q = multilib_matches_raw; 604350599Sobrien while ((p = *q++) != (char *) 0) 604450599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 604550599Sobrien 604650599Sobrien obstack_1grow (&multilib_obstack, 0); 604750599Sobrien multilib_matches = obstack_finish (&multilib_obstack); 604850599Sobrien 604990277Sobrien q = multilib_exclusions_raw; 605090277Sobrien while ((p = *q++) != (char *) 0) 605190277Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 605290277Sobrien 605390277Sobrien obstack_1grow (&multilib_obstack, 0); 605490277Sobrien multilib_exclusions = obstack_finish (&multilib_obstack); 605590277Sobrien 605650599Sobrien need_space = FALSE; 605790277Sobrien for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++) 605850599Sobrien { 605950599Sobrien if (need_space) 606050599Sobrien obstack_1grow (&multilib_obstack, ' '); 606150599Sobrien obstack_grow (&multilib_obstack, 606250599Sobrien multilib_defaults_raw[i], 606350599Sobrien strlen (multilib_defaults_raw[i])); 606450599Sobrien need_space = TRUE; 606550599Sobrien } 606650599Sobrien 606750599Sobrien obstack_1grow (&multilib_obstack, 0); 606850599Sobrien multilib_defaults = obstack_finish (&multilib_obstack); 606950599Sobrien } 607050599Sobrien 607118334Speter /* Set up to remember the pathname of gcc and any options 607218334Speter needed for collect. We use argv[0] instead of programname because 607318334Speter we need the complete pathname. */ 607418334Speter obstack_init (&collect_obstack); 607590277Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1); 607690277Sobrien obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1); 607718334Speter putenv (obstack_finish (&collect_obstack)); 607818334Speter 607918334Speter#ifdef INIT_ENVIRONMENT 608018334Speter /* Set up any other necessary machine specific environment variables. */ 608118334Speter putenv (INIT_ENVIRONMENT); 608218334Speter#endif 608318334Speter 608418334Speter /* Make a table of what switches there are (switches, n_switches). 608518334Speter Make a table of specified input files (infiles, n_infiles). 608618334Speter Decode switches that are handled locally. */ 608718334Speter 608818334Speter process_command (argc, argv); 608918334Speter 609018334Speter /* Initialize the vector of specs to just the default. 609118334Speter This means one element containing 0s, as a terminator. */ 609218334Speter 6093132733Skan compilers = xmalloc (sizeof default_compilers); 6094132733Skan memcpy (compilers, default_compilers, sizeof default_compilers); 609518334Speter n_compilers = n_default_compilers; 609618334Speter 609718334Speter /* Read specs from a file if there is one. */ 609818334Speter 609991561Sobrien#ifdef FREEBSD_NATIVE 610091561Sobrien just_machine_suffix = ""; 610191561Sobrien#else /* FREEBSD_NATIVE */ 610250599Sobrien machine_suffix = concat (spec_machine, dir_separator_str, 610390277Sobrien spec_version, dir_separator_str, NULL); 610490277Sobrien just_machine_suffix = concat (spec_machine, dir_separator_str, NULL); 610550599Sobrien#endif /* FREEBSD_NATIVE */ 610618334Speter 6107104763Skan specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, 0); 610818334Speter /* Read the specs file unless it is a default one. */ 610918334Speter if (specs_file != 0 && strcmp (specs_file, "specs")) 611050599Sobrien read_specs (specs_file, TRUE); 611150599Sobrien else 611250599Sobrien init_spec (); 611318334Speter 611450599Sobrien /* We need to check standard_exec_prefix/just_machine_suffix/specs 611590277Sobrien for any override of as, ld and libraries. */ 611697902Sobrien specs_file = (char *) alloca (strlen (FBSD_DATA_PREFIX) 611750599Sobrien + strlen (just_machine_suffix) 611850599Sobrien + sizeof ("specs")); 611950599Sobrien 612097902Sobrien strcpy (specs_file, FBSD_DATA_PREFIX); 612150599Sobrien strcat (specs_file, just_machine_suffix); 612250599Sobrien strcat (specs_file, "specs"); 612350599Sobrien if (access (specs_file, R_OK) == 0) 612450599Sobrien read_specs (specs_file, TRUE); 612590277Sobrien 6126132733Skan /* Process any configure-time defaults specified for the command line 6127132733Skan options, via OPTION_DEFAULT_SPECS. */ 6128132733Skan for (i = 0; i < ARRAY_SIZE (option_default_specs); i++) 6129132733Skan do_option_spec (option_default_specs[i].name, 6130132733Skan option_default_specs[i].spec); 6131132733Skan 6132132733Skan /* Process DRIVER_SELF_SPECS, adding any new options to the end 6133132733Skan of the command line. */ 6134132733Skan 6135132733Skan for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++) 6136132733Skan do_self_spec (driver_self_specs[i]); 6137132733Skan 6138132733Skan /* If not cross-compiling, look for executables in the standard 6139132733Skan places. */ 6140132733Skan if (*cross_compile == '0') 614118334Speter { 614290277Sobrien if (*md_exec_prefix) 614390277Sobrien { 614490277Sobrien add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 6145104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 614690277Sobrien } 6147132733Skan } 614818334Speter 6149132733Skan /* Process sysroot_suffix_spec. */ 6150132733Skan if (*sysroot_suffix_spec != 0 6151132733Skan && do_spec_2 (sysroot_suffix_spec) == 0) 6152132733Skan { 6153132733Skan if (argbuf_index > 1) 6154132733Skan error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC."); 6155132733Skan else if (argbuf_index == 1) 6156132733Skan target_sysroot_suffix = xstrdup (argbuf[argbuf_index -1]); 6157132733Skan } 6158132733Skan 6159132733Skan /* Process sysroot_hdrs_suffix_spec. */ 6160132733Skan if (*sysroot_hdrs_suffix_spec != 0 6161132733Skan && do_spec_2 (sysroot_hdrs_suffix_spec) == 0) 6162132733Skan { 6163132733Skan if (argbuf_index > 1) 6164132733Skan error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC."); 6165132733Skan else if (argbuf_index == 1) 6166132733Skan target_sysroot_hdrs_suffix = xstrdup (argbuf[argbuf_index -1]); 6167132733Skan } 6168132733Skan 6169132733Skan /* Look for startfiles in the standard places. */ 6170132733Skan if (*startfile_prefix_spec != 0 6171132733Skan && do_spec_2 (startfile_prefix_spec) == 0 6172132733Skan && do_spec_1 (" ", 0, NULL) == 0) 6173132733Skan { 6174132733Skan int ndx; 6175132733Skan for (ndx = 0; ndx < argbuf_index; ndx++) 6176132733Skan add_sysrooted_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS", 6177132733Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 6178132733Skan } 6179132733Skan /* We should eventually get rid of all these and stick to 6180132733Skan startfile_prefix_spec exclusively. */ 6181132733Skan else if (*cross_compile == '0' || target_system_root) 6182132733Skan { 6183132733Skan if (*md_exec_prefix) 6184132733Skan add_sysrooted_prefix (&startfile_prefixes, md_exec_prefix, "GCC", 6185132733Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 6186132733Skan 618790277Sobrien if (*md_startfile_prefix) 6188132733Skan add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix, 6189132733Skan "GCC", PREFIX_PRIORITY_LAST, 0, NULL, 1); 619018334Speter 619190277Sobrien if (*md_startfile_prefix_1) 6192132733Skan add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix_1, 6193132733Skan "GCC", PREFIX_PRIORITY_LAST, 0, NULL, 1); 619418334Speter 619518334Speter /* If standard_startfile_prefix is relative, base it on 619618334Speter standard_exec_prefix. This lets us move the installed tree 619718334Speter as a unit. If GCC_EXEC_PREFIX is defined, base 6198132733Skan standard_startfile_prefix on that as well. 6199132733Skan 6200132733Skan If the prefix is relative, only search it for native compilers; 6201132733Skan otherwise we will search a directory containing host libraries. */ 6202132733Skan if (IS_ABSOLUTE_PATH (standard_startfile_prefix)) 6203132733Skan add_sysrooted_prefix (&startfile_prefixes, 6204132733Skan standard_startfile_prefix, "BINUTILS", 6205132733Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 6206132733Skan else if (*cross_compile == '0') 620718334Speter { 620818334Speter if (gcc_exec_prefix) 620918334Speter add_prefix (&startfile_prefixes, 621050599Sobrien concat (gcc_exec_prefix, machine_suffix, 621190277Sobrien standard_startfile_prefix, NULL), 6212104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); 621318334Speter add_prefix (&startfile_prefixes, 621450599Sobrien concat (standard_exec_prefix, 621550599Sobrien machine_suffix, 621690277Sobrien standard_startfile_prefix, NULL), 6217104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); 621890277Sobrien } 621918334Speter 622018346Speter#ifndef FREEBSD_NATIVE 6221132733Skan add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_1, 6222132733Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); 6223132733Skan add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_2, 6224132733Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); 622591561Sobrien#endif /* not FREEBSD_NATIVE */ 622618334Speter#if 0 /* Can cause surprises, and one can use -B./ instead. */ 622790277Sobrien add_prefix (&startfile_prefixes, "./", NULL, 6228104763Skan PREFIX_PRIORITY_LAST, 1, NULL, 0); 622918334Speter#endif 623018334Speter } 623118334Speter 623252520Sobrien /* Process any user specified specs in the order given on the command 623352520Sobrien line. */ 623452520Sobrien for (uptr = user_specs_head; uptr; uptr = uptr->next) 623552520Sobrien { 6236104763Skan char *filename = find_a_file (&startfile_prefixes, uptr->filename, 6237104763Skan R_OK, 0); 623852520Sobrien read_specs (filename ? filename : uptr->filename, FALSE); 623952520Sobrien } 624052520Sobrien 624118334Speter /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */ 624218334Speter if (gcc_exec_prefix) 624390277Sobrien gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 624490277Sobrien spec_version, dir_separator_str, NULL); 624518334Speter 624618334Speter /* Now we have the specs. 624718334Speter Set the `valid' bits for switches that match anything in any spec. */ 624818334Speter 624918334Speter validate_all_switches (); 625018334Speter 625118334Speter /* Now that we have the switches and the specs, set 625218334Speter the subdirectory based on the options. */ 625318334Speter set_multilib_dir (); 625418334Speter 625518334Speter /* Warn about any switches that no pass was interested in. */ 625618334Speter 625790277Sobrien for (i = 0; (int) i < n_switches; i++) 625852520Sobrien if (! switches[i].validated) 625918334Speter error ("unrecognized option `-%s'", switches[i].part1); 626018334Speter 626118334Speter /* Obey some of the options. */ 626218334Speter 626318334Speter if (print_search_dirs) 626418334Speter { 626590277Sobrien printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix); 626690277Sobrien printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0)); 626790277Sobrien printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0)); 626890277Sobrien return (0); 626918334Speter } 627018334Speter 627118334Speter if (print_file_name) 627218334Speter { 627318334Speter printf ("%s\n", find_file (print_file_name)); 627490277Sobrien return (0); 627518334Speter } 627618334Speter 627718334Speter if (print_prog_name) 627818334Speter { 6279104763Skan char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0); 628018334Speter printf ("%s\n", (newname ? newname : print_prog_name)); 628190277Sobrien return (0); 628218334Speter } 628318334Speter 628418334Speter if (print_multi_lib) 628518334Speter { 628618334Speter print_multilib_info (); 628790277Sobrien return (0); 628818334Speter } 628918334Speter 629018334Speter if (print_multi_directory) 629118334Speter { 629218334Speter if (multilib_dir == NULL) 629318334Speter printf (".\n"); 629418334Speter else 629518334Speter printf ("%s\n", multilib_dir); 629690277Sobrien return (0); 629718334Speter } 629818334Speter 6299104763Skan if (print_multi_os_directory) 6300104763Skan { 6301104763Skan if (multilib_os_dir == NULL) 6302104763Skan printf (".\n"); 6303104763Skan else 6304104763Skan printf ("%s\n", multilib_os_dir); 6305104763Skan return (0); 6306104763Skan } 6307104763Skan 630890277Sobrien if (target_help_flag) 630990277Sobrien { 631090277Sobrien /* Print if any target specific options. */ 631190277Sobrien 631290277Sobrien /* We do not exit here. Instead we have created a fake input file 631390277Sobrien called 'target-dummy' which needs to be compiled, and we pass this 631490277Sobrien on to the various sub-processes, along with the --target-help 631590277Sobrien switch. */ 631690277Sobrien } 631790277Sobrien 631850599Sobrien if (print_help_list) 631950599Sobrien { 632050599Sobrien display_help (); 632150599Sobrien 632250599Sobrien if (! verbose_flag) 632350599Sobrien { 632490277Sobrien printf (_("\nFor bug reporting instructions, please see:\n")); 6325117413Skan printf ("%s.\n", bug_report_url); 632690277Sobrien 632790277Sobrien return (0); 632850599Sobrien } 632950599Sobrien 633050599Sobrien /* We do not exit here. Instead we have created a fake input file 633150599Sobrien called 'help-dummy' which needs to be compiled, and we pass this 633290277Sobrien on the various sub-processes, along with the --help switch. */ 633350599Sobrien } 633490277Sobrien 633518334Speter if (verbose_flag) 633618334Speter { 633750599Sobrien int n; 633890277Sobrien const char *thrmod; 633950599Sobrien 634090277Sobrien notice ("Configured with: %s\n", configuration_arguments); 634190277Sobrien 634290277Sobrien#ifdef THREAD_MODEL_SPEC 634390277Sobrien /* We could have defined THREAD_MODEL_SPEC to "%*" by default, 634490277Sobrien but there's no point in doing all this processing just to get 634590277Sobrien thread_model back. */ 634690277Sobrien obstack_init (&obstack); 634790277Sobrien do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); 634890277Sobrien obstack_1grow (&obstack, '\0'); 634990277Sobrien thrmod = obstack_finish (&obstack); 635090277Sobrien#else 635190277Sobrien thrmod = thread_model; 635290277Sobrien#endif 635390277Sobrien 635490277Sobrien notice ("Thread model: %s\n", thrmod); 635590277Sobrien 635650599Sobrien /* compiler_version is truncated at the first space when initialized 635750599Sobrien from version string, so truncate version_string at the first space 635850599Sobrien before comparing. */ 635950599Sobrien for (n = 0; version_string[n]; n++) 636050599Sobrien if (version_string[n] == ' ') 636150599Sobrien break; 636250599Sobrien 636350599Sobrien if (! strncmp (version_string, compiler_version, n) 636450599Sobrien && compiler_version[n] == 0) 636552520Sobrien notice ("gcc version %s\n", version_string); 636618334Speter else 636752520Sobrien notice ("gcc driver version %s executing gcc version %s\n", 636852520Sobrien version_string, compiler_version); 636918334Speter 637018334Speter if (n_infiles == 0) 637190277Sobrien return (0); 637218334Speter } 637318334Speter 637450599Sobrien if (n_infiles == added_libraries) 637518346Speter fatal ("No input files specified"); 637618334Speter 637718334Speter /* Make a place to record the compiler output file names 637818334Speter that correspond to the input files. */ 637918334Speter 638050599Sobrien i = n_infiles; 638150599Sobrien i += lang_specific_extra_outfiles; 6382132733Skan outfiles = xcalloc (i, sizeof (char *)); 638318334Speter 638418334Speter /* Record which files were specified explicitly as link input. */ 638518334Speter 638690277Sobrien explicit_link_files = xcalloc (1, n_infiles); 638718334Speter 6388132733Skan if (combine_inputs) 638918334Speter { 6390132733Skan int lang_n_infiles = 0; 6391132733Skan for (i = 0; (int) i < n_infiles; i++) 6392132733Skan { 6393132733Skan const char *name = infiles[i].name; 6394132733Skan struct compiler *compiler 6395132733Skan = lookup_compiler (name, strlen (name), infiles[i].language); 6396132733Skan if (compiler == NULL) 6397132733Skan error ("%s: linker input file unused because linking not done", 6398132733Skan name); 6399132733Skan else if (lang_n_infiles > 0 && compiler != input_file_compiler) 6400132733Skan fatal ("cannot specify -o with -c or -S and multiple languages"); 6401132733Skan else 6402132733Skan { 6403132733Skan lang_n_infiles++; 6404132733Skan input_file_compiler = compiler; 6405132733Skan } 6406132733Skan } 6407132733Skan } 6408132733Skan 6409132733Skan for (i = 0; (int) i < (combine_inputs ? 1 : n_infiles); i++) 6410132733Skan { 641118334Speter int this_file_error = 0; 641218334Speter 641318334Speter /* Tell do_spec what to substitute for %i. */ 641418334Speter 641518334Speter input_file_number = i; 641690277Sobrien set_input (infiles[i].name); 641718334Speter 641818334Speter /* Use the same thing in %o, unless cp->spec says otherwise. */ 641918334Speter 642018334Speter outfiles[i] = input_filename; 642118334Speter 642218334Speter /* Figure out which compiler from the file's suffix. */ 642318334Speter 6424132733Skan if (! combine_inputs) 6425132733Skan input_file_compiler 6426132733Skan = lookup_compiler (infiles[i].name, input_filename_length, 6427132733Skan infiles[i].language); 6428117413Skan 642990277Sobrien if (input_file_compiler) 643018334Speter { 643118334Speter /* Ok, we found an applicable compiler. Run its spec. */ 643218334Speter 643390277Sobrien if (input_file_compiler->spec[0] == '#') 643418334Speter { 643590277Sobrien error ("%s: %s compiler not installed on this system", 643690277Sobrien input_filename, &input_file_compiler->spec[1]); 643790277Sobrien this_file_error = 1; 643818334Speter } 643918334Speter else 644090277Sobrien { 644190277Sobrien value = do_spec (input_file_compiler->spec); 644290277Sobrien if (value < 0) 644390277Sobrien this_file_error = 1; 644490277Sobrien } 644518334Speter } 644618334Speter 644718334Speter /* If this file's name does not contain a recognized suffix, 644818334Speter record it as explicit linker input. */ 644918334Speter 645018334Speter else 645118334Speter explicit_link_files[i] = 1; 645218334Speter 645318334Speter /* Clear the delete-on-failure queue, deleting the files in it 645418334Speter if this compilation failed. */ 645518334Speter 645618334Speter if (this_file_error) 645718334Speter { 645818334Speter delete_failure_queue (); 645918334Speter error_count++; 646018334Speter } 646118334Speter /* If this compilation succeeded, don't delete those files later. */ 646218334Speter clear_failure_queue (); 646318334Speter } 646418334Speter 646590277Sobrien /* Reset the output file name to the first input file name, for use 646690277Sobrien with %b in LINK_SPEC on a target that prefers not to emit a.out 646790277Sobrien by default. */ 646890277Sobrien if (n_infiles > 0) 646990277Sobrien set_input (infiles[0].name); 647090277Sobrien 647152520Sobrien if (error_count == 0) 647252520Sobrien { 647352520Sobrien /* Make sure INPUT_FILE_NUMBER points to first available open 647452520Sobrien slot. */ 647552520Sobrien input_file_number = n_infiles; 647652520Sobrien if (lang_specific_pre_link ()) 647752520Sobrien error_count++; 647852520Sobrien } 647950599Sobrien 6480132733Skan /* Determine if there are any linker input files. */ 6481132733Skan num_linker_inputs = 0; 6482132733Skan for (i = 0; (int) i < n_infiles; i++) 6483132733Skan if (explicit_link_files[i] || outfiles[i] != NULL) 6484132733Skan num_linker_inputs++; 6485132733Skan 648618334Speter /* Run ld to link all the compiler output files. */ 648718334Speter 6488132733Skan if (num_linker_inputs > 0 && error_count == 0) 648918334Speter { 649018334Speter int tmp = execution_count; 649118334Speter 649290277Sobrien /* We'll use ld if we can't find collect2. */ 649350599Sobrien if (! strcmp (linker_name_spec, "collect2")) 649450599Sobrien { 6495104763Skan char *s = find_a_file (&exec_prefixes, "collect2", X_OK, 0); 649650599Sobrien if (s == NULL) 649750599Sobrien linker_name_spec = "ld"; 649850599Sobrien } 649918334Speter /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 650018334Speter for collect. */ 650190277Sobrien putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH"); 650290277Sobrien putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV); 650318334Speter 650418334Speter value = do_spec (link_command_spec); 650518334Speter if (value < 0) 650618334Speter error_count = 1; 650718334Speter linker_was_run = (tmp != execution_count); 650818334Speter } 650918334Speter 651018334Speter /* If options said don't run linker, 651118334Speter complain about input files to be given to the linker. */ 651218334Speter 651318334Speter if (! linker_was_run && error_count == 0) 651490277Sobrien for (i = 0; (int) i < n_infiles; i++) 651518334Speter if (explicit_link_files[i]) 651690277Sobrien error ("%s: linker input file unused because linking not done", 651718334Speter outfiles[i]); 651818334Speter 651918334Speter /* Delete some or all of the temporary files we made. */ 652018334Speter 652118334Speter if (error_count) 652218334Speter delete_failure_queue (); 652318334Speter delete_temp_files (); 652418334Speter 652550599Sobrien if (print_help_list) 652650599Sobrien { 652790277Sobrien printf (("\nFor bug reporting instructions, please see:\n")); 6528117413Skan printf ("%s\n", bug_report_url); 652950599Sobrien } 653090277Sobrien 653190277Sobrien return (signal_count != 0 ? 2 653290277Sobrien : error_count > 0 ? (pass_exit_codes ? greatest_status : 1) 653390277Sobrien : 0); 653418334Speter} 653518334Speter 653618334Speter/* Find the proper compilation spec for the file name NAME, 653718334Speter whose length is LENGTH. LANGUAGE is the specified language, 653850599Sobrien or 0 if this file is to be passed to the linker. */ 653918334Speter 654018334Speterstatic struct compiler * 6541132733Skanlookup_compiler (const char *name, size_t length, const char *language) 654218334Speter{ 654318334Speter struct compiler *cp; 654418334Speter 654590277Sobrien /* If this was specified by the user to be a linker input, indicate that. */ 654650599Sobrien if (language != 0 && language[0] == '*') 654750599Sobrien return 0; 654850599Sobrien 654950599Sobrien /* Otherwise, look for the language, if one is spec'd. */ 655018334Speter if (language != 0) 655118334Speter { 655218334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 655350599Sobrien if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language)) 655450599Sobrien return cp; 655550599Sobrien 655618334Speter error ("language %s not recognized", language); 655750599Sobrien return 0; 655818334Speter } 655918334Speter 656018334Speter /* Look for a suffix. */ 656118334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 656218334Speter { 656318334Speter if (/* The suffix `-' matches only the file name `-'. */ 656418334Speter (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 656550599Sobrien || (strlen (cp->suffix) < length 656650599Sobrien /* See if the suffix matches the end of NAME. */ 656750599Sobrien && !strcmp (cp->suffix, 656850599Sobrien name + length - strlen (cp->suffix)) 656950599Sobrien )) 6570117413Skan break; 657190277Sobrien } 657250599Sobrien 657390277Sobrien#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM) 657490277Sobrien /* look again, but case-insensitively this time. */ 657590277Sobrien if (cp < compilers) 657690277Sobrien for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 657790277Sobrien { 657890277Sobrien if (/* The suffix `-' matches only the file name `-'. */ 657990277Sobrien (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 658090277Sobrien || (strlen (cp->suffix) < length 658190277Sobrien /* See if the suffix matches the end of NAME. */ 658290277Sobrien && ((!strcmp (cp->suffix, 658390277Sobrien name + length - strlen (cp->suffix)) 658490277Sobrien || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) 658590277Sobrien && !strcasecmp (cp->suffix, 658690277Sobrien name + length - strlen (cp->suffix))) 658790277Sobrien )) 658890277Sobrien break; 658990277Sobrien } 659090277Sobrien#endif 659150599Sobrien 659290277Sobrien if (cp >= compilers) 659390277Sobrien { 659490277Sobrien if (cp->spec[0] != '@') 659590277Sobrien /* A non-alias entry: return it. */ 659690277Sobrien return cp; 659790277Sobrien 659890277Sobrien /* An alias entry maps a suffix to a language. 659990277Sobrien Search for the language; pass 0 for NAME and LENGTH 660090277Sobrien to avoid infinite recursion if language not found. */ 660190277Sobrien return lookup_compiler (NULL, 0, cp->spec + 1); 660218334Speter } 660318334Speter return 0; 660418334Speter} 660518334Speter 660618334Speterstatic char * 6607132733Skansave_string (const char *s, int len) 660818334Speter{ 660990277Sobrien char *result = xmalloc (len + 1); 661018334Speter 661190277Sobrien memcpy (result, s, len); 661218334Speter result[len] = 0; 661318334Speter return result; 661418334Speter} 661518334Speter 661690277Sobrienvoid 6617132733Skanpfatal_with_name (const char *name) 661818334Speter{ 661952520Sobrien perror_with_name (name); 662052520Sobrien delete_temp_files (); 662152520Sobrien exit (1); 662218334Speter} 662318334Speter 662418334Speterstatic void 6625132733Skanperror_with_name (const char *name) 662618334Speter{ 662752520Sobrien error ("%s: %s", name, xstrerror (errno)); 662818334Speter} 662918334Speter 663018334Speterstatic void 6631132733Skanpfatal_pexecute (const char *errmsg_fmt, const char *errmsg_arg) 663218334Speter{ 663350599Sobrien if (errmsg_arg) 663450599Sobrien { 663552520Sobrien int save_errno = errno; 663652520Sobrien 663750599Sobrien /* Space for trailing '\0' is in %s. */ 663850599Sobrien char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg)); 663950599Sobrien sprintf (msg, errmsg_fmt, errmsg_arg); 664050599Sobrien errmsg_fmt = msg; 664152520Sobrien 664252520Sobrien errno = save_errno; 664350599Sobrien } 664450599Sobrien 664552520Sobrien pfatal_with_name (errmsg_fmt); 664618334Speter} 664718334Speter 6648132733Skan/* Output an error message and exit. */ 664918334Speter 665018334Spetervoid 6651132733Skanfancy_abort (void) 665218334Speter{ 665390277Sobrien fatal ("internal gcc abort"); 665418334Speter} 665518334Speter 6656132733Skan/* Output an error message and exit. */ 665718334Speter 665852520Sobrienvoid 6659132733Skanfatal (const char *msgid, ...) 666018334Speter{ 6661132733Skan va_list ap; 666218334Speter 6663132733Skan va_start (ap, msgid); 6664132733Skan 666518334Speter fprintf (stderr, "%s: ", programname); 666652520Sobrien vfprintf (stderr, _(msgid), ap); 6667132733Skan va_end (ap); 666818334Speter fprintf (stderr, "\n"); 666918334Speter delete_temp_files (); 667018334Speter exit (1); 667118334Speter} 667218334Speter 667390277Sobrienvoid 6674132733Skanerror (const char *msgid, ...) 667518334Speter{ 6676132733Skan va_list ap; 667718334Speter 6678132733Skan va_start (ap, msgid); 667918334Speter fprintf (stderr, "%s: ", programname); 668052520Sobrien vfprintf (stderr, _(msgid), ap); 6681132733Skan va_end (ap); 668218334Speter 668318334Speter fprintf (stderr, "\n"); 668418334Speter} 668552520Sobrien 668652520Sobrienstatic void 6687132733Skannotice (const char *msgid, ...) 668852520Sobrien{ 6689132733Skan va_list ap; 669052520Sobrien 6691132733Skan va_start (ap, msgid); 669252520Sobrien vfprintf (stderr, _(msgid), ap); 6693132733Skan va_end (ap); 669452520Sobrien} 669518334Speter 6696132733Skanstatic inline void 6697132733Skanvalidate_switches_from_spec (const char *spec) 6698132733Skan{ 6699132733Skan const char *p = spec; 6700132733Skan char c; 6701132733Skan while ((c = *p++)) 6702132733Skan if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{'))) 6703132733Skan /* We have a switch spec. */ 6704132733Skan p = validate_switches (p + 1); 6705132733Skan} 6706132733Skan 670718334Speterstatic void 6708132733Skanvalidate_all_switches (void) 670918334Speter{ 671018334Speter struct compiler *comp; 671118334Speter struct spec_list *spec; 671218334Speter 671390277Sobrien for (comp = compilers; comp->spec; comp++) 6714132733Skan validate_switches_from_spec (comp->spec); 671518334Speter 671690277Sobrien /* Look through the linked list of specs read from the specs file. */ 671790277Sobrien for (spec = specs; spec; spec = spec->next) 6718132733Skan validate_switches_from_spec (*spec->ptr_spec); 671918334Speter 6720132733Skan validate_switches_from_spec (link_command_spec); 672118334Speter} 672218334Speter 672318334Speter/* Look at the switch-name that comes after START 672418334Speter and mark as valid all supplied switches that match it. */ 672518334Speter 6726132733Skanstatic const char * 6727132733Skanvalidate_switches (const char *start) 672818334Speter{ 672990277Sobrien const char *p = start; 6730132733Skan const char *atom; 6731132733Skan size_t len; 673290277Sobrien int i; 6733132733Skan bool suffix = false; 6734132733Skan bool starred = false; 673518334Speter 6736132733Skan#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0) 673718334Speter 673890277Sobriennext_member: 6739132733Skan SKIP_WHITE (); 6740132733Skan 674118334Speter if (*p == '!') 6742132733Skan p++; 674318334Speter 6744132733Skan SKIP_WHITE (); 674518334Speter if (*p == '.') 6746132733Skan suffix = true, p++; 674718334Speter 6748132733Skan atom = p; 6749132733Skan while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '=' 6750132733Skan || *p == ',' || *p == '.' || *p == '@') 675190277Sobrien p++; 6752132733Skan len = p - atom; 675318334Speter 6754132733Skan if (*p == '*') 6755132733Skan starred = true, p++; 6756132733Skan 6757132733Skan SKIP_WHITE (); 6758132733Skan 6759132733Skan if (!suffix) 676018334Speter { 676118334Speter /* Mark all matching switches as valid. */ 676218334Speter for (i = 0; i < n_switches; i++) 6763132733Skan if (!strncmp (switches[i].part1, atom, len) 6764132733Skan && (starred || switches[i].part1[len] == 0)) 676552520Sobrien switches[i].validated = 1; 676618334Speter } 6767132733Skan 6768132733Skan if (*p) p++; 6769132733Skan if (*p && (p[-1] == '|' || p[-1] == '&')) 6770132733Skan goto next_member; 6771132733Skan 6772132733Skan if (*p && p[-1] == ':') 677318334Speter { 6774132733Skan while (*p && *p != ';' && *p != '}') 677518334Speter { 6776132733Skan if (*p == '%') 6777132733Skan { 6778132733Skan p++; 6779132733Skan if (*p == '{' || *p == '<') 6780132733Skan p = validate_switches (p+1); 6781132733Skan else if (p[0] == 'W' && p[1] == '{') 6782132733Skan p = validate_switches (p+2); 6783132733Skan } 6784132733Skan else 6785132733Skan p++; 678618334Speter } 6787132733Skan 6788132733Skan if (*p) p++; 6789132733Skan if (*p && p[-1] == ';') 6790132733Skan goto next_member; 679118334Speter } 679290277Sobrien 6793132733Skan return p; 6794132733Skan#undef SKIP_WHITE 679518334Speter} 679618334Speter 6797104763Skanstruct mdswitchstr 6798104763Skan{ 6799104763Skan const char *str; 6800104763Skan int len; 6801104763Skan}; 6802104763Skan 6803104763Skanstatic struct mdswitchstr *mdswitches; 6804104763Skanstatic int n_mdswitches; 6805104763Skan 680650599Sobrien/* Check whether a particular argument was used. The first time we 680750599Sobrien canonicalize the switches to keep only the ones we care about. */ 680818334Speter 680918334Speterstatic int 6810132733Skanused_arg (const char *p, int len) 681118334Speter{ 681290277Sobrien struct mswitchstr 681390277Sobrien { 681490277Sobrien const char *str; 681590277Sobrien const char *replace; 681650599Sobrien int len; 681750599Sobrien int rep_len; 681850599Sobrien }; 681918334Speter 682050599Sobrien static struct mswitchstr *mswitches; 682150599Sobrien static int n_mswitches; 682250599Sobrien int i, j; 682350599Sobrien 682450599Sobrien if (!mswitches) 682550599Sobrien { 682650599Sobrien struct mswitchstr *matches; 682790277Sobrien const char *q; 682850599Sobrien int cnt = 0; 682950599Sobrien 683090277Sobrien /* Break multilib_matches into the component strings of string 683190277Sobrien and replacement string. */ 683250599Sobrien for (q = multilib_matches; *q != '\0'; q++) 683350599Sobrien if (*q == ';') 683450599Sobrien cnt++; 683550599Sobrien 6836132733Skan matches = alloca ((sizeof (struct mswitchstr)) * cnt); 683750599Sobrien i = 0; 683850599Sobrien q = multilib_matches; 683950599Sobrien while (*q != '\0') 684050599Sobrien { 684150599Sobrien matches[i].str = q; 684250599Sobrien while (*q != ' ') 684350599Sobrien { 684450599Sobrien if (*q == '\0') 684550599Sobrien abort (); 684650599Sobrien q++; 684750599Sobrien } 684850599Sobrien matches[i].len = q - matches[i].str; 684950599Sobrien 685050599Sobrien matches[i].replace = ++q; 685150599Sobrien while (*q != ';' && *q != '\0') 685250599Sobrien { 685350599Sobrien if (*q == ' ') 685450599Sobrien abort (); 685550599Sobrien q++; 685650599Sobrien } 685750599Sobrien matches[i].rep_len = q - matches[i].replace; 685850599Sobrien i++; 685950599Sobrien if (*q == ';') 686090277Sobrien q++; 686150599Sobrien } 686250599Sobrien 686350599Sobrien /* Now build a list of the replacement string for switches that we care 686450599Sobrien about. Make sure we allocate at least one entry. This prevents 686550599Sobrien xmalloc from calling fatal, and prevents us from re-executing this 686650599Sobrien block of code. */ 686750599Sobrien mswitches 6868132733Skan = xmalloc (sizeof (struct mswitchstr) 6869104763Skan * (n_mdswitches + (n_switches ? n_switches : 1))); 687050599Sobrien for (i = 0; i < n_switches; i++) 687150599Sobrien { 687250599Sobrien int xlen = strlen (switches[i].part1); 687350599Sobrien for (j = 0; j < cnt; j++) 687490277Sobrien if (xlen == matches[j].len 687590277Sobrien && ! strncmp (switches[i].part1, matches[j].str, xlen)) 687650599Sobrien { 687750599Sobrien mswitches[n_mswitches].str = matches[j].replace; 687850599Sobrien mswitches[n_mswitches].len = matches[j].rep_len; 687990277Sobrien mswitches[n_mswitches].replace = (char *) 0; 688050599Sobrien mswitches[n_mswitches].rep_len = 0; 688150599Sobrien n_mswitches++; 688250599Sobrien break; 688350599Sobrien } 688450599Sobrien } 6885104763Skan 6886104763Skan /* Add MULTILIB_DEFAULTS switches too, as long as they were not present 6887104763Skan on the command line nor any options mutually incompatible with 6888104763Skan them. */ 6889104763Skan for (i = 0; i < n_mdswitches; i++) 6890104763Skan { 6891104763Skan const char *r; 6892104763Skan 6893104763Skan for (q = multilib_options; *q != '\0'; q++) 6894104763Skan { 6895104763Skan while (*q == ' ') 6896104763Skan q++; 6897104763Skan 6898104763Skan r = q; 6899104763Skan while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0 6900104763Skan || strchr (" /", q[mdswitches[i].len]) == NULL) 6901104763Skan { 6902104763Skan while (*q != ' ' && *q != '/' && *q != '\0') 6903104763Skan q++; 6904104763Skan if (*q != '/') 6905104763Skan break; 6906104763Skan q++; 6907104763Skan } 6908104763Skan 6909104763Skan if (*q != ' ' && *q != '\0') 6910104763Skan { 6911104763Skan while (*r != ' ' && *r != '\0') 6912104763Skan { 6913104763Skan q = r; 6914104763Skan while (*q != ' ' && *q != '/' && *q != '\0') 6915104763Skan q++; 6916104763Skan 6917104763Skan if (used_arg (r, q - r)) 6918104763Skan break; 6919104763Skan 6920104763Skan if (*q != '/') 6921104763Skan { 6922104763Skan mswitches[n_mswitches].str = mdswitches[i].str; 6923104763Skan mswitches[n_mswitches].len = mdswitches[i].len; 6924104763Skan mswitches[n_mswitches].replace = (char *) 0; 6925104763Skan mswitches[n_mswitches].rep_len = 0; 6926104763Skan n_mswitches++; 6927104763Skan break; 6928104763Skan } 6929104763Skan 6930104763Skan r = q + 1; 6931104763Skan } 6932104763Skan break; 6933104763Skan } 6934104763Skan } 6935104763Skan } 693650599Sobrien } 693750599Sobrien 693850599Sobrien for (i = 0; i < n_mswitches; i++) 693950599Sobrien if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len)) 694018334Speter return 1; 694150599Sobrien 694218334Speter return 0; 694318334Speter} 694418334Speter 694518334Speterstatic int 6946132733Skandefault_arg (const char *p, int len) 694718334Speter{ 6948104763Skan int i; 694918334Speter 6950104763Skan for (i = 0; i < n_mdswitches; i++) 6951104763Skan if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len)) 6952104763Skan return 1; 695318334Speter 695418334Speter return 0; 695518334Speter} 695618334Speter 695790277Sobrien/* Work out the subdirectory to use based on the options. The format of 695890277Sobrien multilib_select is a list of elements. Each element is a subdirectory 695990277Sobrien name followed by a list of options followed by a semicolon. The format 696090277Sobrien of multilib_exclusions is the same, but without the preceding 696190277Sobrien directory. First gcc will check the exclusions, if none of the options 696290277Sobrien beginning with an exclamation point are present, and all of the other 696390277Sobrien options are present, then we will ignore this completely. Passing 696490277Sobrien that, gcc will consider each multilib_select in turn using the same 696590277Sobrien rules for matching the options. If a match is found, that subdirectory 696690277Sobrien will be used. */ 696718334Speter 696818334Speterstatic void 6969132733Skanset_multilib_dir (void) 697018334Speter{ 697190277Sobrien const char *p; 697290277Sobrien unsigned int this_path_len; 697390277Sobrien const char *this_path, *this_arg; 6974104763Skan const char *start, *end; 697518334Speter int not_arg; 6976104763Skan int ok, ndfltok, first; 697718334Speter 6978104763Skan n_mdswitches = 0; 6979104763Skan start = multilib_defaults; 6980104763Skan while (*start == ' ' || *start == '\t') 6981104763Skan start++; 6982104763Skan while (*start != '\0') 6983104763Skan { 6984104763Skan n_mdswitches++; 6985104763Skan while (*start != ' ' && *start != '\t' && *start != '\0') 6986104763Skan start++; 6987104763Skan while (*start == ' ' || *start == '\t') 6988104763Skan start++; 6989104763Skan } 6990104763Skan 6991104763Skan if (n_mdswitches) 6992104763Skan { 6993104763Skan int i = 0; 6994104763Skan 6995132733Skan mdswitches = xmalloc (sizeof (struct mdswitchstr) * n_mdswitches); 6996104763Skan for (start = multilib_defaults; *start != '\0'; start = end + 1) 6997104763Skan { 6998104763Skan while (*start == ' ' || *start == '\t') 6999104763Skan start++; 7000104763Skan 7001104763Skan if (*start == '\0') 7002104763Skan break; 7003132733Skan 7004104763Skan for (end = start + 1; 7005104763Skan *end != ' ' && *end != '\t' && *end != '\0'; end++) 7006104763Skan ; 7007104763Skan 7008104763Skan obstack_grow (&multilib_obstack, start, end - start); 7009104763Skan obstack_1grow (&multilib_obstack, 0); 7010104763Skan mdswitches[i].str = obstack_finish (&multilib_obstack); 7011104763Skan mdswitches[i++].len = end - start; 7012104763Skan 7013104763Skan if (*end == '\0') 7014104763Skan break; 7015104763Skan } 7016104763Skan } 7017104763Skan 701890277Sobrien p = multilib_exclusions; 701918334Speter while (*p != '\0') 702018334Speter { 702118334Speter /* Ignore newlines. */ 702218334Speter if (*p == '\n') 702318334Speter { 702418334Speter ++p; 702518334Speter continue; 702618334Speter } 702718334Speter 702890277Sobrien /* Check the arguments. */ 702990277Sobrien ok = 1; 703090277Sobrien while (*p != ';') 703190277Sobrien { 703290277Sobrien if (*p == '\0') 703390277Sobrien abort (); 703490277Sobrien 703590277Sobrien if (! ok) 703690277Sobrien { 703790277Sobrien ++p; 703890277Sobrien continue; 703990277Sobrien } 704090277Sobrien 704190277Sobrien this_arg = p; 704290277Sobrien while (*p != ' ' && *p != ';') 704390277Sobrien { 704490277Sobrien if (*p == '\0') 704590277Sobrien abort (); 704690277Sobrien ++p; 704790277Sobrien } 704890277Sobrien 704990277Sobrien if (*this_arg != '!') 705090277Sobrien not_arg = 0; 705190277Sobrien else 705290277Sobrien { 705390277Sobrien not_arg = 1; 705490277Sobrien ++this_arg; 705590277Sobrien } 705690277Sobrien 705790277Sobrien ok = used_arg (this_arg, p - this_arg); 705890277Sobrien if (not_arg) 705990277Sobrien ok = ! ok; 706090277Sobrien 706190277Sobrien if (*p == ' ') 706290277Sobrien ++p; 706390277Sobrien } 706490277Sobrien 706590277Sobrien if (ok) 706690277Sobrien return; 706790277Sobrien 706890277Sobrien ++p; 706990277Sobrien } 707090277Sobrien 7071104763Skan first = 1; 707290277Sobrien p = multilib_select; 707390277Sobrien while (*p != '\0') 707490277Sobrien { 707590277Sobrien /* Ignore newlines. */ 707690277Sobrien if (*p == '\n') 707790277Sobrien { 707890277Sobrien ++p; 707990277Sobrien continue; 708090277Sobrien } 708190277Sobrien 708218334Speter /* Get the initial path. */ 708318334Speter this_path = p; 708418334Speter while (*p != ' ') 708518334Speter { 708618334Speter if (*p == '\0') 708718334Speter abort (); 708818334Speter ++p; 708918334Speter } 709018334Speter this_path_len = p - this_path; 709118334Speter 709218334Speter /* Check the arguments. */ 709318334Speter ok = 1; 7094104763Skan ndfltok = 1; 709518334Speter ++p; 709618334Speter while (*p != ';') 709718334Speter { 709818334Speter if (*p == '\0') 709918334Speter abort (); 710018334Speter 710118334Speter if (! ok) 710218334Speter { 710318334Speter ++p; 710418334Speter continue; 710518334Speter } 710618334Speter 710718334Speter this_arg = p; 710818334Speter while (*p != ' ' && *p != ';') 710918334Speter { 711018334Speter if (*p == '\0') 711118334Speter abort (); 711218334Speter ++p; 711318334Speter } 711418334Speter 711518334Speter if (*this_arg != '!') 711618334Speter not_arg = 0; 711718334Speter else 711818334Speter { 711918334Speter not_arg = 1; 712018334Speter ++this_arg; 712118334Speter } 712218334Speter 712318334Speter /* If this is a default argument, we can just ignore it. 712418334Speter This is true even if this_arg begins with '!'. Beginning 712518334Speter with '!' does not mean that this argument is necessarily 712618334Speter inappropriate for this library: it merely means that 712718334Speter there is a more specific library which uses this 712818334Speter argument. If this argument is a default, we need not 712918334Speter consider that more specific library. */ 7130104763Skan ok = used_arg (this_arg, p - this_arg); 7131104763Skan if (not_arg) 7132104763Skan ok = ! ok; 713318334Speter 7134104763Skan if (! ok) 7135104763Skan ndfltok = 0; 7136104763Skan 7137104763Skan if (default_arg (this_arg, p - this_arg)) 7138104763Skan ok = 1; 7139104763Skan 714018334Speter if (*p == ' ') 714118334Speter ++p; 714218334Speter } 714318334Speter 7144104763Skan if (ok && first) 714518334Speter { 714618334Speter if (this_path_len != 1 714718334Speter || this_path[0] != '.') 714818334Speter { 714990277Sobrien char *new_multilib_dir = xmalloc (this_path_len + 1); 7150104763Skan char *q; 7151104763Skan 715252520Sobrien strncpy (new_multilib_dir, this_path, this_path_len); 715352520Sobrien new_multilib_dir[this_path_len] = '\0'; 7154104763Skan q = strchr (new_multilib_dir, ':'); 7155104763Skan if (q != NULL) 7156104763Skan *q = '\0'; 715752520Sobrien multilib_dir = new_multilib_dir; 715818334Speter } 7159104763Skan first = 0; 716018334Speter } 716118334Speter 7162104763Skan if (ndfltok) 7163104763Skan { 7164104763Skan const char *q = this_path, *end = this_path + this_path_len; 7165104763Skan 7166104763Skan while (q < end && *q != ':') 7167104763Skan q++; 7168104763Skan if (q < end) 7169104763Skan { 7170104763Skan char *new_multilib_os_dir = xmalloc (end - q); 7171104763Skan memcpy (new_multilib_os_dir, q + 1, end - q - 1); 7172104763Skan new_multilib_os_dir[end - q - 1] = '\0'; 7173104763Skan multilib_os_dir = new_multilib_os_dir; 7174104763Skan break; 7175104763Skan } 7176104763Skan } 7177104763Skan 717818334Speter ++p; 717990277Sobrien } 7180104763Skan 7181104763Skan if (multilib_dir == NULL && multilib_os_dir != NULL 7182104763Skan && strcmp (multilib_os_dir, ".") == 0) 7183104763Skan { 7184104763Skan free ((char *) multilib_os_dir); 7185104763Skan multilib_os_dir = NULL; 7186104763Skan } 7187104763Skan else if (multilib_dir != NULL && multilib_os_dir == NULL) 7188104763Skan multilib_os_dir = multilib_dir; 718918334Speter} 719018334Speter 719118334Speter/* Print out the multiple library subdirectory selection 719218334Speter information. This prints out a series of lines. Each line looks 719318334Speter like SUBDIRECTORY;@OPTION@OPTION, with as many options as is 719418334Speter required. Only the desired options are printed out, the negative 719518334Speter matches. The options are print without a leading dash. There are 719618334Speter no spaces to make it easy to use the information in the shell. 719718334Speter Each subdirectory is printed only once. This assumes the ordering 719890277Sobrien generated by the genmultilib script. Also, we leave out ones that match 719990277Sobrien the exclusions. */ 720018334Speter 720118334Speterstatic void 7202132733Skanprint_multilib_info (void) 720318334Speter{ 720490277Sobrien const char *p = multilib_select; 720590277Sobrien const char *last_path = 0, *this_path; 720618334Speter int skip; 720790277Sobrien unsigned int last_path_len = 0; 720818334Speter 720918334Speter while (*p != '\0') 721018334Speter { 721190277Sobrien skip = 0; 721218334Speter /* Ignore newlines. */ 721318334Speter if (*p == '\n') 721418334Speter { 721518334Speter ++p; 721618334Speter continue; 721718334Speter } 721818334Speter 721918334Speter /* Get the initial path. */ 722018334Speter this_path = p; 722118334Speter while (*p != ' ') 722218334Speter { 722318334Speter if (*p == '\0') 722418334Speter abort (); 722518334Speter ++p; 722618334Speter } 722718334Speter 7228104763Skan /* When --disable-multilib was used but target defines 7229104763Skan MULTILIB_OSDIRNAMES, entries starting with .: are there just 7230104763Skan to find multilib_os_dir, so skip them from output. */ 7231104763Skan if (this_path[0] == '.' && this_path[1] == ':') 7232104763Skan skip = 1; 7233104763Skan 723490277Sobrien /* Check for matches with the multilib_exclusions. We don't bother 723590277Sobrien with the '!' in either list. If any of the exclusion rules match 723690277Sobrien all of its options with the select rule, we skip it. */ 723790277Sobrien { 723890277Sobrien const char *e = multilib_exclusions; 723990277Sobrien const char *this_arg; 724018334Speter 724190277Sobrien while (*e != '\0') 724290277Sobrien { 724390277Sobrien int m = 1; 724490277Sobrien /* Ignore newlines. */ 724590277Sobrien if (*e == '\n') 724690277Sobrien { 724790277Sobrien ++e; 724890277Sobrien continue; 724990277Sobrien } 725018334Speter 725190277Sobrien /* Check the arguments. */ 725290277Sobrien while (*e != ';') 725390277Sobrien { 725490277Sobrien const char *q; 725590277Sobrien int mp = 0; 725690277Sobrien 725790277Sobrien if (*e == '\0') 725890277Sobrien abort (); 725990277Sobrien 726090277Sobrien if (! m) 726190277Sobrien { 726290277Sobrien ++e; 726390277Sobrien continue; 726490277Sobrien } 726590277Sobrien 726690277Sobrien this_arg = e; 726790277Sobrien 726890277Sobrien while (*e != ' ' && *e != ';') 726990277Sobrien { 727090277Sobrien if (*e == '\0') 727190277Sobrien abort (); 727290277Sobrien ++e; 727390277Sobrien } 727490277Sobrien 727590277Sobrien q = p + 1; 727690277Sobrien while (*q != ';') 727790277Sobrien { 727890277Sobrien const char *arg; 727990277Sobrien int len = e - this_arg; 728090277Sobrien 728190277Sobrien if (*q == '\0') 728290277Sobrien abort (); 728390277Sobrien 728490277Sobrien arg = q; 728590277Sobrien 728690277Sobrien while (*q != ' ' && *q != ';') 728790277Sobrien { 728890277Sobrien if (*q == '\0') 728990277Sobrien abort (); 729090277Sobrien ++q; 729190277Sobrien } 729290277Sobrien 729390277Sobrien if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) || 729490277Sobrien default_arg (this_arg, e - this_arg)) 729590277Sobrien { 729690277Sobrien mp = 1; 729790277Sobrien break; 729890277Sobrien } 729990277Sobrien 730090277Sobrien if (*q == ' ') 730190277Sobrien ++q; 730290277Sobrien } 730390277Sobrien 730490277Sobrien if (! mp) 730590277Sobrien m = 0; 730690277Sobrien 730790277Sobrien if (*e == ' ') 730890277Sobrien ++e; 730990277Sobrien } 731090277Sobrien 731190277Sobrien if (m) 731290277Sobrien { 731390277Sobrien skip = 1; 731490277Sobrien break; 731590277Sobrien } 731690277Sobrien 731790277Sobrien if (*e != '\0') 731890277Sobrien ++e; 731990277Sobrien } 732090277Sobrien } 732190277Sobrien 732290277Sobrien if (! skip) 732390277Sobrien { 732490277Sobrien /* If this is a duplicate, skip it. */ 732590277Sobrien skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len 732690277Sobrien && ! strncmp (last_path, this_path, last_path_len)); 732790277Sobrien 732890277Sobrien last_path = this_path; 732990277Sobrien last_path_len = p - this_path; 733090277Sobrien } 733190277Sobrien 733218334Speter /* If this directory requires any default arguments, we can skip 733318334Speter it. We will already have printed a directory identical to 733418334Speter this one which does not require that default argument. */ 733518334Speter if (! skip) 733618334Speter { 733790277Sobrien const char *q; 733818334Speter 733918334Speter q = p + 1; 734018334Speter while (*q != ';') 734118334Speter { 734290277Sobrien const char *arg; 734318334Speter 734418334Speter if (*q == '\0') 734518334Speter abort (); 734618334Speter 734718334Speter if (*q == '!') 734818334Speter arg = NULL; 734918334Speter else 735018334Speter arg = q; 735118334Speter 735218334Speter while (*q != ' ' && *q != ';') 735318334Speter { 735418334Speter if (*q == '\0') 735518334Speter abort (); 735618334Speter ++q; 735718334Speter } 735818334Speter 735918334Speter if (arg != NULL 736018334Speter && default_arg (arg, q - arg)) 736118334Speter { 736218334Speter skip = 1; 736318334Speter break; 736418334Speter } 736518334Speter 736618334Speter if (*q == ' ') 736718334Speter ++q; 736818334Speter } 736918334Speter } 737018334Speter 737118334Speter if (! skip) 737218334Speter { 737390277Sobrien const char *p1; 737418334Speter 7375104763Skan for (p1 = last_path; p1 < p && *p1 != ':'; p1++) 737618334Speter putchar (*p1); 737718334Speter putchar (';'); 737818334Speter } 737918334Speter 738018334Speter ++p; 738118334Speter while (*p != ';') 738218334Speter { 738318334Speter int use_arg; 738418334Speter 738518334Speter if (*p == '\0') 738618334Speter abort (); 738718334Speter 738818334Speter if (skip) 738918334Speter { 739018334Speter ++p; 739118334Speter continue; 739218334Speter } 739318334Speter 739418334Speter use_arg = *p != '!'; 739518334Speter 739618334Speter if (use_arg) 739718334Speter putchar ('@'); 739818334Speter 739918334Speter while (*p != ' ' && *p != ';') 740018334Speter { 740118334Speter if (*p == '\0') 740218334Speter abort (); 740318334Speter if (use_arg) 740418334Speter putchar (*p); 740518334Speter ++p; 740618334Speter } 740718334Speter 740818334Speter if (*p == ' ') 740918334Speter ++p; 741018334Speter } 741118334Speter 741218334Speter if (! skip) 741350599Sobrien { 741490277Sobrien /* If there are extra options, print them now. */ 741550599Sobrien if (multilib_extra && *multilib_extra) 741650599Sobrien { 741750599Sobrien int print_at = TRUE; 741890277Sobrien const char *q; 741918334Speter 742050599Sobrien for (q = multilib_extra; *q != '\0'; q++) 742150599Sobrien { 742250599Sobrien if (*q == ' ') 742350599Sobrien print_at = TRUE; 742450599Sobrien else 742550599Sobrien { 742650599Sobrien if (print_at) 742750599Sobrien putchar ('@'); 742850599Sobrien putchar (*q); 742950599Sobrien print_at = FALSE; 743050599Sobrien } 743150599Sobrien } 743250599Sobrien } 743390277Sobrien 743450599Sobrien putchar ('\n'); 743550599Sobrien } 743650599Sobrien 743718334Speter ++p; 743818334Speter } 743918334Speter} 7440117413Skan 7441117413Skan/* if-exists built-in spec function. 7442117413Skan 7443117413Skan Checks to see if the file specified by the absolute pathname in 7444117413Skan ARGS exists. Returns that pathname if found. 7445117413Skan 7446117413Skan The usual use for this function is to check for a library file 7447117413Skan (whose name has been expanded with %s). */ 7448117413Skan 7449117413Skanstatic const char * 7450132733Skanif_exists_spec_function (int argc, const char **argv) 7451117413Skan{ 7452117413Skan /* Must have only one argument. */ 7453132733Skan if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK)) 7454117413Skan return argv[0]; 7455117413Skan 7456117413Skan return NULL; 7457117413Skan} 7458117413Skan 7459117413Skan/* if-exists-else built-in spec function. 7460117413Skan 7461117413Skan This is like if-exists, but takes an additional argument which 7462117413Skan is returned if the first argument does not exist. */ 7463117413Skan 7464117413Skanstatic const char * 7465132733Skanif_exists_else_spec_function (int argc, const char **argv) 7466117413Skan{ 7467117413Skan /* Must have exactly two arguments. */ 7468117413Skan if (argc != 2) 7469117413Skan return NULL; 7470117413Skan 7471132733Skan if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK)) 7472117413Skan return argv[0]; 7473117413Skan 7474117413Skan return argv[1]; 7475117413Skan} 7476