gcc.c revision 122197
118334Speter/* Compiler driver program that can handle many languages. 290277Sobrien Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 390277Sobrien 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 418334Speter 590277SobrienThis file is part of GCC. 618334Speter 790277SobrienGCC is free software; you can redistribute it and/or modify it under 890277Sobrienthe terms of the GNU General Public License as published by the Free 990277SobrienSoftware Foundation; either version 2, or (at your option) any later 1090277Sobrienversion. 1118334Speter 1290277SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1390277SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1490277SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1590277Sobrienfor more details. 1618334Speter 1718334SpeterYou should have received a copy of the GNU General Public License 1890277Sobrienalong with GCC; see the file COPYING. If not, write to the Free 1990277SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2090277Sobrien02111-1307, USA. 2118334Speter 2218334SpeterThis paragraph is here to try to keep Sun CC from dying. 2318334SpeterThe number of chars here seems crucial!!!! */ 2418334Speter 2551232Sbde/* $FreeBSD: head/contrib/gcc/gcc.c 122197 2003-11-07 03:23:43Z kan $ */ 2651232Sbde 2718334Speter/* This program is the user interface to the C compiler and possibly to 2818334Speterother compilers. It is used because compilation is a complicated procedure 2918334Speterwhich involves running several programs and passing temporary files between 3018334Speterthem, forwarding the users switches to those programs selectively, 3118334Speterand deleting the temporary files at the end. 3218334Speter 3318334SpeterCC recognizes how to compile each input file by suffixes in the file names. 3418334SpeterOnce it knows which kind of compilation to perform, the procedure for 3518334Spetercompilation is specified by a string called a "spec". */ 3690277Sobrien 3790277Sobrien/* A Short Introduction to Adding a Command-Line Option. 3890277Sobrien 3990277Sobrien Before adding a command-line option, consider if it is really 4090277Sobrien necessary. Each additional command-line option adds complexity and 4190277Sobrien is difficult to remove in subsequent versions. 4290277Sobrien 4390277Sobrien In the following, consider adding the command-line argument 4490277Sobrien `--bar'. 4590277Sobrien 4690277Sobrien 1. Each command-line option is specified in the specs file. The 4790277Sobrien notation is described below in the comment entitled "The Specs 4890277Sobrien Language". Read it. 4990277Sobrien 5090277Sobrien 2. In this file, add an entry to "option_map" equating the long 5190277Sobrien `--' argument version and any shorter, single letter version. Read 5290277Sobrien the comments in the declaration of "struct option_map" for an 5390277Sobrien explanation. Do not omit the first `-'. 5490277Sobrien 5590277Sobrien 3. Look in the "specs" file to determine which program or option 5690277Sobrien list should be given the argument, e.g., "cc1_options". Add the 5790277Sobrien appropriate syntax for the shorter option version to the 5890277Sobrien corresponding "const char *" entry in this file. Omit the first 5990277Sobrien `-' from the option. For example, use `-bar', rather than `--bar'. 6090277Sobrien 6190277Sobrien 4. If the argument takes an argument, e.g., `--baz argument1', 6290277Sobrien modify either DEFAULT_SWITCH_TAKES_ARG or 6390277Sobrien DEFAULT_WORD_SWITCH_TAKES_ARG in this file. Omit the first `-' 6490277Sobrien from `--baz'. 6590277Sobrien 6690277Sobrien 5. Document the option in this file's display_help(). If the 6790277Sobrien option is passed to a subprogram, modify its corresponding 6890277Sobrien function, e.g., cppinit.c:print_help() or toplev.c:display_help(), 6990277Sobrien instead. 7090277Sobrien 7190277Sobrien 6. Compile and test. Make sure that your new specs file is being 7290277Sobrien read. For example, use a debugger to investigate the value of 7390277Sobrien "specs_file" in main(). */ 7490277Sobrien 7550599Sobrien#include "config.h" 7650599Sobrien#include "system.h" 7750599Sobrien#include <signal.h> 7890277Sobrien#if ! defined( SIGCHLD ) && defined( SIGCLD ) 7990277Sobrien# define SIGCHLD SIGCLD 8090277Sobrien#endif 8150599Sobrien#include "obstack.h" 8252520Sobrien#include "intl.h" 8352520Sobrien#include "prefix.h" 8490277Sobrien#include "gcc.h" 8590277Sobrien#include "flags.h" 8618334Speter 8790277Sobrien#ifdef HAVE_SYS_RESOURCE_H 8890277Sobrien#include <sys/resource.h> 8918334Speter#endif 9090277Sobrien#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE 9190277Sobrienextern int getrusage PARAMS ((int, struct rusage *)); 9290277Sobrien#endif 9318334Speter 9490277Sobrien/* By default there is no special suffix for target executables. */ 9590277Sobrien/* FIXME: when autoconf is fixed, remove the host check - dj */ 9690277Sobrien#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX) 9790277Sobrien#define HAVE_TARGET_EXECUTABLE_SUFFIX 9818334Speter#endif 9918334Speter 10090277Sobrien/* By default there is no special suffix for host executables. */ 10190277Sobrien#ifdef HOST_EXECUTABLE_SUFFIX 10290277Sobrien#define HAVE_HOST_EXECUTABLE_SUFFIX 10318334Speter#else 10490277Sobrien#define HOST_EXECUTABLE_SUFFIX "" 10518334Speter#endif 10618334Speter 10790277Sobrien/* By default, the suffix for target object files is ".o". */ 10890277Sobrien#ifdef TARGET_OBJECT_SUFFIX 10990277Sobrien#define HAVE_TARGET_OBJECT_SUFFIX 11090277Sobrien#else 11190277Sobrien#define TARGET_OBJECT_SUFFIX ".o" 11218334Speter#endif 11318334Speter 11490277Sobrien#ifndef VMS 11590277Sobrien/* FIXME: the location independence code for VMS is hairier than this, 11690277Sobrien and hasn't been written. */ 11790277Sobrien#ifndef DIR_UP 11890277Sobrien#define DIR_UP ".." 11990277Sobrien#endif /* DIR_UP */ 12090277Sobrien#endif /* VMS */ 12118334Speter 12290277Sobrienstatic const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; 12352520Sobrien 12490277Sobrien/* Most every one is fine with LIBRARY_PATH. For some, it conflicts. */ 12590277Sobrien#ifndef LIBRARY_PATH_ENV 12690277Sobrien#define LIBRARY_PATH_ENV "LIBRARY_PATH" 12790277Sobrien#endif 12890277Sobrien 12950599Sobrien#ifndef HAVE_KILL 13050599Sobrien#define kill(p,s) raise(s) 13118334Speter#endif 13218334Speter 13318334Speter/* If a stage of compilation returns an exit status >= 1, 13418334Speter compilation of that file ceases. */ 13518334Speter 13618334Speter#define MIN_FATAL_STATUS 1 13718334Speter 13890277Sobrien/* Flag set by cppspec.c to 1. */ 13990277Sobrienint is_cpp_driver; 14090277Sobrien 14190277Sobrien/* Flag saying to pass the greatest exit code returned by a sub-process 14290277Sobrien to the calling program. */ 14390277Sobrienstatic int pass_exit_codes; 14490277Sobrien 14590277Sobrien/* Definition of string containing the arguments given to configure. */ 14690277Sobrien#include "configargs.h" 14790277Sobrien 14818334Speter/* Flag saying to print the directories gcc will search through looking for 14918334Speter programs, libraries, etc. */ 15018334Speter 15118334Speterstatic int print_search_dirs; 15218334Speter 15318334Speter/* Flag saying to print the full filename of this file 15418334Speter as found through our usual search mechanism. */ 15518334Speter 15652520Sobrienstatic const char *print_file_name = NULL; 15718334Speter 15850599Sobrien/* As print_file_name, but search for executable file. */ 15918334Speter 16052520Sobrienstatic const char *print_prog_name = NULL; 16118334Speter 16218334Speter/* Flag saying to print the relative path we'd use to 16318334Speter find libgcc.a given the current compiler flags. */ 16418334Speter 16518334Speterstatic int print_multi_directory; 16618334Speter 167104763Skan/* Flag saying to print the relative path we'd use to 168104763Skan find OS libraries given the current compiler flags. */ 169104763Skan 170104763Skanstatic int print_multi_os_directory; 171104763Skan 17218334Speter/* Flag saying to print the list of subdirectories and 17318334Speter compiler flags used to select them in a standard form. */ 17418334Speter 17518334Speterstatic int print_multi_lib; 17618334Speter 17750599Sobrien/* Flag saying to print the command line options understood by gcc and its 17850599Sobrien sub-processes. */ 17950599Sobrien 18050599Sobrienstatic int print_help_list; 18150599Sobrien 18218334Speter/* Flag indicating whether we should print the command and arguments */ 18318334Speter 18418334Speterstatic int verbose_flag; 18518334Speter 18690277Sobrien/* Flag indicating whether we should ONLY print the command and 18790277Sobrien arguments (like verbose_flag) without executing the command. 18890277Sobrien Displayed arguments are quoted so that the generated command 18990277Sobrien line is suitable for execution. This is intended for use in 19090277Sobrien shell scripts to capture the driver-generated command line. */ 19190277Sobrienstatic int verbose_only_flag; 19290277Sobrien 19390277Sobrien/* Flag indicating to print target specific command line options. */ 19490277Sobrien 19590277Sobrienstatic int target_help_flag; 19690277Sobrien 19790277Sobrien/* Flag indicating whether we should report subprocess execution times 19890277Sobrien (if this is supported by the system - see pexecute.c). */ 19990277Sobrien 20090277Sobrienstatic int report_times; 20190277Sobrien 20218334Speter/* Nonzero means write "temp" files in source directory 20318334Speter and use the source file's name in them, and don't delete them. */ 20418334Speter 20518334Speterstatic int save_temps_flag; 20618334Speter 20718334Speter/* The compiler version. */ 20818334Speter 20990277Sobrienstatic const char *compiler_version; 21018334Speter 21118334Speter/* The target version specified with -V */ 21218334Speter 213117413Skanstatic const char *const spec_version = DEFAULT_TARGET_VERSION; 21418334Speter 21518334Speter/* The target machine specified with -b. */ 21618334Speter 21752520Sobrienstatic const char *spec_machine = DEFAULT_TARGET_MACHINE; 21818334Speter 21918334Speter/* Nonzero if cross-compiling. 22018334Speter When -b is used, the value comes from the `specs' file. */ 22118334Speter 22218334Speter#ifdef CROSS_COMPILE 22390277Sobrienstatic const char *cross_compile = "1"; 22418334Speter#else 22590277Sobrienstatic const char *cross_compile = "0"; 22618334Speter#endif 22718334Speter 22890277Sobrien#ifdef MODIFY_TARGET_NAME 22990277Sobrien 23090277Sobrien/* Information on how to alter the target name based on a command-line 23190277Sobrien switch. The only case we support now is simply appending or deleting a 23290277Sobrien string to or from the end of the first part of the configuration name. */ 23390277Sobrien 23490277Sobrienstatic const struct modify_target 23590277Sobrien{ 23690277Sobrien const char *const sw; 23790277Sobrien const enum add_del {ADD, DELETE} add_del; 23890277Sobrien const char *const str; 23990277Sobrien} 24090277Sobrienmodify_target[] = MODIFY_TARGET_NAME; 24190277Sobrien#endif 242117413Skan 24318334Speter/* The number of errors that have occurred; the link phase will not be 244117413Skan run if this is nonzero. */ 24518334Speterstatic int error_count = 0; 24618334Speter 24790277Sobrien/* Greatest exit code of sub-processes that has been encountered up to 24890277Sobrien now. */ 24990277Sobrienstatic int greatest_status = 1; 25090277Sobrien 25118334Speter/* This is the obstack which we use to allocate many strings. */ 25218334Speter 25318334Speterstatic struct obstack obstack; 25418334Speter 25518334Speter/* This is the obstack to build an environment variable to pass to 25618334Speter collect2 that describes all of the relevant switches of what to 25718334Speter pass the compiler in building the list of pointers to constructors 25818334Speter and destructors. */ 25918334Speter 26018334Speterstatic struct obstack collect_obstack; 26118334Speter 26290277Sobrien/* These structs are used to collect resource usage information for 26390277Sobrien subprocesses. */ 26490277Sobrien#ifdef HAVE_GETRUSAGE 26590277Sobrienstatic struct rusage rus, prus; 26690277Sobrien#endif 26718334Speter 26818334Speter/* Forward declaration for prototypes. */ 26918334Speterstruct path_prefix; 27018334Speter 27190277Sobrienstatic void init_spec PARAMS ((void)); 27290277Sobrienstatic void store_arg PARAMS ((const char *, int, int)); 27390277Sobrienstatic char *load_specs PARAMS ((const char *)); 27490277Sobrienstatic void read_specs PARAMS ((const char *, int)); 27590277Sobrienstatic void set_spec PARAMS ((const char *, const char *)); 27690277Sobrienstatic struct compiler *lookup_compiler PARAMS ((const char *, size_t, const char *)); 27790277Sobrienstatic char *build_search_list PARAMS ((struct path_prefix *, const char *, int)); 27890277Sobrienstatic void putenv_from_prefixes PARAMS ((struct path_prefix *, const char *)); 27990277Sobrienstatic int access_check PARAMS ((const char *, int)); 280104763Skanstatic char *find_a_file PARAMS ((struct path_prefix *, const char *, 281104763Skan int, int)); 28290277Sobrienstatic void add_prefix PARAMS ((struct path_prefix *, const char *, 283104763Skan const char *, int, int, int *, int)); 28490277Sobrienstatic void translate_options PARAMS ((int *, const char *const **)); 28590277Sobrienstatic char *skip_whitespace PARAMS ((char *)); 28690277Sobrienstatic void delete_if_ordinary PARAMS ((const char *)); 28790277Sobrienstatic void delete_temp_files PARAMS ((void)); 28890277Sobrienstatic void delete_failure_queue PARAMS ((void)); 28990277Sobrienstatic void clear_failure_queue PARAMS ((void)); 29090277Sobrienstatic int check_live_switch PARAMS ((int, int)); 29190277Sobrienstatic const char *handle_braces PARAMS ((const char *)); 292117413Skanstatic const struct spec_function *lookup_spec_function PARAMS ((const char *)); 293117413Skanstatic const char *eval_spec_function PARAMS ((const char *, const char *)); 294117413Skanstatic const char *handle_spec_function PARAMS ((const char *)); 29590277Sobrienstatic char *save_string PARAMS ((const char *, int)); 29690277Sobrienstatic void set_collect_gcc_options PARAMS ((void)); 29790277Sobrienstatic int do_spec_1 PARAMS ((const char *, int, const char *)); 298117413Skanstatic int do_spec_2 PARAMS ((const char *)); 299117413Skanstatic void do_self_spec PARAMS ((const char *)); 30090277Sobrienstatic const char *find_file PARAMS ((const char *)); 30190277Sobrienstatic int is_directory PARAMS ((const char *, const char *, int)); 30290277Sobrienstatic void validate_switches PARAMS ((const char *)); 30390277Sobrienstatic void validate_all_switches PARAMS ((void)); 30490277Sobrienstatic void give_switch PARAMS ((int, int, int)); 30590277Sobrienstatic int used_arg PARAMS ((const char *, int)); 30690277Sobrienstatic int default_arg PARAMS ((const char *, int)); 30790277Sobrienstatic void set_multilib_dir PARAMS ((void)); 30890277Sobrienstatic void print_multilib_info PARAMS ((void)); 30990277Sobrienstatic void perror_with_name PARAMS ((const char *)); 31090277Sobrienstatic void pfatal_pexecute PARAMS ((const char *, const char *)) 31152520Sobrien ATTRIBUTE_NORETURN; 31290277Sobrienstatic void notice PARAMS ((const char *, ...)) 31352520Sobrien ATTRIBUTE_PRINTF_1; 31490277Sobrienstatic void display_help PARAMS ((void)); 31590277Sobrienstatic void add_preprocessor_option PARAMS ((const char *, int)); 31690277Sobrienstatic void add_assembler_option PARAMS ((const char *, int)); 31790277Sobrienstatic void add_linker_option PARAMS ((const char *, int)); 31890277Sobrienstatic void process_command PARAMS ((int, const char *const *)); 31990277Sobrienstatic int execute PARAMS ((void)); 320117413Skanstatic void alloc_args PARAMS ((void)); 32190277Sobrienstatic void clear_args PARAMS ((void)); 32290277Sobrienstatic void fatal_error PARAMS ((int)); 32390277Sobrien#ifdef ENABLE_SHARED_LIBGCC 32490277Sobrienstatic void init_gcc_specs PARAMS ((struct obstack *, 32590277Sobrien const char *, const char *, 32690277Sobrien const char *)); 32790277Sobrien#endif 32890277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 32990277Sobrienstatic const char *convert_filename PARAMS ((const char *, int, int)); 33090277Sobrien#endif 331117413Skan 332117413Skanstatic const char *if_exists_spec_function PARAMS ((int, const char **)); 333117413Skanstatic const char *if_exists_else_spec_function PARAMS ((int, const char **)); 33490277Sobrien 33590277Sobrien/* The Specs Language 33618334Speter 33790277SobrienSpecs are strings containing lines, each of which (if not blank) 33818334Speteris made up of a program name, and arguments separated by spaces. 33918334SpeterThe program name must be exact and start from root, since no path 34018334Speteris searched and it is unreliable to depend on the current working directory. 34118334SpeterRedirection of input or output is not supported; the subprograms must 34218334Speteraccept filenames saying what files to read and write. 34318334Speter 34418334SpeterIn addition, the specs can contain %-sequences to substitute variable text 34518334Speteror for conditional text. Here is a table of all defined %-sequences. 34618334SpeterNote that spaces are not generated automatically around the results of 34718334Speterexpanding these sequences; therefore, you can concatenate them together 34818334Speteror with constant text in a single argument. 34918334Speter 35018334Speter %% substitute one % into the program name or argument. 35118334Speter %i substitute the name of the input file being processed. 35218334Speter %b substitute the basename of the input file being processed. 35318334Speter This is the substring up to (and not including) the last period 35418334Speter and not including the directory. 35590277Sobrien %B same as %b, but include the file suffix (text after the last period). 35650599Sobrien %gSUFFIX 35750599Sobrien substitute a file name that has suffix SUFFIX and is chosen 35850599Sobrien once per compilation, and mark the argument a la %d. To reduce 35950599Sobrien exposure to denial-of-service attacks, the file name is now 36050599Sobrien chosen in a way that is hard to predict even when previously 36150599Sobrien chosen file names are known. For example, `%g.s ... %g.o ... %g.s' 36250599Sobrien might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'. SUFFIX matches 36390277Sobrien the regexp "[.A-Za-z]*%O"; "%O" is treated exactly as if it 36490277Sobrien had been pre-processed. Previously, %g was simply substituted 36590277Sobrien with a file name chosen once per compilation, without regard 36690277Sobrien to any appended suffix (which was therefore treated just like 36790277Sobrien ordinary text), making such attacks more likely to succeed. 36850599Sobrien %uSUFFIX 36950599Sobrien like %g, but generates a new temporary file name even if %uSUFFIX 37050599Sobrien was already seen. 37150599Sobrien %USUFFIX 37250599Sobrien substitutes the last file name generated with %uSUFFIX, generating a 37350599Sobrien new one if there is no such last file name. In the absence of any 37450599Sobrien %uSUFFIX, this is just like %gSUFFIX, except they don't share 37550599Sobrien the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s' 37650599Sobrien would involve the generation of two distinct file names, one 37750599Sobrien for each `%g.s' and another for each `%U.s'. Previously, %U was 37850599Sobrien simply substituted with a file name chosen for the previous %u, 37950599Sobrien without regard to any appended suffix. 38090277Sobrien %jSUFFIX 38190277Sobrien substitutes the name of the HOST_BIT_BUCKET, if any, and if it is 38290277Sobrien writable, and if save-temps is off; otherwise, substitute the name 38390277Sobrien of a temporary file, just like %u. This temporary file is not 38490277Sobrien meant for communication between processes, but rather as a junk 38590277Sobrien disposal mechanism. 38690277Sobrien %.SUFFIX 38790277Sobrien substitutes .SUFFIX for the suffixes of a matched switch's args when 38890277Sobrien it is subsequently output with %*. SUFFIX is terminated by the next 38990277Sobrien space or %. 39018334Speter %d marks the argument containing or following the %d as a 39118334Speter temporary file name, so that that file will be deleted if CC exits 39218334Speter successfully. Unlike %g, this contributes no text to the argument. 39318334Speter %w marks the argument containing or following the %w as the 39418334Speter "output file" of this compilation. This puts the argument 39518334Speter into the sequence of arguments that %o will substitute later. 39618334Speter %W{...} 39718334Speter like %{...} but mark last argument supplied within 39818334Speter as a file to be deleted on failure. 39918334Speter %o substitutes the names of all the output files, with spaces 40018334Speter automatically placed around them. You should write spaces 40118334Speter around the %o as well or the results are undefined. 40218334Speter %o is for use in the specs for running the linker. 40318334Speter Input files whose names have no recognized suffix are not compiled 40418334Speter at all, but they are included among the output files, so they will 40518334Speter be linked. 40650599Sobrien %O substitutes the suffix for object files. Note that this is 40790277Sobrien handled specially when it immediately follows %g, %u, or %U 40890277Sobrien (with or without a suffix argument) because of the need for 40990277Sobrien those to form complete file names. The handling is such that 41090277Sobrien %O is treated exactly as if it had already been substituted, 41190277Sobrien except that %g, %u, and %U do not currently support additional 41290277Sobrien SUFFIX characters following %O as they would following, for 41390277Sobrien example, `.o'. 41418334Speter %p substitutes the standard macro predefinitions for the 41518334Speter current target machine. Use this when running cpp. 41618334Speter %P like %p, but puts `__' before and after the name of each macro. 41718334Speter (Except macros that already have __.) 41818334Speter This is for ANSI C. 41918334Speter %I Substitute a -iprefix option made from GCC_EXEC_PREFIX. 42018334Speter %s current argument is the name of a library or startup file of some sort. 42118334Speter Search for that file in a standard list of directories 42218334Speter and substitute the full name found. 42318334Speter %eSTR Print STR as an error message. STR is terminated by a newline. 42418334Speter Use this when inconsistent options are detected. 425117413Skan %nSTR Print STR as a notice. STR is terminated by a newline. 42618334Speter %x{OPTION} Accumulate an option for %X. 42718334Speter %X Output the accumulated linker options specified by compilations. 42818334Speter %Y Output the accumulated assembler options specified by compilations. 42918334Speter %Z Output the accumulated preprocessor options specified by compilations. 43018334Speter %v1 Substitute the major version number of GCC. 43190277Sobrien (For version 2.5.3, this is 2.) 43218334Speter %v2 Substitute the minor version number of GCC. 43390277Sobrien (For version 2.5.3, this is 5.) 43490277Sobrien %v3 Substitute the patch level number of GCC. 43590277Sobrien (For version 2.5.3, this is 3.) 43618334Speter %a process ASM_SPEC as a spec. 43718334Speter This allows config.h to specify part of the spec for running as. 43818334Speter %A process ASM_FINAL_SPEC as a spec. A capital A is actually 43918334Speter used here. This can be used to run a post-processor after the 44050599Sobrien assembler has done its job. 44118334Speter %D Dump out a -L option for each directory in startfile_prefixes. 44218334Speter If multilib_dir is set, extra entries are generated with it affixed. 44318334Speter %l process LINK_SPEC as a spec. 44418334Speter %L process LIB_SPEC as a spec. 44518334Speter %G process LIBGCC_SPEC as a spec. 44690277Sobrien %M output multilib_dir with directory separators replaced with "_"; 44790277Sobrien if multilib_dir is not set or is ".", output "". 44818334Speter %S process STARTFILE_SPEC as a spec. A capital S is actually used here. 44918334Speter %E process ENDFILE_SPEC as a spec. A capital E is actually used here. 45090277Sobrien %C process CPP_SPEC as a spec. 45118334Speter %1 process CC1_SPEC as a spec. 45218334Speter %2 process CC1PLUS_SPEC as a spec. 45318334Speter %| output "-" if the input for the current command is coming from a pipe. 45418334Speter %* substitute the variable part of a matched option. (See below.) 45518334Speter Note that each comma in the substituted string is replaced by 45618334Speter a single space. 457117413Skan %:function(args) 458117413Skan Call the named function FUNCTION, passing it ARGS. ARGS is 459117413Skan first processed as a nested spec string, then split into an 460117413Skan argument vector in the usual fashion. The function returns 461117413Skan a string which is processed as if it had appeared literally 462117413Skan as part of the current spec. 46318334Speter %{S} substitutes the -S switch, if that switch was given to CC. 46418334Speter If that switch was not specified, this substitutes nothing. 46518334Speter Here S is a metasyntactic variable. 46618334Speter %{S*} substitutes all the switches specified to CC whose names start 46790277Sobrien with -S. This is used for -o, -I, etc; switches that take 46818334Speter arguments. CC considers `-o foo' as being one switch whose 46918334Speter name starts with `o'. %{o*} would substitute this text, 47018334Speter including the space; thus, two arguments would be generated. 47150599Sobrien %{^S*} likewise, but don't put a blank between a switch and any args. 47290277Sobrien %{S*&T*} likewise, but preserve order of S and T options (the order 47390277Sobrien of S and T in the spec is not significant). Can be any number 47490277Sobrien of ampersand-separated variables; for each the wild card is 47590277Sobrien optional. Useful for CPP as %{D*&U*&A*}. 47618334Speter %{S*:X} substitutes X if one or more switches whose names start with -S are 47718334Speter specified to CC. Note that the tail part of the -S option 47818334Speter (i.e. the part matched by the `*') will be substituted for each 47918334Speter occurrence of %* within X. 48090277Sobrien %{<S} remove all occurrences of -S from the command line. 48190277Sobrien Note - this option is position dependent. % commands in the 48290277Sobrien spec string before this option will see -S, % commands in the 48390277Sobrien spec string after this option will not. 48418334Speter %{S:X} substitutes X, but only if the -S switch was given to CC. 48518334Speter %{!S:X} substitutes X, but only if the -S switch was NOT given to CC. 48618334Speter %{|S:X} like %{S:X}, but if no S switch, substitute `-'. 48718334Speter %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'. 48818334Speter %{.S:X} substitutes X, but only if processing a file with suffix S. 48918334Speter %{!.S:X} substitutes X, but only if NOT processing a file with suffix S. 49050599Sobrien %{S|P:X} substitutes X if either -S or -P was given to CC. This may be 49150599Sobrien combined with ! and . as above binding stronger than the OR. 49218334Speter %(Spec) processes a specification defined in a specs file as *Spec: 49318334Speter %[Spec] as above, but put __ around -D arguments 49418334Speter 49518334SpeterThe conditional text X in a %{S:X} or %{!S:X} construct may contain 49618334Speterother nested % constructs or spaces, or even newlines. They are 49718334Speterprocessed as usual, as described above. 49818334Speter 49918334SpeterThe -O, -f, -m, and -W switches are handled specifically in these 50018334Speterconstructs. If another value of -O or the negated form of a -f, -m, or 50118334Speter-W switch is found later in the command line, the earlier switch 50218334Spetervalue is ignored, except with {S*} where S is just one letter; this 50318334Speterpasses all matching options. 50418334Speter 50550599SobrienThe character | at the beginning of the predicate text is used to indicate 50650599Sobrienthat a command should be piped to the following command, but only if -pipe 50750599Sobrienis specified. 50818334Speter 50918334SpeterNote that it is built into CC which switches take arguments and which 51018334Speterdo not. You might think it would be useful to generalize this to 51118334Speterallow each compiler's spec to say which switches take arguments. But 51218334Speterthis cannot be done in a consistent fashion. CC cannot even decide 51318334Speterwhich input files have been specified without knowing which switches 51418334Spetertake arguments, and it must know which input files to compile in order 51518334Speterto tell which compilers to run. 51618334Speter 51718334SpeterCC also knows implicitly that arguments starting in `-l' are to be 51818334Spetertreated as compiler output files, and passed to the linker in their 51918334Speterproper position among the other output files. */ 52018334Speter 52196285Sobrien/* Define the macros used for specs %a, %l, %L, %S, %C, %1. */ 52218334Speter 52318334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler 52418334Speter or extra switch-translations. */ 52518334Speter#ifndef ASM_SPEC 52618334Speter#define ASM_SPEC "" 52718334Speter#endif 52818334Speter 52918334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after 53018334Speter the assembler has run. */ 53118334Speter#ifndef ASM_FINAL_SPEC 53218334Speter#define ASM_FINAL_SPEC "" 53318334Speter#endif 53418334Speter 53518334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor 53618334Speter or extra switch-translations. */ 53718334Speter#ifndef CPP_SPEC 53818334Speter#define CPP_SPEC "" 53918334Speter#endif 54018334Speter 54118334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus 54218334Speter or extra switch-translations. */ 54318334Speter#ifndef CC1_SPEC 54418334Speter#define CC1_SPEC "" 54518334Speter#endif 54618334Speter 54718334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus 54818334Speter or extra switch-translations. */ 54918334Speter#ifndef CC1PLUS_SPEC 55018334Speter#define CC1PLUS_SPEC "" 55118334Speter#endif 55218334Speter 55318334Speter/* config.h can define LINK_SPEC to provide extra args to the linker 55418334Speter or extra switch-translations. */ 55518334Speter#ifndef LINK_SPEC 55618334Speter#define LINK_SPEC "" 55718334Speter#endif 55818334Speter 55918334Speter/* config.h can define LIB_SPEC to override the default libraries. */ 56018334Speter#ifndef LIB_SPEC 56118334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}" 56218334Speter#endif 56318334Speter 56418334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is 56518334Speter included. */ 56618334Speter#ifndef LIBGCC_SPEC 56718334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1) 56818334Speter/* Have gcc do the search for libgcc.a. */ 56950599Sobrien#define LIBGCC_SPEC "libgcc.a%s" 57018334Speter#else 57150599Sobrien#define LIBGCC_SPEC "-lgcc" 57218334Speter#endif 57318334Speter#endif 57418334Speter 57518334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files. */ 57618334Speter#ifndef STARTFILE_SPEC 57718334Speter#define STARTFILE_SPEC \ 57818334Speter "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}" 57918334Speter#endif 58018334Speter 58150599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options 58250599Sobrien require spaces between the option and the argument. */ 58318334Speter#ifndef SWITCHES_NEED_SPACES 58418334Speter#define SWITCHES_NEED_SPACES "" 58518334Speter#endif 58618334Speter 58718334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files. */ 58818334Speter#ifndef ENDFILE_SPEC 58918334Speter#define ENDFILE_SPEC "" 59018334Speter#endif 59118334Speter 59250599Sobrien#ifndef LINKER_NAME 59350599Sobrien#define LINKER_NAME "collect2" 59418334Speter#endif 59518334Speter 59690277Sobrien/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g' 59790277Sobrien to the assembler. */ 59890277Sobrien#ifndef ASM_DEBUG_SPEC 59990277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \ 60090277Sobrien && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) 60190277Sobrien# define ASM_DEBUG_SPEC \ 60290277Sobrien (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \ 60390277Sobrien ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" \ 60490277Sobrien : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}") 60590277Sobrien# else 60690277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) 60790277Sobrien# define ASM_DEBUG_SPEC "%{g*:--gstabs}" 60890277Sobrien# endif 60990277Sobrien# if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) 61090277Sobrien# define ASM_DEBUG_SPEC "%{g*:--gdwarf2}" 61190277Sobrien# endif 61290277Sobrien# endif 61390277Sobrien#endif 61490277Sobrien#ifndef ASM_DEBUG_SPEC 61590277Sobrien# define ASM_DEBUG_SPEC "" 61690277Sobrien#endif 61718334Speter 61890277Sobrien/* Here is the spec for running the linker, after compiling all files. */ 61990277Sobrien 62096285Sobrien/* This is overridable by the target in case they need to specify the 62196285Sobrien -lgcc and -lc order specially, yet not require them to override all 62296285Sobrien of LINK_COMMAND_SPEC. */ 62396285Sobrien#ifndef LINK_GCC_C_SEQUENCE_SPEC 62496285Sobrien#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G" 62596285Sobrien#endif 62696285Sobrien 62790277Sobrien/* -u* was put back because both BSD and SysV seem to support it. */ 62890277Sobrien/* %{static:} simply prevents an error message if the target machine 62990277Sobrien doesn't handle -static. */ 63090277Sobrien/* We want %{T*} after %{L*} and %D so that it can be used to specify linker 63190277Sobrien scripts which exist in user specified directories, or in standard 63290277Sobrien directories. */ 63390277Sobrien#ifndef LINK_COMMAND_SPEC 63490277Sobrien#define LINK_COMMAND_SPEC "\ 63590277Sobrien%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ 63690277Sobrien %(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r} %{s} %{t}\ 63790277Sobrien %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ 63896285Sobrien %{static:} %{L*} %(link_libgcc) %o %{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\ 63990277Sobrien %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}" 64090277Sobrien#endif 64190277Sobrien 64290277Sobrien#ifndef LINK_LIBGCC_SPEC 64390277Sobrien# ifdef LINK_LIBGCC_SPECIAL 64490277Sobrien/* Don't generate -L options for startfile prefix list. */ 64590277Sobrien# define LINK_LIBGCC_SPEC "" 64690277Sobrien# else 64790277Sobrien/* Do generate them. */ 64890277Sobrien# define LINK_LIBGCC_SPEC "%D" 64990277Sobrien# endif 65090277Sobrien#endif 65190277Sobrien 652117413Skan#ifndef STARTFILE_PREFIX_SPEC 653117413Skan# define STARTFILE_PREFIX_SPEC "" 654117413Skan#endif 655117413Skan 656117413Skanstatic const char *asm_debug; 65790277Sobrienstatic const char *cpp_spec = CPP_SPEC; 65890277Sobrienstatic const char *cpp_predefines = CPP_PREDEFINES; 65990277Sobrienstatic const char *cc1_spec = CC1_SPEC; 66090277Sobrienstatic const char *cc1plus_spec = CC1PLUS_SPEC; 66196285Sobrienstatic const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC; 66290277Sobrienstatic const char *asm_spec = ASM_SPEC; 66390277Sobrienstatic const char *asm_final_spec = ASM_FINAL_SPEC; 66490277Sobrienstatic const char *link_spec = LINK_SPEC; 66590277Sobrienstatic const char *lib_spec = LIB_SPEC; 66690277Sobrienstatic const char *libgcc_spec = LIBGCC_SPEC; 66790277Sobrienstatic const char *endfile_spec = ENDFILE_SPEC; 66890277Sobrienstatic const char *startfile_spec = STARTFILE_SPEC; 66990277Sobrienstatic const char *switches_need_spaces = SWITCHES_NEED_SPACES; 67090277Sobrienstatic const char *linker_name_spec = LINKER_NAME; 67190277Sobrienstatic const char *link_command_spec = LINK_COMMAND_SPEC; 67290277Sobrienstatic const char *link_libgcc_spec = LINK_LIBGCC_SPEC; 673117413Skanstatic const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC; 67490277Sobrien 67590277Sobrien/* Standard options to cpp, cc1, and as, to reduce duplication in specs. 67690277Sobrien There should be no need to override these in target dependent files, 67790277Sobrien but we need to copy them to the specs file so that newer versions 67890277Sobrien of the GCC driver can correctly drive older tool chains with the 67990277Sobrien appropriate -B options. */ 68090277Sobrien 681117413Skan/* When cpplib handles traditional preprocessing, get rid of this, and 682117413Skan call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so 683117413Skan that we default the front end language better. */ 68490277Sobrienstatic const char *trad_capable_cpp = 685117413Skan"cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}"; 68690277Sobrien 687107594Sobrien/* We don't wrap .d files in %W{} since a missing .d file, and 688107594Sobrien therefore no dependency entry, confuses make into thinking a .o 689107594Sobrien file that happens to exist is up-to-date. */ 69090277Sobrienstatic const char *cpp_unique_options = 69190277Sobrien"%{C:%{!E:%eGNU C does not support -C without using -E}}\ 692117413Skan %{CC:%{!E:%eGNU C does not support -CC without using -E}}\ 693117413Skan %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*} %{P} %I\ 694107594Sobrien %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\ 695107594Sobrien %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\ 696107594Sobrien %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\ 69796285Sobrien %{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\ 698117413Skan %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\ 69990277Sobrien %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\ 700117413Skan %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\ 70196285Sobrien %{E|M|MM:%W{o*}}"; 70290277Sobrien 70390277Sobrien/* This contains cpp options which are common with cc1_options and are passed 704117413Skan only when preprocessing only to avoid duplication. We pass the cc1 spec 705117413Skan options to the preprocessor so that it the cc1 spec may manipulate 706117413Skan options used to set target flags. Those special target flags settings may 707117413Skan in turn cause preprocessor symbols to be defined specially. */ 70890277Sobrienstatic const char *cpp_options = 709117413Skan"%(cpp_unique_options) %1 %{m*} %{std*} %{ansi} %{W*&pedantic*} %{w} %{f*}\ 710117413Skan %{O*} %{undef}"; 71190277Sobrien 712117413Skan/* This contains cpp options which are not passed when the preprocessor 713117413Skan output will be used by another program. */ 714117413Skanstatic const char *cpp_debug_options = "%{d*}"; 715117413Skan 71690277Sobrien/* NB: This is shared amongst all front-ends. */ 71790277Sobrienstatic const char *cc1_options = 71890277Sobrien"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 71990277Sobrien %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\ 720117413Skan -auxbase%{c|S:%{o*:-strip %*}%{!o*: %b}}%{!c:%{!S: %b}}\ 721117413Skan %{g*} %{O*} %{W*&pedantic*} %{w} %{std*} %{ansi}\ 722117413Skan %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\ 72390277Sobrien %{Qn:-fno-ident} %{--help:--help}\ 72490277Sobrien %{--target-help:--target-help}\ 72590277Sobrien %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\ 72690277Sobrien %{fsyntax-only:-o %j} %{-param*}"; 72790277Sobrien 72890277Sobrienstatic const char *asm_options = 72990277Sobrien"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}"; 73090277Sobrien 73190277Sobrienstatic const char *invoke_as = 73290277Sobrien"%{!S:-o %{|!pipe:%g.s} |\n as %(asm_options) %{!pipe:%g.s} %A }"; 73390277Sobrien 73450599Sobrien/* Some compilers have limits on line lengths, and the multilib_select 73550599Sobrien and/or multilib_matches strings can be very long, so we build them at 73650599Sobrien run time. */ 73750599Sobrienstatic struct obstack multilib_obstack; 73890277Sobrienstatic const char *multilib_select; 73990277Sobrienstatic const char *multilib_matches; 74090277Sobrienstatic const char *multilib_defaults; 74190277Sobrienstatic const char *multilib_exclusions; 74250599Sobrien#include "multilib.h" 74350599Sobrien 74450599Sobrien/* Check whether a particular argument is a default argument. */ 74550599Sobrien 74650599Sobrien#ifndef MULTILIB_DEFAULTS 74750599Sobrien#define MULTILIB_DEFAULTS { "" } 74850599Sobrien#endif 74950599Sobrien 75090277Sobrienstatic const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS; 75150599Sobrien 752117413Skan#ifndef DRIVER_SELF_SPECS 753117413Skan#define DRIVER_SELF_SPECS "" 754117413Skan#endif 755117413Skan 756117413Skanstatic const char *const driver_self_specs[] = { DRIVER_SELF_SPECS }; 757117413Skan 75890277Sobrienstruct user_specs 75990277Sobrien{ 76050599Sobrien struct user_specs *next; 76152520Sobrien const char *filename; 76250599Sobrien}; 76350599Sobrien 76450599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail; 76550599Sobrien 76650599Sobrien#ifndef SWITCH_TAKES_ARG 76750599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR) 76818334Speter#endif 76918334Speter 77018334Speter#ifndef WORD_SWITCH_TAKES_ARG 77118334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR) 77218334Speter#endif 77318334Speter 77490277Sobrien#ifdef HAVE_TARGET_EXECUTABLE_SUFFIX 77550599Sobrien/* This defines which switches stop a full compilation. */ 77650599Sobrien#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \ 77750599Sobrien ((CHAR) == 'c' || (CHAR) == 'S') 77850599Sobrien 77950599Sobrien#ifndef SWITCH_CURTAILS_COMPILATION 78050599Sobrien#define SWITCH_CURTAILS_COMPILATION(CHAR) \ 78150599Sobrien DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) 78250599Sobrien#endif 78350599Sobrien#endif 78450599Sobrien 78518334Speter/* Record the mapping from file suffixes for compilation specs. */ 78618334Speter 78718334Speterstruct compiler 78818334Speter{ 78952520Sobrien const char *suffix; /* Use this compiler for input files 79018334Speter whose names end in this suffix. */ 79118334Speter 79290277Sobrien const char *spec; /* To use this compiler, run this spec. */ 79390277Sobrien 79490277Sobrien const char *cpp_spec; /* If non-NULL, substitute this spec 79590277Sobrien for `%C', rather than the usual 79690277Sobrien cpp_spec. */ 79718334Speter}; 79818334Speter 79918334Speter/* Pointer to a vector of `struct compiler' that gives the spec for 80018334Speter compiling a file, based on its suffix. 80118334Speter A file that does not end in any of these suffixes will be passed 80218334Speter unchanged to the loader and nothing else will be done to it. 80318334Speter 80418334Speter An entry containing two 0s is used to terminate the vector. 80518334Speter 80618334Speter If multiple entries match a file, the last matching one is used. */ 80718334Speter 80818334Speterstatic struct compiler *compilers; 80918334Speter 81018334Speter/* Number of entries in `compilers', not counting the null terminator. */ 81118334Speter 81218334Speterstatic int n_compilers; 81318334Speter 81418334Speter/* The default list of file name suffixes and their compilation specs. */ 81518334Speter 81690277Sobrienstatic const struct compiler default_compilers[] = 81718334Speter{ 81850599Sobrien /* Add lists of suffixes of known languages here. If those languages 81950599Sobrien were not present when we built the driver, we will hit these copies 82050599Sobrien and be given a more meaningful error than "file not used since 82150599Sobrien linking is not done". */ 82290277Sobrien {".m", "#Objective-C", 0}, {".mi", "#Objective-C", 0}, 82390277Sobrien {".cc", "#C++", 0}, {".cxx", "#C++", 0}, {".cpp", "#C++", 0}, 82490277Sobrien {".cp", "#C++", 0}, {".c++", "#C++", 0}, {".C", "#C++", 0}, 82590277Sobrien {".ii", "#C++", 0}, 82690277Sobrien {".ads", "#Ada", 0}, {".adb", "#Ada", 0}, 82790277Sobrien {".f", "#Fortran", 0}, {".for", "#Fortran", 0}, {".fpp", "#Fortran", 0}, 82890277Sobrien {".F", "#Fortran", 0}, {".FOR", "#Fortran", 0}, {".FPP", "#Fortran", 0}, 82990277Sobrien {".r", "#Ratfor", 0}, 83090277Sobrien {".p", "#Pascal", 0}, {".pas", "#Pascal", 0}, 83190277Sobrien {".java", "#Java", 0}, {".class", "#Java", 0}, 83290277Sobrien {".zip", "#Java", 0}, {".jar", "#Java", 0}, 83350599Sobrien /* Next come the entries for C. */ 83490277Sobrien {".c", "@c", 0}, 83518334Speter {"@c", 83690277Sobrien /* cc1 has an integrated ISO C preprocessor. We should invoke the 837117413Skan external preprocessor if -save-temps is given. */ 838117413Skan "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\ 83990277Sobrien %{!E:%{!M:%{!MM:\ 840117413Skan %{traditional|ftraditional:\ 841117413Skan%eGNU C no longer supports -traditional without -E}\ 842117413Skan %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ 84396285Sobrien %(cpp_options) %{save-temps:%b.i} %{!save-temps:%g.i} \n\ 84496285Sobrien cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} %(cc1_options)}\ 845117413Skan %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\ 846117413Skan cc1 %(cpp_unique_options) %(cc1_options)}}}\ 84790277Sobrien %{!fsyntax-only:%(invoke_as)}}}}", 0}, 84818334Speter {"-", 84990277Sobrien "%{!E:%e-E required when input is from standard input}\ 850117413Skan %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0}, 85190277Sobrien {".h", "@c-header", 0}, 85218334Speter {"@c-header", 85390277Sobrien "%{!E:%ecompilation of header file requested} \ 854117413Skan %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 855117413Skan 0}, 85690277Sobrien {".i", "@cpp-output", 0}, 85718334Speter {"@cpp-output", 85890277Sobrien "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0}, 85990277Sobrien {".s", "@assembler", 0}, 86018334Speter {"@assembler", 86190277Sobrien "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0}, 86290277Sobrien {".S", "@assembler-with-cpp", 0}, 86318334Speter {"@assembler-with-cpp", 86490277Sobrien "%(trad_capable_cpp) -lang-asm %(cpp_options)\ 865117413Skan %{E|M|MM:%(cpp_debug_options)}\ 86690277Sobrien %{!M:%{!MM:%{!E:%{!S:-o %{|!pipe:%g.s} |\n\ 86790277Sobrien as %(asm_debug) %(asm_options) %{!pipe:%g.s} %A }}}}", 0}, 86818334Speter#include "specs.h" 86918334Speter /* Mark end of table */ 87090277Sobrien {0, 0, 0} 87118334Speter}; 87218334Speter 87318334Speter/* Number of elements in default_compilers, not counting the terminator. */ 87418334Speter 875117413Skanstatic const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1; 87618334Speter 87718334Speter/* A vector of options to give to the linker. 87818334Speter These options are accumulated by %x, 87918334Speter and substituted into the linker command with %X. */ 88018334Speterstatic int n_linker_options; 88118334Speterstatic char **linker_options; 88218334Speter 88318334Speter/* A vector of options to give to the assembler. 88418334Speter These options are accumulated by -Wa, 88518334Speter and substituted into the assembler command with %Y. */ 88618334Speterstatic int n_assembler_options; 88718334Speterstatic char **assembler_options; 88818334Speter 88918334Speter/* A vector of options to give to the preprocessor. 89018334Speter These options are accumulated by -Wp, 89118334Speter and substituted into the preprocessor command with %Z. */ 89218334Speterstatic int n_preprocessor_options; 89318334Speterstatic char **preprocessor_options; 89418334Speter 89518334Speter/* Define how to map long options into short ones. */ 89618334Speter 89718334Speter/* This structure describes one mapping. */ 89818334Speterstruct option_map 89918334Speter{ 90018334Speter /* The long option's name. */ 90190277Sobrien const char *const name; 90218334Speter /* The equivalent short option. */ 90390277Sobrien const char *const equivalent; 90418334Speter /* Argument info. A string of flag chars; NULL equals no options. 90518334Speter a => argument required. 90618334Speter o => argument optional. 90718334Speter j => join argument to equivalent, making one word. 90818334Speter * => require other text after NAME as an argument. */ 90990277Sobrien const char *const arg_info; 91018334Speter}; 91118334Speter 91218334Speter/* This is the table of mappings. Mappings are tried sequentially 91318334Speter for each option encountered; the first one that matches, wins. */ 91418334Speter 91590277Sobrienstatic const struct option_map option_map[] = 91618334Speter { 91718334Speter {"--all-warnings", "-Wall", 0}, 91818334Speter {"--ansi", "-ansi", 0}, 91918334Speter {"--assemble", "-S", 0}, 92018334Speter {"--assert", "-A", "a"}, 92152520Sobrien {"--classpath", "-fclasspath=", "aj"}, 92296285Sobrien {"--bootclasspath", "-fbootclasspath=", "aj"}, 92396285Sobrien {"--CLASSPATH", "-fclasspath=", "aj"}, 92418334Speter {"--comments", "-C", 0}, 925117413Skan {"--comments-in-macros", "-CC", 0}, 92618334Speter {"--compile", "-c", 0}, 92718334Speter {"--debug", "-g", "oj"}, 92850599Sobrien {"--define-macro", "-D", "aj"}, 92918334Speter {"--dependencies", "-M", 0}, 93018334Speter {"--dump", "-d", "a"}, 93118334Speter {"--dumpbase", "-dumpbase", "a"}, 93218334Speter {"--entry", "-e", 0}, 93318334Speter {"--extra-warnings", "-W", 0}, 93418334Speter {"--for-assembler", "-Wa", "a"}, 93518334Speter {"--for-linker", "-Xlinker", "a"}, 93618334Speter {"--force-link", "-u", "a"}, 93718334Speter {"--imacros", "-imacros", "a"}, 93818334Speter {"--include", "-include", "a"}, 93918334Speter {"--include-barrier", "-I-", 0}, 94050599Sobrien {"--include-directory", "-I", "aj"}, 94118334Speter {"--include-directory-after", "-idirafter", "a"}, 94218334Speter {"--include-prefix", "-iprefix", "a"}, 94318334Speter {"--include-with-prefix", "-iwithprefix", "a"}, 94418334Speter {"--include-with-prefix-before", "-iwithprefixbefore", "a"}, 94518334Speter {"--include-with-prefix-after", "-iwithprefix", "a"}, 94618334Speter {"--language", "-x", "a"}, 94718334Speter {"--library-directory", "-L", "a"}, 94818334Speter {"--machine", "-m", "aj"}, 94918334Speter {"--machine-", "-m", "*j"}, 95096285Sobrien {"--no-integrated-cpp", "-no-integrated-cpp", 0}, 95118334Speter {"--no-line-commands", "-P", 0}, 95218334Speter {"--no-precompiled-includes", "-noprecomp", 0}, 95318334Speter {"--no-standard-includes", "-nostdinc", 0}, 95418334Speter {"--no-standard-libraries", "-nostdlib", 0}, 95518334Speter {"--no-warnings", "-w", 0}, 95618334Speter {"--optimize", "-O", "oj"}, 95718334Speter {"--output", "-o", "a"}, 95852520Sobrien {"--output-class-directory", "-foutput-class-dir=", "ja"}, 95990277Sobrien {"--param", "--param", "a"}, 96018334Speter {"--pedantic", "-pedantic", 0}, 96118334Speter {"--pedantic-errors", "-pedantic-errors", 0}, 96218334Speter {"--pipe", "-pipe", 0}, 96318334Speter {"--prefix", "-B", "a"}, 96418334Speter {"--preprocess", "-E", 0}, 96518334Speter {"--print-search-dirs", "-print-search-dirs", 0}, 96618334Speter {"--print-file-name", "-print-file-name=", "aj"}, 96718334Speter {"--print-libgcc-file-name", "-print-libgcc-file-name", 0}, 96818334Speter {"--print-missing-file-dependencies", "-MG", 0}, 96918334Speter {"--print-multi-lib", "-print-multi-lib", 0}, 97018334Speter {"--print-multi-directory", "-print-multi-directory", 0}, 971104763Skan {"--print-multi-os-directory", "-print-multi-os-directory", 0}, 97218334Speter {"--print-prog-name", "-print-prog-name=", "aj"}, 97318334Speter {"--profile", "-p", 0}, 97418334Speter {"--profile-blocks", "-a", 0}, 97518334Speter {"--quiet", "-q", 0}, 97696285Sobrien {"--resource", "-fcompile-resource=", "aj"}, 97718334Speter {"--save-temps", "-save-temps", 0}, 97818334Speter {"--shared", "-shared", 0}, 97918334Speter {"--silent", "-q", 0}, 98050599Sobrien {"--specs", "-specs=", "aj"}, 98118334Speter {"--static", "-static", 0}, 98252520Sobrien {"--std", "-std=", "aj"}, 98318334Speter {"--symbolic", "-symbolic", 0}, 98418334Speter {"--target", "-b", "a"}, 98590277Sobrien {"--time", "-time", 0}, 98618334Speter {"--trace-includes", "-H", 0}, 98718334Speter {"--traditional", "-traditional", 0}, 98818334Speter {"--traditional-cpp", "-traditional-cpp", 0}, 98918334Speter {"--trigraphs", "-trigraphs", 0}, 99050599Sobrien {"--undefine-macro", "-U", "aj"}, 99118334Speter {"--use-version", "-V", "a"}, 99218334Speter {"--user-dependencies", "-MM", 0}, 99318334Speter {"--verbose", "-v", 0}, 99418334Speter {"--warn-", "-W", "*j"}, 99518334Speter {"--write-dependencies", "-MD", 0}, 99618334Speter {"--write-user-dependencies", "-MMD", 0}, 99718334Speter {"--", "-f", "*j"} 99818334Speter }; 99918334Speter 100090277Sobrien 100190277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE 100290277Sobrienstatic const struct { 100390277Sobrien const char *const option_found; 100490277Sobrien const char *const replacements; 100590277Sobrien} target_option_translations[] = 100690277Sobrien{ 100790277Sobrien TARGET_OPTION_TRANSLATE_TABLE, 100890277Sobrien { 0, 0 } 100990277Sobrien}; 101090277Sobrien#endif 101190277Sobrien 101218334Speter/* Translate the options described by *ARGCP and *ARGVP. 101318334Speter Make a new vector and store it back in *ARGVP, 101418334Speter and store its length in *ARGVC. */ 101518334Speter 101618334Speterstatic void 101718334Spetertranslate_options (argcp, argvp) 101818334Speter int *argcp; 101990277Sobrien const char *const **argvp; 102018334Speter{ 102152520Sobrien int i; 102218334Speter int argc = *argcp; 102390277Sobrien const char *const *argv = *argvp; 102490277Sobrien int newvsize = (argc + 2) * 2 * sizeof (const char *); 102552520Sobrien const char **newv = 102690277Sobrien (const char **) xmalloc (newvsize); 102718334Speter int newindex = 0; 102818334Speter 102918334Speter i = 0; 103018334Speter newv[newindex++] = argv[i++]; 103118334Speter 103218334Speter while (i < argc) 103318334Speter { 103490277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE 103590277Sobrien int tott_idx; 103690277Sobrien 103790277Sobrien for (tott_idx = 0; 103890277Sobrien target_option_translations[tott_idx].option_found; 103990277Sobrien tott_idx++) 104090277Sobrien { 104190277Sobrien if (strcmp (target_option_translations[tott_idx].option_found, 104290277Sobrien argv[i]) == 0) 104390277Sobrien { 104490277Sobrien int spaces = 1; 104590277Sobrien const char *sp; 104690277Sobrien char *np; 104790277Sobrien 104890277Sobrien for (sp = target_option_translations[tott_idx].replacements; 104990277Sobrien *sp; sp++) 105090277Sobrien { 105190277Sobrien if (*sp == ' ') 105290277Sobrien spaces ++; 105390277Sobrien } 105490277Sobrien 105590277Sobrien newvsize += spaces * sizeof (const char *); 105690277Sobrien newv = (const char **) xrealloc (newv, newvsize); 105790277Sobrien 105890277Sobrien sp = target_option_translations[tott_idx].replacements; 105990277Sobrien np = xstrdup (sp); 106090277Sobrien 106190277Sobrien while (1) 106290277Sobrien { 106390277Sobrien while (*np == ' ') 106490277Sobrien np++; 106590277Sobrien if (*np == 0) 106690277Sobrien break; 106790277Sobrien newv[newindex++] = np; 106890277Sobrien while (*np != ' ' && *np) 106990277Sobrien np++; 107090277Sobrien if (*np == 0) 107190277Sobrien break; 107290277Sobrien *np++ = 0; 107390277Sobrien } 107490277Sobrien 107590277Sobrien i ++; 107690277Sobrien break; 107790277Sobrien } 107890277Sobrien } 107990277Sobrien if (target_option_translations[tott_idx].option_found) 108090277Sobrien continue; 108190277Sobrien#endif 108290277Sobrien 108318334Speter /* Translate -- options. */ 108418334Speter if (argv[i][0] == '-' && argv[i][1] == '-') 108518334Speter { 108652520Sobrien size_t j; 108718334Speter /* Find a mapping that applies to this option. */ 108890277Sobrien for (j = 0; j < ARRAY_SIZE (option_map); j++) 108918334Speter { 109050599Sobrien size_t optlen = strlen (option_map[j].name); 109150599Sobrien size_t arglen = strlen (argv[i]); 109250599Sobrien size_t complen = arglen > optlen ? optlen : arglen; 109352520Sobrien const char *arginfo = option_map[j].arg_info; 109418334Speter 109518334Speter if (arginfo == 0) 109618334Speter arginfo = ""; 109718334Speter 109818334Speter if (!strncmp (argv[i], option_map[j].name, complen)) 109918334Speter { 110052520Sobrien const char *arg = 0; 110118334Speter 110218334Speter if (arglen < optlen) 110318334Speter { 110452520Sobrien size_t k; 110590277Sobrien for (k = j + 1; k < ARRAY_SIZE (option_map); k++) 110618334Speter if (strlen (option_map[k].name) >= arglen 110718334Speter && !strncmp (argv[i], option_map[k].name, arglen)) 110818334Speter { 110990277Sobrien error ("ambiguous abbreviation %s", argv[i]); 111018334Speter break; 111118334Speter } 111218334Speter 111390277Sobrien if (k != ARRAY_SIZE (option_map)) 111418334Speter break; 111518334Speter } 111618334Speter 111718334Speter if (arglen > optlen) 111818334Speter { 111918334Speter /* If the option has an argument, accept that. */ 112018334Speter if (argv[i][optlen] == '=') 112118334Speter arg = argv[i] + optlen + 1; 112218334Speter 112318334Speter /* If this mapping requires extra text at end of name, 112418334Speter accept that as "argument". */ 112590277Sobrien else if (strchr (arginfo, '*') != 0) 112618334Speter arg = argv[i] + optlen; 112718334Speter 112818334Speter /* Otherwise, extra text at end means mismatch. 112918334Speter Try other mappings. */ 113018334Speter else 113118334Speter continue; 113218334Speter } 113318334Speter 113490277Sobrien else if (strchr (arginfo, '*') != 0) 113518334Speter { 113690277Sobrien error ("incomplete `%s' option", option_map[j].name); 113718334Speter break; 113818334Speter } 113918334Speter 114018334Speter /* Handle arguments. */ 114190277Sobrien if (strchr (arginfo, 'a') != 0) 114218334Speter { 114318334Speter if (arg == 0) 114418334Speter { 114518334Speter if (i + 1 == argc) 114618334Speter { 114790277Sobrien error ("missing argument to `%s' option", 114818334Speter option_map[j].name); 114918334Speter break; 115018334Speter } 115118334Speter 115218334Speter arg = argv[++i]; 115318334Speter } 115418334Speter } 115590277Sobrien else if (strchr (arginfo, '*') != 0) 115618334Speter ; 115790277Sobrien else if (strchr (arginfo, 'o') == 0) 115818334Speter { 115918334Speter if (arg != 0) 116090277Sobrien error ("extraneous argument to `%s' option", 116118334Speter option_map[j].name); 116218334Speter arg = 0; 116318334Speter } 116418334Speter 116518334Speter /* Store the translation as one argv elt or as two. */ 116690277Sobrien if (arg != 0 && strchr (arginfo, 'j') != 0) 116750599Sobrien newv[newindex++] = concat (option_map[j].equivalent, arg, 116890277Sobrien NULL); 116918334Speter else if (arg != 0) 117018334Speter { 117118334Speter newv[newindex++] = option_map[j].equivalent; 117218334Speter newv[newindex++] = arg; 117318334Speter } 117418334Speter else 117518334Speter newv[newindex++] = option_map[j].equivalent; 117618334Speter 117718334Speter break; 117818334Speter } 117918334Speter } 118018334Speter i++; 118118334Speter } 118218334Speter 118318334Speter /* Handle old-fashioned options--just copy them through, 118418334Speter with their arguments. */ 118518334Speter else if (argv[i][0] == '-') 118618334Speter { 118752520Sobrien const char *p = argv[i] + 1; 118818334Speter int c = *p; 118918334Speter int nskip = 1; 119018334Speter 119118334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 119218334Speter nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0); 119318334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 119418334Speter nskip += WORD_SWITCH_TAKES_ARG (p); 1195117413Skan else if ((c == 'B' || c == 'b' || c == 'x') 119618334Speter && p[1] == 0) 119718334Speter nskip += 1; 119818334Speter else if (! strcmp (p, "Xlinker")) 119918334Speter nskip += 1; 120018334Speter 120118334Speter /* Watch out for an option at the end of the command line that 120218334Speter is missing arguments, and avoid skipping past the end of the 120318334Speter command line. */ 120418334Speter if (nskip + i > argc) 120518334Speter nskip = argc - i; 120618334Speter 120718334Speter while (nskip > 0) 120818334Speter { 120918334Speter newv[newindex++] = argv[i++]; 121018334Speter nskip--; 121118334Speter } 121218334Speter } 121318334Speter else 121418334Speter /* Ordinary operands, or +e options. */ 121518334Speter newv[newindex++] = argv[i++]; 121618334Speter } 121718334Speter 121818334Speter newv[newindex] = 0; 121918334Speter 122018334Speter *argvp = newv; 122118334Speter *argcp = newindex; 122218334Speter} 122318334Speter 122418334Speterstatic char * 122518334Speterskip_whitespace (p) 122618334Speter char *p; 122718334Speter{ 122818334Speter while (1) 122918334Speter { 123018334Speter /* A fully-blank line is a delimiter in the SPEC file and shouldn't 123118334Speter be considered whitespace. */ 123218334Speter if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n') 123318334Speter return p + 1; 123418334Speter else if (*p == '\n' || *p == ' ' || *p == '\t') 123518334Speter p++; 123618334Speter else if (*p == '#') 123718334Speter { 123890277Sobrien while (*p != '\n') 123990277Sobrien p++; 124018334Speter p++; 124118334Speter } 124218334Speter else 124318334Speter break; 124418334Speter } 124518334Speter 124618334Speter return p; 124718334Speter} 124890277Sobrien/* Structures to keep track of prefixes to try when looking for files. */ 124990277Sobrien 125090277Sobrienstruct prefix_list 125190277Sobrien{ 125290277Sobrien const char *prefix; /* String to prepend to the path. */ 125390277Sobrien struct prefix_list *next; /* Next in linked list. */ 125490277Sobrien int require_machine_suffix; /* Don't use without machine_suffix. */ 125590277Sobrien /* 2 means try both machine_suffix and just_machine_suffix. */ 125690277Sobrien int *used_flag_ptr; /* 1 if a file was found with this prefix. */ 1257104763Skan int priority; /* Sort key - priority within list. */ 1258104763Skan int os_multilib; /* 1 if OS multilib scheme should be used, 1259104763Skan 0 for GCC multilib scheme. */ 126090277Sobrien}; 126190277Sobrien 126290277Sobrienstruct path_prefix 126390277Sobrien{ 126490277Sobrien struct prefix_list *plist; /* List of prefixes to try */ 126590277Sobrien int max_len; /* Max length of a prefix in PLIST */ 126690277Sobrien const char *name; /* Name of this list (used in config stuff) */ 126790277Sobrien}; 126890277Sobrien 126990277Sobrien/* List of prefixes to try when looking for executables. */ 127090277Sobrien 127190277Sobrienstatic struct path_prefix exec_prefixes = { 0, 0, "exec" }; 127290277Sobrien 127390277Sobrien/* List of prefixes to try when looking for startup (crt0) files. */ 127490277Sobrien 127590277Sobrienstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" }; 127690277Sobrien 127790277Sobrien/* List of prefixes to try when looking for include files. */ 127890277Sobrien 127990277Sobrienstatic struct path_prefix include_prefixes = { 0, 0, "include" }; 128090277Sobrien 128190277Sobrien/* Suffix to attach to directories searched for commands. 128290277Sobrien This looks like `MACHINE/VERSION/'. */ 128390277Sobrien 128490277Sobrienstatic const char *machine_suffix = 0; 128590277Sobrien 128690277Sobrien/* Suffix to attach to directories searched for commands. 128790277Sobrien This is just `MACHINE/'. */ 128890277Sobrien 128990277Sobrienstatic const char *just_machine_suffix = 0; 129090277Sobrien 129190277Sobrien/* Adjusted value of GCC_EXEC_PREFIX envvar. */ 129290277Sobrien 129390277Sobrienstatic const char *gcc_exec_prefix; 129490277Sobrien 129590277Sobrien/* Default prefixes to attach to command names. */ 129690277Sobrien 129790277Sobrien#ifdef CROSS_COMPILE /* Don't use these prefixes for a cross compiler. */ 129890277Sobrien#undef MD_EXEC_PREFIX 129990277Sobrien#undef MD_STARTFILE_PREFIX 130090277Sobrien#undef MD_STARTFILE_PREFIX_1 130190277Sobrien#endif 130290277Sobrien 130390277Sobrien/* If no prefixes defined, use the null string, which will disable them. */ 130490277Sobrien#ifndef MD_EXEC_PREFIX 130590277Sobrien#define MD_EXEC_PREFIX "" 130690277Sobrien#endif 130790277Sobrien#ifndef MD_STARTFILE_PREFIX 130890277Sobrien#define MD_STARTFILE_PREFIX "" 130990277Sobrien#endif 131090277Sobrien#ifndef MD_STARTFILE_PREFIX_1 131190277Sobrien#define MD_STARTFILE_PREFIX_1 "" 131290277Sobrien#endif 131390277Sobrien 131490277Sobrien/* Supply defaults for the standard prefixes. */ 131590277Sobrien 131690277Sobrien#ifndef STANDARD_EXEC_PREFIX 131790277Sobrien#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/" 131890277Sobrien#endif 131990277Sobrien#ifndef STANDARD_STARTFILE_PREFIX 132090277Sobrien#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/" 132190277Sobrien#endif 132290277Sobrien#ifndef TOOLDIR_BASE_PREFIX 132390277Sobrien#define TOOLDIR_BASE_PREFIX "/usr/local/" 132490277Sobrien#endif 132596736Sru#ifndef FREEBSD_NATIVE 132690277Sobrien#ifndef STANDARD_BINDIR_PREFIX 132790277Sobrien#define STANDARD_BINDIR_PREFIX "/usr/local/bin" 132890277Sobrien#endif 132996736Sru#endif /* not FREEBSD_NATIVE */ 133090277Sobrien 133190277Sobrienstatic const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX; 133290277Sobrienstatic const char *const standard_exec_prefix_1 = "/usr/lib/gcc/"; 133390277Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX; 133490277Sobrien 133590277Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX; 133690277Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1; 133790277Sobrienstatic const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; 133890277Sobrienstatic const char *const standard_startfile_prefix_1 = "/lib/"; 133990277Sobrienstatic const char *const standard_startfile_prefix_2 = "/usr/lib/"; 134090277Sobrien 134190277Sobrienstatic const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX; 134290277Sobrienstatic const char *tooldir_prefix; 134390277Sobrien 134496736Sru#ifndef FREEBSD_NATIVE 134590277Sobrienstatic const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX; 134696736Sru#endif /* not FREEBSD_NATIVE */ 134790277Sobrien 134890277Sobrien/* Subdirectory to use for locating libraries. Set by 134990277Sobrien set_multilib_dir based on the compilation options. */ 135090277Sobrien 135190277Sobrienstatic const char *multilib_dir; 1352104763Skan 1353104763Skan/* Subdirectory to use for locating libraries in OS conventions. Set by 1354104763Skan set_multilib_dir based on the compilation options. */ 1355104763Skan 1356104763Skanstatic const char *multilib_os_dir; 135718334Speter 135850599Sobrien/* Structure to keep track of the specs that have been defined so far. 135950599Sobrien These are accessed using %(specname) or %[specname] in a compiler 136050599Sobrien or link spec. */ 136118334Speter 136218334Speterstruct spec_list 136318334Speter{ 136450599Sobrien /* The following 2 fields must be first */ 136550599Sobrien /* to allow EXTRA_SPECS to be initialized */ 136690277Sobrien const char *name; /* name of the spec. */ 136790277Sobrien const char *ptr; /* available ptr if no static pointer */ 136850599Sobrien 136950599Sobrien /* The following fields are not initialized */ 137050599Sobrien /* by EXTRA_SPECS */ 137190277Sobrien const char **ptr_spec; /* pointer to the spec itself. */ 137250599Sobrien struct spec_list *next; /* Next spec in linked list. */ 137350599Sobrien int name_len; /* length of the name */ 137450599Sobrien int alloc_p; /* whether string was allocated */ 137518334Speter}; 137618334Speter 137750599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \ 137890277Sobrien{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 } 137918334Speter 138090277Sobrien/* List of statically defined specs. */ 138190277Sobrienstatic struct spec_list static_specs[] = 138290277Sobrien{ 138350599Sobrien INIT_STATIC_SPEC ("asm", &asm_spec), 138490277Sobrien INIT_STATIC_SPEC ("asm_debug", &asm_debug), 138550599Sobrien INIT_STATIC_SPEC ("asm_final", &asm_final_spec), 138690277Sobrien INIT_STATIC_SPEC ("asm_options", &asm_options), 138790277Sobrien INIT_STATIC_SPEC ("invoke_as", &invoke_as), 138850599Sobrien INIT_STATIC_SPEC ("cpp", &cpp_spec), 138990277Sobrien INIT_STATIC_SPEC ("cpp_options", &cpp_options), 1390117413Skan INIT_STATIC_SPEC ("cpp_debug_options", &cpp_debug_options), 139190277Sobrien INIT_STATIC_SPEC ("cpp_unique_options", &cpp_unique_options), 139290277Sobrien INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp), 139350599Sobrien INIT_STATIC_SPEC ("cc1", &cc1_spec), 139490277Sobrien INIT_STATIC_SPEC ("cc1_options", &cc1_options), 139550599Sobrien INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec), 139696285Sobrien INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec), 139750599Sobrien INIT_STATIC_SPEC ("endfile", &endfile_spec), 139850599Sobrien INIT_STATIC_SPEC ("link", &link_spec), 139950599Sobrien INIT_STATIC_SPEC ("lib", &lib_spec), 140050599Sobrien INIT_STATIC_SPEC ("libgcc", &libgcc_spec), 140150599Sobrien INIT_STATIC_SPEC ("startfile", &startfile_spec), 140250599Sobrien INIT_STATIC_SPEC ("switches_need_spaces", &switches_need_spaces), 140350599Sobrien INIT_STATIC_SPEC ("predefines", &cpp_predefines), 140450599Sobrien INIT_STATIC_SPEC ("cross_compile", &cross_compile), 140550599Sobrien INIT_STATIC_SPEC ("version", &compiler_version), 140650599Sobrien INIT_STATIC_SPEC ("multilib", &multilib_select), 140750599Sobrien INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults), 140850599Sobrien INIT_STATIC_SPEC ("multilib_extra", &multilib_extra), 140950599Sobrien INIT_STATIC_SPEC ("multilib_matches", &multilib_matches), 141090277Sobrien INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions), 1411104763Skan INIT_STATIC_SPEC ("multilib_options", &multilib_options), 141250599Sobrien INIT_STATIC_SPEC ("linker", &linker_name_spec), 141390277Sobrien INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec), 141490277Sobrien INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix), 141590277Sobrien INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix), 141690277Sobrien INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1), 1417117413Skan INIT_STATIC_SPEC ("startfile_prefix_spec", &startfile_prefix_spec), 141850599Sobrien}; 141950599Sobrien 142050599Sobrien#ifdef EXTRA_SPECS /* additional specs needed */ 142152520Sobrien/* Structure to keep track of just the first two args of a spec_list. 142290277Sobrien That is all that the EXTRA_SPECS macro gives us. */ 142352520Sobrienstruct spec_list_1 142452520Sobrien{ 142590277Sobrien const char *const name; 142690277Sobrien const char *const ptr; 142752520Sobrien}; 142852520Sobrien 142990277Sobrienstatic const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS }; 143090277Sobrienstatic struct spec_list *extra_specs = (struct spec_list *) 0; 143150599Sobrien#endif 143250599Sobrien 143350599Sobrien/* List of dynamically allocates specs that have been defined so far. */ 143450599Sobrien 143590277Sobrienstatic struct spec_list *specs = (struct spec_list *) 0; 143690277Sobrien 1437117413Skan/* List of static spec functions. */ 1438117413Skan 1439117413Skanstatic const struct spec_function static_spec_functions[] = 1440117413Skan{ 1441117413Skan { "if-exists", if_exists_spec_function }, 1442117413Skan { "if-exists-else", if_exists_else_spec_function }, 1443117413Skan { 0, 0 } 1444117413Skan}; 1445117413Skan 1446117413Skanstatic int processing_spec_function; 1447117413Skan 144890277Sobrien/* Add appropriate libgcc specs to OBSTACK, taking into account 144990277Sobrien various permutations of -shared-libgcc, -shared, and such. */ 145050599Sobrien 145190277Sobrien#ifdef ENABLE_SHARED_LIBGCC 145290277Sobrienstatic void 145390277Sobrieninit_gcc_specs (obstack, shared_name, static_name, eh_name) 145490277Sobrien struct obstack *obstack; 145590277Sobrien const char *shared_name; 145690277Sobrien const char *static_name; 145790277Sobrien const char *eh_name; 145890277Sobrien{ 145996285Sobrien char *buf; 146090277Sobrien 146196285Sobrien buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name, 146296285Sobrien "}%{!static:%{!static-libgcc:", 146396285Sobrien "%{!shared:%{!shared-libgcc:", static_name, " ", 146496285Sobrien eh_name, "}%{shared-libgcc:", shared_name, " ", 146596285Sobrien static_name, "}}%{shared:", 146690277Sobrien#ifdef LINK_EH_SPEC 146796285Sobrien "%{shared-libgcc:", shared_name, 146896285Sobrien "}%{!shared-libgcc:", static_name, "}", 146990277Sobrien#else 147096285Sobrien shared_name, 147190277Sobrien#endif 147296285Sobrien "}}}", NULL); 147396285Sobrien 147496285Sobrien obstack_grow (obstack, buf, strlen (buf)); 147596285Sobrien free (buf); 147690277Sobrien} 147790277Sobrien#endif /* ENABLE_SHARED_LIBGCC */ 147890277Sobrien 147950599Sobrien/* Initialize the specs lookup routines. */ 148050599Sobrien 148150599Sobrienstatic void 148250599Sobrieninit_spec () 148350599Sobrien{ 148490277Sobrien struct spec_list *next = (struct spec_list *) 0; 148590277Sobrien struct spec_list *sl = (struct spec_list *) 0; 148650599Sobrien int i; 148750599Sobrien 148850599Sobrien if (specs) 148990277Sobrien return; /* Already initialized. */ 149050599Sobrien 149150599Sobrien if (verbose_flag) 149290277Sobrien notice ("Using built-in specs.\n"); 149350599Sobrien 149450599Sobrien#ifdef EXTRA_SPECS 149552520Sobrien extra_specs = (struct spec_list *) 149690277Sobrien xcalloc (sizeof (struct spec_list), ARRAY_SIZE (extra_specs_1)); 149790277Sobrien 149890277Sobrien for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--) 149950599Sobrien { 150050599Sobrien sl = &extra_specs[i]; 150152520Sobrien sl->name = extra_specs_1[i].name; 150252520Sobrien sl->ptr = extra_specs_1[i].ptr; 150350599Sobrien sl->next = next; 150450599Sobrien sl->name_len = strlen (sl->name); 150550599Sobrien sl->ptr_spec = &sl->ptr; 150650599Sobrien next = sl; 150750599Sobrien } 150850599Sobrien#endif 150950599Sobrien 1510117413Skan /* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes 1511117413Skan on ?: in file-scope variable initializations. */ 1512117413Skan asm_debug = ASM_DEBUG_SPEC; 1513117413Skan 151490277Sobrien for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) 151550599Sobrien { 151650599Sobrien sl = &static_specs[i]; 151750599Sobrien sl->next = next; 151850599Sobrien next = sl; 151950599Sobrien } 152050599Sobrien 152190277Sobrien#ifdef ENABLE_SHARED_LIBGCC 152290277Sobrien /* ??? If neither -shared-libgcc nor --static-libgcc was 152390277Sobrien seen, then we should be making an educated guess. Some proposed 152490277Sobrien heuristics for ELF include: 152590277Sobrien 152690277Sobrien (1) If "-Wl,--export-dynamic", then it's a fair bet that the 152790277Sobrien program will be doing dynamic loading, which will likely 152890277Sobrien need the shared libgcc. 152990277Sobrien 153090277Sobrien (2) If "-ldl", then it's also a fair bet that we're doing 153190277Sobrien dynamic loading. 153290277Sobrien 153390277Sobrien (3) For each ET_DYN we're linking against (either through -lfoo 153490277Sobrien or /some/path/foo.so), check to see whether it or one of 153590277Sobrien its dependencies depends on a shared libgcc. 153690277Sobrien 153790277Sobrien (4) If "-shared" 153890277Sobrien 153990277Sobrien If the runtime is fixed to look for program headers instead 154090277Sobrien of calling __register_frame_info at all, for each object, 154190277Sobrien use the shared libgcc if any EH symbol referenced. 154290277Sobrien 154390277Sobrien If crtstuff is fixed to not invoke __register_frame_info 154490277Sobrien automatically, for each object, use the shared libgcc if 154590277Sobrien any non-empty unwind section found. 154690277Sobrien 154790277Sobrien Doing any of this probably requires invoking an external program to 154890277Sobrien do the actual object file scanning. */ 154990277Sobrien { 155090277Sobrien const char *p = libgcc_spec; 155190277Sobrien int in_sep = 1; 1552117413Skan 155390277Sobrien /* Transform the extant libgcc_spec into one that uses the shared libgcc 155490277Sobrien when given the proper command line arguments. */ 155590277Sobrien while (*p) 155690277Sobrien { 1557117413Skan if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0) 155890277Sobrien { 155990277Sobrien init_gcc_specs (&obstack, 156090277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB 156190277Sobrien "-lgcc_s" 156290277Sobrien#else 156390277Sobrien "-lgcc_s%M" 156490277Sobrien#endif 1565122197Skan#ifdef USE_LIBUNWIND_EXCEPTIONS 1566122197Skan " -lunwind" 1567122197Skan#endif 156890277Sobrien , 156990277Sobrien "-lgcc", 157090277Sobrien "-lgcc_eh"); 157190277Sobrien p += 5; 157290277Sobrien in_sep = 0; 157390277Sobrien } 157490277Sobrien else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0) 157590277Sobrien { 157690277Sobrien /* Ug. We don't know shared library extensions. Hope that 157790277Sobrien systems that use this form don't do shared libraries. */ 157890277Sobrien init_gcc_specs (&obstack, 157990277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB 158090277Sobrien "-lgcc_s" 158190277Sobrien#else 158290277Sobrien "-lgcc_s%M" 158390277Sobrien#endif 158490277Sobrien , 158590277Sobrien "libgcc.a%s", 158690277Sobrien "libgcc_eh.a%s"); 158790277Sobrien p += 10; 158890277Sobrien in_sep = 0; 158990277Sobrien } 159090277Sobrien else 159190277Sobrien { 159290277Sobrien obstack_1grow (&obstack, *p); 159390277Sobrien in_sep = (*p == ' '); 159490277Sobrien p += 1; 159590277Sobrien } 159690277Sobrien } 159790277Sobrien 159890277Sobrien obstack_1grow (&obstack, '\0'); 159990277Sobrien libgcc_spec = obstack_finish (&obstack); 160090277Sobrien } 160190277Sobrien#endif 160290277Sobrien#ifdef USE_AS_TRADITIONAL_FORMAT 160390277Sobrien /* Prepend "--traditional-format" to whatever asm_spec we had before. */ 160490277Sobrien { 160590277Sobrien static const char tf[] = "--traditional-format "; 160690277Sobrien obstack_grow (&obstack, tf, sizeof(tf) - 1); 160790277Sobrien obstack_grow0 (&obstack, asm_spec, strlen (asm_spec)); 160890277Sobrien asm_spec = obstack_finish (&obstack); 160990277Sobrien } 161090277Sobrien#endif 161190277Sobrien#ifdef LINK_EH_SPEC 161290277Sobrien /* Prepend LINK_EH_SPEC to whatever link_spec we had before. */ 161390277Sobrien obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1); 161490277Sobrien obstack_grow0 (&obstack, link_spec, strlen (link_spec)); 161590277Sobrien link_spec = obstack_finish (&obstack); 161690277Sobrien#endif 161790277Sobrien 161850599Sobrien specs = sl; 161950599Sobrien} 162050599Sobrien 162118334Speter/* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is 162218334Speter removed; If the spec starts with a + then SPEC is added to the end of the 162350599Sobrien current spec. */ 162418334Speter 162518334Speterstatic void 162618334Speterset_spec (name, spec) 162752520Sobrien const char *name; 162852520Sobrien const char *spec; 162918334Speter{ 163018334Speter struct spec_list *sl; 163190277Sobrien const char *old_spec; 163250599Sobrien int name_len = strlen (name); 163350599Sobrien int i; 163418334Speter 163590277Sobrien /* If this is the first call, initialize the statically allocated specs. */ 163650599Sobrien if (!specs) 163750599Sobrien { 163890277Sobrien struct spec_list *next = (struct spec_list *) 0; 163990277Sobrien for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) 164050599Sobrien { 164150599Sobrien sl = &static_specs[i]; 164250599Sobrien sl->next = next; 164350599Sobrien next = sl; 164450599Sobrien } 164550599Sobrien specs = sl; 164650599Sobrien } 164750599Sobrien 164890277Sobrien /* See if the spec already exists. */ 164918334Speter for (sl = specs; sl; sl = sl->next) 165050599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, name)) 165118334Speter break; 165218334Speter 165318334Speter if (!sl) 165418334Speter { 165590277Sobrien /* Not found - make it. */ 165618334Speter sl = (struct spec_list *) xmalloc (sizeof (struct spec_list)); 165790277Sobrien sl->name = xstrdup (name); 165850599Sobrien sl->name_len = name_len; 165950599Sobrien sl->ptr_spec = &sl->ptr; 166050599Sobrien sl->alloc_p = 0; 166150599Sobrien *(sl->ptr_spec) = ""; 166218334Speter sl->next = specs; 166318334Speter specs = sl; 166418334Speter } 166518334Speter 166650599Sobrien old_spec = *(sl->ptr_spec); 166752520Sobrien *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1])) 166890277Sobrien ? concat (old_spec, spec + 1, NULL) 166990277Sobrien : xstrdup (spec)); 167018334Speter 167150599Sobrien#ifdef DEBUG_SPECS 167250599Sobrien if (verbose_flag) 167352520Sobrien notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec)); 167450599Sobrien#endif 167550599Sobrien 167690277Sobrien /* Free the old spec. */ 167750599Sobrien if (old_spec && sl->alloc_p) 167890277Sobrien free ((PTR) old_spec); 167950599Sobrien 168050599Sobrien sl->alloc_p = 1; 168118334Speter} 168218334Speter 168318334Speter/* Accumulate a command (program name and args), and run it. */ 168418334Speter 168518334Speter/* Vector of pointers to arguments in the current line of specifications. */ 168618334Speter 168790277Sobrienstatic const char **argbuf; 168818334Speter 168918334Speter/* Number of elements allocated in argbuf. */ 169018334Speter 169118334Speterstatic int argbuf_length; 169218334Speter 169318334Speter/* Number of elements in argbuf currently in use (containing args). */ 169418334Speter 169518334Speterstatic int argbuf_index; 169618334Speter 169790277Sobrien/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated 169890277Sobrien temp file. If the HOST_BIT_BUCKET is used for %j, no entry is made for 169990277Sobrien it here. */ 170050599Sobrien 170118334Speterstatic struct temp_name { 170252520Sobrien const char *suffix; /* suffix associated with the code. */ 170318334Speter int length; /* strlen (suffix). */ 170418334Speter int unique; /* Indicates whether %g or %u/%U was used. */ 170552520Sobrien const char *filename; /* associated filename. */ 170618334Speter int filename_length; /* strlen (filename). */ 170718334Speter struct temp_name *next; 170818334Speter} *temp_names; 170918334Speter 171018334Speter/* Number of commands executed so far. */ 171118334Speter 171218334Speterstatic int execution_count; 171318334Speter 171418334Speter/* Number of commands that exited with a signal. */ 171518334Speter 171618334Speterstatic int signal_count; 171718334Speter 171818334Speter/* Name with which this program was invoked. */ 171918334Speter 172052520Sobrienstatic const char *programname; 172118334Speter 1722117413Skan/* Allocate the argument vector. */ 1723117413Skan 1724117413Skanstatic void 1725117413Skanalloc_args () 1726117413Skan{ 1727117413Skan argbuf_length = 10; 1728117413Skan argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *)); 1729117413Skan} 1730117413Skan 173118334Speter/* Clear out the vector of arguments (after a command is executed). */ 173218334Speter 173318334Speterstatic void 173418334Speterclear_args () 173518334Speter{ 173618334Speter argbuf_index = 0; 173718334Speter} 173818334Speter 173918334Speter/* Add one argument to the vector at the end. 174018334Speter This is done when a space is seen or at the end of the line. 174118334Speter If DELETE_ALWAYS is nonzero, the arg is a filename 174218334Speter and the file should be deleted eventually. 174318334Speter If DELETE_FAILURE is nonzero, the arg is a filename 174418334Speter and the file should be deleted if this compilation fails. */ 174518334Speter 174618334Speterstatic void 174718334Speterstore_arg (arg, delete_always, delete_failure) 174890277Sobrien const char *arg; 174918334Speter int delete_always, delete_failure; 175018334Speter{ 175118334Speter if (argbuf_index + 1 == argbuf_length) 175250599Sobrien argbuf 175390277Sobrien = (const char **) xrealloc (argbuf, 175490277Sobrien (argbuf_length *= 2) * sizeof (const char *)); 175518334Speter 175618334Speter argbuf[argbuf_index++] = arg; 175718334Speter argbuf[argbuf_index] = 0; 175818334Speter 175918334Speter if (delete_always || delete_failure) 176018334Speter record_temp_file (arg, delete_always, delete_failure); 176118334Speter} 176218334Speter 176390277Sobrien/* Load specs from a file name named FILENAME, replacing occurrences of 176490277Sobrien various different types of line-endings, \r\n, \n\r and just \r, with 176590277Sobrien a single \n. */ 176650599Sobrien 176790277Sobrienstatic char * 176890277Sobrienload_specs (filename) 176952520Sobrien const char *filename; 177050599Sobrien{ 177150599Sobrien int desc; 177250599Sobrien int readlen; 177350599Sobrien struct stat statbuf; 177450599Sobrien char *buffer; 177590277Sobrien char *buffer_p; 177690277Sobrien char *specs; 177790277Sobrien char *specs_p; 177850599Sobrien 177950599Sobrien if (verbose_flag) 178052520Sobrien notice ("Reading specs from %s\n", filename); 178150599Sobrien 178250599Sobrien /* Open and stat the file. */ 178350599Sobrien desc = open (filename, O_RDONLY, 0); 178450599Sobrien if (desc < 0) 178550599Sobrien pfatal_with_name (filename); 178650599Sobrien if (stat (filename, &statbuf) < 0) 178750599Sobrien pfatal_with_name (filename); 178850599Sobrien 178950599Sobrien /* Read contents of file into BUFFER. */ 179050599Sobrien buffer = xmalloc ((unsigned) statbuf.st_size + 1); 179150599Sobrien readlen = read (desc, buffer, (unsigned) statbuf.st_size); 179250599Sobrien if (readlen < 0) 179350599Sobrien pfatal_with_name (filename); 179450599Sobrien buffer[readlen] = 0; 179550599Sobrien close (desc); 179650599Sobrien 179790277Sobrien specs = xmalloc (readlen + 1); 179890277Sobrien specs_p = specs; 179990277Sobrien for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++) 180090277Sobrien { 180190277Sobrien int skip = 0; 180290277Sobrien char c = *buffer_p; 180390277Sobrien if (c == '\r') 180490277Sobrien { 180590277Sobrien if (buffer_p > buffer && *(buffer_p - 1) == '\n') /* \n\r */ 180690277Sobrien skip = 1; 180790277Sobrien else if (*(buffer_p + 1) == '\n') /* \r\n */ 180890277Sobrien skip = 1; 180990277Sobrien else /* \r */ 181090277Sobrien c = '\n'; 181190277Sobrien } 181290277Sobrien if (! skip) 181390277Sobrien *specs_p++ = c; 181490277Sobrien } 181590277Sobrien *specs_p = '\0'; 181690277Sobrien 181790277Sobrien free (buffer); 181890277Sobrien return (specs); 181990277Sobrien} 182090277Sobrien 182190277Sobrien/* Read compilation specs from a file named FILENAME, 182290277Sobrien replacing the default ones. 182390277Sobrien 182490277Sobrien A suffix which starts with `*' is a definition for 182590277Sobrien one of the machine-specific sub-specs. The "suffix" should be 182696285Sobrien *asm, *cc1, *cpp, *link, *startfile, etc. 182790277Sobrien The corresponding spec is stored in asm_spec, etc., 182890277Sobrien rather than in the `compilers' vector. 182990277Sobrien 183090277Sobrien Anything invalid in the file is a fatal error. */ 183190277Sobrien 183290277Sobrienstatic void 183390277Sobrienread_specs (filename, main_p) 183490277Sobrien const char *filename; 183590277Sobrien int main_p; 183690277Sobrien{ 183790277Sobrien char *buffer; 183890277Sobrien char *p; 183990277Sobrien 184090277Sobrien buffer = load_specs (filename); 184190277Sobrien 184250599Sobrien /* Scan BUFFER for specs, putting them in the vector. */ 184350599Sobrien p = buffer; 184450599Sobrien while (1) 184550599Sobrien { 184650599Sobrien char *suffix; 184750599Sobrien char *spec; 184850599Sobrien char *in, *out, *p1, *p2, *p3; 184950599Sobrien 185050599Sobrien /* Advance P in BUFFER to the next nonblank nocomment line. */ 185150599Sobrien p = skip_whitespace (p); 185250599Sobrien if (*p == 0) 185350599Sobrien break; 185450599Sobrien 185550599Sobrien /* Is this a special command that starts with '%'? */ 185650599Sobrien /* Don't allow this for the main specs file, since it would 185750599Sobrien encourage people to overwrite it. */ 185850599Sobrien if (*p == '%' && !main_p) 185950599Sobrien { 186050599Sobrien p1 = p; 186150599Sobrien while (*p && *p != '\n') 186250599Sobrien p++; 186350599Sobrien 186490277Sobrien /* Skip '\n'. */ 186590277Sobrien p++; 186650599Sobrien 186790277Sobrien if (!strncmp (p1, "%include", sizeof ("%include") - 1) 186850599Sobrien && (p1[sizeof "%include" - 1] == ' ' 186950599Sobrien || p1[sizeof "%include" - 1] == '\t')) 187050599Sobrien { 187150599Sobrien char *new_filename; 187250599Sobrien 187350599Sobrien p1 += sizeof ("%include"); 187450599Sobrien while (*p1 == ' ' || *p1 == '\t') 187550599Sobrien p1++; 187650599Sobrien 187750599Sobrien if (*p1++ != '<' || p[-2] != '>') 187852520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 187952520Sobrien (long) (p1 - buffer + 1)); 188050599Sobrien 188150599Sobrien p[-2] = '\0'; 1882104763Skan new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0); 188350599Sobrien read_specs (new_filename ? new_filename : p1, FALSE); 188450599Sobrien continue; 188550599Sobrien } 188650599Sobrien else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1) 188750599Sobrien && (p1[sizeof "%include_noerr" - 1] == ' ' 188850599Sobrien || p1[sizeof "%include_noerr" - 1] == '\t')) 188950599Sobrien { 189050599Sobrien char *new_filename; 189150599Sobrien 189250599Sobrien p1 += sizeof "%include_noerr"; 189390277Sobrien while (*p1 == ' ' || *p1 == '\t') 189490277Sobrien p1++; 189550599Sobrien 189650599Sobrien if (*p1++ != '<' || p[-2] != '>') 189752520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 189852520Sobrien (long) (p1 - buffer + 1)); 189950599Sobrien 190050599Sobrien p[-2] = '\0'; 1901104763Skan new_filename = find_a_file (&startfile_prefixes, p1, R_OK, 0); 190250599Sobrien if (new_filename) 190350599Sobrien read_specs (new_filename, FALSE); 190450599Sobrien else if (verbose_flag) 190590277Sobrien notice ("could not find specs file %s\n", p1); 190650599Sobrien continue; 190750599Sobrien } 190850599Sobrien else if (!strncmp (p1, "%rename", sizeof "%rename" - 1) 190950599Sobrien && (p1[sizeof "%rename" - 1] == ' ' 191050599Sobrien || p1[sizeof "%rename" - 1] == '\t')) 191150599Sobrien { 191250599Sobrien int name_len; 191350599Sobrien struct spec_list *sl; 1914117413Skan struct spec_list *newsl; 191550599Sobrien 1916117413Skan /* Get original name. */ 191750599Sobrien p1 += sizeof "%rename"; 191850599Sobrien while (*p1 == ' ' || *p1 == '\t') 191950599Sobrien p1++; 192050599Sobrien 192190277Sobrien if (! ISALPHA ((unsigned char) *p1)) 192252520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 192352520Sobrien (long) (p1 - buffer)); 192450599Sobrien 192550599Sobrien p2 = p1; 192690277Sobrien while (*p2 && !ISSPACE ((unsigned char) *p2)) 192750599Sobrien p2++; 192850599Sobrien 192950599Sobrien if (*p2 != ' ' && *p2 != '\t') 193052520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 193152520Sobrien (long) (p2 - buffer)); 193250599Sobrien 193350599Sobrien name_len = p2 - p1; 193450599Sobrien *p2++ = '\0'; 193550599Sobrien while (*p2 == ' ' || *p2 == '\t') 193650599Sobrien p2++; 193750599Sobrien 193890277Sobrien if (! ISALPHA ((unsigned char) *p2)) 193952520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 194052520Sobrien (long) (p2 - buffer)); 194150599Sobrien 194290277Sobrien /* Get new spec name. */ 194350599Sobrien p3 = p2; 194490277Sobrien while (*p3 && !ISSPACE ((unsigned char) *p3)) 194550599Sobrien p3++; 194650599Sobrien 194790277Sobrien if (p3 != p - 1) 194852520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 194952520Sobrien (long) (p3 - buffer)); 195050599Sobrien *p3 = '\0'; 195150599Sobrien 195250599Sobrien for (sl = specs; sl; sl = sl->next) 195350599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, p1)) 195450599Sobrien break; 195550599Sobrien 195650599Sobrien if (!sl) 195750599Sobrien fatal ("specs %s spec was not found to be renamed", p1); 195850599Sobrien 195950599Sobrien if (strcmp (p1, p2) == 0) 196050599Sobrien continue; 196150599Sobrien 1962117413Skan for (newsl = specs; newsl; newsl = newsl->next) 1963117413Skan if (strcmp (newsl->name, p2) == 0) 1964117413Skan fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'", 1965117413Skan filename, p1, p2); 1966117413Skan 196750599Sobrien if (verbose_flag) 196850599Sobrien { 196952520Sobrien notice ("rename spec %s to %s\n", p1, p2); 197050599Sobrien#ifdef DEBUG_SPECS 197152520Sobrien notice ("spec is '%s'\n\n", *(sl->ptr_spec)); 197250599Sobrien#endif 197350599Sobrien } 197450599Sobrien 197550599Sobrien set_spec (p2, *(sl->ptr_spec)); 197650599Sobrien if (sl->alloc_p) 197790277Sobrien free ((PTR) *(sl->ptr_spec)); 197850599Sobrien 197950599Sobrien *(sl->ptr_spec) = ""; 198050599Sobrien sl->alloc_p = 0; 198150599Sobrien continue; 198250599Sobrien } 198350599Sobrien else 198452520Sobrien fatal ("specs unknown %% command after %ld characters", 198552520Sobrien (long) (p1 - buffer)); 198650599Sobrien } 198750599Sobrien 198850599Sobrien /* Find the colon that should end the suffix. */ 198950599Sobrien p1 = p; 199050599Sobrien while (*p1 && *p1 != ':' && *p1 != '\n') 199150599Sobrien p1++; 199250599Sobrien 199350599Sobrien /* The colon shouldn't be missing. */ 199450599Sobrien if (*p1 != ':') 199552520Sobrien fatal ("specs file malformed after %ld characters", 199652520Sobrien (long) (p1 - buffer)); 199750599Sobrien 199850599Sobrien /* Skip back over trailing whitespace. */ 199950599Sobrien p2 = p1; 200050599Sobrien while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) 200150599Sobrien p2--; 200250599Sobrien 200350599Sobrien /* Copy the suffix to a string. */ 200450599Sobrien suffix = save_string (p, p2 - p); 200550599Sobrien /* Find the next line. */ 200650599Sobrien p = skip_whitespace (p1 + 1); 200750599Sobrien if (p[1] == 0) 200852520Sobrien fatal ("specs file malformed after %ld characters", 200952520Sobrien (long) (p - buffer)); 201050599Sobrien 201150599Sobrien p1 = p; 201250599Sobrien /* Find next blank line or end of string. */ 201350599Sobrien while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0'))) 201450599Sobrien p1++; 201550599Sobrien 201650599Sobrien /* Specs end at the blank line and do not include the newline. */ 201750599Sobrien spec = save_string (p, p1 - p); 201850599Sobrien p = p1; 201950599Sobrien 202050599Sobrien /* Delete backslash-newline sequences from the spec. */ 202150599Sobrien in = spec; 202250599Sobrien out = spec; 202350599Sobrien while (*in != 0) 202450599Sobrien { 202550599Sobrien if (in[0] == '\\' && in[1] == '\n') 202650599Sobrien in += 2; 202750599Sobrien else if (in[0] == '#') 202850599Sobrien while (*in && *in != '\n') 202950599Sobrien in++; 203050599Sobrien 203150599Sobrien else 203250599Sobrien *out++ = *in++; 203350599Sobrien } 203450599Sobrien *out = 0; 203550599Sobrien 203650599Sobrien if (suffix[0] == '*') 203750599Sobrien { 203850599Sobrien if (! strcmp (suffix, "*link_command")) 203950599Sobrien link_command_spec = spec; 204050599Sobrien else 204150599Sobrien set_spec (suffix + 1, spec); 204250599Sobrien } 204350599Sobrien else 204450599Sobrien { 204550599Sobrien /* Add this pair to the vector. */ 204650599Sobrien compilers 204750599Sobrien = ((struct compiler *) 204850599Sobrien xrealloc (compilers, 204950599Sobrien (n_compilers + 2) * sizeof (struct compiler))); 205050599Sobrien 205150599Sobrien compilers[n_compilers].suffix = suffix; 205290277Sobrien compilers[n_compilers].spec = spec; 205350599Sobrien n_compilers++; 205490277Sobrien memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]); 205550599Sobrien } 205650599Sobrien 205750599Sobrien if (*suffix == 0) 205850599Sobrien link_command_spec = spec; 205950599Sobrien } 206050599Sobrien 206150599Sobrien if (link_command_spec == 0) 206250599Sobrien fatal ("spec file has no spec for linking"); 206350599Sobrien} 206450599Sobrien 206518334Speter/* Record the names of temporary files we tell compilers to write, 206618334Speter and delete them at the end of the run. */ 206718334Speter 206818334Speter/* This is the common prefix we use to make temp file names. 206918334Speter It is chosen once for each run of this program. 207090277Sobrien It is substituted into a spec by %g or %j. 207118334Speter Thus, all temp file names contain this prefix. 207218334Speter In practice, all temp file names start with this prefix. 207318334Speter 207418334Speter This prefix comes from the envvar TMPDIR if it is defined; 207518334Speter otherwise, from the P_tmpdir macro if that is defined; 207650599Sobrien otherwise, in /usr/tmp or /tmp; 207750599Sobrien or finally the current directory if all else fails. */ 207818334Speter 207952520Sobrienstatic const char *temp_filename; 208018334Speter 208118334Speter/* Length of the prefix. */ 208218334Speter 208318334Speterstatic int temp_filename_length; 208418334Speter 208518334Speter/* Define the list of temporary files to delete. */ 208618334Speter 208718334Speterstruct temp_file 208818334Speter{ 208952520Sobrien const char *name; 209018334Speter struct temp_file *next; 209118334Speter}; 209218334Speter 209318334Speter/* Queue of files to delete on success or failure of compilation. */ 209418334Speterstatic struct temp_file *always_delete_queue; 209518334Speter/* Queue of files to delete on failure of compilation. */ 209618334Speterstatic struct temp_file *failure_delete_queue; 209718334Speter 209818334Speter/* Record FILENAME as a file to be deleted automatically. 209918334Speter ALWAYS_DELETE nonzero means delete it if all compilation succeeds; 210018334Speter otherwise delete it in any case. 210118334Speter FAIL_DELETE nonzero means delete it if a compilation step fails; 210218334Speter otherwise delete it in any case. */ 210318334Speter 210490277Sobrienvoid 210518334Speterrecord_temp_file (filename, always_delete, fail_delete) 210652520Sobrien const char *filename; 210718334Speter int always_delete; 210818334Speter int fail_delete; 210918334Speter{ 211090277Sobrien char *const name = xstrdup (filename); 211118334Speter 211218334Speter if (always_delete) 211318334Speter { 211490277Sobrien struct temp_file *temp; 211518334Speter for (temp = always_delete_queue; temp; temp = temp->next) 211618334Speter if (! strcmp (name, temp->name)) 211718334Speter goto already1; 211850599Sobrien 211918334Speter temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); 212018334Speter temp->next = always_delete_queue; 212118334Speter temp->name = name; 212218334Speter always_delete_queue = temp; 212350599Sobrien 212418334Speter already1:; 212518334Speter } 212618334Speter 212718334Speter if (fail_delete) 212818334Speter { 212990277Sobrien struct temp_file *temp; 213018334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 213118334Speter if (! strcmp (name, temp->name)) 213218334Speter goto already2; 213350599Sobrien 213418334Speter temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); 213518334Speter temp->next = failure_delete_queue; 213618334Speter temp->name = name; 213718334Speter failure_delete_queue = temp; 213850599Sobrien 213918334Speter already2:; 214018334Speter } 214118334Speter} 214218334Speter 214318334Speter/* Delete all the temporary files whose names we previously recorded. */ 214418334Speter 214518334Speterstatic void 214618334Speterdelete_if_ordinary (name) 214752520Sobrien const char *name; 214818334Speter{ 214918334Speter struct stat st; 215018334Speter#ifdef DEBUG 215118334Speter int i, c; 215218334Speter 215318334Speter printf ("Delete %s? (y or n) ", name); 215418334Speter fflush (stdout); 215518334Speter i = getchar (); 215618334Speter if (i != '\n') 215750599Sobrien while ((c = getchar ()) != '\n' && c != EOF) 215850599Sobrien ; 215950599Sobrien 216018334Speter if (i == 'y' || i == 'Y') 216118334Speter#endif /* DEBUG */ 216218334Speter if (stat (name, &st) >= 0 && S_ISREG (st.st_mode)) 216318334Speter if (unlink (name) < 0) 216418334Speter if (verbose_flag) 216518334Speter perror_with_name (name); 216618334Speter} 216718334Speter 216818334Speterstatic void 216918334Speterdelete_temp_files () 217018334Speter{ 217190277Sobrien struct temp_file *temp; 217218334Speter 217318334Speter for (temp = always_delete_queue; temp; temp = temp->next) 217418334Speter delete_if_ordinary (temp->name); 217518334Speter always_delete_queue = 0; 217618334Speter} 217718334Speter 217818334Speter/* Delete all the files to be deleted on error. */ 217918334Speter 218018334Speterstatic void 218118334Speterdelete_failure_queue () 218218334Speter{ 218390277Sobrien struct temp_file *temp; 218418334Speter 218518334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 218618334Speter delete_if_ordinary (temp->name); 218718334Speter} 218818334Speter 218918334Speterstatic void 219018334Speterclear_failure_queue () 219118334Speter{ 219218334Speter failure_delete_queue = 0; 219318334Speter} 219418334Speter 219518334Speter/* Build a list of search directories from PATHS. 219618334Speter PREFIX is a string to prepend to the list. 2197117413Skan If CHECK_DIR_P is nonzero we ensure the directory exists. 219818334Speter This is used mostly by putenv_from_prefixes so we use `collect_obstack'. 219918334Speter It is also used by the --print-search-dirs flag. */ 220018334Speter 220118334Speterstatic char * 220218334Speterbuild_search_list (paths, prefix, check_dir_p) 220318334Speter struct path_prefix *paths; 220452520Sobrien const char *prefix; 220518334Speter int check_dir_p; 220618334Speter{ 220718334Speter int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0; 220818334Speter int just_suffix_len 220918334Speter = (just_machine_suffix) ? strlen (just_machine_suffix) : 0; 221018334Speter int first_time = TRUE; 221118334Speter struct prefix_list *pprefix; 221218334Speter 221318334Speter obstack_grow (&collect_obstack, prefix, strlen (prefix)); 221490277Sobrien obstack_1grow (&collect_obstack, '='); 221518334Speter 221618334Speter for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next) 221718334Speter { 221818334Speter int len = strlen (pprefix->prefix); 221918334Speter 222018334Speter if (machine_suffix 222150599Sobrien && (! check_dir_p 222218334Speter || is_directory (pprefix->prefix, machine_suffix, 0))) 222318334Speter { 222418334Speter if (!first_time) 222518334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 222690277Sobrien 222718334Speter first_time = FALSE; 222818334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 222918334Speter obstack_grow (&collect_obstack, machine_suffix, suffix_len); 223018334Speter } 223118334Speter 223218334Speter if (just_machine_suffix 223318334Speter && pprefix->require_machine_suffix == 2 223450599Sobrien && (! check_dir_p 223518334Speter || is_directory (pprefix->prefix, just_machine_suffix, 0))) 223618334Speter { 223750599Sobrien if (! first_time) 223818334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 223990277Sobrien 224018334Speter first_time = FALSE; 224118334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 224218334Speter obstack_grow (&collect_obstack, just_machine_suffix, 224318334Speter just_suffix_len); 224418334Speter } 224518334Speter 224650599Sobrien if (! pprefix->require_machine_suffix) 224718334Speter { 224850599Sobrien if (! first_time) 224918334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 225018334Speter 225118334Speter first_time = FALSE; 225218334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 225318334Speter } 225418334Speter } 225550599Sobrien 225618334Speter obstack_1grow (&collect_obstack, '\0'); 225718334Speter return obstack_finish (&collect_obstack); 225818334Speter} 225918334Speter 226050599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 226150599Sobrien for collect. */ 226218334Speter 226318334Speterstatic void 226418334Speterputenv_from_prefixes (paths, env_var) 226518334Speter struct path_prefix *paths; 226652520Sobrien const char *env_var; 226718334Speter{ 226818334Speter putenv (build_search_list (paths, env_var, 1)); 226918334Speter} 227018334Speter 227190277Sobrien/* Check whether NAME can be accessed in MODE. This is like access, 227290277Sobrien except that it never considers directories to be executable. */ 227390277Sobrien 227490277Sobrienstatic int 227590277Sobrienaccess_check (name, mode) 227690277Sobrien const char *name; 227790277Sobrien int mode; 227890277Sobrien{ 227990277Sobrien if (mode == X_OK) 228090277Sobrien { 228190277Sobrien struct stat st; 228290277Sobrien 228390277Sobrien if (stat (name, &st) < 0 228490277Sobrien || S_ISDIR (st.st_mode)) 228590277Sobrien return -1; 228690277Sobrien } 228790277Sobrien 228890277Sobrien return access (name, mode); 228990277Sobrien} 229090277Sobrien 229118334Speter/* Search for NAME using the prefix list PREFIXES. MODE is passed to 229218334Speter access to check permissions. 229350599Sobrien Return 0 if not found, otherwise return its name, allocated with malloc. */ 229418334Speter 229518334Speterstatic char * 2296104763Skanfind_a_file (pprefix, name, mode, multilib) 229718334Speter struct path_prefix *pprefix; 229852520Sobrien const char *name; 2299104763Skan int mode, multilib; 230018334Speter{ 230118334Speter char *temp; 230290277Sobrien const char *const file_suffix = 230390277Sobrien ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : ""); 230418334Speter struct prefix_list *pl; 230518334Speter int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1; 2306104763Skan const char *multilib_name, *multilib_os_name; 230718334Speter 230852520Sobrien#ifdef DEFAULT_ASSEMBLER 230990277Sobrien if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) 231090277Sobrien return xstrdup (DEFAULT_ASSEMBLER); 231152520Sobrien#endif 231252520Sobrien 231352520Sobrien#ifdef DEFAULT_LINKER 231490277Sobrien if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) 231590277Sobrien return xstrdup (DEFAULT_LINKER); 231652520Sobrien#endif 231752520Sobrien 231818334Speter if (machine_suffix) 231918334Speter len += strlen (machine_suffix); 232018334Speter 2321104763Skan multilib_name = name; 2322104763Skan multilib_os_name = name; 2323104763Skan if (multilib && multilib_os_dir) 2324104763Skan { 2325104763Skan int len1 = multilib_dir ? strlen (multilib_dir) + 1 : 0; 2326104763Skan int len2 = strlen (multilib_os_dir) + 1; 2327104763Skan 2328104763Skan len += len1 > len2 ? len1 : len2; 2329104763Skan if (multilib_dir) 2330104763Skan multilib_name = ACONCAT ((multilib_dir, dir_separator_str, name, 2331104763Skan NULL)); 2332104763Skan if (strcmp (multilib_os_dir, ".") != 0) 2333104763Skan multilib_os_name = ACONCAT ((multilib_os_dir, dir_separator_str, name, 2334104763Skan NULL)); 2335104763Skan } 2336104763Skan 233718334Speter temp = xmalloc (len); 233818334Speter 233918334Speter /* Determine the filename to execute (special case for absolute paths). */ 234018334Speter 234190277Sobrien if (IS_ABSOLUTE_PATHNAME (name)) 234218334Speter { 234352520Sobrien if (access (name, mode) == 0) 234418334Speter { 234518334Speter strcpy (temp, name); 234618334Speter return temp; 234718334Speter } 234818334Speter } 234918334Speter else 235018334Speter for (pl = pprefix->plist; pl; pl = pl->next) 235118334Speter { 2352104763Skan const char *this_name 2353104763Skan = pl->os_multilib ? multilib_os_name : multilib_name; 2354104763Skan 235518334Speter if (machine_suffix) 235618334Speter { 235718334Speter /* Some systems have a suffix for executable files. 235818334Speter So try appending that first. */ 235918334Speter if (file_suffix[0] != 0) 236018334Speter { 236118334Speter strcpy (temp, pl->prefix); 236218334Speter strcat (temp, machine_suffix); 2363104763Skan strcat (temp, multilib_name); 236418334Speter strcat (temp, file_suffix); 236590277Sobrien if (access_check (temp, mode) == 0) 236618334Speter { 236718334Speter if (pl->used_flag_ptr != 0) 236818334Speter *pl->used_flag_ptr = 1; 236918334Speter return temp; 237018334Speter } 237118334Speter } 237218334Speter 2373104763Skan /* Now try just the multilib_name. */ 237418334Speter strcpy (temp, pl->prefix); 237518334Speter strcat (temp, machine_suffix); 2376104763Skan strcat (temp, multilib_name); 237790277Sobrien if (access_check (temp, mode) == 0) 237818334Speter { 237918334Speter if (pl->used_flag_ptr != 0) 238018334Speter *pl->used_flag_ptr = 1; 238118334Speter return temp; 238218334Speter } 238318334Speter } 238418334Speter 238518334Speter /* Certain prefixes are tried with just the machine type, 238618334Speter not the version. This is used for finding as, ld, etc. */ 238718334Speter if (just_machine_suffix && pl->require_machine_suffix == 2) 238818334Speter { 238918334Speter /* Some systems have a suffix for executable files. 239018334Speter So try appending that first. */ 239118334Speter if (file_suffix[0] != 0) 239218334Speter { 239318334Speter strcpy (temp, pl->prefix); 239418334Speter strcat (temp, just_machine_suffix); 2395104763Skan strcat (temp, multilib_name); 239618334Speter strcat (temp, file_suffix); 239790277Sobrien if (access_check (temp, mode) == 0) 239818334Speter { 239918334Speter if (pl->used_flag_ptr != 0) 240018334Speter *pl->used_flag_ptr = 1; 240118334Speter return temp; 240218334Speter } 240318334Speter } 240418334Speter 240518334Speter strcpy (temp, pl->prefix); 240618334Speter strcat (temp, just_machine_suffix); 2407104763Skan strcat (temp, multilib_name); 240890277Sobrien if (access_check (temp, mode) == 0) 240918334Speter { 241018334Speter if (pl->used_flag_ptr != 0) 241118334Speter *pl->used_flag_ptr = 1; 241218334Speter return temp; 241318334Speter } 241418334Speter } 241518334Speter 241618334Speter /* Certain prefixes can't be used without the machine suffix 241718334Speter when the machine or version is explicitly specified. */ 241850599Sobrien if (! pl->require_machine_suffix) 241918334Speter { 242018334Speter /* Some systems have a suffix for executable files. 242118334Speter So try appending that first. */ 242218334Speter if (file_suffix[0] != 0) 242318334Speter { 242418334Speter strcpy (temp, pl->prefix); 2425104763Skan strcat (temp, this_name); 242618334Speter strcat (temp, file_suffix); 242790277Sobrien if (access_check (temp, mode) == 0) 242818334Speter { 242918334Speter if (pl->used_flag_ptr != 0) 243018334Speter *pl->used_flag_ptr = 1; 243118334Speter return temp; 243218334Speter } 243318334Speter } 243418334Speter 243518334Speter strcpy (temp, pl->prefix); 2436104763Skan strcat (temp, this_name); 243790277Sobrien if (access_check (temp, mode) == 0) 243818334Speter { 243918334Speter if (pl->used_flag_ptr != 0) 244018334Speter *pl->used_flag_ptr = 1; 244118334Speter return temp; 244218334Speter } 244318334Speter } 244418334Speter } 244518334Speter 244618334Speter free (temp); 244718334Speter return 0; 244818334Speter} 244918334Speter 245090277Sobrien/* Ranking of prefixes in the sort list. -B prefixes are put before 245190277Sobrien all others. */ 245218334Speter 245390277Sobrienenum path_prefix_priority 245490277Sobrien{ 245590277Sobrien PREFIX_PRIORITY_B_OPT, 245690277Sobrien PREFIX_PRIORITY_LAST 245790277Sobrien}; 245890277Sobrien 245990277Sobrien/* Add an entry for PREFIX in PLIST. The PLIST is kept in assending 246090277Sobrien order according to PRIORITY. Within each PRIORITY, new entries are 246190277Sobrien appended. 246290277Sobrien 246318334Speter If WARN is nonzero, we will warn if no file is found 246418334Speter through this prefix. WARN should point to an int 246518334Speter which will be set to 1 if this entry is used. 246618334Speter 246750599Sobrien COMPONENT is the value to be passed to update_path. 246850599Sobrien 246918334Speter REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without 247018334Speter the complete value of machine_suffix. 247118334Speter 2 means try both machine_suffix and just_machine_suffix. */ 247218334Speter 247318334Speterstatic void 2474104763Skanadd_prefix (pprefix, prefix, component, priority, require_machine_suffix, 2475104763Skan warn, os_multilib) 247618334Speter struct path_prefix *pprefix; 247752520Sobrien const char *prefix; 247852520Sobrien const char *component; 247990277Sobrien /* enum prefix_priority */ int priority; 248018334Speter int require_machine_suffix; 248118334Speter int *warn; 2482104763Skan int os_multilib; 248318334Speter{ 248418334Speter struct prefix_list *pl, **prev; 248518334Speter int len; 248618334Speter 248790277Sobrien for (prev = &pprefix->plist; 248890277Sobrien (*prev) != NULL && (*prev)->priority <= priority; 248990277Sobrien prev = &(*prev)->next) 249090277Sobrien ; 249118334Speter 249218334Speter /* Keep track of the longest prefix */ 249318334Speter 249450599Sobrien prefix = update_path (prefix, component); 249518334Speter len = strlen (prefix); 249618334Speter if (len > pprefix->max_len) 249718334Speter pprefix->max_len = len; 249818334Speter 249918334Speter pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list)); 250090277Sobrien pl->prefix = prefix; 250118334Speter pl->require_machine_suffix = require_machine_suffix; 250218334Speter pl->used_flag_ptr = warn; 250390277Sobrien pl->priority = priority; 2504104763Skan pl->os_multilib = os_multilib; 250518334Speter if (warn) 250618334Speter *warn = 0; 250718334Speter 250890277Sobrien /* Insert after PREV */ 250990277Sobrien pl->next = (*prev); 251090277Sobrien (*prev) = pl; 251118334Speter} 251218334Speter 251318334Speter/* Execute the command specified by the arguments on the current line of spec. 251418334Speter When using pipes, this includes several piped-together commands 251518334Speter with `|' between them. 251618334Speter 251718334Speter Return 0 if successful, -1 if failed. */ 251818334Speter 251918334Speterstatic int 252018334Speterexecute () 252118334Speter{ 252218334Speter int i; 252318334Speter int n_commands; /* # of command. */ 252418334Speter char *string; 252518334Speter struct command 252690277Sobrien { 252790277Sobrien const char *prog; /* program name. */ 252890277Sobrien const char **argv; /* vector of args. */ 252990277Sobrien int pid; /* pid of process for this command. */ 253090277Sobrien }; 253118334Speter 253218334Speter struct command *commands; /* each command buffer with above info. */ 253318334Speter 2534117413Skan if (processing_spec_function) 2535117413Skan abort (); 2536117413Skan 253718334Speter /* Count # of piped commands. */ 253818334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 253918334Speter if (strcmp (argbuf[i], "|") == 0) 254018334Speter n_commands++; 254118334Speter 254218334Speter /* Get storage for each command. */ 254390277Sobrien commands = (struct command *) alloca (n_commands * sizeof (struct command)); 254418334Speter 254518334Speter /* Split argbuf into its separate piped processes, 254618334Speter and record info about each one. 254718334Speter Also search for the programs that are to be run. */ 254818334Speter 254918334Speter commands[0].prog = argbuf[0]; /* first command. */ 255018334Speter commands[0].argv = &argbuf[0]; 2551104763Skan string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, 0); 255250599Sobrien 255318334Speter if (string) 255418334Speter commands[0].argv[0] = string; 255518334Speter 255618334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 255718334Speter if (strcmp (argbuf[i], "|") == 0) 255818334Speter { /* each command. */ 255952520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS) 256090277Sobrien fatal ("-pipe not supported"); 256118334Speter#endif 256218334Speter argbuf[i] = 0; /* termination of command args. */ 256318334Speter commands[n_commands].prog = argbuf[i + 1]; 256418334Speter commands[n_commands].argv = &argbuf[i + 1]; 2565104763Skan string = find_a_file (&exec_prefixes, commands[n_commands].prog, 2566104763Skan X_OK, 0); 256718334Speter if (string) 256818334Speter commands[n_commands].argv[0] = string; 256918334Speter n_commands++; 257018334Speter } 257118334Speter 257218334Speter argbuf[argbuf_index] = 0; 257318334Speter 257418334Speter /* If -v, print what we are about to do, and maybe query. */ 257518334Speter 257618334Speter if (verbose_flag) 257718334Speter { 257850599Sobrien /* For help listings, put a blank line between sub-processes. */ 257950599Sobrien if (print_help_list) 258050599Sobrien fputc ('\n', stderr); 258190277Sobrien 258218334Speter /* Print each piped command as a separate line. */ 258390277Sobrien for (i = 0; i < n_commands; i++) 258418334Speter { 258590277Sobrien const char *const *j; 258618334Speter 2587117413Skan if (verbose_only_flag) 2588117413Skan { 258990277Sobrien for (j = commands[i].argv; *j; j++) 259090277Sobrien { 259190277Sobrien const char *p; 259290277Sobrien fprintf (stderr, " \""); 259390277Sobrien for (p = *j; *p; ++p) 259490277Sobrien { 259590277Sobrien if (*p == '"' || *p == '\\' || *p == '$') 259690277Sobrien fputc ('\\', stderr); 259790277Sobrien fputc (*p, stderr); 259890277Sobrien } 259990277Sobrien fputc ('"', stderr); 260090277Sobrien } 2601117413Skan } 2602117413Skan else 260390277Sobrien for (j = commands[i].argv; *j; j++) 260490277Sobrien fprintf (stderr, " %s", *j); 260518334Speter 260618334Speter /* Print a pipe symbol after all but the last command. */ 260718334Speter if (i + 1 != n_commands) 260818334Speter fprintf (stderr, " |"); 260918334Speter fprintf (stderr, "\n"); 261018334Speter } 261118334Speter fflush (stderr); 261290277Sobrien if (verbose_only_flag != 0) 2613117413Skan return 0; 261418334Speter#ifdef DEBUG 261552520Sobrien notice ("\nGo ahead? (y or n) "); 261618334Speter fflush (stderr); 261718334Speter i = getchar (); 261818334Speter if (i != '\n') 261950599Sobrien while (getchar () != '\n') 262050599Sobrien ; 262150599Sobrien 262218334Speter if (i != 'y' && i != 'Y') 262318334Speter return 0; 262418334Speter#endif /* DEBUG */ 262518334Speter } 262618334Speter 2627117413Skan#ifdef ENABLE_VALGRIND_CHECKING 2628117413Skan /* Run the each command through valgrind. To simplifiy prepending the 2629117413Skan path to valgrind and the option "-q" (for quiet operation unless 2630117413Skan something triggers), we allocate a separate argv array. */ 2631117413Skan 2632117413Skan for (i = 0; i < n_commands; i++) 2633117413Skan { 2634117413Skan const char **argv; 2635117413Skan int argc; 2636117413Skan int j; 2637117413Skan 2638117413Skan for (argc = 0; commands[i].argv[argc] != NULL; argc++) 2639117413Skan ; 2640117413Skan 2641117413Skan argv = alloca ((argc + 3) * sizeof (char *)); 2642117413Skan 2643117413Skan argv[0] = VALGRIND_PATH; 2644117413Skan argv[1] = "-q"; 2645117413Skan for (j = 2; j < argc + 2; j++) 2646117413Skan argv[j] = commands[i].argv[j - 2]; 2647117413Skan argv[j] = NULL; 2648117413Skan 2649117413Skan commands[i].argv = argv; 2650117413Skan commands[i].prog = argv[0]; 2651117413Skan } 2652117413Skan#endif 2653117413Skan 265418334Speter /* Run each piped subprocess. */ 265518334Speter 265618334Speter for (i = 0; i < n_commands; i++) 265718334Speter { 265850599Sobrien char *errmsg_fmt, *errmsg_arg; 265990277Sobrien const char *string = commands[i].argv[0]; 266018334Speter 266190277Sobrien /* For some bizarre reason, the second argument of execvp() is 266290277Sobrien char *const *, not const char *const *. */ 266390277Sobrien commands[i].pid = pexecute (string, (char *const *) commands[i].argv, 266450599Sobrien programname, temp_filename, 266550599Sobrien &errmsg_fmt, &errmsg_arg, 266650599Sobrien ((i == 0 ? PEXECUTE_FIRST : 0) 266750599Sobrien | (i + 1 == n_commands ? PEXECUTE_LAST : 0) 266850599Sobrien | (string == commands[i].prog 266950599Sobrien ? PEXECUTE_SEARCH : 0) 267050599Sobrien | (verbose_flag ? PEXECUTE_VERBOSE : 0))); 267118334Speter 267250599Sobrien if (commands[i].pid == -1) 267350599Sobrien pfatal_pexecute (errmsg_fmt, errmsg_arg); 267450599Sobrien 267518334Speter if (string != commands[i].prog) 267690277Sobrien free ((PTR) string); 267718334Speter } 267818334Speter 267918334Speter execution_count++; 268018334Speter 268118334Speter /* Wait for all the subprocesses to finish. 268218334Speter We don't care what order they finish in; 268318334Speter we know that N_COMMANDS waits will get them all. 268418334Speter Ignore subprocesses that we don't know about, 268518334Speter since they can be spawned by the process that exec'ed us. */ 268618334Speter 268718334Speter { 268818334Speter int ret_code = 0; 268990277Sobrien#ifdef HAVE_GETRUSAGE 269090277Sobrien struct timeval d; 269190277Sobrien double ut = 0.0, st = 0.0; 269290277Sobrien#endif 269318334Speter 269490277Sobrien for (i = 0; i < n_commands;) 269518334Speter { 269618334Speter int j; 269718334Speter int status; 269818334Speter int pid; 269918334Speter 270050599Sobrien pid = pwait (commands[i].pid, &status, 0); 270118334Speter if (pid < 0) 270218334Speter abort (); 270318334Speter 270490277Sobrien#ifdef HAVE_GETRUSAGE 270590277Sobrien if (report_times) 270690277Sobrien { 270790277Sobrien /* getrusage returns the total resource usage of all children 270890277Sobrien up to now. Copy the previous values into prus, get the 270990277Sobrien current statistics, then take the difference. */ 271090277Sobrien 271190277Sobrien prus = rus; 271290277Sobrien getrusage (RUSAGE_CHILDREN, &rus); 271390277Sobrien d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec; 271490277Sobrien d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec; 271590277Sobrien ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6; 271690277Sobrien 271790277Sobrien d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec; 271890277Sobrien d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec; 271990277Sobrien st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6; 272090277Sobrien } 272190277Sobrien#endif 272290277Sobrien 272318334Speter for (j = 0; j < n_commands; j++) 272418334Speter if (commands[j].pid == pid) 272518334Speter { 272618334Speter i++; 272790277Sobrien if (WIFSIGNALED (status)) 272818334Speter { 272990277Sobrien#ifdef SIGPIPE 273090277Sobrien /* SIGPIPE is a special case. It happens in -pipe mode 273190277Sobrien when the compiler dies before the preprocessor is 273290277Sobrien done, or the assembler dies before the compiler is 273390277Sobrien done. There's generally been an error already, and 273490277Sobrien this is just fallout. So don't generate another error 273590277Sobrien unless we would otherwise have succeeded. */ 273690277Sobrien if (WTERMSIG (status) == SIGPIPE 273790277Sobrien && (signal_count || greatest_status >= MIN_FATAL_STATUS)) 273890277Sobrien ; 273990277Sobrien else 274090277Sobrien#endif 274190277Sobrien fatal ("\ 274290277SobrienInternal error: %s (program %s)\n\ 274390277SobrienPlease submit a full bug report.\n\ 274490277SobrienSee %s for instructions.", 274590277Sobrien strsignal (WTERMSIG (status)), commands[j].prog, 2746117413Skan bug_report_url); 274790277Sobrien signal_count++; 274890277Sobrien ret_code = -1; 274918334Speter } 275090277Sobrien else if (WIFEXITED (status) 275190277Sobrien && WEXITSTATUS (status) >= MIN_FATAL_STATUS) 275290277Sobrien { 275390277Sobrien if (WEXITSTATUS (status) > greatest_status) 275490277Sobrien greatest_status = WEXITSTATUS (status); 275590277Sobrien ret_code = -1; 275690277Sobrien } 275790277Sobrien#ifdef HAVE_GETRUSAGE 275890277Sobrien if (report_times && ut + st != 0) 275990277Sobrien notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st); 276090277Sobrien#endif 276118334Speter break; 276218334Speter } 276318334Speter } 276418334Speter return ret_code; 276518334Speter } 276618334Speter} 276718334Speter 276818334Speter/* Find all the switches given to us 276918334Speter and make a vector describing them. 277018334Speter The elements of the vector are strings, one per switch given. 277118334Speter If a switch uses following arguments, then the `part1' field 277218334Speter is the switch itself and the `args' field 277318334Speter is a null-terminated vector containing the following arguments. 277490277Sobrien The `live_cond' field is: 277590277Sobrien 0 when initialized 277690277Sobrien 1 if the switch is true in a conditional spec, 277790277Sobrien -1 if false (overridden by a later switch) 277890277Sobrien -2 if this switch should be ignored (used in %{<S}) 277952520Sobrien The `validated' field is nonzero if any spec has looked at this switch; 278018334Speter if it remains zero at the end of the run, it must be meaningless. */ 278118334Speter 278290277Sobrien#define SWITCH_OK 0 278390277Sobrien#define SWITCH_FALSE -1 278490277Sobrien#define SWITCH_IGNORE -2 278590277Sobrien#define SWITCH_LIVE 1 278690277Sobrien 278718334Speterstruct switchstr 278818334Speter{ 278952520Sobrien const char *part1; 279090277Sobrien const char **args; 279118334Speter int live_cond; 279290277Sobrien unsigned char validated; 279390277Sobrien unsigned char ordering; 279418334Speter}; 279518334Speter 279618334Speterstatic struct switchstr *switches; 279718334Speter 279818334Speterstatic int n_switches; 279918334Speter 280018334Speterstruct infile 280118334Speter{ 280252520Sobrien const char *name; 280352520Sobrien const char *language; 280418334Speter}; 280518334Speter 280618334Speter/* Also a vector of input files specified. */ 280718334Speter 280818334Speterstatic struct infile *infiles; 280918334Speter 281090277Sobrienint n_infiles; 281118334Speter 281252520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that 281350599Sobrien we can tell if there were any user supplied any files or libraries. */ 281450599Sobrien 281550599Sobrienstatic int added_libraries; 281650599Sobrien 281718334Speter/* And a vector of corresponding output files is made up later. */ 281818334Speter 281990277Sobrienconst char **outfiles; 282018334Speter 282150599Sobrien/* Used to track if none of the -B paths are used. */ 282250599Sobrienstatic int warn_B; 282350599Sobrien 282450599Sobrien/* Gives value to pass as "warn" to add_prefix for standard prefixes. */ 282550599Sobrienstatic int *warn_std_ptr = 0; 282650599Sobrien 282790277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 282850599Sobrien 282950599Sobrien/* Convert NAME to a new name if it is the standard suffix. DO_EXE 283090277Sobrien is true if we should look for an executable suffix. DO_OBJ 283190277Sobrien is true if we should look for an object suffix. */ 283250599Sobrien 283390277Sobrienstatic const char * 283490277Sobrienconvert_filename (name, do_exe, do_obj) 283590277Sobrien const char *name; 283690277Sobrien int do_exe ATTRIBUTE_UNUSED; 283790277Sobrien int do_obj ATTRIBUTE_UNUSED; 283850599Sobrien{ 283990277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 284050599Sobrien int i; 284190277Sobrien#endif 284252520Sobrien int len; 284350599Sobrien 284452520Sobrien if (name == NULL) 284552520Sobrien return NULL; 284690277Sobrien 284752520Sobrien len = strlen (name); 284852520Sobrien 284990277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX 285090277Sobrien /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj". */ 285190277Sobrien if (do_obj && len > 2 285250599Sobrien && name[len - 2] == '.' 285350599Sobrien && name[len - 1] == 'o') 285450599Sobrien { 285550599Sobrien obstack_grow (&obstack, name, len - 2); 285690277Sobrien obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); 285750599Sobrien name = obstack_finish (&obstack); 285850599Sobrien } 285950599Sobrien#endif 286050599Sobrien 286190277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 286250599Sobrien /* If there is no filetype, make it the executable suffix (which includes 286350599Sobrien the "."). But don't get confused if we have just "-o". */ 286490277Sobrien if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-')) 286550599Sobrien return name; 286650599Sobrien 286750599Sobrien for (i = len - 1; i >= 0; i--) 286852520Sobrien if (IS_DIR_SEPARATOR (name[i])) 286950599Sobrien break; 287050599Sobrien 287150599Sobrien for (i++; i < len; i++) 287250599Sobrien if (name[i] == '.') 287350599Sobrien return name; 287450599Sobrien 287550599Sobrien obstack_grow (&obstack, name, len); 287690277Sobrien obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX, 287790277Sobrien strlen (TARGET_EXECUTABLE_SUFFIX)); 287850599Sobrien name = obstack_finish (&obstack); 287950599Sobrien#endif 288050599Sobrien 288150599Sobrien return name; 288250599Sobrien} 288350599Sobrien#endif 288450599Sobrien 288550599Sobrien/* Display the command line switches accepted by gcc. */ 288650599Sobrienstatic void 288750599Sobriendisplay_help () 288850599Sobrien{ 288990277Sobrien printf (_("Usage: %s [options] file...\n"), programname); 289090277Sobrien fputs (_("Options:\n"), stdout); 289150599Sobrien 289290277Sobrien fputs (_(" -pass-exit-codes Exit with highest error code from a phase\n"), stdout); 289390277Sobrien fputs (_(" --help Display this information\n"), stdout); 289490277Sobrien fputs (_(" --target-help Display target specific command line options\n"), stdout); 289550599Sobrien if (! verbose_flag) 289690277Sobrien fputs (_(" (Use '-v --help' to display command line options of sub-processes)\n"), stdout); 289790277Sobrien fputs (_(" -dumpspecs Display all of the built in spec strings\n"), stdout); 289890277Sobrien fputs (_(" -dumpversion Display the version of the compiler\n"), stdout); 289990277Sobrien fputs (_(" -dumpmachine Display the compiler's target processor\n"), stdout); 290090277Sobrien fputs (_(" -print-search-dirs Display the directories in the compiler's search path\n"), stdout); 290190277Sobrien fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library\n"), stdout); 290290277Sobrien fputs (_(" -print-file-name=<lib> Display the full path to library <lib>\n"), stdout); 290390277Sobrien fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>\n"), stdout); 290490277Sobrien fputs (_(" -print-multi-directory Display the root directory for versions of libgcc\n"), stdout); 290590277Sobrien fputs (_("\ 290690277Sobrien -print-multi-lib Display the mapping between command line options and\n\ 290790277Sobrien multiple library search directories\n"), stdout); 2908104763Skan fputs (_(" -print-multi-os-directory Display the relative path to OS libraries\n"), stdout); 290990277Sobrien fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler\n"), stdout); 291090277Sobrien fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout); 291190277Sobrien fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker\n"), stdout); 291290277Sobrien fputs (_(" -Xlinker <arg> Pass <arg> on to the linker\n"), stdout); 291390277Sobrien fputs (_(" -save-temps Do not delete intermediate files\n"), stdout); 291490277Sobrien fputs (_(" -pipe Use pipes rather than intermediate files\n"), stdout); 291590277Sobrien fputs (_(" -time Time the execution of each subprocess\n"), stdout); 291690277Sobrien fputs (_(" -specs=<file> Override built-in specs with the contents of <file>\n"), stdout); 291790277Sobrien fputs (_(" -std=<standard> Assume that the input sources are for <standard>\n"), stdout); 291890277Sobrien fputs (_(" -B <directory> Add <directory> to the compiler's search paths\n"), stdout); 291990277Sobrien fputs (_(" -b <machine> Run gcc for target <machine>, if installed\n"), stdout); 292090277Sobrien fputs (_(" -V <version> Run gcc version number <version>, if installed\n"), stdout); 292190277Sobrien fputs (_(" -v Display the programs invoked by the compiler\n"), stdout); 292290277Sobrien fputs (_(" -### Like -v but options quoted and commands not executed\n"), stdout); 292390277Sobrien fputs (_(" -E Preprocess only; do not compile, assemble or link\n"), stdout); 292490277Sobrien fputs (_(" -S Compile only; do not assemble or link\n"), stdout); 292590277Sobrien fputs (_(" -c Compile and assemble, but do not link\n"), stdout); 292690277Sobrien fputs (_(" -o <file> Place the output into <file>\n"), stdout); 292790277Sobrien fputs (_("\ 292890277Sobrien -x <language> Specify the language of the following input files\n\ 2929117413Skan Permissible languages include: c c++ assembler none\n\ 293090277Sobrien 'none' means revert to the default behavior of\n\ 293190277Sobrien guessing the language based on the file's extension\n\ 293290277Sobrien"), stdout); 293350599Sobrien 293490277Sobrien printf (_("\ 293590277Sobrien\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\ 293690277Sobrien passed on to the various sub-processes invoked by %s. In order to pass\n\ 293790277Sobrien other options on to these processes the -W<letter> options must be used.\n\ 293890277Sobrien"), programname); 293950599Sobrien 294050599Sobrien /* The rest of the options are displayed by invocations of the various 294150599Sobrien sub-processes. */ 294250599Sobrien} 294350599Sobrien 294490277Sobrienstatic void 294590277Sobrienadd_preprocessor_option (option, len) 294690277Sobrien const char *option; 294752520Sobrien int len; 294890277Sobrien{ 294952520Sobrien n_preprocessor_options++; 295090277Sobrien 295152520Sobrien if (! preprocessor_options) 295252520Sobrien preprocessor_options 295352520Sobrien = (char **) xmalloc (n_preprocessor_options * sizeof (char *)); 295452520Sobrien else 295552520Sobrien preprocessor_options 295652520Sobrien = (char **) xrealloc (preprocessor_options, 295752520Sobrien n_preprocessor_options * sizeof (char *)); 295890277Sobrien 295952520Sobrien preprocessor_options [n_preprocessor_options - 1] = 296052520Sobrien save_string (option, len); 296150599Sobrien} 296290277Sobrien 296390277Sobrienstatic void 296490277Sobrienadd_assembler_option (option, len) 296590277Sobrien const char *option; 296652520Sobrien int len; 296752520Sobrien{ 296852520Sobrien n_assembler_options++; 296952520Sobrien 297052520Sobrien if (! assembler_options) 297152520Sobrien assembler_options 297252520Sobrien = (char **) xmalloc (n_assembler_options * sizeof (char *)); 297352520Sobrien else 297452520Sobrien assembler_options 297552520Sobrien = (char **) xrealloc (assembler_options, 297652520Sobrien n_assembler_options * sizeof (char *)); 297752520Sobrien 297852520Sobrien assembler_options [n_assembler_options - 1] = save_string (option, len); 297950599Sobrien} 298090277Sobrien 298190277Sobrienstatic void 298290277Sobrienadd_linker_option (option, len) 298390277Sobrien const char *option; 298490277Sobrien int len; 298552520Sobrien{ 298652520Sobrien n_linker_options++; 298752520Sobrien 298852520Sobrien if (! linker_options) 298952520Sobrien linker_options 299052520Sobrien = (char **) xmalloc (n_linker_options * sizeof (char *)); 299152520Sobrien else 299252520Sobrien linker_options 299352520Sobrien = (char **) xrealloc (linker_options, 299452520Sobrien n_linker_options * sizeof (char *)); 299552520Sobrien 299652520Sobrien linker_options [n_linker_options - 1] = save_string (option, len); 299750599Sobrien} 299850599Sobrien 299918334Speter/* Create the vector `switches' and its contents. 300018334Speter Store its length in `n_switches'. */ 300118334Speter 300218334Speterstatic void 300318334Speterprocess_command (argc, argv) 300418334Speter int argc; 300590277Sobrien const char *const *argv; 300618334Speter{ 300790277Sobrien int i; 300852520Sobrien const char *temp; 300952520Sobrien char *temp1; 301090277Sobrien const char *spec_lang = 0; 301118334Speter int last_language_n_infiles; 301250599Sobrien int have_c = 0; 301350599Sobrien int have_o = 0; 301450599Sobrien int lang_n_infiles = 0; 301590277Sobrien#ifdef MODIFY_TARGET_NAME 301690277Sobrien int is_modify_target_name; 301790277Sobrien int j; 301890277Sobrien#endif 301918334Speter 3020117413Skan GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX"); 302118334Speter 302218334Speter n_switches = 0; 302318334Speter n_infiles = 0; 302450599Sobrien added_libraries = 0; 302518334Speter 302618334Speter /* Figure compiler version from version string. */ 302718334Speter 302890277Sobrien compiler_version = temp1 = xstrdup (version_string); 302990277Sobrien 303052520Sobrien for (; *temp1; ++temp1) 303118334Speter { 303252520Sobrien if (*temp1 == ' ') 303318334Speter { 303452520Sobrien *temp1 = '\0'; 303518334Speter break; 303618334Speter } 303718334Speter } 303818334Speter 3039117413Skan /* If there is a -V or -b option (or both), process it now, before 3040117413Skan trying to interpret the rest of the command line. */ 3041117413Skan if (argc > 1 && argv[1][0] == '-' 3042117413Skan && (argv[1][1] == 'V' || argv[1][1] == 'b')) 3043117413Skan { 3044117413Skan const char *new_version = DEFAULT_TARGET_VERSION; 3045117413Skan const char *new_machine = DEFAULT_TARGET_MACHINE; 3046117413Skan const char *progname = argv[0]; 3047117413Skan char **new_argv; 3048117413Skan char *new_argv0; 3049117413Skan int baselen; 3050117413Skan 3051117413Skan while (argc > 1 && argv[1][0] == '-' 3052117413Skan && (argv[1][1] == 'V' || argv[1][1] == 'b')) 3053117413Skan { 3054117413Skan char opt = argv[1][1]; 3055117413Skan const char *arg; 3056117413Skan if (argv[1][2] != '\0') 3057117413Skan { 3058117413Skan arg = argv[1] + 2; 3059117413Skan argc -= 1; 3060117413Skan argv += 1; 3061117413Skan } 3062117413Skan else if (argc > 2) 3063117413Skan { 3064117413Skan arg = argv[2]; 3065117413Skan argc -= 2; 3066117413Skan argv += 2; 3067117413Skan } 3068117413Skan else 3069117413Skan fatal ("`-%c' option must have argument", opt); 3070117413Skan if (opt == 'V') 3071117413Skan new_version = arg; 3072117413Skan else 3073117413Skan new_machine = arg; 3074117413Skan } 3075117413Skan 3076117413Skan for (baselen = strlen (progname); baselen > 0; baselen--) 3077117413Skan if (IS_DIR_SEPARATOR (progname[baselen-1])) 3078117413Skan break; 3079117413Skan new_argv0 = xmemdup (progname, baselen, 3080117413Skan baselen + concat_length (new_version, new_machine, 3081117413Skan "-gcc-", NULL) + 1); 3082117413Skan strcpy (new_argv0 + baselen, new_machine); 3083117413Skan strcat (new_argv0, "-gcc-"); 3084117413Skan strcat (new_argv0, new_version); 3085117413Skan 3086117413Skan new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]), 3087117413Skan (argc + 1) * sizeof (argv[0])); 3088117413Skan new_argv[0] = new_argv0; 3089117413Skan 3090117413Skan execvp (new_argv0, new_argv); 3091117413Skan fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno)); 3092117413Skan } 3093117413Skan 309490277Sobrien /* Set up the default search paths. If there is no GCC_EXEC_PREFIX, 309590277Sobrien see if we can create it from the pathname specified in argv[0]. */ 309618334Speter 309796736Sru#ifndef FREEBSD_NATIVE 309890277Sobrien#ifndef VMS 309990277Sobrien /* FIXME: make_relative_prefix doesn't yet work for VMS. */ 310090277Sobrien if (!gcc_exec_prefix) 310190277Sobrien { 310290277Sobrien gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix, 310390277Sobrien standard_exec_prefix); 310490277Sobrien if (gcc_exec_prefix) 310590277Sobrien putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL)); 310690277Sobrien } 310790277Sobrien#endif 310896736Sru#endif /* not FREEBSD_NATIVE */ 310990277Sobrien 311018334Speter if (gcc_exec_prefix) 311118334Speter { 311250599Sobrien int len = strlen (gcc_exec_prefix); 311390277Sobrien 311490277Sobrien if (len > (int) sizeof ("/lib/gcc-lib/") - 1 311552520Sobrien && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1]))) 311650599Sobrien { 311750599Sobrien temp = gcc_exec_prefix + len - sizeof ("/lib/gcc-lib/") + 1; 311852520Sobrien if (IS_DIR_SEPARATOR (*temp) 311990277Sobrien && strncmp (temp + 1, "lib", 3) == 0 312052520Sobrien && IS_DIR_SEPARATOR (temp[4]) 312190277Sobrien && strncmp (temp + 5, "gcc-lib", 7) == 0) 312250599Sobrien len -= sizeof ("/lib/gcc-lib/") - 1; 312350599Sobrien } 312450599Sobrien 312550599Sobrien set_std_prefix (gcc_exec_prefix, len); 312690277Sobrien add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC", 3127104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 312890277Sobrien add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 3129104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 313018334Speter } 313118334Speter 313218334Speter /* COMPILER_PATH and LIBRARY_PATH have values 313318334Speter that are lists of directory names with colons. */ 313418334Speter 3135117413Skan GET_ENVIRONMENT (temp, "COMPILER_PATH"); 313618334Speter if (temp) 313718334Speter { 313852520Sobrien const char *startp, *endp; 313918334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 314018334Speter 314118334Speter startp = endp = temp; 314218334Speter while (1) 314318334Speter { 314418334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 314518334Speter { 314690277Sobrien strncpy (nstore, startp, endp - startp); 314718334Speter if (endp == startp) 314890277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 314952520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 315018334Speter { 315190277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 315290277Sobrien nstore[endp - startp + 1] = 0; 315318334Speter } 315418334Speter else 315590277Sobrien nstore[endp - startp] = 0; 315690277Sobrien add_prefix (&exec_prefixes, nstore, 0, 3157104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 315850599Sobrien add_prefix (&include_prefixes, 315990277Sobrien concat (nstore, "include", NULL), 3160104763Skan 0, PREFIX_PRIORITY_LAST, 0, NULL, 0); 316118334Speter if (*endp == 0) 316218334Speter break; 316318334Speter endp = startp = endp + 1; 316418334Speter } 316518334Speter else 316618334Speter endp++; 316718334Speter } 316818334Speter } 316918334Speter 3170117413Skan GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV); 317191651Sobrien if (temp && *cross_compile == '0') 317218334Speter { 317352520Sobrien const char *startp, *endp; 317418334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 317518334Speter 317618334Speter startp = endp = temp; 317718334Speter while (1) 317818334Speter { 317918334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 318018334Speter { 318190277Sobrien strncpy (nstore, startp, endp - startp); 318218334Speter if (endp == startp) 318390277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 318452520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 318518334Speter { 318690277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 318790277Sobrien nstore[endp - startp + 1] = 0; 318818334Speter } 318918334Speter else 319090277Sobrien nstore[endp - startp] = 0; 319190277Sobrien add_prefix (&startfile_prefixes, nstore, NULL, 3192104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 319318334Speter if (*endp == 0) 319418334Speter break; 319518334Speter endp = startp = endp + 1; 319618334Speter } 319718334Speter else 319818334Speter endp++; 319918334Speter } 320018334Speter } 320118334Speter 320218334Speter /* Use LPATH like LIBRARY_PATH (for the CMU build program). */ 3203117413Skan GET_ENVIRONMENT (temp, "LPATH"); 320450599Sobrien if (temp && *cross_compile == '0') 320518334Speter { 320652520Sobrien const char *startp, *endp; 320718334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 320818334Speter 320918334Speter startp = endp = temp; 321018334Speter while (1) 321118334Speter { 321218334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 321318334Speter { 321490277Sobrien strncpy (nstore, startp, endp - startp); 321518334Speter if (endp == startp) 321690277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 321752520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 321818334Speter { 321990277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 322090277Sobrien nstore[endp - startp + 1] = 0; 322118334Speter } 322218334Speter else 322390277Sobrien nstore[endp - startp] = 0; 322490277Sobrien add_prefix (&startfile_prefixes, nstore, NULL, 3225104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 322618334Speter if (*endp == 0) 322718334Speter break; 322818334Speter endp = startp = endp + 1; 322918334Speter } 323018334Speter else 323118334Speter endp++; 323218334Speter } 323318334Speter } 323418334Speter 323577389Sobrien /* Options specified as if they appeared on the command line. */ 323677389Sobrien temp = getenv ("GCC_OPTIONS"); 323777389Sobrien if ((temp) && (strlen (temp) > 0)) 323877389Sobrien { 323977389Sobrien int len; 324077389Sobrien int optc = 1; 324177389Sobrien int new_argc; 3242110024Sobrien const char **new_argv; 324377389Sobrien char *envopts; 324477389Sobrien 324577389Sobrien while (isspace (*temp)) 324677389Sobrien temp++; 324777389Sobrien len = strlen (temp); 324877389Sobrien envopts = (char *) xmalloc (len + 1); 324977389Sobrien strcpy (envopts, temp); 325077389Sobrien 325177389Sobrien for (i = 0; i < (len - 1); i++) 325277389Sobrien if ((isspace (envopts[i])) && ! (isspace (envopts[i+1]))) 325377389Sobrien optc++; 325477389Sobrien 3255110024Sobrien new_argv = (const char **) alloca ((optc + argc) * sizeof(char *)); 325677389Sobrien 325777389Sobrien for (i = 0, new_argc = 1; new_argc <= optc; new_argc++) 325877389Sobrien { 325977389Sobrien while (isspace (envopts[i])) 326077389Sobrien i++; 326177389Sobrien new_argv[new_argc] = envopts + i; 326277389Sobrien while (!isspace (envopts[i]) && (envopts[i] != '\0')) 326377389Sobrien i++; 326477389Sobrien envopts[i++] = '\0'; 326577389Sobrien } 326677389Sobrien for (i = 1; i < argc; i++) 326777389Sobrien new_argv[new_argc++] = argv[i]; 326877389Sobrien 326977389Sobrien argv = new_argv; 327077389Sobrien argc = new_argc; 327177389Sobrien } 327277389Sobrien 327318334Speter /* Convert new-style -- options to old-style. */ 327418334Speter translate_options (&argc, &argv); 327518334Speter 327650599Sobrien /* Do language-specific adjustment/addition of flags. */ 327790277Sobrien lang_specific_driver (&argc, &argv, &added_libraries); 327850599Sobrien 327918334Speter /* Scan argv twice. Here, the first time, just count how many switches 328018334Speter there will be in their vector, and how many input files in theirs. 328118334Speter Here we also parse the switches that cc itself uses (e.g. -v). */ 328218334Speter 328318334Speter for (i = 1; i < argc; i++) 328418334Speter { 328518334Speter if (! strcmp (argv[i], "-dumpspecs")) 328618334Speter { 328750599Sobrien struct spec_list *sl; 328850599Sobrien init_spec (); 328950599Sobrien for (sl = specs; sl; sl = sl->next) 329050599Sobrien printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec)); 329190277Sobrien if (link_command_spec) 329290277Sobrien printf ("*link_command:\n%s\n\n", link_command_spec); 329318334Speter exit (0); 329418334Speter } 329518334Speter else if (! strcmp (argv[i], "-dumpversion")) 329618334Speter { 329750599Sobrien printf ("%s\n", spec_version); 329818334Speter exit (0); 329918334Speter } 330018334Speter else if (! strcmp (argv[i], "-dumpmachine")) 330118334Speter { 330218334Speter printf ("%s\n", spec_machine); 330390277Sobrien exit (0); 330418334Speter } 330590277Sobrien else if (strcmp (argv[i], "-fversion") == 0) 330690277Sobrien { 330790277Sobrien /* translate_options () has turned --version into -fversion. */ 330890277Sobrien printf (_("%s (GCC) %s\n"), programname, version_string); 3309117413Skan fputs (_("Copyright (C) 2003 Free Software Foundation, Inc.\n"), 331090277Sobrien stdout); 331190277Sobrien fputs (_("This is free software; see the source for copying conditions. There is NO\n\ 331290277Sobrienwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"), 331390277Sobrien stdout); 331490277Sobrien exit (0); 331590277Sobrien } 331650599Sobrien else if (strcmp (argv[i], "-fhelp") == 0) 331750599Sobrien { 331850599Sobrien /* translate_options () has turned --help into -fhelp. */ 331950599Sobrien print_help_list = 1; 332050599Sobrien 332150599Sobrien /* We will be passing a dummy file on to the sub-processes. */ 332250599Sobrien n_infiles++; 332350599Sobrien n_switches++; 332490277Sobrien 332590277Sobrien /* CPP driver cannot obtain switch from cc1_options. */ 332690277Sobrien if (is_cpp_driver) 332790277Sobrien add_preprocessor_option ("--help", 6); 332850599Sobrien add_assembler_option ("--help", 6); 332950599Sobrien add_linker_option ("--help", 6); 333050599Sobrien } 333190277Sobrien else if (strcmp (argv[i], "-ftarget-help") == 0) 3332117413Skan { 3333117413Skan /* translate_options() has turned --target-help into -ftarget-help. */ 3334117413Skan target_help_flag = 1; 333590277Sobrien 3336117413Skan /* We will be passing a dummy file on to the sub-processes. */ 3337117413Skan n_infiles++; 3338117413Skan n_switches++; 333990277Sobrien 334090277Sobrien /* CPP driver cannot obtain switch from cc1_options. */ 334190277Sobrien if (is_cpp_driver) 334290277Sobrien add_preprocessor_option ("--target-help", 13); 3343117413Skan add_assembler_option ("--target-help", 13); 3344117413Skan add_linker_option ("--target-help", 13); 3345117413Skan } 334690277Sobrien else if (! strcmp (argv[i], "-pass-exit-codes")) 334790277Sobrien { 334890277Sobrien pass_exit_codes = 1; 334990277Sobrien n_switches++; 335090277Sobrien } 335118334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 335218334Speter print_search_dirs = 1; 335318334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 335418334Speter print_file_name = "libgcc.a"; 335518334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 335618334Speter print_file_name = argv[i] + 17; 335718334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 335818334Speter print_prog_name = argv[i] + 17; 335918334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 336018334Speter print_multi_lib = 1; 336118334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 336218334Speter print_multi_directory = 1; 3363104763Skan else if (! strcmp (argv[i], "-print-multi-os-directory")) 3364104763Skan print_multi_os_directory = 1; 336518334Speter else if (! strncmp (argv[i], "-Wa,", 4)) 336618334Speter { 336718334Speter int prev, j; 336818334Speter /* Pass the rest of this option to the assembler. */ 336918334Speter 337018334Speter /* Split the argument at commas. */ 337118334Speter prev = 4; 337218334Speter for (j = 4; argv[i][j]; j++) 337318334Speter if (argv[i][j] == ',') 337418334Speter { 337550599Sobrien add_assembler_option (argv[i] + prev, j - prev); 337618334Speter prev = j + 1; 337718334Speter } 337890277Sobrien 337918334Speter /* Record the part after the last comma. */ 338050599Sobrien add_assembler_option (argv[i] + prev, j - prev); 338118334Speter } 338218334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 338318334Speter { 338418334Speter int prev, j; 338518334Speter /* Pass the rest of this option to the preprocessor. */ 338618334Speter 338718334Speter /* Split the argument at commas. */ 338818334Speter prev = 4; 338918334Speter for (j = 4; argv[i][j]; j++) 339018334Speter if (argv[i][j] == ',') 339118334Speter { 339250599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 339318334Speter prev = j + 1; 339418334Speter } 339590277Sobrien 339618334Speter /* Record the part after the last comma. */ 339750599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 339818334Speter } 339918334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 340018334Speter /* The +e options to the C++ front-end. */ 340118334Speter n_switches++; 340218334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 340318334Speter { 340418334Speter int j; 340518334Speter /* Split the argument at commas. */ 340618334Speter for (j = 3; argv[i][j]; j++) 340718334Speter n_infiles += (argv[i][j] == ','); 340818334Speter } 340918334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 341018334Speter { 341118334Speter if (i + 1 == argc) 341218334Speter fatal ("argument to `-Xlinker' is missing"); 341318334Speter 341418334Speter n_infiles++; 341518334Speter i++; 341618334Speter } 341777389Sobrien else if (strcmp (argv[i], "-l") == 0) 341877389Sobrien { 341977389Sobrien if (i + 1 == argc) 342077389Sobrien fatal ("argument to `-l' is missing"); 342177389Sobrien 342277389Sobrien n_infiles++; 342377389Sobrien i++; 342477389Sobrien } 342518334Speter else if (strncmp (argv[i], "-l", 2) == 0) 342618334Speter n_infiles++; 342750599Sobrien else if (strcmp (argv[i], "-save-temps") == 0) 342850599Sobrien { 342950599Sobrien save_temps_flag = 1; 343050599Sobrien n_switches++; 343150599Sobrien } 343250599Sobrien else if (strcmp (argv[i], "-specs") == 0) 343350599Sobrien { 343450599Sobrien struct user_specs *user = (struct user_specs *) 343550599Sobrien xmalloc (sizeof (struct user_specs)); 343650599Sobrien if (++i >= argc) 343750599Sobrien fatal ("argument to `-specs' is missing"); 343850599Sobrien 343990277Sobrien user->next = (struct user_specs *) 0; 344050599Sobrien user->filename = argv[i]; 344150599Sobrien if (user_specs_tail) 344250599Sobrien user_specs_tail->next = user; 344350599Sobrien else 344450599Sobrien user_specs_head = user; 344550599Sobrien user_specs_tail = user; 344650599Sobrien } 344750599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 344850599Sobrien { 344950599Sobrien struct user_specs *user = (struct user_specs *) 345050599Sobrien xmalloc (sizeof (struct user_specs)); 345150599Sobrien if (strlen (argv[i]) == 7) 345250599Sobrien fatal ("argument to `-specs=' is missing"); 345350599Sobrien 345490277Sobrien user->next = (struct user_specs *) 0; 345590277Sobrien user->filename = argv[i] + 7; 345650599Sobrien if (user_specs_tail) 345750599Sobrien user_specs_tail->next = user; 345850599Sobrien else 345950599Sobrien user_specs_head = user; 346050599Sobrien user_specs_tail = user; 346150599Sobrien } 346290277Sobrien else if (strcmp (argv[i], "-time") == 0) 346390277Sobrien report_times = 1; 346490277Sobrien else if (strcmp (argv[i], "-###") == 0) 346590277Sobrien { 346690277Sobrien /* This is similar to -v except that there is no execution 346790277Sobrien of the commands and the echoed arguments are quoted. It 346890277Sobrien is intended for use in shell scripts to capture the 346990277Sobrien driver-generated command line. */ 347090277Sobrien verbose_only_flag++; 347190277Sobrien verbose_flag++; 347290277Sobrien } 347318334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 347418334Speter { 347590277Sobrien const char *p = &argv[i][1]; 347690277Sobrien int c = *p; 347718334Speter 347818334Speter switch (c) 347918334Speter { 348018334Speter case 'b': 3481117413Skan case 'V': 3482117413Skan fatal ("`-%c' must come at the start of the command line", c); 348318334Speter break; 348418334Speter 348518334Speter case 'B': 348618334Speter { 348790277Sobrien const char *value; 348890277Sobrien int len; 348990277Sobrien 349018334Speter if (p[1] == 0 && i + 1 == argc) 349118334Speter fatal ("argument to `-B' is missing"); 349218334Speter if (p[1] == 0) 349318334Speter value = argv[++i]; 349418334Speter else 349518334Speter value = p + 1; 349618334Speter 349790277Sobrien len = strlen (value); 349890277Sobrien 349990277Sobrien /* Catch the case where the user has forgotten to append a 350090277Sobrien directory separator to the path. Note, they may be using 350190277Sobrien -B to add an executable name prefix, eg "i386-elf-", in 350290277Sobrien order to distinguish between multiple installations of 350390277Sobrien GCC in the same directory. Hence we must check to see 350490277Sobrien if appending a directory separator actually makes a 350590277Sobrien valid directory name. */ 350690277Sobrien if (! IS_DIR_SEPARATOR (value [len - 1]) 350790277Sobrien && is_directory (value, "", 0)) 350890277Sobrien { 350990277Sobrien char *tmp = xmalloc (len + 2); 351090277Sobrien strcpy (tmp, value); 351190277Sobrien tmp[len] = DIR_SEPARATOR; 351290277Sobrien tmp[++ len] = 0; 351390277Sobrien value = tmp; 351490277Sobrien } 3515117413Skan 351690277Sobrien /* As a kludge, if the arg is "[foo/]stageN/", just 351790277Sobrien add "[foo/]include" to the include prefix. */ 351890277Sobrien if ((len == 7 351990277Sobrien || (len > 7 352090277Sobrien && (IS_DIR_SEPARATOR (value[len - 8])))) 352190277Sobrien && strncmp (value + len - 7, "stage", 5) == 0 352290277Sobrien && ISDIGIT (value[len - 2]) 352390277Sobrien && (IS_DIR_SEPARATOR (value[len - 1]))) 352490277Sobrien { 352590277Sobrien if (len == 7) 352690277Sobrien add_prefix (&include_prefixes, "include", NULL, 3527104763Skan PREFIX_PRIORITY_B_OPT, 0, NULL, 0); 352890277Sobrien else 352990277Sobrien { 353090277Sobrien char * string = xmalloc (len + 1); 353190277Sobrien 353290277Sobrien strncpy (string, value, len - 7); 353390277Sobrien strcpy (string + len - 7, "include"); 353490277Sobrien add_prefix (&include_prefixes, string, NULL, 3535104763Skan PREFIX_PRIORITY_B_OPT, 0, NULL, 0); 353690277Sobrien } 353790277Sobrien } 353890277Sobrien 353990277Sobrien add_prefix (&exec_prefixes, value, NULL, 3540104763Skan PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0); 354190277Sobrien add_prefix (&startfile_prefixes, value, NULL, 3542104763Skan PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0); 354390277Sobrien add_prefix (&include_prefixes, concat (value, "include", NULL), 3544104763Skan NULL, PREFIX_PRIORITY_B_OPT, 0, NULL, 0); 354590277Sobrien n_switches++; 354618334Speter } 354718334Speter break; 354818334Speter 354918334Speter case 'v': /* Print our subcommands and print versions. */ 355018334Speter n_switches++; 355118334Speter /* If they do anything other than exactly `-v', don't set 355218334Speter verbose_flag; rather, continue on to give the error. */ 355318334Speter if (p[1] != 0) 355418334Speter break; 355518334Speter verbose_flag++; 355618334Speter break; 355718334Speter 355850599Sobrien case 'S': 355950599Sobrien case 'c': 356050599Sobrien if (p[1] == 0) 356118334Speter { 356250599Sobrien have_c = 1; 356318334Speter n_switches++; 356418334Speter break; 356518334Speter } 356650599Sobrien goto normal_switch; 356750599Sobrien 356850599Sobrien case 'o': 356950599Sobrien have_o = 1; 357090277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 357150599Sobrien if (! have_c) 357250599Sobrien { 357350599Sobrien int skip; 357490277Sobrien 357550599Sobrien /* Forward scan, just in case -S or -c is specified 357650599Sobrien after -o. */ 357750599Sobrien int j = i + 1; 357850599Sobrien if (p[1] == 0) 357950599Sobrien ++j; 358050599Sobrien while (j < argc) 358150599Sobrien { 358250599Sobrien if (argv[j][0] == '-') 358350599Sobrien { 358450599Sobrien if (SWITCH_CURTAILS_COMPILATION (argv[j][1]) 358550599Sobrien && argv[j][2] == 0) 358650599Sobrien { 358750599Sobrien have_c = 1; 358850599Sobrien break; 358950599Sobrien } 359090277Sobrien else if ((skip = SWITCH_TAKES_ARG (argv[j][1]))) 359150599Sobrien j += skip - (argv[j][2] != 0); 359290277Sobrien else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1))) 359350599Sobrien j += skip; 359450599Sobrien } 359550599Sobrien j++; 359650599Sobrien } 359750599Sobrien } 359850599Sobrien#endif 359990277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX) 360050599Sobrien if (p[1] == 0) 360190277Sobrien argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0); 360250599Sobrien else 360390277Sobrien argv[i] = convert_filename (argv[i], ! have_c, 0); 360450599Sobrien#endif 360550599Sobrien goto normal_switch; 360650599Sobrien 360718334Speter default: 360850599Sobrien normal_switch: 360990277Sobrien 361090277Sobrien#ifdef MODIFY_TARGET_NAME 361190277Sobrien is_modify_target_name = 0; 361290277Sobrien 3613117413Skan for (j = 0; j < ARRAY_SIZE (modify_target); j++) 361490277Sobrien if (! strcmp (argv[i], modify_target[j].sw)) 361590277Sobrien { 361690277Sobrien char *new_name 361790277Sobrien = (char *) xmalloc (strlen (modify_target[j].str) 361890277Sobrien + strlen (spec_machine)); 361990277Sobrien const char *p, *r; 362090277Sobrien char *q; 362190277Sobrien int made_addition = 0; 362290277Sobrien 362390277Sobrien is_modify_target_name = 1; 362490277Sobrien for (p = spec_machine, q = new_name; *p != 0; ) 362590277Sobrien { 362690277Sobrien if (modify_target[j].add_del == DELETE 362790277Sobrien && (! strncmp (q, modify_target[j].str, 362890277Sobrien strlen (modify_target[j].str)))) 362990277Sobrien p += strlen (modify_target[j].str); 363090277Sobrien else if (modify_target[j].add_del == ADD 363190277Sobrien && ! made_addition && *p == '-') 363290277Sobrien { 363390277Sobrien for (r = modify_target[j].str; *r != 0; ) 363490277Sobrien *q++ = *r++; 363590277Sobrien made_addition = 1; 363690277Sobrien } 363790277Sobrien 363890277Sobrien *q++ = *p++; 363990277Sobrien } 364090277Sobrien 364190277Sobrien spec_machine = new_name; 364290277Sobrien } 364390277Sobrien 364490277Sobrien if (is_modify_target_name) 364590277Sobrien break; 3646117413Skan#endif 364790277Sobrien 364818334Speter n_switches++; 364918334Speter 365018334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 365118334Speter i += SWITCH_TAKES_ARG (c) - (p[1] != 0); 365218334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 365318334Speter i += WORD_SWITCH_TAKES_ARG (p); 365418334Speter } 365518334Speter } 365618334Speter else 365750599Sobrien { 365850599Sobrien n_infiles++; 365950599Sobrien lang_n_infiles++; 366050599Sobrien } 366118334Speter } 366218334Speter 366350599Sobrien if (have_c && have_o && lang_n_infiles > 1) 366450599Sobrien fatal ("cannot specify -o with -c or -S and multiple compilations"); 366550599Sobrien 366618334Speter /* Set up the search paths before we go looking for config files. */ 366718334Speter 366818334Speter /* These come before the md prefixes so that we will find gcc's subcommands 366918334Speter (such as cpp) rather than those of the host system. */ 367018334Speter /* Use 2 as fourth arg meaning try just the machine as a suffix, 367118334Speter as well as trying the machine and the version. */ 367218346Speter#ifdef FREEBSD_NATIVE 3673104953Sobrien add_prefix (&exec_prefixes, PREFIX"/bin/", "BINUTILS", 3674104763Skan 0, 0, warn_std_ptr, 0); 367591561Sobrien#endif /* FREEBSD_NATIVE */ 367618334Speter#ifndef OS2 367790277Sobrien add_prefix (&exec_prefixes, standard_exec_prefix, "GCC", 3678104763Skan PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); 367950599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", 3680104763Skan PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); 368196736Sru#ifndef FREEBSD_NATIVE 368250599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS", 3683104763Skan PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0); 368491578Sobrien#endif /* not FREEBSD_NATIVE */ 368518334Speter#endif 368618334Speter 368791578Sobrien#ifndef FREEBSD_NATIVE 368850599Sobrien add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", 3689104763Skan PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); 369050599Sobrien add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS", 3691104763Skan PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); 369291561Sobrien#endif /* not FREEBSD_NATIVE */ 369318334Speter 369490277Sobrien tooldir_prefix = concat (tooldir_base_prefix, spec_machine, 369590277Sobrien dir_separator_str, NULL); 369618334Speter 369718334Speter /* If tooldir is relative, base it on exec_prefixes. A relative 369818334Speter tooldir lets us move the installed tree as a unit. 369918334Speter 370018334Speter If GCC_EXEC_PREFIX is defined, then we want to add two relative 370118334Speter directories, so that we can search both the user specified directory 370218334Speter and the standard place. */ 370318334Speter 370490277Sobrien if (!IS_ABSOLUTE_PATHNAME (tooldir_prefix)) 370518334Speter { 370618334Speter if (gcc_exec_prefix) 370718334Speter { 370818334Speter char *gcc_exec_tooldir_prefix 370950599Sobrien = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 371090277Sobrien spec_version, dir_separator_str, tooldir_prefix, NULL); 371118334Speter 371218334Speter add_prefix (&exec_prefixes, 371390277Sobrien concat (gcc_exec_tooldir_prefix, "bin", 371490277Sobrien dir_separator_str, NULL), 3715104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 0); 371618334Speter add_prefix (&startfile_prefixes, 371790277Sobrien concat (gcc_exec_tooldir_prefix, "lib", 371890277Sobrien dir_separator_str, NULL), 3719104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); 372018334Speter } 372118334Speter 372250599Sobrien tooldir_prefix = concat (standard_exec_prefix, spec_machine, 372390277Sobrien dir_separator_str, spec_version, 372490277Sobrien dir_separator_str, tooldir_prefix, NULL); 372518334Speter } 372618334Speter 372718346Speter#ifndef FREEBSD_NATIVE 372890277Sobrien add_prefix (&exec_prefixes, 372990277Sobrien concat (tooldir_prefix, "bin", dir_separator_str, NULL), 3730104763Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 0); 373118334Speter add_prefix (&startfile_prefixes, 373290277Sobrien concat (tooldir_prefix, "lib", dir_separator_str, NULL), 3733104763Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); 373418346Speter#endif /* FREEBSD_NATIVE */ 373518334Speter 373618334Speter /* More prefixes are enabled in main, after we read the specs file 373718334Speter and determine whether this is cross-compilation or not. */ 373818334Speter 373918334Speter /* Then create the space for the vectors and scan again. */ 374018334Speter 374118334Speter switches = ((struct switchstr *) 374218334Speter xmalloc ((n_switches + 1) * sizeof (struct switchstr))); 374318334Speter infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile)); 374418334Speter n_switches = 0; 374518334Speter n_infiles = 0; 374618334Speter last_language_n_infiles = -1; 374718334Speter 374818334Speter /* This, time, copy the text of each switch and store a pointer 374918334Speter to the copy in the vector of switches. 375018334Speter Store all the infiles in their vector. */ 375118334Speter 375218334Speter for (i = 1; i < argc; i++) 375318334Speter { 375418334Speter /* Just skip the switches that were handled by the preceding loop. */ 375590277Sobrien#ifdef MODIFY_TARGET_NAME 375690277Sobrien is_modify_target_name = 0; 375790277Sobrien 3758117413Skan for (j = 0; j < ARRAY_SIZE (modify_target); j++) 375990277Sobrien if (! strcmp (argv[i], modify_target[j].sw)) 376090277Sobrien is_modify_target_name = 1; 376190277Sobrien 376290277Sobrien if (is_modify_target_name) 376390277Sobrien ; 376490277Sobrien else 376590277Sobrien#endif 376618334Speter if (! strncmp (argv[i], "-Wa,", 4)) 376718334Speter ; 376818334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 376918334Speter ; 377090277Sobrien else if (! strcmp (argv[i], "-pass-exit-codes")) 377190277Sobrien ; 377218334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 377318334Speter ; 377418334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 377518334Speter ; 377618334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 377718334Speter ; 377818334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 377918334Speter ; 378018334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 378118334Speter ; 378218334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 378318334Speter ; 3784104763Skan else if (! strcmp (argv[i], "-print-multi-os-directory")) 3785104763Skan ; 378690277Sobrien else if (! strcmp (argv[i], "-ftarget-help")) 378790277Sobrien ; 378890277Sobrien else if (! strcmp (argv[i], "-fhelp")) 378990277Sobrien ; 379018334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 379118334Speter { 379218334Speter /* Compensate for the +e options to the C++ front-end; 379318334Speter they're there simply for cfront call-compatibility. We do 379418334Speter some magic in default_compilers to pass them down properly. 379518334Speter Note we deliberately start at the `+' here, to avoid passing 379618334Speter -e0 or -e1 down into the linker. */ 379718334Speter switches[n_switches].part1 = &argv[i][0]; 379818334Speter switches[n_switches].args = 0; 379990277Sobrien switches[n_switches].live_cond = SWITCH_OK; 380052520Sobrien switches[n_switches].validated = 0; 380118334Speter n_switches++; 380218334Speter } 380318334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 380418334Speter { 380518334Speter int prev, j; 380618334Speter /* Split the argument at commas. */ 380718334Speter prev = 4; 380818334Speter for (j = 4; argv[i][j]; j++) 380918334Speter if (argv[i][j] == ',') 381018334Speter { 381150599Sobrien infiles[n_infiles].language = "*"; 381218334Speter infiles[n_infiles++].name 381318334Speter = save_string (argv[i] + prev, j - prev); 381418334Speter prev = j + 1; 381518334Speter } 381618334Speter /* Record the part after the last comma. */ 381750599Sobrien infiles[n_infiles].language = "*"; 381818334Speter infiles[n_infiles++].name = argv[i] + prev; 381918334Speter } 382018334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 382118334Speter { 382250599Sobrien infiles[n_infiles].language = "*"; 382318334Speter infiles[n_infiles++].name = argv[++i]; 382418334Speter } 382577389Sobrien else if (strcmp (argv[i], "-l") == 0) 382677389Sobrien { /* POSIX allows separation of -l and the lib arg; 382777389Sobrien canonicalize by concatenating -l with its arg */ 382877389Sobrien infiles[n_infiles].language = "*"; 382977389Sobrien infiles[n_infiles++].name = concat ("-l", argv[++i], NULL); 383077389Sobrien } 383118334Speter else if (strncmp (argv[i], "-l", 2) == 0) 383218334Speter { 383350599Sobrien infiles[n_infiles].language = "*"; 383418334Speter infiles[n_infiles++].name = argv[i]; 383518334Speter } 383650599Sobrien else if (strcmp (argv[i], "-specs") == 0) 383750599Sobrien i++; 383850599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 383950599Sobrien ; 384090277Sobrien else if (strcmp (argv[i], "-time") == 0) 384190277Sobrien ; 384290277Sobrien else if ((save_temps_flag || report_times) 384390277Sobrien && strcmp (argv[i], "-pipe") == 0) 384490277Sobrien { 384590277Sobrien /* -save-temps overrides -pipe, so that temp files are produced */ 384690277Sobrien if (save_temps_flag) 384790277Sobrien error ("warning: -pipe ignored because -save-temps specified"); 3848117413Skan /* -time overrides -pipe because we can't get correct stats when 384990277Sobrien multiple children are running at once. */ 385090277Sobrien else if (report_times) 385190277Sobrien error ("warning: -pipe ignored because -time specified"); 385290277Sobrien } 385390277Sobrien else if (strcmp (argv[i], "-###") == 0) 385490277Sobrien ; 385518334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 385618334Speter { 385790277Sobrien const char *p = &argv[i][1]; 385890277Sobrien int c = *p; 385918334Speter 386018334Speter if (c == 'x') 386118334Speter { 386218334Speter if (p[1] == 0 && i + 1 == argc) 386318334Speter fatal ("argument to `-x' is missing"); 386418334Speter if (p[1] == 0) 386518334Speter spec_lang = argv[++i]; 386618334Speter else 386718334Speter spec_lang = p + 1; 386818334Speter if (! strcmp (spec_lang, "none")) 386918334Speter /* Suppress the warning if -xnone comes after the last input 387018334Speter file, because alternate command interfaces like g++ might 387118334Speter find it useful to place -xnone after each input file. */ 387218334Speter spec_lang = 0; 387318334Speter else 387418334Speter last_language_n_infiles = n_infiles; 387518334Speter continue; 387618334Speter } 387718334Speter switches[n_switches].part1 = p; 387818334Speter /* Deal with option arguments in separate argv elements. */ 387918334Speter if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) 388018334Speter || WORD_SWITCH_TAKES_ARG (p)) 388118334Speter { 388218334Speter int j = 0; 388318334Speter int n_args = WORD_SWITCH_TAKES_ARG (p); 388418334Speter 388518334Speter if (n_args == 0) 388618334Speter { 388718334Speter /* Count only the option arguments in separate argv elements. */ 388818334Speter n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); 388918334Speter } 389018334Speter if (i + n_args >= argc) 389118334Speter fatal ("argument to `-%s' is missing", p); 389218334Speter switches[n_switches].args 389390277Sobrien = (const char **) xmalloc ((n_args + 1) * sizeof(const char *)); 389418334Speter while (j < n_args) 389518334Speter switches[n_switches].args[j++] = argv[++i]; 389618334Speter /* Null-terminate the vector. */ 389718334Speter switches[n_switches].args[j] = 0; 389818334Speter } 389990277Sobrien else if (strchr (switches_need_spaces, c)) 390018334Speter { 390150599Sobrien /* On some systems, ld cannot handle some options without 390250599Sobrien a space. So split the option from its argument. */ 390350599Sobrien char *part1 = (char *) xmalloc (2); 390450599Sobrien part1[0] = c; 390550599Sobrien part1[1] = '\0'; 390690277Sobrien 390750599Sobrien switches[n_switches].part1 = part1; 390890277Sobrien switches[n_switches].args 390990277Sobrien = (const char **) xmalloc (2 * sizeof (const char *)); 391090277Sobrien switches[n_switches].args[0] = xstrdup (p+1); 391118334Speter switches[n_switches].args[1] = 0; 391218334Speter } 391318334Speter else 391418334Speter switches[n_switches].args = 0; 391518334Speter 391690277Sobrien switches[n_switches].live_cond = SWITCH_OK; 391752520Sobrien switches[n_switches].validated = 0; 391890277Sobrien switches[n_switches].ordering = 0; 391990277Sobrien /* These are always valid, since gcc.c itself understands it. */ 392090277Sobrien if (!strcmp (p, "save-temps") 392190277Sobrien || !strcmp (p, "static-libgcc") 392290277Sobrien || !strcmp (p, "shared-libgcc")) 392352520Sobrien switches[n_switches].validated = 1; 392490277Sobrien else 392590277Sobrien { 392690277Sobrien char ch = switches[n_switches].part1[0]; 3927117413Skan if (ch == 'B') 392890277Sobrien switches[n_switches].validated = 1; 392990277Sobrien } 393018334Speter n_switches++; 393118334Speter } 393218334Speter else 393318334Speter { 393490277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX 393590277Sobrien argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK)); 393618334Speter#endif 393718334Speter 393890277Sobrien if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0) 393918334Speter { 394018334Speter perror_with_name (argv[i]); 394118334Speter error_count++; 394218334Speter } 394318334Speter else 394418334Speter { 394518334Speter infiles[n_infiles].language = spec_lang; 394618334Speter infiles[n_infiles++].name = argv[i]; 394718334Speter } 394818334Speter } 394918334Speter } 395018334Speter 395118334Speter if (n_infiles == last_language_n_infiles && spec_lang != 0) 395290277Sobrien error ("warning: `-x %s' after last input file has no effect", spec_lang); 395318334Speter 395490277Sobrien /* Ensure we only invoke each subprocess once. */ 395590277Sobrien if (target_help_flag || print_help_list) 395690277Sobrien { 395790277Sobrien n_infiles = 1; 395890277Sobrien 395990277Sobrien /* Create a dummy input file, so that we can pass --target-help on to 396090277Sobrien the various sub-processes. */ 396190277Sobrien infiles[0].language = "c"; 396290277Sobrien infiles[0].name = "help-dummy"; 396390277Sobrien 396490277Sobrien if (target_help_flag) 396590277Sobrien { 396690277Sobrien switches[n_switches].part1 = "--target-help"; 396790277Sobrien switches[n_switches].args = 0; 396890277Sobrien switches[n_switches].live_cond = SWITCH_OK; 396990277Sobrien switches[n_switches].validated = 0; 397090277Sobrien 397190277Sobrien n_switches++; 397290277Sobrien } 397390277Sobrien 397490277Sobrien if (print_help_list) 397590277Sobrien { 397690277Sobrien switches[n_switches].part1 = "--help"; 397790277Sobrien switches[n_switches].args = 0; 397890277Sobrien switches[n_switches].live_cond = SWITCH_OK; 397990277Sobrien switches[n_switches].validated = 0; 398090277Sobrien 398190277Sobrien n_switches++; 398290277Sobrien } 398390277Sobrien } 398490277Sobrien 398518334Speter switches[n_switches].part1 = 0; 398618334Speter infiles[n_infiles].name = 0; 398718334Speter} 398890277Sobrien 398990277Sobrien/* Store switches not filtered out by %{<S} in spec in COLLECT_GCC_OPTIONS 399090277Sobrien and place that in the environment. */ 399190277Sobrien 399290277Sobrienstatic void 399390277Sobrienset_collect_gcc_options () 399490277Sobrien{ 399590277Sobrien int i; 399690277Sobrien int first_time; 399790277Sobrien 399890277Sobrien /* Build COLLECT_GCC_OPTIONS to have all of the options specified to 399990277Sobrien the compiler. */ 400090277Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=", 400190277Sobrien sizeof ("COLLECT_GCC_OPTIONS=") - 1); 400290277Sobrien 400390277Sobrien first_time = TRUE; 400490277Sobrien for (i = 0; (int) i < n_switches; i++) 400590277Sobrien { 400690277Sobrien const char *const *args; 400790277Sobrien const char *p, *q; 400890277Sobrien if (!first_time) 400990277Sobrien obstack_grow (&collect_obstack, " ", 1); 401090277Sobrien 401190277Sobrien first_time = FALSE; 401290277Sobrien 401390277Sobrien /* Ignore elided switches. */ 401490277Sobrien if (switches[i].live_cond == SWITCH_IGNORE) 401590277Sobrien continue; 401690277Sobrien 401790277Sobrien obstack_grow (&collect_obstack, "'-", 2); 401890277Sobrien q = switches[i].part1; 401990277Sobrien while ((p = strchr (q, '\''))) 402090277Sobrien { 402190277Sobrien obstack_grow (&collect_obstack, q, p - q); 402290277Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 402390277Sobrien q = ++p; 402490277Sobrien } 402590277Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 402690277Sobrien obstack_grow (&collect_obstack, "'", 1); 402790277Sobrien 402890277Sobrien for (args = switches[i].args; args && *args; args++) 402990277Sobrien { 403090277Sobrien obstack_grow (&collect_obstack, " '", 2); 403190277Sobrien q = *args; 403290277Sobrien while ((p = strchr (q, '\''))) 403390277Sobrien { 403490277Sobrien obstack_grow (&collect_obstack, q, p - q); 403590277Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 403690277Sobrien q = ++p; 403790277Sobrien } 403890277Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 403990277Sobrien obstack_grow (&collect_obstack, "'", 1); 404090277Sobrien } 404190277Sobrien } 404290277Sobrien obstack_grow (&collect_obstack, "\0", 1); 404390277Sobrien putenv (obstack_finish (&collect_obstack)); 404490277Sobrien} 404518334Speter 404618334Speter/* Process a spec string, accumulating and running commands. */ 404718334Speter 404818334Speter/* These variables describe the input file name. 404918334Speter input_file_number is the index on outfiles of this file, 405018334Speter so that the output file name can be stored for later use by %o. 405118334Speter input_basename is the start of the part of the input file 405218334Speter sans all directory names, and basename_length is the number 405318334Speter of characters starting there excluding the suffix .c or whatever. */ 405418334Speter 405552520Sobrienconst char *input_filename; 405618334Speterstatic int input_file_number; 405750599Sobriensize_t input_filename_length; 405818334Speterstatic int basename_length; 405990277Sobrienstatic int suffixed_basename_length; 406052520Sobrienstatic const char *input_basename; 406152520Sobrienstatic const char *input_suffix; 406290277Sobrienstatic struct stat input_stat; 406390277Sobrienstatic int input_stat_set; 406418334Speter 406590277Sobrien/* The compiler used to process the current input file. */ 406690277Sobrienstatic struct compiler *input_file_compiler; 406790277Sobrien 406818334Speter/* These are variables used within do_spec and do_spec_1. */ 406918334Speter 407018334Speter/* Nonzero if an arg has been started and not yet terminated 407118334Speter (with space, tab or newline). */ 407218334Speterstatic int arg_going; 407318334Speter 407418334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated 407518334Speter is a temporary file name. */ 407618334Speterstatic int delete_this_arg; 407718334Speter 407818334Speter/* Nonzero means %w has been seen; the next arg to be terminated 407918334Speter is the output file name of this compilation. */ 408018334Speterstatic int this_is_output_file; 408118334Speter 408218334Speter/* Nonzero means %s has been seen; the next arg to be terminated 408318334Speter is the name of a library file and we should try the standard 408418334Speter search dirs for it. */ 408518334Speterstatic int this_is_library_file; 408618334Speter 408718334Speter/* Nonzero means that the input of this command is coming from a pipe. */ 408818334Speterstatic int input_from_pipe; 408918334Speter 409090277Sobrien/* Nonnull means substitute this for any suffix when outputting a switches 409190277Sobrien arguments. */ 409290277Sobrienstatic const char *suffix_subst; 409390277Sobrien 409418334Speter/* Process the spec SPEC and run the commands specified therein. 409518334Speter Returns 0 if the spec is successfully processed; -1 if failed. */ 409618334Speter 409750599Sobrienint 409818334Speterdo_spec (spec) 409952520Sobrien const char *spec; 410018334Speter{ 410118334Speter int value; 410218334Speter 4103117413Skan value = do_spec_2 (spec); 410418334Speter 410518334Speter /* Force out any unfinished command. 410618334Speter If -pipe, this forces out the last command if it ended in `|'. */ 410718334Speter if (value == 0) 410818334Speter { 410918334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 411018334Speter argbuf_index--; 411118334Speter 411290277Sobrien set_collect_gcc_options (); 411390277Sobrien 411418334Speter if (argbuf_index > 0) 411518334Speter value = execute (); 411618334Speter } 411718334Speter 411818334Speter return value; 411918334Speter} 412018334Speter 4121117413Skanstatic int 4122117413Skando_spec_2 (spec) 4123117413Skan const char *spec; 4124117413Skan{ 4125117413Skan clear_args (); 4126117413Skan arg_going = 0; 4127117413Skan delete_this_arg = 0; 4128117413Skan this_is_output_file = 0; 4129117413Skan this_is_library_file = 0; 4130117413Skan input_from_pipe = 0; 4131117413Skan suffix_subst = NULL; 4132117413Skan 4133117413Skan return do_spec_1 (spec, 0, NULL); 4134117413Skan} 4135117413Skan 4136117413Skan 4137117413Skan/* Process the given spec string and add any new options to the end 4138117413Skan of the switches/n_switches array. */ 4139117413Skan 4140117413Skanstatic void 4141117413Skando_self_spec (spec) 4142117413Skan const char *spec; 4143117413Skan{ 4144117413Skan do_spec_2 (spec); 4145117413Skan do_spec_1 (" ", 0, NULL); 4146117413Skan 4147117413Skan if (argbuf_index > 0) 4148117413Skan { 4149117413Skan int i, first; 4150117413Skan 4151117413Skan first = n_switches; 4152117413Skan n_switches += argbuf_index; 4153117413Skan switches = xrealloc (switches, 4154117413Skan sizeof (struct switchstr) * (n_switches + 1)); 4155117413Skan 4156117413Skan switches[n_switches] = switches[first]; 4157117413Skan for (i = 0; i < argbuf_index; i++) 4158117413Skan { 4159117413Skan struct switchstr *sw; 4160117413Skan 4161117413Skan /* Each switch should start with '-'. */ 4162117413Skan if (argbuf[i][0] != '-') 4163117413Skan abort (); 4164117413Skan 4165117413Skan sw = &switches[i + first]; 4166117413Skan sw->part1 = &argbuf[i][1]; 4167117413Skan sw->args = 0; 4168117413Skan sw->live_cond = SWITCH_OK; 4169117413Skan sw->validated = 0; 4170117413Skan sw->ordering = 0; 4171117413Skan } 4172117413Skan } 4173117413Skan} 4174117413Skan 417518334Speter/* Process the sub-spec SPEC as a portion of a larger spec. 417618334Speter This is like processing a whole spec except that we do 417718334Speter not initialize at the beginning and we do not supply a 417818334Speter newline by default at the end. 417918334Speter INSWITCH nonzero means don't process %-sequences in SPEC; 418018334Speter in this case, % is treated as an ordinary character. 418118334Speter This is used while substituting switches. 418218334Speter INSWITCH nonzero also causes SPC not to terminate an argument. 418318334Speter 418418334Speter Value is zero unless a line was finished 418518334Speter and the command on that line reported an error. */ 418618334Speter 418718334Speterstatic int 418818334Speterdo_spec_1 (spec, inswitch, soft_matched_part) 418952520Sobrien const char *spec; 419018334Speter int inswitch; 419152520Sobrien const char *soft_matched_part; 419218334Speter{ 419390277Sobrien const char *p = spec; 419490277Sobrien int c; 419518334Speter int i; 419652520Sobrien const char *string; 419718334Speter int value; 419818334Speter 419950599Sobrien while ((c = *p++)) 420018334Speter /* If substituting a switch, treat all chars like letters. 420118334Speter Otherwise, NL, SPC, TAB and % are special. */ 420218334Speter switch (inswitch ? 'a' : c) 420318334Speter { 420418334Speter case '\n': 420518334Speter /* End of line: finish any pending argument, 420618334Speter then run the pending command if one has been started. */ 420718334Speter if (arg_going) 420818334Speter { 420918334Speter obstack_1grow (&obstack, 0); 421018334Speter string = obstack_finish (&obstack); 421118334Speter if (this_is_library_file) 421218334Speter string = find_file (string); 421318334Speter store_arg (string, delete_this_arg, this_is_output_file); 421418334Speter if (this_is_output_file) 421518334Speter outfiles[input_file_number] = string; 421618334Speter } 421718334Speter arg_going = 0; 421818334Speter 421918334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 422018334Speter { 422118334Speter for (i = 0; i < n_switches; i++) 422218334Speter if (!strcmp (switches[i].part1, "pipe")) 422318334Speter break; 422418334Speter 422518334Speter /* A `|' before the newline means use a pipe here, 422618334Speter but only if -pipe was specified. 422718334Speter Otherwise, execute now and don't pass the `|' as an arg. */ 422818334Speter if (i < n_switches) 422918334Speter { 423018334Speter input_from_pipe = 1; 423152520Sobrien switches[i].validated = 1; 423218334Speter break; 423318334Speter } 423418334Speter else 423518334Speter argbuf_index--; 423618334Speter } 423718334Speter 423890277Sobrien set_collect_gcc_options (); 423990277Sobrien 424018334Speter if (argbuf_index > 0) 424118334Speter { 424218334Speter value = execute (); 424318334Speter if (value) 424418334Speter return value; 424518334Speter } 424618334Speter /* Reinitialize for a new command, and for a new argument. */ 424718334Speter clear_args (); 424818334Speter arg_going = 0; 424918334Speter delete_this_arg = 0; 425018334Speter this_is_output_file = 0; 425118334Speter this_is_library_file = 0; 425218334Speter input_from_pipe = 0; 425318334Speter break; 425418334Speter 425518334Speter case '|': 425618334Speter /* End any pending argument. */ 425718334Speter if (arg_going) 425818334Speter { 425918334Speter obstack_1grow (&obstack, 0); 426018334Speter string = obstack_finish (&obstack); 426118334Speter if (this_is_library_file) 426218334Speter string = find_file (string); 426318334Speter store_arg (string, delete_this_arg, this_is_output_file); 426418334Speter if (this_is_output_file) 426518334Speter outfiles[input_file_number] = string; 426618334Speter } 426718334Speter 426818334Speter /* Use pipe */ 426918334Speter obstack_1grow (&obstack, c); 427018334Speter arg_going = 1; 427118334Speter break; 427218334Speter 427318334Speter case '\t': 427418334Speter case ' ': 427518334Speter /* Space or tab ends an argument if one is pending. */ 427618334Speter if (arg_going) 427718334Speter { 427818334Speter obstack_1grow (&obstack, 0); 427918334Speter string = obstack_finish (&obstack); 428018334Speter if (this_is_library_file) 428118334Speter string = find_file (string); 428218334Speter store_arg (string, delete_this_arg, this_is_output_file); 428318334Speter if (this_is_output_file) 428418334Speter outfiles[input_file_number] = string; 428518334Speter } 428618334Speter /* Reinitialize for a new argument. */ 428718334Speter arg_going = 0; 428818334Speter delete_this_arg = 0; 428918334Speter this_is_output_file = 0; 429018334Speter this_is_library_file = 0; 429118334Speter break; 429218334Speter 429318334Speter case '%': 429418334Speter switch (c = *p++) 429518334Speter { 429618334Speter case 0: 429790277Sobrien fatal ("invalid specification! Bug in cc"); 429818334Speter 429918334Speter case 'b': 430018334Speter obstack_grow (&obstack, input_basename, basename_length); 430118334Speter arg_going = 1; 430218334Speter break; 430318334Speter 430490277Sobrien case 'B': 430590277Sobrien obstack_grow (&obstack, input_basename, suffixed_basename_length); 430690277Sobrien arg_going = 1; 430790277Sobrien break; 430890277Sobrien 430918334Speter case 'd': 431018334Speter delete_this_arg = 2; 431118334Speter break; 431218334Speter 431318334Speter /* Dump out the directories specified with LIBRARY_PATH, 431418334Speter followed by the absolute directories 431518334Speter that we search for startfiles. */ 431618334Speter case 'D': 431718334Speter { 431818334Speter struct prefix_list *pl = startfile_prefixes.plist; 431950599Sobrien size_t bufsize = 100; 432018334Speter char *buffer = (char *) xmalloc (bufsize); 432118334Speter int idx; 432218334Speter 432318334Speter for (; pl; pl = pl->next) 432418334Speter { 432518334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR 432618334Speter /* Used on systems which record the specified -L dirs 432718334Speter and use them to search for dynamic linking. */ 432818334Speter /* Relative directories always come from -B, 432918334Speter and it is better not to use them for searching 433090277Sobrien at run time. In particular, stage1 loses. */ 433190277Sobrien if (!IS_ABSOLUTE_PATHNAME (pl->prefix)) 433218334Speter continue; 433318334Speter#endif 433418334Speter /* Try subdirectory if there is one. */ 4335104763Skan if (multilib_dir != NULL 4336104763Skan || (pl->os_multilib && multilib_os_dir != NULL)) 433718334Speter { 4338104763Skan const char *multi_dir; 4339104763Skan 4340104763Skan multi_dir = pl->os_multilib ? multilib_os_dir 4341104763Skan : multilib_dir; 4342104763Skan if (machine_suffix && multilib_dir) 434318334Speter { 434418334Speter if (strlen (pl->prefix) + strlen (machine_suffix) 434518334Speter >= bufsize) 434618334Speter bufsize = (strlen (pl->prefix) 434718334Speter + strlen (machine_suffix)) * 2 + 1; 434818334Speter buffer = (char *) xrealloc (buffer, bufsize); 434918334Speter strcpy (buffer, pl->prefix); 435018334Speter strcat (buffer, machine_suffix); 435118334Speter if (is_directory (buffer, multilib_dir, 1)) 435218334Speter { 435390277Sobrien do_spec_1 ("-L", 0, NULL); 435418334Speter#ifdef SPACE_AFTER_L_OPTION 435590277Sobrien do_spec_1 (" ", 0, NULL); 435618334Speter#endif 435790277Sobrien do_spec_1 (buffer, 1, NULL); 435890277Sobrien do_spec_1 (multilib_dir, 1, NULL); 435918334Speter /* Make this a separate argument. */ 436090277Sobrien do_spec_1 (" ", 0, NULL); 436118334Speter } 436218334Speter } 436318334Speter if (!pl->require_machine_suffix) 436418334Speter { 4365104763Skan if (is_directory (pl->prefix, multi_dir, 1)) 436618334Speter { 436790277Sobrien do_spec_1 ("-L", 0, NULL); 436818334Speter#ifdef SPACE_AFTER_L_OPTION 436990277Sobrien do_spec_1 (" ", 0, NULL); 437018334Speter#endif 437190277Sobrien do_spec_1 (pl->prefix, 1, NULL); 4372104763Skan do_spec_1 (multi_dir, 1, NULL); 437318334Speter /* Make this a separate argument. */ 437490277Sobrien do_spec_1 (" ", 0, NULL); 437518334Speter } 437618334Speter } 437718334Speter } 437818334Speter if (machine_suffix) 437918334Speter { 438018334Speter if (is_directory (pl->prefix, machine_suffix, 1)) 438118334Speter { 438290277Sobrien do_spec_1 ("-L", 0, NULL); 438318334Speter#ifdef SPACE_AFTER_L_OPTION 438490277Sobrien do_spec_1 (" ", 0, NULL); 438518334Speter#endif 438690277Sobrien do_spec_1 (pl->prefix, 1, NULL); 438718334Speter /* Remove slash from machine_suffix. */ 438818334Speter if (strlen (machine_suffix) >= bufsize) 438918334Speter bufsize = strlen (machine_suffix) * 2 + 1; 439018334Speter buffer = (char *) xrealloc (buffer, bufsize); 439118334Speter strcpy (buffer, machine_suffix); 439218334Speter idx = strlen (buffer); 439352520Sobrien if (IS_DIR_SEPARATOR (buffer[idx - 1])) 439418334Speter buffer[idx - 1] = 0; 439590277Sobrien do_spec_1 (buffer, 1, NULL); 439618334Speter /* Make this a separate argument. */ 439790277Sobrien do_spec_1 (" ", 0, NULL); 439818334Speter } 439918334Speter } 440018334Speter if (!pl->require_machine_suffix) 440118334Speter { 440218334Speter if (is_directory (pl->prefix, "", 1)) 440318334Speter { 440490277Sobrien do_spec_1 ("-L", 0, NULL); 440518334Speter#ifdef SPACE_AFTER_L_OPTION 440690277Sobrien do_spec_1 (" ", 0, NULL); 440718334Speter#endif 440818334Speter /* Remove slash from pl->prefix. */ 440918334Speter if (strlen (pl->prefix) >= bufsize) 441018334Speter bufsize = strlen (pl->prefix) * 2 + 1; 441118334Speter buffer = (char *) xrealloc (buffer, bufsize); 441218334Speter strcpy (buffer, pl->prefix); 441318334Speter idx = strlen (buffer); 441452520Sobrien if (IS_DIR_SEPARATOR (buffer[idx - 1])) 441518334Speter buffer[idx - 1] = 0; 441690277Sobrien do_spec_1 (buffer, 1, NULL); 441718334Speter /* Make this a separate argument. */ 441890277Sobrien do_spec_1 (" ", 0, NULL); 441918334Speter } 442018334Speter } 442118334Speter } 442218334Speter free (buffer); 442318334Speter } 442418334Speter break; 442518334Speter 442618334Speter case 'e': 442752520Sobrien /* %efoo means report an error with `foo' as error message 442818334Speter and don't execute any more commands for this file. */ 442918334Speter { 443052520Sobrien const char *q = p; 443118334Speter char *buf; 443290277Sobrien while (*p != 0 && *p != '\n') 443390277Sobrien p++; 443418334Speter buf = (char *) alloca (p - q + 1); 443518334Speter strncpy (buf, q, p - q); 443618334Speter buf[p - q] = 0; 443790277Sobrien error ("%s", buf); 443818334Speter return -1; 443918334Speter } 444018334Speter break; 444190277Sobrien case 'n': 4442117413Skan /* %nfoo means report a notice with `foo' on stderr. */ 444390277Sobrien { 444490277Sobrien const char *q = p; 444590277Sobrien char *buf; 444690277Sobrien while (*p != 0 && *p != '\n') 444790277Sobrien p++; 444890277Sobrien buf = (char *) alloca (p - q + 1); 444990277Sobrien strncpy (buf, q, p - q); 445090277Sobrien buf[p - q] = 0; 445190277Sobrien notice ("%s\n", buf); 445290277Sobrien if (*p) 445390277Sobrien p++; 445490277Sobrien } 445590277Sobrien break; 445618334Speter 445790277Sobrien case 'j': 445890277Sobrien { 445990277Sobrien struct stat st; 446090277Sobrien 446190277Sobrien /* If save_temps_flag is off, and the HOST_BIT_BUCKET is defined, 446290277Sobrien and it is not a directory, and it is writable, use it. 446390277Sobrien Otherwise, fall through and treat this like any other 446490277Sobrien temporary file. */ 446590277Sobrien 446690277Sobrien if ((!save_temps_flag) 446790277Sobrien && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode)) 446890277Sobrien && (access (HOST_BIT_BUCKET, W_OK) == 0)) 446990277Sobrien { 447090277Sobrien obstack_grow (&obstack, HOST_BIT_BUCKET, 447190277Sobrien strlen (HOST_BIT_BUCKET)); 447290277Sobrien delete_this_arg = 0; 447390277Sobrien arg_going = 1; 447490277Sobrien break; 447590277Sobrien } 447690277Sobrien } 447718334Speter case 'g': 447818334Speter case 'u': 447918334Speter case 'U': 448018334Speter { 448118334Speter struct temp_name *t; 448250599Sobrien int suffix_length; 448352520Sobrien const char *suffix = p; 448490277Sobrien char *saved_suffix = NULL; 448518334Speter 448690277Sobrien while (*p == '.' || ISALPHA ((unsigned char) *p)) 448790277Sobrien p++; 448890277Sobrien suffix_length = p - suffix; 448950599Sobrien if (p[0] == '%' && p[1] == 'O') 449050599Sobrien { 449150599Sobrien p += 2; 449250599Sobrien /* We don't support extra suffix characters after %O. */ 449390277Sobrien if (*p == '.' || ISALPHA ((unsigned char) *p)) 449450599Sobrien abort (); 449590277Sobrien if (suffix_length == 0) 449690277Sobrien suffix = TARGET_OBJECT_SUFFIX; 449790277Sobrien else 449890277Sobrien { 449990277Sobrien saved_suffix 450090277Sobrien = (char *) xmalloc (suffix_length 450190277Sobrien + strlen (TARGET_OBJECT_SUFFIX)); 450290277Sobrien strncpy (saved_suffix, suffix, suffix_length); 450390277Sobrien strcpy (saved_suffix + suffix_length, 450490277Sobrien TARGET_OBJECT_SUFFIX); 450590277Sobrien } 450690277Sobrien suffix_length += strlen (TARGET_OBJECT_SUFFIX); 450750599Sobrien } 4508117413Skan 450990277Sobrien /* If the input_filename has the same suffix specified 451090277Sobrien for the %g, %u, or %U, and -save-temps is specified, 451190277Sobrien we could end up using that file as an intermediate 451290277Sobrien thus clobbering the user's source file (.e.g., 451390277Sobrien gcc -save-temps foo.s would clobber foo.s with the 451490277Sobrien output of cpp0). So check for this condition and 451590277Sobrien generate a temp file as the intermediate. */ 4516117413Skan 451790277Sobrien if (save_temps_flag) 451850599Sobrien { 451990277Sobrien temp_filename_length = basename_length + suffix_length; 452090277Sobrien temp_filename = alloca (temp_filename_length + 1); 452190277Sobrien strncpy ((char *) temp_filename, input_basename, basename_length); 452290277Sobrien strncpy ((char *) temp_filename + basename_length, suffix, 452390277Sobrien suffix_length); 452490277Sobrien *((char *) temp_filename + temp_filename_length) = '\0'; 452590277Sobrien if (strcmp (temp_filename, input_filename) != 0) 452690277Sobrien { 452790277Sobrien struct stat st_temp; 4528117413Skan 452990277Sobrien /* Note, set_input() resets input_stat_set to 0. */ 453090277Sobrien if (input_stat_set == 0) 453190277Sobrien { 453290277Sobrien input_stat_set = stat (input_filename, &input_stat); 453390277Sobrien if (input_stat_set >= 0) 453490277Sobrien input_stat_set = 1; 453590277Sobrien } 4536117413Skan 453790277Sobrien /* If we have the stat for the input_filename 453890277Sobrien and we can do the stat for the temp_filename 453990277Sobrien then the they could still refer to the same 454090277Sobrien file if st_dev/st_ino's are the same. */ 4541117413Skan 454290277Sobrien if (input_stat_set != 1 454390277Sobrien || stat (temp_filename, &st_temp) < 0 454490277Sobrien || input_stat.st_dev != st_temp.st_dev 454590277Sobrien || input_stat.st_ino != st_temp.st_ino) 4546117413Skan { 454790277Sobrien temp_filename = save_string (temp_filename, 454890277Sobrien temp_filename_length + 1); 454990277Sobrien obstack_grow (&obstack, temp_filename, 455090277Sobrien temp_filename_length); 455190277Sobrien arg_going = 1; 4552117413Skan delete_this_arg = 0; 455390277Sobrien break; 455490277Sobrien } 455590277Sobrien } 455650599Sobrien } 455750599Sobrien 455818334Speter /* See if we already have an association of %g/%u/%U and 455918334Speter suffix. */ 456018334Speter for (t = temp_names; t; t = t->next) 456150599Sobrien if (t->length == suffix_length 456250599Sobrien && strncmp (t->suffix, suffix, suffix_length) == 0 456318334Speter && t->unique == (c != 'g')) 456418334Speter break; 456518334Speter 456690277Sobrien /* Make a new association if needed. %u and %j 456790277Sobrien require one. */ 456890277Sobrien if (t == 0 || c == 'u' || c == 'j') 456918334Speter { 457018334Speter if (t == 0) 457118334Speter { 457218334Speter t = (struct temp_name *) xmalloc (sizeof (struct temp_name)); 457318334Speter t->next = temp_names; 457418334Speter temp_names = t; 457518334Speter } 457650599Sobrien t->length = suffix_length; 457790277Sobrien if (saved_suffix) 457890277Sobrien { 457990277Sobrien t->suffix = saved_suffix; 458090277Sobrien saved_suffix = NULL; 458190277Sobrien } 458290277Sobrien else 458390277Sobrien t->suffix = save_string (suffix, suffix_length); 458418334Speter t->unique = (c != 'g'); 458550599Sobrien temp_filename = make_temp_file (t->suffix); 458650599Sobrien temp_filename_length = strlen (temp_filename); 458718334Speter t->filename = temp_filename; 458818334Speter t->filename_length = temp_filename_length; 458918334Speter } 459018334Speter 459190277Sobrien if (saved_suffix) 459290277Sobrien free (saved_suffix); 459390277Sobrien 459418334Speter obstack_grow (&obstack, t->filename, t->filename_length); 459518334Speter delete_this_arg = 1; 459618334Speter } 459718334Speter arg_going = 1; 459818334Speter break; 459918334Speter 460018334Speter case 'i': 460118334Speter obstack_grow (&obstack, input_filename, input_filename_length); 460218334Speter arg_going = 1; 460318334Speter break; 460418334Speter 460518334Speter case 'I': 460618334Speter { 460718334Speter struct prefix_list *pl = include_prefixes.plist; 460818334Speter 460918334Speter if (gcc_exec_prefix) 461018334Speter { 461190277Sobrien do_spec_1 ("-iprefix", 1, NULL); 461218334Speter /* Make this a separate argument. */ 461390277Sobrien do_spec_1 (" ", 0, NULL); 461490277Sobrien do_spec_1 (gcc_exec_prefix, 1, NULL); 461590277Sobrien do_spec_1 (" ", 0, NULL); 461618334Speter } 461718334Speter 461818334Speter for (; pl; pl = pl->next) 461918334Speter { 462090277Sobrien do_spec_1 ("-isystem", 1, NULL); 462118334Speter /* Make this a separate argument. */ 462290277Sobrien do_spec_1 (" ", 0, NULL); 462390277Sobrien do_spec_1 (pl->prefix, 1, NULL); 462490277Sobrien do_spec_1 (" ", 0, NULL); 462518334Speter } 462618334Speter } 462718334Speter break; 462818334Speter 462918334Speter case 'o': 463052520Sobrien { 463152520Sobrien int max = n_infiles; 463252520Sobrien max += lang_specific_extra_outfiles; 463318334Speter 463452520Sobrien for (i = 0; i < max; i++) 463552520Sobrien if (outfiles[i]) 463652520Sobrien store_arg (outfiles[i], 0, 0); 463752520Sobrien break; 463852520Sobrien } 463952520Sobrien 464018334Speter case 'O': 464190277Sobrien obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); 464218334Speter arg_going = 1; 464318334Speter break; 464418334Speter 464518334Speter case 's': 464618334Speter this_is_library_file = 1; 464718334Speter break; 464818334Speter 464918334Speter case 'w': 465018334Speter this_is_output_file = 1; 465118334Speter break; 465218334Speter 465318334Speter case 'W': 465418334Speter { 465550599Sobrien int cur_index = argbuf_index; 465618334Speter /* Handle the {...} following the %W. */ 465718334Speter if (*p != '{') 465818334Speter abort (); 465918334Speter p = handle_braces (p + 1); 466018334Speter if (p == 0) 466118334Speter return -1; 466218334Speter /* If any args were output, mark the last one for deletion 466318334Speter on failure. */ 466450599Sobrien if (argbuf_index != cur_index) 466518334Speter record_temp_file (argbuf[argbuf_index - 1], 0, 1); 466618334Speter break; 466718334Speter } 466818334Speter 466918334Speter /* %x{OPTION} records OPTION for %X to output. */ 467018334Speter case 'x': 467118334Speter { 467252520Sobrien const char *p1 = p; 467318334Speter char *string; 467418334Speter 467518334Speter /* Skip past the option value and make a copy. */ 467618334Speter if (*p != '{') 467718334Speter abort (); 467818334Speter while (*p++ != '}') 467918334Speter ; 468018334Speter string = save_string (p1 + 1, p - p1 - 2); 468118334Speter 468218334Speter /* See if we already recorded this option. */ 468318334Speter for (i = 0; i < n_linker_options; i++) 468418334Speter if (! strcmp (string, linker_options[i])) 468518334Speter { 468618334Speter free (string); 468718334Speter return 0; 468818334Speter } 468918334Speter 469018334Speter /* This option is new; add it. */ 469150599Sobrien add_linker_option (string, strlen (string)); 469218334Speter } 469318334Speter break; 469418334Speter 469518334Speter /* Dump out the options accumulated previously using %x. */ 469618334Speter case 'X': 469718334Speter for (i = 0; i < n_linker_options; i++) 469818334Speter { 469990277Sobrien do_spec_1 (linker_options[i], 1, NULL); 470018334Speter /* Make each accumulated option a separate argument. */ 470190277Sobrien do_spec_1 (" ", 0, NULL); 470218334Speter } 470318334Speter break; 470418334Speter 470518334Speter /* Dump out the options accumulated previously using -Wa,. */ 470618334Speter case 'Y': 470718334Speter for (i = 0; i < n_assembler_options; i++) 470818334Speter { 470990277Sobrien do_spec_1 (assembler_options[i], 1, NULL); 471018334Speter /* Make each accumulated option a separate argument. */ 471190277Sobrien do_spec_1 (" ", 0, NULL); 471218334Speter } 471318334Speter break; 471418334Speter 471518334Speter /* Dump out the options accumulated previously using -Wp,. */ 471618334Speter case 'Z': 471718334Speter for (i = 0; i < n_preprocessor_options; i++) 471818334Speter { 471990277Sobrien do_spec_1 (preprocessor_options[i], 1, NULL); 472018334Speter /* Make each accumulated option a separate argument. */ 472190277Sobrien do_spec_1 (" ", 0, NULL); 472218334Speter } 472318334Speter break; 472418334Speter 472518334Speter /* Here are digits and numbers that just process 472618334Speter a certain constant string as a spec. */ 472718334Speter 472818334Speter case '1': 472990277Sobrien value = do_spec_1 (cc1_spec, 0, NULL); 473018334Speter if (value != 0) 473118334Speter return value; 473218334Speter break; 473318334Speter 473418334Speter case '2': 473590277Sobrien value = do_spec_1 (cc1plus_spec, 0, NULL); 473618334Speter if (value != 0) 473718334Speter return value; 473818334Speter break; 473918334Speter 474018334Speter case 'a': 474190277Sobrien value = do_spec_1 (asm_spec, 0, NULL); 474218334Speter if (value != 0) 474318334Speter return value; 474418334Speter break; 474518334Speter 474618334Speter case 'A': 474790277Sobrien value = do_spec_1 (asm_final_spec, 0, NULL); 474818334Speter if (value != 0) 474918334Speter return value; 475018334Speter break; 475118334Speter 475218334Speter case 'C': 475390277Sobrien { 475490277Sobrien const char *const spec 4755117413Skan = (input_file_compiler->cpp_spec 4756117413Skan ? input_file_compiler->cpp_spec 475790277Sobrien : cpp_spec); 475890277Sobrien value = do_spec_1 (spec, 0, NULL); 475990277Sobrien if (value != 0) 476090277Sobrien return value; 476190277Sobrien } 476218334Speter break; 476318334Speter 476418334Speter case 'E': 476590277Sobrien value = do_spec_1 (endfile_spec, 0, NULL); 476618334Speter if (value != 0) 476718334Speter return value; 476818334Speter break; 476918334Speter 477018334Speter case 'l': 477190277Sobrien value = do_spec_1 (link_spec, 0, NULL); 477218334Speter if (value != 0) 477318334Speter return value; 477418334Speter break; 477518334Speter 477618334Speter case 'L': 477790277Sobrien value = do_spec_1 (lib_spec, 0, NULL); 477818334Speter if (value != 0) 477918334Speter return value; 478018334Speter break; 478118334Speter 478218334Speter case 'G': 478390277Sobrien value = do_spec_1 (libgcc_spec, 0, NULL); 478418334Speter if (value != 0) 478518334Speter return value; 478618334Speter break; 478718334Speter 478890277Sobrien case 'M': 478990277Sobrien if (multilib_dir && strcmp (multilib_dir, ".") != 0) 479090277Sobrien { 479190277Sobrien char *p; 479290277Sobrien const char *q; 479390277Sobrien size_t len; 479490277Sobrien 479590277Sobrien len = strlen (multilib_dir); 479690277Sobrien obstack_blank (&obstack, len + 1); 479790277Sobrien p = obstack_next_free (&obstack) - (len + 1); 479890277Sobrien 479990277Sobrien *p++ = '_'; 480090277Sobrien for (q = multilib_dir; *q ; ++q, ++p) 480190277Sobrien *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q); 480290277Sobrien } 480390277Sobrien break; 480490277Sobrien 480518334Speter case 'p': 480618334Speter { 480718334Speter char *x = (char *) alloca (strlen (cpp_predefines) + 1); 480818334Speter char *buf = x; 480990277Sobrien const char *y; 481018334Speter 481118334Speter /* Copy all of the -D options in CPP_PREDEFINES into BUF. */ 481218334Speter y = cpp_predefines; 481318334Speter while (*y != 0) 481418334Speter { 481518334Speter if (! strncmp (y, "-D", 2)) 481618334Speter /* Copy the whole option. */ 481718334Speter while (*y && *y != ' ' && *y != '\t') 481818334Speter *x++ = *y++; 481918334Speter else if (*y == ' ' || *y == '\t') 482018334Speter /* Copy whitespace to the result. */ 482118334Speter *x++ = *y++; 482218334Speter /* Don't copy other options. */ 482318334Speter else 482418334Speter y++; 482518334Speter } 482618334Speter 482718334Speter *x = 0; 482818334Speter 482990277Sobrien value = do_spec_1 (buf, 0, NULL); 483018334Speter if (value != 0) 483118334Speter return value; 483218334Speter } 483318334Speter break; 483418334Speter 483518334Speter case 'P': 483618334Speter { 483718334Speter char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1); 483818334Speter char *buf = x; 483990277Sobrien const char *y; 484018334Speter 484118334Speter /* Copy all of CPP_PREDEFINES into BUF, 484290277Sobrien but force them all into the reserved name space if they 484390277Sobrien aren't already there. The reserved name space is all 484490277Sobrien identifiers beginning with two underscores or with one 484590277Sobrien underscore and a capital letter. We do the forcing by 484690277Sobrien adding up to two underscores to the beginning and end 484790277Sobrien of each symbol. e.g. mips, _mips, mips_, and _mips_ all 484890277Sobrien become __mips__. */ 484918334Speter y = cpp_predefines; 485018334Speter while (*y != 0) 485118334Speter { 485218334Speter if (! strncmp (y, "-D", 2)) 485318334Speter { 485418334Speter int flag = 0; 485518334Speter 485618334Speter *x++ = *y++; 485718334Speter *x++ = *y++; 485818334Speter 485918334Speter if (*y != '_' 486090277Sobrien || (*(y + 1) != '_' 486190277Sobrien && ! ISUPPER ((unsigned char) *(y + 1)))) 486290277Sobrien { 486318334Speter /* Stick __ at front of macro name. */ 486490277Sobrien if (*y != '_') 486590277Sobrien *x++ = '_'; 486618334Speter *x++ = '_'; 486718334Speter /* Arrange to stick __ at the end as well. */ 486818334Speter flag = 1; 486918334Speter } 487018334Speter 487118334Speter /* Copy the macro name. */ 487218334Speter while (*y && *y != '=' && *y != ' ' && *y != '\t') 487318334Speter *x++ = *y++; 487418334Speter 487518334Speter if (flag) 487690277Sobrien { 487790277Sobrien if (x[-1] != '_') 487890277Sobrien { 487990277Sobrien if (x[-2] != '_') 488090277Sobrien *x++ = '_'; 488190277Sobrien *x++ = '_'; 488290277Sobrien } 488318334Speter } 488418334Speter 488518334Speter /* Copy the value given, if any. */ 488618334Speter while (*y && *y != ' ' && *y != '\t') 488718334Speter *x++ = *y++; 488818334Speter } 488918334Speter else if (*y == ' ' || *y == '\t') 489018334Speter /* Copy whitespace to the result. */ 489118334Speter *x++ = *y++; 489218334Speter /* Don't copy -A options */ 489318334Speter else 489418334Speter y++; 489518334Speter } 489618334Speter *x++ = ' '; 489718334Speter 489818334Speter /* Copy all of CPP_PREDEFINES into BUF, 489918334Speter but put __ after every -D. */ 490018334Speter y = cpp_predefines; 490118334Speter while (*y != 0) 490218334Speter { 490318334Speter if (! strncmp (y, "-D", 2)) 490418334Speter { 490518334Speter y += 2; 490618334Speter 490718334Speter if (*y != '_' 490890277Sobrien || (*(y + 1) != '_' 490990277Sobrien && ! ISUPPER ((unsigned char) *(y + 1)))) 491090277Sobrien { 491118334Speter /* Stick -D__ at front of macro name. */ 491218334Speter *x++ = '-'; 491318334Speter *x++ = 'D'; 491490277Sobrien if (*y != '_') 491590277Sobrien *x++ = '_'; 491618334Speter *x++ = '_'; 491718334Speter 491818334Speter /* Copy the macro name. */ 491918334Speter while (*y && *y != '=' && *y != ' ' && *y != '\t') 492018334Speter *x++ = *y++; 492118334Speter 492218334Speter /* Copy the value given, if any. */ 492318334Speter while (*y && *y != ' ' && *y != '\t') 492418334Speter *x++ = *y++; 492518334Speter } 492618334Speter else 492718334Speter { 492818334Speter /* Do not copy this macro - we have just done it before */ 492918334Speter while (*y && *y != ' ' && *y != '\t') 493018334Speter y++; 493118334Speter } 493218334Speter } 493318334Speter else if (*y == ' ' || *y == '\t') 493418334Speter /* Copy whitespace to the result. */ 493518334Speter *x++ = *y++; 493690277Sobrien /* Don't copy -A options. */ 493718334Speter else 493818334Speter y++; 493918334Speter } 494018334Speter *x++ = ' '; 494118334Speter 494218334Speter /* Copy all of the -A options in CPP_PREDEFINES into BUF. */ 494318334Speter y = cpp_predefines; 494418334Speter while (*y != 0) 494518334Speter { 494618334Speter if (! strncmp (y, "-A", 2)) 494718334Speter /* Copy the whole option. */ 494818334Speter while (*y && *y != ' ' && *y != '\t') 494918334Speter *x++ = *y++; 495018334Speter else if (*y == ' ' || *y == '\t') 495118334Speter /* Copy whitespace to the result. */ 495218334Speter *x++ = *y++; 495318334Speter /* Don't copy other options. */ 495418334Speter else 495518334Speter y++; 495618334Speter } 495718334Speter 495818334Speter *x = 0; 495918334Speter 496090277Sobrien value = do_spec_1 (buf, 0, NULL); 496118334Speter if (value != 0) 496218334Speter return value; 496318334Speter } 496418334Speter break; 496518334Speter 496618334Speter case 'S': 496790277Sobrien value = do_spec_1 (startfile_spec, 0, NULL); 496818334Speter if (value != 0) 496918334Speter return value; 497018334Speter break; 497118334Speter 497218334Speter /* Here we define characters other than letters and digits. */ 497318334Speter 497418334Speter case '{': 497518334Speter p = handle_braces (p); 497618334Speter if (p == 0) 497718334Speter return -1; 497818334Speter break; 497918334Speter 4980117413Skan case ':': 4981117413Skan p = handle_spec_function (p); 4982117413Skan if (p == 0) 4983117413Skan return -1; 4984117413Skan break; 4985117413Skan 498618334Speter case '%': 498718334Speter obstack_1grow (&obstack, '%'); 498818334Speter break; 498918334Speter 4990117413Skan case '.': 4991117413Skan { 4992117413Skan unsigned len = 0; 499390277Sobrien 4994117413Skan while (p[len] && p[len] != ' ' && p[len] != '%') 4995117413Skan len++; 4996117413Skan suffix_subst = save_string (p - 1, len + 1); 4997117413Skan p += len; 4998117413Skan } 499990277Sobrien break; 5000117413Skan 500118334Speter case '*': 500290277Sobrien if (soft_matched_part) 500390277Sobrien { 500490277Sobrien do_spec_1 (soft_matched_part, 1, NULL); 500590277Sobrien do_spec_1 (" ", 0, NULL); 500690277Sobrien } 500790277Sobrien else 500890277Sobrien /* Catch the case where a spec string contains something like 500990277Sobrien '%{foo:%*}'. ie there is no * in the pattern on the left 501090277Sobrien hand side of the :. */ 501190277Sobrien error ("spec failure: '%%*' has not been initialized by pattern match"); 501218334Speter break; 501318334Speter 501418334Speter /* Process a string found as the value of a spec given by name. 501518334Speter This feature allows individual machine descriptions 501618334Speter to add and use their own specs. 501718334Speter %[...] modifies -D options the way %P does; 501818334Speter %(...) uses the spec unmodified. */ 501950599Sobrien case '[': 502090277Sobrien error ("warning: use of obsolete %%[ operator in specs"); 502118334Speter case '(': 502218334Speter { 502352520Sobrien const char *name = p; 502418334Speter struct spec_list *sl; 502518334Speter int len; 502618334Speter 502718334Speter /* The string after the S/P is the name of a spec that is to be 502850599Sobrien processed. */ 502918334Speter while (*p && *p != ')' && *p != ']') 503018334Speter p++; 503118334Speter 503290277Sobrien /* See if it's in the list. */ 503318334Speter for (len = p - name, sl = specs; sl; sl = sl->next) 503450599Sobrien if (sl->name_len == len && !strncmp (sl->name, name, len)) 503518334Speter { 503650599Sobrien name = *(sl->ptr_spec); 503750599Sobrien#ifdef DEBUG_SPECS 503852520Sobrien notice ("Processing spec %c%s%c, which is '%s'\n", 503952520Sobrien c, sl->name, (c == '(') ? ')' : ']', name); 504050599Sobrien#endif 504118334Speter break; 504218334Speter } 504318334Speter 504418334Speter if (sl) 504518334Speter { 504618334Speter if (c == '(') 504718334Speter { 504890277Sobrien value = do_spec_1 (name, 0, NULL); 504918334Speter if (value != 0) 505018334Speter return value; 505118334Speter } 505218334Speter else 505318334Speter { 505418334Speter char *x = (char *) alloca (strlen (name) * 2 + 1); 505518334Speter char *buf = x; 505652520Sobrien const char *y = name; 505750599Sobrien int flag = 0; 505818334Speter 505918334Speter /* Copy all of NAME into BUF, but put __ after 506090277Sobrien every -D and at the end of each arg. */ 506118334Speter while (1) 506218334Speter { 506318334Speter if (! strncmp (y, "-D", 2)) 506418334Speter { 506518334Speter *x++ = '-'; 506618334Speter *x++ = 'D'; 506718334Speter *x++ = '_'; 506818334Speter *x++ = '_'; 506918334Speter y += 2; 507050599Sobrien flag = 1; 507150599Sobrien continue; 507218334Speter } 507390277Sobrien else if (flag 507490277Sobrien && (*y == ' ' || *y == '\t' || *y == '=' 507590277Sobrien || *y == '}' || *y == 0)) 507618334Speter { 507718334Speter *x++ = '_'; 507818334Speter *x++ = '_'; 507950599Sobrien flag = 0; 508018334Speter } 508190277Sobrien if (*y == 0) 508250599Sobrien break; 508318334Speter else 508418334Speter *x++ = *y++; 508518334Speter } 508618334Speter *x = 0; 508718334Speter 508890277Sobrien value = do_spec_1 (buf, 0, NULL); 508918334Speter if (value != 0) 509018334Speter return value; 509118334Speter } 509218334Speter } 509318334Speter 509418334Speter /* Discard the closing paren or bracket. */ 509518334Speter if (*p) 509618334Speter p++; 509718334Speter } 509818334Speter break; 509918334Speter 510018334Speter case 'v': 510118334Speter { 510218334Speter int c1 = *p++; /* Select first or second version number. */ 510390277Sobrien const char *v = compiler_version; 510490277Sobrien const char *q; 510590277Sobrien static const char zeroc = '0'; 510650599Sobrien 510750599Sobrien /* The format of the version string is 510850599Sobrien ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */ 510950599Sobrien 511050599Sobrien /* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */ 511150599Sobrien while (! ISDIGIT (*v)) 511250599Sobrien v++; 511350599Sobrien if (v > compiler_version && v[-1] != '-') 511450599Sobrien abort (); 511550599Sobrien 511618334Speter /* If desired, advance to second version number. */ 511790277Sobrien if (c1 >= '2') 511818334Speter { 511950599Sobrien /* Set V after the first period. */ 512050599Sobrien while (ISDIGIT (*v)) 512118334Speter v++; 512250599Sobrien if (*v != '.') 512350599Sobrien abort (); 512450599Sobrien v++; 512518334Speter } 512650599Sobrien 512790277Sobrien /* If desired, advance to third version number. 512890277Sobrien But don't complain if it's not present */ 512990277Sobrien if (c1 == '3') 513090277Sobrien { 513190277Sobrien /* Set V after the second period. */ 513290277Sobrien while (ISDIGIT (*v)) 513390277Sobrien v++; 513490277Sobrien if ((*v != 0) && (*v != ' ') && (*v != '.') && (*v != '-')) 513590277Sobrien abort (); 513690277Sobrien if (*v != 0) 513790277Sobrien v++; 513890277Sobrien } 513990277Sobrien 514018334Speter /* Set Q at the next period or at the end. */ 514118334Speter q = v; 514250599Sobrien while (ISDIGIT (*q)) 514318334Speter q++; 514490277Sobrien if (*q != 0 && q > v && *q != ' ' && *q != '.' && *q != '-') 514550599Sobrien abort (); 514650599Sobrien 514790277Sobrien if (q > v) 514890277Sobrien /* Put that part into the command. */ 514990277Sobrien obstack_grow (&obstack, v, q - v); 515090277Sobrien else 515190277Sobrien /* Default to "0" */ 515290277Sobrien obstack_grow (&obstack, &zeroc, 1); 515318334Speter arg_going = 1; 515418334Speter } 515518334Speter break; 515618334Speter 515718334Speter case '|': 515818334Speter if (input_from_pipe) 515990277Sobrien do_spec_1 ("-", 0, NULL); 516018334Speter break; 516118334Speter 516218334Speter default: 516390277Sobrien error ("spec failure: unrecognized spec option '%c'", c); 516490277Sobrien break; 516518334Speter } 516618334Speter break; 516718334Speter 516818334Speter case '\\': 516918334Speter /* Backslash: treat next character as ordinary. */ 517018334Speter c = *p++; 517118334Speter 517218334Speter /* fall through */ 517318334Speter default: 517418334Speter /* Ordinary character: put it into the current argument. */ 517518334Speter obstack_1grow (&obstack, c); 517618334Speter arg_going = 1; 517718334Speter } 517818334Speter 5179117413Skan /* End of string. If we are processing a spec function, we need to 5180117413Skan end any pending argument. */ 5181117413Skan if (processing_spec_function && arg_going) 5182117413Skan { 5183117413Skan obstack_1grow (&obstack, 0); 5184117413Skan string = obstack_finish (&obstack); 5185117413Skan if (this_is_library_file) 5186117413Skan string = find_file (string); 5187117413Skan store_arg (string, delete_this_arg, this_is_output_file); 5188117413Skan if (this_is_output_file) 5189117413Skan outfiles[input_file_number] = string; 5190117413Skan arg_going = 0; 5191117413Skan } 5192117413Skan 519390277Sobrien return 0; 519418334Speter} 519518334Speter 5196117413Skan/* Look up a spec function. */ 5197117413Skan 5198117413Skanstatic const struct spec_function * 5199117413Skanlookup_spec_function (name) 5200117413Skan const char *name; 5201117413Skan{ 5202117413Skan static const struct spec_function * const spec_function_tables[] = 5203117413Skan { 5204117413Skan static_spec_functions, 5205117413Skan lang_specific_spec_functions, 5206117413Skan }; 5207117413Skan const struct spec_function *sf; 5208117413Skan unsigned int i; 5209117413Skan 5210117413Skan for (i = 0; i < ARRAY_SIZE (spec_function_tables); i++) 5211117413Skan { 5212117413Skan for (sf = spec_function_tables[i]; sf->name != NULL; sf++) 5213117413Skan if (strcmp (sf->name, name) == 0) 5214117413Skan return sf; 5215117413Skan } 5216117413Skan 5217117413Skan return NULL; 5218117413Skan} 5219117413Skan 5220117413Skan/* Evaluate a spec function. */ 5221117413Skan 5222117413Skanstatic const char * 5223117413Skaneval_spec_function (func, args) 5224117413Skan const char *func, *args; 5225117413Skan{ 5226117413Skan const struct spec_function *sf; 5227117413Skan const char *funcval; 5228117413Skan 5229117413Skan /* Saved spec processing context. */ 5230117413Skan int save_argbuf_index; 5231117413Skan int save_argbuf_length; 5232117413Skan const char **save_argbuf; 5233117413Skan 5234117413Skan int save_arg_going; 5235117413Skan int save_delete_this_arg; 5236117413Skan int save_this_is_output_file; 5237117413Skan int save_this_is_library_file; 5238117413Skan int save_input_from_pipe; 5239117413Skan const char *save_suffix_subst; 5240117413Skan 5241117413Skan 5242117413Skan sf = lookup_spec_function (func); 5243117413Skan if (sf == NULL) 5244117413Skan fatal ("unknown spec function `%s'", func); 5245117413Skan 5246117413Skan /* Push the spec processing context. */ 5247117413Skan save_argbuf_index = argbuf_index; 5248117413Skan save_argbuf_length = argbuf_length; 5249117413Skan save_argbuf = argbuf; 5250117413Skan 5251117413Skan save_arg_going = arg_going; 5252117413Skan save_delete_this_arg = delete_this_arg; 5253117413Skan save_this_is_output_file = this_is_output_file; 5254117413Skan save_this_is_library_file = this_is_library_file; 5255117413Skan save_input_from_pipe = input_from_pipe; 5256117413Skan save_suffix_subst = suffix_subst; 5257117413Skan 5258117413Skan /* Create a new spec processing context, and build the function 5259117413Skan arguments. */ 5260117413Skan 5261117413Skan alloc_args (); 5262117413Skan if (do_spec_2 (args) < 0) 5263117413Skan fatal ("error in args to spec function `%s'", func); 5264117413Skan 5265117413Skan /* argbuf_index is an index for the next argument to be inserted, and 5266117413Skan so contains the count of the args already inserted. */ 5267117413Skan 5268117413Skan funcval = (*sf->func) (argbuf_index, argbuf); 5269117413Skan 5270117413Skan /* Pop the spec processing context. */ 5271117413Skan argbuf_index = save_argbuf_index; 5272117413Skan argbuf_length = save_argbuf_length; 5273117413Skan free (argbuf); 5274117413Skan argbuf = save_argbuf; 5275117413Skan 5276117413Skan arg_going = save_arg_going; 5277117413Skan delete_this_arg = save_delete_this_arg; 5278117413Skan this_is_output_file = save_this_is_output_file; 5279117413Skan this_is_library_file = save_this_is_library_file; 5280117413Skan input_from_pipe = save_input_from_pipe; 5281117413Skan suffix_subst = save_suffix_subst; 5282117413Skan 5283117413Skan return funcval; 5284117413Skan} 5285117413Skan 5286117413Skan/* Handle a spec function call of the form: 5287117413Skan 5288117413Skan %:function(args) 5289117413Skan 5290117413Skan ARGS is processed as a spec in a separate context and split into an 5291117413Skan argument vector in the normal fashion. The function returns a string 5292117413Skan containing a spec which we then process in the caller's context, or 5293117413Skan NULL if no processing is required. */ 5294117413Skan 5295117413Skanstatic const char * 5296117413Skanhandle_spec_function (p) 5297117413Skan const char *p; 5298117413Skan{ 5299117413Skan char *func, *args; 5300117413Skan const char *endp, *funcval; 5301117413Skan int count; 5302117413Skan 5303117413Skan processing_spec_function++; 5304117413Skan 5305117413Skan /* Get the function name. */ 5306117413Skan for (endp = p; *endp != '\0'; endp++) 5307117413Skan { 5308117413Skan if (*endp == '(') /* ) */ 5309117413Skan break; 5310117413Skan /* Only allow [A-Za-z0-9], -, and _ in function names. */ 5311117413Skan if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_')) 5312117413Skan fatal ("malformed spec function name"); 5313117413Skan } 5314117413Skan if (*endp != '(') /* ) */ 5315117413Skan fatal ("no arguments for spec function"); 5316117413Skan func = save_string (p, endp - p); 5317117413Skan p = ++endp; 5318117413Skan 5319117413Skan /* Get the arguments. */ 5320117413Skan for (count = 0; *endp != '\0'; endp++) 5321117413Skan { 5322117413Skan /* ( */ 5323117413Skan if (*endp == ')') 5324117413Skan { 5325117413Skan if (count == 0) 5326117413Skan break; 5327117413Skan count--; 5328117413Skan } 5329117413Skan else if (*endp == '(') /* ) */ 5330117413Skan count++; 5331117413Skan } 5332117413Skan /* ( */ 5333117413Skan if (*endp != ')') 5334117413Skan fatal ("malformed spec function arguments"); 5335117413Skan args = save_string (p, endp - p); 5336117413Skan p = ++endp; 5337117413Skan 5338117413Skan /* p now points to just past the end of the spec function expression. */ 5339117413Skan 5340117413Skan funcval = eval_spec_function (func, args); 5341117413Skan if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0) 5342117413Skan p = NULL; 5343117413Skan 5344117413Skan free (func); 5345117413Skan free (args); 5346117413Skan 5347117413Skan processing_spec_function--; 5348117413Skan 5349117413Skan return p; 5350117413Skan} 5351117413Skan 535218334Speter/* Return 0 if we call do_spec_1 and that returns -1. */ 535318334Speter 535452520Sobrienstatic const char * 535518334Speterhandle_braces (p) 535690277Sobrien const char *p; 535718334Speter{ 535852520Sobrien const char *filter, *body = NULL, *endbody = NULL; 535950599Sobrien int pipe_p = 0; 536090277Sobrien int true_once = 0; /* If, in %{a|b:d}, at least one of a,b was seen. */ 536150599Sobrien int negate; 536250599Sobrien int suffix; 536350599Sobrien int include_blanks = 1; 536490277Sobrien int elide_switch = 0; 536590277Sobrien int ordered = 0; 536618334Speter 536750599Sobrien if (*p == '^') 536890277Sobrien { 536990277Sobrien /* A '^' after the open-brace means to not give blanks before args. */ 537090277Sobrien include_blanks = 0; 537190277Sobrien ++p; 537290277Sobrien } 537350599Sobrien 537418334Speter if (*p == '|') 537590277Sobrien { 537690277Sobrien /* A `|' after the open-brace means, 537790277Sobrien if the test fails, output a single minus sign rather than nothing. 537890277Sobrien This is used in %{|!pipe:...}. */ 537990277Sobrien pipe_p = 1; 538090277Sobrien ++p; 538190277Sobrien } 538218334Speter 538390277Sobrien if (*p == '<') 538490277Sobrien { 538590277Sobrien /* A `<' after the open-brace means that the switch should be 538690277Sobrien removed from the command-line. */ 538790277Sobrien elide_switch = 1; 538890277Sobrien ++p; 538990277Sobrien } 539090277Sobrien 539150599Sobriennext_member: 539250599Sobrien negate = suffix = 0; 539350599Sobrien 539418334Speter if (*p == '!') 539518334Speter /* A `!' after the open-brace negates the condition: 539618334Speter succeed if the specified switch is not present. */ 539718334Speter negate = 1, ++p; 539818334Speter 539918334Speter if (*p == '.') 540018334Speter /* A `.' after the open-brace means test against the current suffix. */ 540118334Speter { 540250599Sobrien if (pipe_p) 540318334Speter abort (); 540418334Speter 540518334Speter suffix = 1; 540618334Speter ++p; 540718334Speter } 540818334Speter 540990277Sobrien if (elide_switch && (negate || pipe_p || suffix)) 541090277Sobrien { 541190277Sobrien /* It doesn't make sense to mix elision with other flags. We 541290277Sobrien could fatal() here, but the standard seems to be to abort. */ 541390277Sobrien abort (); 541490277Sobrien } 541590277Sobrien 541690277Sobrien next_ampersand: 541718334Speter filter = p; 541890277Sobrien while (*p != ':' && *p != '}' && *p != '|' && *p != '&') 541990277Sobrien p++; 542050599Sobrien 542190277Sobrien if (*p == '|' && (pipe_p || ordered)) 542250599Sobrien abort (); 542350599Sobrien 542450599Sobrien if (!body) 542518334Speter { 542690277Sobrien if (*p != '}' && *p != '&') 542790277Sobrien { 542890277Sobrien int count = 1; 542990277Sobrien const char *q = p; 543050599Sobrien 543190277Sobrien while (*q++ != ':') 543290277Sobrien continue; 543350599Sobrien body = q; 543490277Sobrien 543550599Sobrien while (count > 0) 543650599Sobrien { 543750599Sobrien if (*q == '{') 543890277Sobrien count++; 543950599Sobrien else if (*q == '}') 544090277Sobrien count--; 544150599Sobrien else if (*q == 0) 544290277Sobrien fatal ("mismatched braces in specs"); 544350599Sobrien q++; 544450599Sobrien } 544550599Sobrien endbody = q; 544618334Speter } 544750599Sobrien else 544890277Sobrien body = p, endbody = p + 1; 544918334Speter } 545018334Speter 545118334Speter if (suffix) 545218334Speter { 545318334Speter int found = (input_suffix != 0 545490277Sobrien && (long) strlen (input_suffix) == (long) (p - filter) 545518334Speter && strncmp (input_suffix, filter, p - filter) == 0); 545618334Speter 545750599Sobrien if (body[0] == '}') 545818334Speter abort (); 545918334Speter 546018334Speter if (negate != found 546190277Sobrien && do_spec_1 (save_string (body, endbody-body-1), 0, NULL) < 0) 546218334Speter return 0; 546318334Speter } 546490277Sobrien else if (p[-1] == '*' && (p[0] == '}' || p[0] == '&')) 546518334Speter { 546618334Speter /* Substitute all matching switches as separate args. */ 546790277Sobrien int i; 546890277Sobrien 546918334Speter for (i = 0; i < n_switches; i++) 547090277Sobrien if (!strncmp (switches[i].part1, filter, p - 1 - filter) 547190277Sobrien && check_live_switch (i, p - 1 - filter)) 547290277Sobrien { 547390277Sobrien if (elide_switch) 547490277Sobrien { 547590277Sobrien switches[i].live_cond = SWITCH_IGNORE; 547690277Sobrien switches[i].validated = 1; 547790277Sobrien } 547890277Sobrien else 547990277Sobrien ordered = 1, switches[i].ordering = 1; 548090277Sobrien } 548118334Speter } 548218334Speter else 548318334Speter { 548418334Speter /* Test for presence of the specified switch. */ 548590277Sobrien int i; 548618334Speter int present = 0; 548718334Speter 548818334Speter /* If name specified ends in *, as in {x*:...}, 548918334Speter check for %* and handle that case. */ 549018334Speter if (p[-1] == '*' && !negate) 549118334Speter { 549218334Speter int substitution; 549352520Sobrien const char *r = body; 549418334Speter 549518334Speter /* First see whether we have %*. */ 549618334Speter substitution = 0; 549750599Sobrien while (r < endbody) 549818334Speter { 549918334Speter if (*r == '%' && r[1] == '*') 550018334Speter substitution = 1; 550118334Speter r++; 550218334Speter } 550318334Speter /* If we do, handle that case. */ 550418334Speter if (substitution) 550518334Speter { 550618334Speter /* Substitute all matching switches as separate args. 550718334Speter But do this by substituting for %* 550818334Speter in the text that follows the colon. */ 550918334Speter 551018334Speter unsigned hard_match_len = p - filter - 1; 551150599Sobrien char *string = save_string (body, endbody - body - 1); 551218334Speter 551318334Speter for (i = 0; i < n_switches; i++) 551418334Speter if (!strncmp (switches[i].part1, filter, hard_match_len) 551518334Speter && check_live_switch (i, -1)) 551618334Speter { 551718334Speter do_spec_1 (string, 0, &switches[i].part1[hard_match_len]); 551818334Speter /* Pass any arguments this switch has. */ 551950599Sobrien give_switch (i, 1, 1); 552090277Sobrien suffix_subst = NULL; 552118334Speter } 552218334Speter 552350599Sobrien /* We didn't match. Try again. */ 552450599Sobrien if (*p++ == '|') 552550599Sobrien goto next_member; 552650599Sobrien return endbody; 552718334Speter } 552818334Speter } 552918334Speter 553018334Speter /* If name specified ends in *, as in {x*:...}, 553118334Speter check for presence of any switch name starting with x. */ 553218334Speter if (p[-1] == '*') 553318334Speter { 553418334Speter for (i = 0; i < n_switches; i++) 553518334Speter { 553618334Speter unsigned hard_match_len = p - filter - 1; 553718334Speter 553818334Speter if (!strncmp (switches[i].part1, filter, hard_match_len) 553918334Speter && check_live_switch (i, hard_match_len)) 554018334Speter { 554118334Speter present = 1; 554290277Sobrien break; 554318334Speter } 554418334Speter } 554518334Speter } 554618334Speter /* Otherwise, check for presence of exact name specified. */ 554718334Speter else 554818334Speter { 554918334Speter for (i = 0; i < n_switches; i++) 555018334Speter { 555118334Speter if (!strncmp (switches[i].part1, filter, p - filter) 555218334Speter && switches[i].part1[p - filter] == 0 555318334Speter && check_live_switch (i, -1)) 555418334Speter { 555518334Speter present = 1; 555618334Speter break; 555718334Speter } 555818334Speter } 555918334Speter } 556018334Speter 556150599Sobrien /* If it is as desired (present for %{s...}, absent for %{!s...}) 556218334Speter then substitute either the switch or the specified 556318334Speter conditional text. */ 556418334Speter if (present != negate) 556518334Speter { 556690277Sobrien if (elide_switch) 556718334Speter { 556890277Sobrien switches[i].live_cond = SWITCH_IGNORE; 556990277Sobrien switches[i].validated = 1; 557018334Speter } 557190277Sobrien else if (ordered || *p == '&') 557290277Sobrien ordered = 1, switches[i].ordering = 1; 557390277Sobrien else if (*p == '}') 557490277Sobrien give_switch (i, 0, include_blanks); 557518334Speter else 557690277Sobrien /* Even if many alternatives are matched, only output once. */ 557790277Sobrien true_once = 1; 557818334Speter } 557950599Sobrien else if (pipe_p) 558018334Speter { 558118334Speter /* Here if a %{|...} conditional fails: output a minus sign, 558218334Speter which means "standard output" or "standard input". */ 558390277Sobrien do_spec_1 ("-", 0, NULL); 558450599Sobrien return endbody; 558518334Speter } 558618334Speter } 558718334Speter 558850599Sobrien /* We didn't match; try again. */ 558950599Sobrien if (*p++ == '|') 559050599Sobrien goto next_member; 559150599Sobrien 559290277Sobrien if (p[-1] == '&') 559390277Sobrien { 559490277Sobrien body = 0; 559590277Sobrien goto next_ampersand; 559690277Sobrien } 559790277Sobrien 559890277Sobrien if (ordered) 559990277Sobrien { 560090277Sobrien int i; 560190277Sobrien /* Doing this set of switches later preserves their command-line 560290277Sobrien ordering. This is needed for e.g. -U, -D and -A. */ 560390277Sobrien for (i = 0; i < n_switches; i++) 560490277Sobrien if (switches[i].ordering == 1) 560590277Sobrien { 560690277Sobrien switches[i].ordering = 0; 560790277Sobrien give_switch (i, 0, include_blanks); 560890277Sobrien } 560990277Sobrien } 561090277Sobrien /* Process the spec just once, regardless of match count. */ 561190277Sobrien else if (true_once) 561290277Sobrien { 561390277Sobrien if (do_spec_1 (save_string (body, endbody - body - 1), 561490277Sobrien 0, NULL) < 0) 561590277Sobrien return 0; 561690277Sobrien } 561790277Sobrien 561850599Sobrien return endbody; 561918334Speter} 562018334Speter 562118334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch 562218334Speter on the command line. PREFIX_LENGTH is the length of XXX in an {XXX*} 562318334Speter spec, or -1 if either exact match or %* is used. 562418334Speter 562518334Speter A -O switch is obsoleted by a later -O switch. A -f, -m, or -W switch 562618334Speter whose value does not begin with "no-" is obsoleted by the same value 562718334Speter with the "no-", similarly for a switch with the "no-" prefix. */ 562818334Speter 562918334Speterstatic int 563018334Spetercheck_live_switch (switchnum, prefix_length) 563118334Speter int switchnum; 563218334Speter int prefix_length; 563318334Speter{ 563452520Sobrien const char *name = switches[switchnum].part1; 563518334Speter int i; 563618334Speter 563718334Speter /* In the common case of {<at-most-one-letter>*}, a negating 563818334Speter switch would always match, so ignore that case. We will just 563918334Speter send the conflicting switches to the compiler phase. */ 564018334Speter if (prefix_length >= 0 && prefix_length <= 1) 564118334Speter return 1; 564218334Speter 564318334Speter /* If we already processed this switch and determined if it was 564418334Speter live or not, return our past determination. */ 564518334Speter if (switches[switchnum].live_cond != 0) 564618334Speter return switches[switchnum].live_cond > 0; 564718334Speter 564818334Speter /* Now search for duplicate in a manner that depends on the name. */ 564918334Speter switch (*name) 565018334Speter { 565118334Speter case 'O': 565290277Sobrien for (i = switchnum + 1; i < n_switches; i++) 565390277Sobrien if (switches[i].part1[0] == 'O') 565490277Sobrien { 565590277Sobrien switches[switchnum].validated = 1; 565690277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 565790277Sobrien return 0; 565890277Sobrien } 565918334Speter break; 566018334Speter 566118334Speter case 'W': case 'f': case 'm': 566218334Speter if (! strncmp (name + 1, "no-", 3)) 566318334Speter { 566450599Sobrien /* We have Xno-YYY, search for XYYY. */ 566518334Speter for (i = switchnum + 1; i < n_switches; i++) 566618334Speter if (switches[i].part1[0] == name[0] 566718334Speter && ! strcmp (&switches[i].part1[1], &name[4])) 566890277Sobrien { 566990277Sobrien switches[switchnum].validated = 1; 567090277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 567190277Sobrien return 0; 567290277Sobrien } 567318334Speter } 567418334Speter else 567518334Speter { 567618334Speter /* We have XYYY, search for Xno-YYY. */ 567718334Speter for (i = switchnum + 1; i < n_switches; i++) 567818334Speter if (switches[i].part1[0] == name[0] 567918334Speter && switches[i].part1[1] == 'n' 568018334Speter && switches[i].part1[2] == 'o' 568118334Speter && switches[i].part1[3] == '-' 568218334Speter && !strcmp (&switches[i].part1[4], &name[1])) 568390277Sobrien { 568490277Sobrien switches[switchnum].validated = 1; 568590277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 568690277Sobrien return 0; 568790277Sobrien } 568818334Speter } 568918334Speter break; 569018334Speter } 569118334Speter 569218334Speter /* Otherwise the switch is live. */ 569390277Sobrien switches[switchnum].live_cond = SWITCH_LIVE; 569418334Speter return 1; 569518334Speter} 569618334Speter 569718334Speter/* Pass a switch to the current accumulating command 569818334Speter in the same form that we received it. 569918334Speter SWITCHNUM identifies the switch; it is an index into 570018334Speter the vector of switches gcc received, which is `switches'. 570118334Speter This cannot fail since it never finishes a command line. 570218334Speter 570350599Sobrien If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. 570418334Speter 570550599Sobrien If INCLUDE_BLANKS is nonzero, then we include blanks before each argument 570650599Sobrien of the switch. */ 570750599Sobrien 570818334Speterstatic void 570950599Sobriengive_switch (switchnum, omit_first_word, include_blanks) 571018334Speter int switchnum; 571118334Speter int omit_first_word; 571250599Sobrien int include_blanks; 571318334Speter{ 571490277Sobrien if (switches[switchnum].live_cond == SWITCH_IGNORE) 571590277Sobrien return; 571690277Sobrien 571718334Speter if (!omit_first_word) 571818334Speter { 571990277Sobrien do_spec_1 ("-", 0, NULL); 572090277Sobrien do_spec_1 (switches[switchnum].part1, 1, NULL); 572118334Speter } 572250599Sobrien 572318334Speter if (switches[switchnum].args != 0) 572418334Speter { 572590277Sobrien const char **p; 572618334Speter for (p = switches[switchnum].args; *p; p++) 572718334Speter { 572890277Sobrien const char *arg = *p; 572990277Sobrien 573050599Sobrien if (include_blanks) 573190277Sobrien do_spec_1 (" ", 0, NULL); 573290277Sobrien if (suffix_subst) 573390277Sobrien { 573490277Sobrien unsigned length = strlen (arg); 573590277Sobrien int dot = 0; 573690277Sobrien 573790277Sobrien while (length-- && !IS_DIR_SEPARATOR (arg[length])) 573890277Sobrien if (arg[length] == '.') 573990277Sobrien { 574090277Sobrien ((char *)arg)[length] = 0; 574190277Sobrien dot = 1; 574290277Sobrien break; 574390277Sobrien } 574490277Sobrien do_spec_1 (arg, 1, NULL); 574590277Sobrien if (dot) 574690277Sobrien ((char *)arg)[length] = '.'; 574790277Sobrien do_spec_1 (suffix_subst, 1, NULL); 574890277Sobrien } 574990277Sobrien else 575090277Sobrien do_spec_1 (arg, 1, NULL); 575118334Speter } 575218334Speter } 575350599Sobrien 575490277Sobrien do_spec_1 (" ", 0, NULL); 575552520Sobrien switches[switchnum].validated = 1; 575618334Speter} 575718334Speter 575818334Speter/* Search for a file named NAME trying various prefixes including the 575918334Speter user's -B prefix and some standard ones. 576018334Speter Return the absolute file name found. If nothing is found, return NAME. */ 576118334Speter 576252520Sobrienstatic const char * 576318334Speterfind_file (name) 576452520Sobrien const char *name; 576518334Speter{ 576618334Speter char *newname; 576718334Speter 576818334Speter /* Try multilib_dir if it is defined. */ 5769104763Skan if (multilib_os_dir != NULL) 577018334Speter { 5771104763Skan newname = find_a_file (&startfile_prefixes, name, R_OK, 1); 577218334Speter 577318334Speter /* If we don't find it in the multi library dir, then fall 577418334Speter through and look for it in the normal places. */ 577518334Speter if (newname != NULL) 577618334Speter return newname; 577718334Speter } 577818334Speter 5779104763Skan newname = find_a_file (&startfile_prefixes, name, R_OK, 0); 578018334Speter return newname ? newname : name; 578118334Speter} 578218334Speter 578318334Speter/* Determine whether a directory exists. If LINKER, return 0 for 578418334Speter certain fixed names not needed by the linker. If not LINKER, it is 578518334Speter only important to return 0 if the host machine has a small ARG_MAX 578618334Speter limit. */ 578718334Speter 578818334Speterstatic int 578918334Speteris_directory (path1, path2, linker) 579052520Sobrien const char *path1; 579152520Sobrien const char *path2; 579218334Speter int linker; 579318334Speter{ 579418334Speter int len1 = strlen (path1); 579518334Speter int len2 = strlen (path2); 579618334Speter char *path = (char *) alloca (3 + len1 + len2); 579718334Speter char *cp; 579818334Speter struct stat st; 579918334Speter 580018334Speter#ifndef SMALL_ARG_MAX 580118334Speter if (! linker) 580218334Speter return 1; 580318334Speter#endif 580418334Speter 580518334Speter /* Construct the path from the two parts. Ensure the string ends with "/.". 580618334Speter The resulting path will be a directory even if the given path is a 580718334Speter symbolic link. */ 580852520Sobrien memcpy (path, path1, len1); 580952520Sobrien memcpy (path + len1, path2, len2); 581018334Speter cp = path + len1 + len2; 581152520Sobrien if (!IS_DIR_SEPARATOR (cp[-1])) 581218334Speter *cp++ = DIR_SEPARATOR; 581318334Speter *cp++ = '.'; 581418334Speter *cp = '\0'; 581518334Speter 581651232Sbde#ifndef FREEBSD_NATIVE 581718334Speter /* Exclude directories that the linker is known to search. */ 581818334Speter if (linker 581918334Speter && ((cp - path == 6 582090277Sobrien && strcmp (path, concat (dir_separator_str, "lib", 582190277Sobrien dir_separator_str, ".", NULL)) == 0) 582218334Speter || (cp - path == 10 582390277Sobrien && strcmp (path, concat (dir_separator_str, "usr", 582490277Sobrien dir_separator_str, "lib", 582590277Sobrien dir_separator_str, ".", NULL)) == 0))) 582618334Speter return 0; 582751232Sbde#endif /* FREEBSD_NATIVE */ 582818334Speter 582918334Speter return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode)); 583018334Speter} 583190277Sobrien 583290277Sobrien/* Set up the various global variables to indicate that we're processing 583390277Sobrien the input file named FILENAME. */ 583490277Sobrien 583590277Sobrienvoid 583690277Sobrienset_input (filename) 583790277Sobrien const char *filename; 583890277Sobrien{ 583990277Sobrien const char *p; 584090277Sobrien 584190277Sobrien input_filename = filename; 584290277Sobrien input_filename_length = strlen (input_filename); 584390277Sobrien 584490277Sobrien input_basename = input_filename; 584590277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 584690277Sobrien /* Skip drive name so 'x:foo' is handled properly. */ 584790277Sobrien if (input_basename[1] == ':') 584890277Sobrien input_basename += 2; 584990277Sobrien#endif 585090277Sobrien for (p = input_basename; *p; p++) 585190277Sobrien if (IS_DIR_SEPARATOR (*p)) 585290277Sobrien input_basename = p + 1; 585390277Sobrien 585490277Sobrien /* Find a suffix starting with the last period, 585590277Sobrien and set basename_length to exclude that suffix. */ 585690277Sobrien basename_length = strlen (input_basename); 585790277Sobrien suffixed_basename_length = basename_length; 585890277Sobrien p = input_basename + basename_length; 585990277Sobrien while (p != input_basename && *p != '.') 586090277Sobrien --p; 586190277Sobrien if (*p == '.' && p != input_basename) 586290277Sobrien { 586390277Sobrien basename_length = p - input_basename; 586490277Sobrien input_suffix = p + 1; 586590277Sobrien } 586690277Sobrien else 586790277Sobrien input_suffix = ""; 5868117413Skan 586990277Sobrien /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then 587090277Sobrien we will need to do a stat on the input_filename. The 587190277Sobrien INPUT_STAT_SET signals that the stat is needed. */ 587290277Sobrien input_stat_set = 0; 587390277Sobrien} 587418334Speter 587518334Speter/* On fatal signals, delete all the temporary files. */ 587618334Speter 587718334Speterstatic void 587818334Speterfatal_error (signum) 587918334Speter int signum; 588018334Speter{ 588118334Speter signal (signum, SIG_DFL); 588218334Speter delete_failure_queue (); 588318334Speter delete_temp_files (); 588418334Speter /* Get the same signal again, this time not handled, 588518334Speter so its normal effect occurs. */ 588618334Speter kill (getpid (), signum); 588718334Speter} 588818334Speter 588990277Sobrienextern int main PARAMS ((int, const char *const *)); 589090277Sobrien 589118334Speterint 589218334Spetermain (argc, argv) 589318334Speter int argc; 589490277Sobrien const char *const *argv; 589518334Speter{ 589690277Sobrien size_t i; 589718334Speter int value; 589818334Speter int linker_was_run = 0; 589918334Speter char *explicit_link_files; 590018334Speter char *specs_file; 590152520Sobrien const char *p; 590250599Sobrien struct user_specs *uptr; 590318334Speter 590418334Speter p = argv[0] + strlen (argv[0]); 590552520Sobrien while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) 590652520Sobrien --p; 590718334Speter programname = p; 590818334Speter 590990277Sobrien xmalloc_set_program_name (programname); 591090277Sobrien 591190277Sobrien#ifdef GCC_DRIVER_HOST_INITIALIZATION 591290277Sobrien /* Perform host dependent initialization when needed. */ 591390277Sobrien GCC_DRIVER_HOST_INITIALIZATION; 591452520Sobrien#endif 591552520Sobrien 591690277Sobrien gcc_init_libintl (); 591790277Sobrien 591818334Speter if (signal (SIGINT, SIG_IGN) != SIG_IGN) 591918334Speter signal (SIGINT, fatal_error); 592018334Speter#ifdef SIGHUP 592118334Speter if (signal (SIGHUP, SIG_IGN) != SIG_IGN) 592218334Speter signal (SIGHUP, fatal_error); 592318334Speter#endif 592418334Speter if (signal (SIGTERM, SIG_IGN) != SIG_IGN) 592518334Speter signal (SIGTERM, fatal_error); 592618334Speter#ifdef SIGPIPE 592718334Speter if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) 592818334Speter signal (SIGPIPE, fatal_error); 592918334Speter#endif 593090277Sobrien#ifdef SIGCHLD 593190277Sobrien /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will 593290277Sobrien receive the signal. A different setting is inheritable */ 593390277Sobrien signal (SIGCHLD, SIG_DFL); 593490277Sobrien#endif 593518334Speter 5936117413Skan /* Allocate the argument vector. */ 5937117413Skan alloc_args (); 593818334Speter 593918334Speter obstack_init (&obstack); 594018334Speter 594150599Sobrien /* Build multilib_select, et. al from the separate lines that make up each 594250599Sobrien multilib selection. */ 594350599Sobrien { 594490277Sobrien const char *const *q = multilib_raw; 594550599Sobrien int need_space; 594650599Sobrien 594750599Sobrien obstack_init (&multilib_obstack); 594850599Sobrien while ((p = *q++) != (char *) 0) 594950599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 595050599Sobrien 595150599Sobrien obstack_1grow (&multilib_obstack, 0); 595250599Sobrien multilib_select = obstack_finish (&multilib_obstack); 595350599Sobrien 595450599Sobrien q = multilib_matches_raw; 595550599Sobrien while ((p = *q++) != (char *) 0) 595650599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 595750599Sobrien 595850599Sobrien obstack_1grow (&multilib_obstack, 0); 595950599Sobrien multilib_matches = obstack_finish (&multilib_obstack); 596050599Sobrien 596190277Sobrien q = multilib_exclusions_raw; 596290277Sobrien while ((p = *q++) != (char *) 0) 596390277Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 596490277Sobrien 596590277Sobrien obstack_1grow (&multilib_obstack, 0); 596690277Sobrien multilib_exclusions = obstack_finish (&multilib_obstack); 596790277Sobrien 596850599Sobrien need_space = FALSE; 596990277Sobrien for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++) 597050599Sobrien { 597150599Sobrien if (need_space) 597250599Sobrien obstack_1grow (&multilib_obstack, ' '); 597350599Sobrien obstack_grow (&multilib_obstack, 597450599Sobrien multilib_defaults_raw[i], 597550599Sobrien strlen (multilib_defaults_raw[i])); 597650599Sobrien need_space = TRUE; 597750599Sobrien } 597850599Sobrien 597950599Sobrien obstack_1grow (&multilib_obstack, 0); 598050599Sobrien multilib_defaults = obstack_finish (&multilib_obstack); 598150599Sobrien } 598250599Sobrien 598318334Speter /* Set up to remember the pathname of gcc and any options 598418334Speter needed for collect. We use argv[0] instead of programname because 598518334Speter we need the complete pathname. */ 598618334Speter obstack_init (&collect_obstack); 598790277Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1); 598890277Sobrien obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1); 598918334Speter putenv (obstack_finish (&collect_obstack)); 599018334Speter 599118334Speter#ifdef INIT_ENVIRONMENT 599218334Speter /* Set up any other necessary machine specific environment variables. */ 599318334Speter putenv (INIT_ENVIRONMENT); 599418334Speter#endif 599518334Speter 599618334Speter /* Make a table of what switches there are (switches, n_switches). 599718334Speter Make a table of specified input files (infiles, n_infiles). 599818334Speter Decode switches that are handled locally. */ 599918334Speter 600018334Speter process_command (argc, argv); 600118334Speter 6002117413Skan /* Process DRIVER_SELF_SPECS, adding any new options to the end 6003117413Skan of the command line. */ 6004117413Skan 6005117413Skan for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++) 6006117413Skan do_self_spec (driver_self_specs[i]); 6007117413Skan 600818334Speter /* Initialize the vector of specs to just the default. 600918334Speter This means one element containing 0s, as a terminator. */ 601018334Speter 601118334Speter compilers = (struct compiler *) xmalloc (sizeof default_compilers); 601290277Sobrien memcpy ((char *) compilers, (char *) default_compilers, 601390277Sobrien sizeof default_compilers); 601418334Speter n_compilers = n_default_compilers; 601518334Speter 601618334Speter /* Read specs from a file if there is one. */ 601718334Speter 601891561Sobrien#ifdef FREEBSD_NATIVE 601991561Sobrien just_machine_suffix = ""; 602091561Sobrien#else /* FREEBSD_NATIVE */ 602150599Sobrien machine_suffix = concat (spec_machine, dir_separator_str, 602290277Sobrien spec_version, dir_separator_str, NULL); 602390277Sobrien just_machine_suffix = concat (spec_machine, dir_separator_str, NULL); 602450599Sobrien#endif /* FREEBSD_NATIVE */ 602518334Speter 6026104763Skan specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, 0); 602718334Speter /* Read the specs file unless it is a default one. */ 602818334Speter if (specs_file != 0 && strcmp (specs_file, "specs")) 602950599Sobrien read_specs (specs_file, TRUE); 603050599Sobrien else 603150599Sobrien init_spec (); 603218334Speter 603350599Sobrien /* We need to check standard_exec_prefix/just_machine_suffix/specs 603490277Sobrien for any override of as, ld and libraries. */ 603597902Sobrien specs_file = (char *) alloca (strlen (FBSD_DATA_PREFIX) 603650599Sobrien + strlen (just_machine_suffix) 603750599Sobrien + sizeof ("specs")); 603850599Sobrien 603997902Sobrien strcpy (specs_file, FBSD_DATA_PREFIX); 604050599Sobrien strcat (specs_file, just_machine_suffix); 604150599Sobrien strcat (specs_file, "specs"); 604250599Sobrien if (access (specs_file, R_OK) == 0) 604350599Sobrien read_specs (specs_file, TRUE); 604490277Sobrien 6045117413Skan /* If not cross-compiling, look for startfiles in the standard places. 6046117413Skan Similarly, don't add the standard prefixes if startfile handling 6047117413Skan will be under control of startfile_prefix_spec. */ 6048117413Skan if (*cross_compile == '0' && *startfile_prefix_spec == 0) 604918334Speter { 605090277Sobrien if (*md_exec_prefix) 605190277Sobrien { 605290277Sobrien add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 6053104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 605490277Sobrien add_prefix (&startfile_prefixes, md_exec_prefix, "GCC", 6055104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 0); 605690277Sobrien } 605718334Speter 605890277Sobrien if (*md_startfile_prefix) 605990277Sobrien add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC", 6060104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 606118334Speter 606290277Sobrien if (*md_startfile_prefix_1) 606390277Sobrien add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC", 6064104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 606518334Speter 606618334Speter /* If standard_startfile_prefix is relative, base it on 606718334Speter standard_exec_prefix. This lets us move the installed tree 606818334Speter as a unit. If GCC_EXEC_PREFIX is defined, base 606918334Speter standard_startfile_prefix on that as well. */ 607090277Sobrien if (IS_ABSOLUTE_PATHNAME (standard_startfile_prefix)) 607150599Sobrien add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS", 6072104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 607318334Speter else 607418334Speter { 607518334Speter if (gcc_exec_prefix) 607618334Speter add_prefix (&startfile_prefixes, 607750599Sobrien concat (gcc_exec_prefix, machine_suffix, 607890277Sobrien standard_startfile_prefix, NULL), 6079104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); 608018334Speter add_prefix (&startfile_prefixes, 608150599Sobrien concat (standard_exec_prefix, 608250599Sobrien machine_suffix, 608390277Sobrien standard_startfile_prefix, NULL), 6084104763Skan NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1); 608590277Sobrien } 608618334Speter 608718346Speter#ifndef FREEBSD_NATIVE 608850599Sobrien add_prefix (&startfile_prefixes, standard_startfile_prefix_1, 6089104763Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); 609050599Sobrien add_prefix (&startfile_prefixes, standard_startfile_prefix_2, 6091104763Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); 609291561Sobrien#endif /* not FREEBSD_NATIVE */ 609318334Speter#if 0 /* Can cause surprises, and one can use -B./ instead. */ 609490277Sobrien add_prefix (&startfile_prefixes, "./", NULL, 6095104763Skan PREFIX_PRIORITY_LAST, 1, NULL, 0); 609618334Speter#endif 609718334Speter } 609818334Speter else 609918334Speter { 610090277Sobrien if (!IS_ABSOLUTE_PATHNAME (standard_startfile_prefix) 610190277Sobrien && gcc_exec_prefix) 610218334Speter add_prefix (&startfile_prefixes, 610350599Sobrien concat (gcc_exec_prefix, machine_suffix, 610490277Sobrien standard_startfile_prefix, NULL), 6105104763Skan "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1); 610691651Sobrien#ifdef CROSS_STARTFILE_PREFIX 610791651Sobrien add_prefix (&startfile_prefixes, CROSS_STARTFILE_PREFIX, "BINUTILS", 6108104763Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 610991651Sobrien#endif 611018334Speter } 611118334Speter 6112117413Skan if (*startfile_prefix_spec != 0 6113117413Skan && do_spec_2 (startfile_prefix_spec) == 0 6114117413Skan && do_spec_1 (" ", 0, NULL) == 0) 6115117413Skan { 6116117413Skan int ndx; 6117117413Skan for (ndx = 0; ndx < argbuf_index; ndx++) 6118117413Skan add_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS", 6119117413Skan PREFIX_PRIORITY_LAST, 0, NULL, 1); 6120117413Skan } 6121117413Skan 612252520Sobrien /* Process any user specified specs in the order given on the command 612352520Sobrien line. */ 612452520Sobrien for (uptr = user_specs_head; uptr; uptr = uptr->next) 612552520Sobrien { 6126104763Skan char *filename = find_a_file (&startfile_prefixes, uptr->filename, 6127104763Skan R_OK, 0); 612852520Sobrien read_specs (filename ? filename : uptr->filename, FALSE); 612952520Sobrien } 613052520Sobrien 613118334Speter /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */ 613218334Speter if (gcc_exec_prefix) 613390277Sobrien gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 613490277Sobrien spec_version, dir_separator_str, NULL); 613518334Speter 613618334Speter /* Now we have the specs. 613718334Speter Set the `valid' bits for switches that match anything in any spec. */ 613818334Speter 613918334Speter validate_all_switches (); 614018334Speter 614118334Speter /* Now that we have the switches and the specs, set 614218334Speter the subdirectory based on the options. */ 614318334Speter set_multilib_dir (); 614418334Speter 614518334Speter /* Warn about any switches that no pass was interested in. */ 614618334Speter 614790277Sobrien for (i = 0; (int) i < n_switches; i++) 614852520Sobrien if (! switches[i].validated) 614918334Speter error ("unrecognized option `-%s'", switches[i].part1); 615018334Speter 615118334Speter /* Obey some of the options. */ 615218334Speter 615318334Speter if (print_search_dirs) 615418334Speter { 615590277Sobrien printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix); 615690277Sobrien printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0)); 615790277Sobrien printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0)); 615890277Sobrien return (0); 615918334Speter } 616018334Speter 616118334Speter if (print_file_name) 616218334Speter { 616318334Speter printf ("%s\n", find_file (print_file_name)); 616490277Sobrien return (0); 616518334Speter } 616618334Speter 616718334Speter if (print_prog_name) 616818334Speter { 6169104763Skan char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0); 617018334Speter printf ("%s\n", (newname ? newname : print_prog_name)); 617190277Sobrien return (0); 617218334Speter } 617318334Speter 617418334Speter if (print_multi_lib) 617518334Speter { 617618334Speter print_multilib_info (); 617790277Sobrien return (0); 617818334Speter } 617918334Speter 618018334Speter if (print_multi_directory) 618118334Speter { 618218334Speter if (multilib_dir == NULL) 618318334Speter printf (".\n"); 618418334Speter else 618518334Speter printf ("%s\n", multilib_dir); 618690277Sobrien return (0); 618718334Speter } 618818334Speter 6189104763Skan if (print_multi_os_directory) 6190104763Skan { 6191104763Skan if (multilib_os_dir == NULL) 6192104763Skan printf (".\n"); 6193104763Skan else 6194104763Skan printf ("%s\n", multilib_os_dir); 6195104763Skan return (0); 6196104763Skan } 6197104763Skan 619890277Sobrien if (target_help_flag) 619990277Sobrien { 620090277Sobrien /* Print if any target specific options. */ 620190277Sobrien 620290277Sobrien /* We do not exit here. Instead we have created a fake input file 620390277Sobrien called 'target-dummy' which needs to be compiled, and we pass this 620490277Sobrien on to the various sub-processes, along with the --target-help 620590277Sobrien switch. */ 620690277Sobrien } 620790277Sobrien 620850599Sobrien if (print_help_list) 620950599Sobrien { 621050599Sobrien display_help (); 621150599Sobrien 621250599Sobrien if (! verbose_flag) 621350599Sobrien { 621490277Sobrien printf (_("\nFor bug reporting instructions, please see:\n")); 6215117413Skan printf ("%s.\n", bug_report_url); 621690277Sobrien 621790277Sobrien return (0); 621850599Sobrien } 621950599Sobrien 622050599Sobrien /* We do not exit here. Instead we have created a fake input file 622150599Sobrien called 'help-dummy' which needs to be compiled, and we pass this 622290277Sobrien on the various sub-processes, along with the --help switch. */ 622350599Sobrien } 622490277Sobrien 622518334Speter if (verbose_flag) 622618334Speter { 622750599Sobrien int n; 622890277Sobrien const char *thrmod; 622950599Sobrien 623090277Sobrien notice ("Configured with: %s\n", configuration_arguments); 623190277Sobrien 623290277Sobrien#ifdef THREAD_MODEL_SPEC 623390277Sobrien /* We could have defined THREAD_MODEL_SPEC to "%*" by default, 623490277Sobrien but there's no point in doing all this processing just to get 623590277Sobrien thread_model back. */ 623690277Sobrien obstack_init (&obstack); 623790277Sobrien do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); 623890277Sobrien obstack_1grow (&obstack, '\0'); 623990277Sobrien thrmod = obstack_finish (&obstack); 624090277Sobrien#else 624190277Sobrien thrmod = thread_model; 624290277Sobrien#endif 624390277Sobrien 624490277Sobrien notice ("Thread model: %s\n", thrmod); 624590277Sobrien 624650599Sobrien /* compiler_version is truncated at the first space when initialized 624750599Sobrien from version string, so truncate version_string at the first space 624850599Sobrien before comparing. */ 624950599Sobrien for (n = 0; version_string[n]; n++) 625050599Sobrien if (version_string[n] == ' ') 625150599Sobrien break; 625250599Sobrien 625350599Sobrien if (! strncmp (version_string, compiler_version, n) 625450599Sobrien && compiler_version[n] == 0) 625552520Sobrien notice ("gcc version %s\n", version_string); 625618334Speter else 625752520Sobrien notice ("gcc driver version %s executing gcc version %s\n", 625852520Sobrien version_string, compiler_version); 625918334Speter 626018334Speter if (n_infiles == 0) 626190277Sobrien return (0); 626218334Speter } 626318334Speter 626450599Sobrien if (n_infiles == added_libraries) 626518346Speter fatal ("No input files specified"); 626618334Speter 626718334Speter /* Make a place to record the compiler output file names 626818334Speter that correspond to the input files. */ 626918334Speter 627050599Sobrien i = n_infiles; 627150599Sobrien i += lang_specific_extra_outfiles; 627290277Sobrien outfiles = (const char **) xcalloc (i, sizeof (char *)); 627318334Speter 627418334Speter /* Record which files were specified explicitly as link input. */ 627518334Speter 627690277Sobrien explicit_link_files = xcalloc (1, n_infiles); 627718334Speter 627890277Sobrien for (i = 0; (int) i < n_infiles; i++) 627918334Speter { 628018334Speter int this_file_error = 0; 628118334Speter 628218334Speter /* Tell do_spec what to substitute for %i. */ 628318334Speter 628418334Speter input_file_number = i; 628590277Sobrien set_input (infiles[i].name); 628618334Speter 628718334Speter /* Use the same thing in %o, unless cp->spec says otherwise. */ 628818334Speter 628918334Speter outfiles[i] = input_filename; 629018334Speter 629118334Speter /* Figure out which compiler from the file's suffix. */ 629218334Speter 629390277Sobrien input_file_compiler 629490277Sobrien = lookup_compiler (infiles[i].name, input_filename_length, 629590277Sobrien infiles[i].language); 6296117413Skan 629790277Sobrien if (input_file_compiler) 629818334Speter { 629918334Speter /* Ok, we found an applicable compiler. Run its spec. */ 630018334Speter 630190277Sobrien if (input_file_compiler->spec[0] == '#') 630218334Speter { 630390277Sobrien error ("%s: %s compiler not installed on this system", 630490277Sobrien input_filename, &input_file_compiler->spec[1]); 630590277Sobrien this_file_error = 1; 630618334Speter } 630718334Speter else 630890277Sobrien { 630990277Sobrien value = do_spec (input_file_compiler->spec); 631090277Sobrien if (value < 0) 631190277Sobrien this_file_error = 1; 631290277Sobrien } 631318334Speter } 631418334Speter 631518334Speter /* If this file's name does not contain a recognized suffix, 631618334Speter record it as explicit linker input. */ 631718334Speter 631818334Speter else 631918334Speter explicit_link_files[i] = 1; 632018334Speter 632118334Speter /* Clear the delete-on-failure queue, deleting the files in it 632218334Speter if this compilation failed. */ 632318334Speter 632418334Speter if (this_file_error) 632518334Speter { 632618334Speter delete_failure_queue (); 632718334Speter error_count++; 632818334Speter } 632918334Speter /* If this compilation succeeded, don't delete those files later. */ 633018334Speter clear_failure_queue (); 633118334Speter } 633218334Speter 633390277Sobrien /* Reset the output file name to the first input file name, for use 633490277Sobrien with %b in LINK_SPEC on a target that prefers not to emit a.out 633590277Sobrien by default. */ 633690277Sobrien if (n_infiles > 0) 633790277Sobrien set_input (infiles[0].name); 633890277Sobrien 633952520Sobrien if (error_count == 0) 634052520Sobrien { 634152520Sobrien /* Make sure INPUT_FILE_NUMBER points to first available open 634252520Sobrien slot. */ 634352520Sobrien input_file_number = n_infiles; 634452520Sobrien if (lang_specific_pre_link ()) 634552520Sobrien error_count++; 634652520Sobrien } 634750599Sobrien 634818334Speter /* Run ld to link all the compiler output files. */ 634918334Speter 635018334Speter if (error_count == 0) 635118334Speter { 635218334Speter int tmp = execution_count; 635318334Speter 635490277Sobrien /* We'll use ld if we can't find collect2. */ 635550599Sobrien if (! strcmp (linker_name_spec, "collect2")) 635650599Sobrien { 6357104763Skan char *s = find_a_file (&exec_prefixes, "collect2", X_OK, 0); 635850599Sobrien if (s == NULL) 635950599Sobrien linker_name_spec = "ld"; 636050599Sobrien } 636118334Speter /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 636218334Speter for collect. */ 636390277Sobrien putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH"); 636490277Sobrien putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV); 636518334Speter 636618334Speter value = do_spec (link_command_spec); 636718334Speter if (value < 0) 636818334Speter error_count = 1; 636918334Speter linker_was_run = (tmp != execution_count); 637018334Speter } 637118334Speter 637218334Speter /* If options said don't run linker, 637318334Speter complain about input files to be given to the linker. */ 637418334Speter 637518334Speter if (! linker_was_run && error_count == 0) 637690277Sobrien for (i = 0; (int) i < n_infiles; i++) 637718334Speter if (explicit_link_files[i]) 637890277Sobrien error ("%s: linker input file unused because linking not done", 637918334Speter outfiles[i]); 638018334Speter 638118334Speter /* Delete some or all of the temporary files we made. */ 638218334Speter 638318334Speter if (error_count) 638418334Speter delete_failure_queue (); 638518334Speter delete_temp_files (); 638618334Speter 638750599Sobrien if (print_help_list) 638850599Sobrien { 638990277Sobrien printf (("\nFor bug reporting instructions, please see:\n")); 6390117413Skan printf ("%s\n", bug_report_url); 639150599Sobrien } 639290277Sobrien 639390277Sobrien return (signal_count != 0 ? 2 639490277Sobrien : error_count > 0 ? (pass_exit_codes ? greatest_status : 1) 639590277Sobrien : 0); 639618334Speter} 639718334Speter 639818334Speter/* Find the proper compilation spec for the file name NAME, 639918334Speter whose length is LENGTH. LANGUAGE is the specified language, 640050599Sobrien or 0 if this file is to be passed to the linker. */ 640118334Speter 640218334Speterstatic struct compiler * 640318334Speterlookup_compiler (name, length, language) 640452520Sobrien const char *name; 640550599Sobrien size_t length; 640652520Sobrien const char *language; 640718334Speter{ 640818334Speter struct compiler *cp; 640918334Speter 641090277Sobrien /* If this was specified by the user to be a linker input, indicate that. */ 641150599Sobrien if (language != 0 && language[0] == '*') 641250599Sobrien return 0; 641350599Sobrien 641450599Sobrien /* Otherwise, look for the language, if one is spec'd. */ 641518334Speter if (language != 0) 641618334Speter { 641718334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 641850599Sobrien if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language)) 641950599Sobrien return cp; 642050599Sobrien 642118334Speter error ("language %s not recognized", language); 642250599Sobrien return 0; 642318334Speter } 642418334Speter 642518334Speter /* Look for a suffix. */ 642618334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 642718334Speter { 642818334Speter if (/* The suffix `-' matches only the file name `-'. */ 642918334Speter (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 643050599Sobrien || (strlen (cp->suffix) < length 643150599Sobrien /* See if the suffix matches the end of NAME. */ 643250599Sobrien && !strcmp (cp->suffix, 643350599Sobrien name + length - strlen (cp->suffix)) 643450599Sobrien )) 6435117413Skan break; 643690277Sobrien } 643750599Sobrien 643890277Sobrien#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM) 643990277Sobrien /* look again, but case-insensitively this time. */ 644090277Sobrien if (cp < compilers) 644190277Sobrien for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 644290277Sobrien { 644390277Sobrien if (/* The suffix `-' matches only the file name `-'. */ 644490277Sobrien (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 644590277Sobrien || (strlen (cp->suffix) < length 644690277Sobrien /* See if the suffix matches the end of NAME. */ 644790277Sobrien && ((!strcmp (cp->suffix, 644890277Sobrien name + length - strlen (cp->suffix)) 644990277Sobrien || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) 645090277Sobrien && !strcasecmp (cp->suffix, 645190277Sobrien name + length - strlen (cp->suffix))) 645290277Sobrien )) 645390277Sobrien break; 645490277Sobrien } 645590277Sobrien#endif 645650599Sobrien 645790277Sobrien if (cp >= compilers) 645890277Sobrien { 645990277Sobrien if (cp->spec[0] != '@') 646090277Sobrien /* A non-alias entry: return it. */ 646190277Sobrien return cp; 646290277Sobrien 646390277Sobrien /* An alias entry maps a suffix to a language. 646490277Sobrien Search for the language; pass 0 for NAME and LENGTH 646590277Sobrien to avoid infinite recursion if language not found. */ 646690277Sobrien return lookup_compiler (NULL, 0, cp->spec + 1); 646718334Speter } 646818334Speter return 0; 646918334Speter} 647018334Speter 647118334Speterstatic char * 647218334Spetersave_string (s, len) 647390277Sobrien const char *s; 647490277Sobrien int len; 647518334Speter{ 647690277Sobrien char *result = xmalloc (len + 1); 647718334Speter 647890277Sobrien memcpy (result, s, len); 647918334Speter result[len] = 0; 648018334Speter return result; 648118334Speter} 648218334Speter 648390277Sobrienvoid 648418334Speterpfatal_with_name (name) 648552520Sobrien const char *name; 648618334Speter{ 648752520Sobrien perror_with_name (name); 648852520Sobrien delete_temp_files (); 648952520Sobrien exit (1); 649018334Speter} 649118334Speter 649218334Speterstatic void 649318334Speterperror_with_name (name) 649452520Sobrien const char *name; 649518334Speter{ 649652520Sobrien error ("%s: %s", name, xstrerror (errno)); 649718334Speter} 649818334Speter 649918334Speterstatic void 650050599Sobrienpfatal_pexecute (errmsg_fmt, errmsg_arg) 650152520Sobrien const char *errmsg_fmt; 650252520Sobrien const char *errmsg_arg; 650318334Speter{ 650450599Sobrien if (errmsg_arg) 650550599Sobrien { 650652520Sobrien int save_errno = errno; 650752520Sobrien 650850599Sobrien /* Space for trailing '\0' is in %s. */ 650950599Sobrien char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg)); 651050599Sobrien sprintf (msg, errmsg_fmt, errmsg_arg); 651150599Sobrien errmsg_fmt = msg; 651252520Sobrien 651352520Sobrien errno = save_errno; 651450599Sobrien } 651550599Sobrien 651652520Sobrien pfatal_with_name (errmsg_fmt); 651718334Speter} 651818334Speter 651990277Sobrien/* Output an error message and exit */ 652018334Speter 652118334Spetervoid 652218334Speterfancy_abort () 652318334Speter{ 652490277Sobrien fatal ("internal gcc abort"); 652518334Speter} 652618334Speter 652718334Speter/* Output an error message and exit */ 652818334Speter 652952520Sobrienvoid 653090277Sobrienfatal VPARAMS ((const char *msgid, ...)) 653118334Speter{ 653290277Sobrien VA_OPEN (ap, msgid); 653390277Sobrien VA_FIXEDARG (ap, const char *, msgid); 653418334Speter 653518334Speter fprintf (stderr, "%s: ", programname); 653652520Sobrien vfprintf (stderr, _(msgid), ap); 653790277Sobrien VA_CLOSE (ap); 653818334Speter fprintf (stderr, "\n"); 653918334Speter delete_temp_files (); 654018334Speter exit (1); 654118334Speter} 654218334Speter 654390277Sobrienvoid 654490277Sobrienerror VPARAMS ((const char *msgid, ...)) 654518334Speter{ 654690277Sobrien VA_OPEN (ap, msgid); 654790277Sobrien VA_FIXEDARG (ap, const char *, msgid); 654818334Speter 654918334Speter fprintf (stderr, "%s: ", programname); 655052520Sobrien vfprintf (stderr, _(msgid), ap); 655190277Sobrien VA_CLOSE (ap); 655218334Speter 655318334Speter fprintf (stderr, "\n"); 655418334Speter} 655552520Sobrien 655652520Sobrienstatic void 655790277Sobriennotice VPARAMS ((const char *msgid, ...)) 655852520Sobrien{ 655990277Sobrien VA_OPEN (ap, msgid); 656090277Sobrien VA_FIXEDARG (ap, const char *, msgid); 656152520Sobrien 656252520Sobrien vfprintf (stderr, _(msgid), ap); 656390277Sobrien VA_CLOSE (ap); 656452520Sobrien} 656518334Speter 656618334Speterstatic void 656718334Spetervalidate_all_switches () 656818334Speter{ 656918334Speter struct compiler *comp; 657090277Sobrien const char *p; 657190277Sobrien char c; 657218334Speter struct spec_list *spec; 657318334Speter 657490277Sobrien for (comp = compilers; comp->spec; comp++) 657518334Speter { 657690277Sobrien p = comp->spec; 657790277Sobrien while ((c = *p++)) 657896285Sobrien if (c == '%' && (*p == '{' || (*p == 'W' && *++p == '{'))) 657990277Sobrien /* We have a switch spec. */ 658090277Sobrien validate_switches (p + 1); 658118334Speter } 658218334Speter 658390277Sobrien /* Look through the linked list of specs read from the specs file. */ 658490277Sobrien for (spec = specs; spec; spec = spec->next) 658518334Speter { 658650599Sobrien p = *(spec->ptr_spec); 658750599Sobrien while ((c = *p++)) 658896285Sobrien if (c == '%' && (*p == '{' || (*p == 'W' && *++p == '{'))) 658918334Speter /* We have a switch spec. */ 659018334Speter validate_switches (p + 1); 659118334Speter } 659218334Speter 659318334Speter p = link_command_spec; 659450599Sobrien while ((c = *p++)) 659596285Sobrien if (c == '%' && (*p == '{' || (*p == 'W' && *++p == '{'))) 659618334Speter /* We have a switch spec. */ 659718334Speter validate_switches (p + 1); 659818334Speter} 659918334Speter 660018334Speter/* Look at the switch-name that comes after START 660118334Speter and mark as valid all supplied switches that match it. */ 660218334Speter 660318334Speterstatic void 660418334Spetervalidate_switches (start) 660552520Sobrien const char *start; 660618334Speter{ 660790277Sobrien const char *p = start; 660852520Sobrien const char *filter; 660990277Sobrien int i; 661090277Sobrien int suffix; 661118334Speter 661218334Speter if (*p == '|') 661318334Speter ++p; 661418334Speter 661590277Sobriennext_member: 661618334Speter if (*p == '!') 661718334Speter ++p; 661818334Speter 661990277Sobrien suffix = 0; 662018334Speter if (*p == '.') 662118334Speter suffix = 1, ++p; 662218334Speter 662318334Speter filter = p; 662490277Sobrien while (*p != ':' && *p != '}' && *p != '|' && *p != '&') 662590277Sobrien p++; 662618334Speter 662718334Speter if (suffix) 662818334Speter ; 662918334Speter else if (p[-1] == '*') 663018334Speter { 663118334Speter /* Mark all matching switches as valid. */ 663218334Speter for (i = 0; i < n_switches; i++) 663390277Sobrien if (!strncmp (switches[i].part1, filter, p - filter - 1)) 663452520Sobrien switches[i].validated = 1; 663518334Speter } 663618334Speter else 663718334Speter { 663818334Speter /* Mark an exact matching switch as valid. */ 663918334Speter for (i = 0; i < n_switches; i++) 664018334Speter { 664118334Speter if (!strncmp (switches[i].part1, filter, p - filter) 664218334Speter && switches[i].part1[p - filter] == 0) 664352520Sobrien switches[i].validated = 1; 664418334Speter } 664518334Speter } 664690277Sobrien 664790277Sobrien if (*p++ == '|' || p[-1] == '&') 664890277Sobrien goto next_member; 664918334Speter} 665018334Speter 6651104763Skanstruct mdswitchstr 6652104763Skan{ 6653104763Skan const char *str; 6654104763Skan int len; 6655104763Skan}; 6656104763Skan 6657104763Skanstatic struct mdswitchstr *mdswitches; 6658104763Skanstatic int n_mdswitches; 6659104763Skan 666050599Sobrien/* Check whether a particular argument was used. The first time we 666150599Sobrien canonicalize the switches to keep only the ones we care about. */ 666218334Speter 666318334Speterstatic int 666418334Speterused_arg (p, len) 666552520Sobrien const char *p; 666618334Speter int len; 666718334Speter{ 666890277Sobrien struct mswitchstr 666990277Sobrien { 667090277Sobrien const char *str; 667190277Sobrien const char *replace; 667250599Sobrien int len; 667350599Sobrien int rep_len; 667450599Sobrien }; 667518334Speter 667650599Sobrien static struct mswitchstr *mswitches; 667750599Sobrien static int n_mswitches; 667850599Sobrien int i, j; 667950599Sobrien 668050599Sobrien if (!mswitches) 668150599Sobrien { 668250599Sobrien struct mswitchstr *matches; 668390277Sobrien const char *q; 668450599Sobrien int cnt = 0; 668550599Sobrien 668690277Sobrien /* Break multilib_matches into the component strings of string 668790277Sobrien and replacement string. */ 668850599Sobrien for (q = multilib_matches; *q != '\0'; q++) 668950599Sobrien if (*q == ';') 669050599Sobrien cnt++; 669150599Sobrien 669290277Sobrien matches = 669390277Sobrien (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt); 669450599Sobrien i = 0; 669550599Sobrien q = multilib_matches; 669650599Sobrien while (*q != '\0') 669750599Sobrien { 669850599Sobrien matches[i].str = q; 669950599Sobrien while (*q != ' ') 670050599Sobrien { 670150599Sobrien if (*q == '\0') 670250599Sobrien abort (); 670350599Sobrien q++; 670450599Sobrien } 670550599Sobrien matches[i].len = q - matches[i].str; 670650599Sobrien 670750599Sobrien matches[i].replace = ++q; 670850599Sobrien while (*q != ';' && *q != '\0') 670950599Sobrien { 671050599Sobrien if (*q == ' ') 671150599Sobrien abort (); 671250599Sobrien q++; 671350599Sobrien } 671450599Sobrien matches[i].rep_len = q - matches[i].replace; 671550599Sobrien i++; 671650599Sobrien if (*q == ';') 671790277Sobrien q++; 671850599Sobrien } 671950599Sobrien 672050599Sobrien /* Now build a list of the replacement string for switches that we care 672150599Sobrien about. Make sure we allocate at least one entry. This prevents 672250599Sobrien xmalloc from calling fatal, and prevents us from re-executing this 672350599Sobrien block of code. */ 672450599Sobrien mswitches 6725104763Skan = (struct mswitchstr *) 6726104763Skan xmalloc (sizeof (struct mswitchstr) 6727104763Skan * (n_mdswitches + (n_switches ? n_switches : 1))); 672850599Sobrien for (i = 0; i < n_switches; i++) 672950599Sobrien { 673050599Sobrien int xlen = strlen (switches[i].part1); 673150599Sobrien for (j = 0; j < cnt; j++) 673290277Sobrien if (xlen == matches[j].len 673390277Sobrien && ! strncmp (switches[i].part1, matches[j].str, xlen)) 673450599Sobrien { 673550599Sobrien mswitches[n_mswitches].str = matches[j].replace; 673650599Sobrien mswitches[n_mswitches].len = matches[j].rep_len; 673790277Sobrien mswitches[n_mswitches].replace = (char *) 0; 673850599Sobrien mswitches[n_mswitches].rep_len = 0; 673950599Sobrien n_mswitches++; 674050599Sobrien break; 674150599Sobrien } 674250599Sobrien } 6743104763Skan 6744104763Skan /* Add MULTILIB_DEFAULTS switches too, as long as they were not present 6745104763Skan on the command line nor any options mutually incompatible with 6746104763Skan them. */ 6747104763Skan for (i = 0; i < n_mdswitches; i++) 6748104763Skan { 6749104763Skan const char *r; 6750104763Skan 6751104763Skan for (q = multilib_options; *q != '\0'; q++) 6752104763Skan { 6753104763Skan while (*q == ' ') 6754104763Skan q++; 6755104763Skan 6756104763Skan r = q; 6757104763Skan while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0 6758104763Skan || strchr (" /", q[mdswitches[i].len]) == NULL) 6759104763Skan { 6760104763Skan while (*q != ' ' && *q != '/' && *q != '\0') 6761104763Skan q++; 6762104763Skan if (*q != '/') 6763104763Skan break; 6764104763Skan q++; 6765104763Skan } 6766104763Skan 6767104763Skan if (*q != ' ' && *q != '\0') 6768104763Skan { 6769104763Skan while (*r != ' ' && *r != '\0') 6770104763Skan { 6771104763Skan q = r; 6772104763Skan while (*q != ' ' && *q != '/' && *q != '\0') 6773104763Skan q++; 6774104763Skan 6775104763Skan if (used_arg (r, q - r)) 6776104763Skan break; 6777104763Skan 6778104763Skan if (*q != '/') 6779104763Skan { 6780104763Skan mswitches[n_mswitches].str = mdswitches[i].str; 6781104763Skan mswitches[n_mswitches].len = mdswitches[i].len; 6782104763Skan mswitches[n_mswitches].replace = (char *) 0; 6783104763Skan mswitches[n_mswitches].rep_len = 0; 6784104763Skan n_mswitches++; 6785104763Skan break; 6786104763Skan } 6787104763Skan 6788104763Skan r = q + 1; 6789104763Skan } 6790104763Skan break; 6791104763Skan } 6792104763Skan } 6793104763Skan } 679450599Sobrien } 679550599Sobrien 679650599Sobrien for (i = 0; i < n_mswitches; i++) 679750599Sobrien if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len)) 679818334Speter return 1; 679950599Sobrien 680018334Speter return 0; 680118334Speter} 680218334Speter 680318334Speterstatic int 680418334Speterdefault_arg (p, len) 680552520Sobrien const char *p; 680618334Speter int len; 680718334Speter{ 6808104763Skan int i; 680918334Speter 6810104763Skan for (i = 0; i < n_mdswitches; i++) 6811104763Skan if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len)) 6812104763Skan return 1; 681318334Speter 681418334Speter return 0; 681518334Speter} 681618334Speter 681790277Sobrien/* Work out the subdirectory to use based on the options. The format of 681890277Sobrien multilib_select is a list of elements. Each element is a subdirectory 681990277Sobrien name followed by a list of options followed by a semicolon. The format 682090277Sobrien of multilib_exclusions is the same, but without the preceding 682190277Sobrien directory. First gcc will check the exclusions, if none of the options 682290277Sobrien beginning with an exclamation point are present, and all of the other 682390277Sobrien options are present, then we will ignore this completely. Passing 682490277Sobrien that, gcc will consider each multilib_select in turn using the same 682590277Sobrien rules for matching the options. If a match is found, that subdirectory 682690277Sobrien will be used. */ 682718334Speter 682818334Speterstatic void 682918334Speterset_multilib_dir () 683018334Speter{ 683190277Sobrien const char *p; 683290277Sobrien unsigned int this_path_len; 683390277Sobrien const char *this_path, *this_arg; 6834104763Skan const char *start, *end; 683518334Speter int not_arg; 6836104763Skan int ok, ndfltok, first; 683718334Speter 6838104763Skan n_mdswitches = 0; 6839104763Skan start = multilib_defaults; 6840104763Skan while (*start == ' ' || *start == '\t') 6841104763Skan start++; 6842104763Skan while (*start != '\0') 6843104763Skan { 6844104763Skan n_mdswitches++; 6845104763Skan while (*start != ' ' && *start != '\t' && *start != '\0') 6846104763Skan start++; 6847104763Skan while (*start == ' ' || *start == '\t') 6848104763Skan start++; 6849104763Skan } 6850104763Skan 6851104763Skan if (n_mdswitches) 6852104763Skan { 6853104763Skan int i = 0; 6854104763Skan 6855104763Skan mdswitches 6856104763Skan = (struct mdswitchstr *) xmalloc (sizeof (struct mdswitchstr) 6857104763Skan * n_mdswitches); 6858104763Skan for (start = multilib_defaults; *start != '\0'; start = end + 1) 6859104763Skan { 6860104763Skan while (*start == ' ' || *start == '\t') 6861104763Skan start++; 6862104763Skan 6863104763Skan if (*start == '\0') 6864104763Skan break; 6865104763Skan 6866104763Skan for (end = start + 1; 6867104763Skan *end != ' ' && *end != '\t' && *end != '\0'; end++) 6868104763Skan ; 6869104763Skan 6870104763Skan obstack_grow (&multilib_obstack, start, end - start); 6871104763Skan obstack_1grow (&multilib_obstack, 0); 6872104763Skan mdswitches[i].str = obstack_finish (&multilib_obstack); 6873104763Skan mdswitches[i++].len = end - start; 6874104763Skan 6875104763Skan if (*end == '\0') 6876104763Skan break; 6877104763Skan } 6878104763Skan } 6879104763Skan 688090277Sobrien p = multilib_exclusions; 688118334Speter while (*p != '\0') 688218334Speter { 688318334Speter /* Ignore newlines. */ 688418334Speter if (*p == '\n') 688518334Speter { 688618334Speter ++p; 688718334Speter continue; 688818334Speter } 688918334Speter 689090277Sobrien /* Check the arguments. */ 689190277Sobrien ok = 1; 689290277Sobrien while (*p != ';') 689390277Sobrien { 689490277Sobrien if (*p == '\0') 689590277Sobrien abort (); 689690277Sobrien 689790277Sobrien if (! ok) 689890277Sobrien { 689990277Sobrien ++p; 690090277Sobrien continue; 690190277Sobrien } 690290277Sobrien 690390277Sobrien this_arg = p; 690490277Sobrien while (*p != ' ' && *p != ';') 690590277Sobrien { 690690277Sobrien if (*p == '\0') 690790277Sobrien abort (); 690890277Sobrien ++p; 690990277Sobrien } 691090277Sobrien 691190277Sobrien if (*this_arg != '!') 691290277Sobrien not_arg = 0; 691390277Sobrien else 691490277Sobrien { 691590277Sobrien not_arg = 1; 691690277Sobrien ++this_arg; 691790277Sobrien } 691890277Sobrien 691990277Sobrien ok = used_arg (this_arg, p - this_arg); 692090277Sobrien if (not_arg) 692190277Sobrien ok = ! ok; 692290277Sobrien 692390277Sobrien if (*p == ' ') 692490277Sobrien ++p; 692590277Sobrien } 692690277Sobrien 692790277Sobrien if (ok) 692890277Sobrien return; 692990277Sobrien 693090277Sobrien ++p; 693190277Sobrien } 693290277Sobrien 6933104763Skan first = 1; 693490277Sobrien p = multilib_select; 693590277Sobrien while (*p != '\0') 693690277Sobrien { 693790277Sobrien /* Ignore newlines. */ 693890277Sobrien if (*p == '\n') 693990277Sobrien { 694090277Sobrien ++p; 694190277Sobrien continue; 694290277Sobrien } 694390277Sobrien 694418334Speter /* Get the initial path. */ 694518334Speter this_path = p; 694618334Speter while (*p != ' ') 694718334Speter { 694818334Speter if (*p == '\0') 694918334Speter abort (); 695018334Speter ++p; 695118334Speter } 695218334Speter this_path_len = p - this_path; 695318334Speter 695418334Speter /* Check the arguments. */ 695518334Speter ok = 1; 6956104763Skan ndfltok = 1; 695718334Speter ++p; 695818334Speter while (*p != ';') 695918334Speter { 696018334Speter if (*p == '\0') 696118334Speter abort (); 696218334Speter 696318334Speter if (! ok) 696418334Speter { 696518334Speter ++p; 696618334Speter continue; 696718334Speter } 696818334Speter 696918334Speter this_arg = p; 697018334Speter while (*p != ' ' && *p != ';') 697118334Speter { 697218334Speter if (*p == '\0') 697318334Speter abort (); 697418334Speter ++p; 697518334Speter } 697618334Speter 697718334Speter if (*this_arg != '!') 697818334Speter not_arg = 0; 697918334Speter else 698018334Speter { 698118334Speter not_arg = 1; 698218334Speter ++this_arg; 698318334Speter } 698418334Speter 698518334Speter /* If this is a default argument, we can just ignore it. 698618334Speter This is true even if this_arg begins with '!'. Beginning 698718334Speter with '!' does not mean that this argument is necessarily 698818334Speter inappropriate for this library: it merely means that 698918334Speter there is a more specific library which uses this 699018334Speter argument. If this argument is a default, we need not 699118334Speter consider that more specific library. */ 6992104763Skan ok = used_arg (this_arg, p - this_arg); 6993104763Skan if (not_arg) 6994104763Skan ok = ! ok; 699518334Speter 6996104763Skan if (! ok) 6997104763Skan ndfltok = 0; 6998104763Skan 6999104763Skan if (default_arg (this_arg, p - this_arg)) 7000104763Skan ok = 1; 7001104763Skan 700218334Speter if (*p == ' ') 700318334Speter ++p; 700418334Speter } 700518334Speter 7006104763Skan if (ok && first) 700718334Speter { 700818334Speter if (this_path_len != 1 700918334Speter || this_path[0] != '.') 701018334Speter { 701190277Sobrien char *new_multilib_dir = xmalloc (this_path_len + 1); 7012104763Skan char *q; 7013104763Skan 701452520Sobrien strncpy (new_multilib_dir, this_path, this_path_len); 701552520Sobrien new_multilib_dir[this_path_len] = '\0'; 7016104763Skan q = strchr (new_multilib_dir, ':'); 7017104763Skan if (q != NULL) 7018104763Skan *q = '\0'; 701952520Sobrien multilib_dir = new_multilib_dir; 702018334Speter } 7021104763Skan first = 0; 702218334Speter } 702318334Speter 7024104763Skan if (ndfltok) 7025104763Skan { 7026104763Skan const char *q = this_path, *end = this_path + this_path_len; 7027104763Skan 7028104763Skan while (q < end && *q != ':') 7029104763Skan q++; 7030104763Skan if (q < end) 7031104763Skan { 7032104763Skan char *new_multilib_os_dir = xmalloc (end - q); 7033104763Skan memcpy (new_multilib_os_dir, q + 1, end - q - 1); 7034104763Skan new_multilib_os_dir[end - q - 1] = '\0'; 7035104763Skan multilib_os_dir = new_multilib_os_dir; 7036104763Skan break; 7037104763Skan } 7038104763Skan } 7039104763Skan 704018334Speter ++p; 704190277Sobrien } 7042104763Skan 7043104763Skan if (multilib_dir == NULL && multilib_os_dir != NULL 7044104763Skan && strcmp (multilib_os_dir, ".") == 0) 7045104763Skan { 7046104763Skan free ((char *) multilib_os_dir); 7047104763Skan multilib_os_dir = NULL; 7048104763Skan } 7049104763Skan else if (multilib_dir != NULL && multilib_os_dir == NULL) 7050104763Skan multilib_os_dir = multilib_dir; 705118334Speter} 705218334Speter 705318334Speter/* Print out the multiple library subdirectory selection 705418334Speter information. This prints out a series of lines. Each line looks 705518334Speter like SUBDIRECTORY;@OPTION@OPTION, with as many options as is 705618334Speter required. Only the desired options are printed out, the negative 705718334Speter matches. The options are print without a leading dash. There are 705818334Speter no spaces to make it easy to use the information in the shell. 705918334Speter Each subdirectory is printed only once. This assumes the ordering 706090277Sobrien generated by the genmultilib script. Also, we leave out ones that match 706190277Sobrien the exclusions. */ 706218334Speter 706318334Speterstatic void 706418334Speterprint_multilib_info () 706518334Speter{ 706690277Sobrien const char *p = multilib_select; 706790277Sobrien const char *last_path = 0, *this_path; 706818334Speter int skip; 706990277Sobrien unsigned int last_path_len = 0; 707018334Speter 707118334Speter while (*p != '\0') 707218334Speter { 707390277Sobrien skip = 0; 707418334Speter /* Ignore newlines. */ 707518334Speter if (*p == '\n') 707618334Speter { 707718334Speter ++p; 707818334Speter continue; 707918334Speter } 708018334Speter 708118334Speter /* Get the initial path. */ 708218334Speter this_path = p; 708318334Speter while (*p != ' ') 708418334Speter { 708518334Speter if (*p == '\0') 708618334Speter abort (); 708718334Speter ++p; 708818334Speter } 708918334Speter 7090104763Skan /* When --disable-multilib was used but target defines 7091104763Skan MULTILIB_OSDIRNAMES, entries starting with .: are there just 7092104763Skan to find multilib_os_dir, so skip them from output. */ 7093104763Skan if (this_path[0] == '.' && this_path[1] == ':') 7094104763Skan skip = 1; 7095104763Skan 709690277Sobrien /* Check for matches with the multilib_exclusions. We don't bother 709790277Sobrien with the '!' in either list. If any of the exclusion rules match 709890277Sobrien all of its options with the select rule, we skip it. */ 709990277Sobrien { 710090277Sobrien const char *e = multilib_exclusions; 710190277Sobrien const char *this_arg; 710218334Speter 710390277Sobrien while (*e != '\0') 710490277Sobrien { 710590277Sobrien int m = 1; 710690277Sobrien /* Ignore newlines. */ 710790277Sobrien if (*e == '\n') 710890277Sobrien { 710990277Sobrien ++e; 711090277Sobrien continue; 711190277Sobrien } 711218334Speter 711390277Sobrien /* Check the arguments. */ 711490277Sobrien while (*e != ';') 711590277Sobrien { 711690277Sobrien const char *q; 711790277Sobrien int mp = 0; 711890277Sobrien 711990277Sobrien if (*e == '\0') 712090277Sobrien abort (); 712190277Sobrien 712290277Sobrien if (! m) 712390277Sobrien { 712490277Sobrien ++e; 712590277Sobrien continue; 712690277Sobrien } 712790277Sobrien 712890277Sobrien this_arg = e; 712990277Sobrien 713090277Sobrien while (*e != ' ' && *e != ';') 713190277Sobrien { 713290277Sobrien if (*e == '\0') 713390277Sobrien abort (); 713490277Sobrien ++e; 713590277Sobrien } 713690277Sobrien 713790277Sobrien q = p + 1; 713890277Sobrien while (*q != ';') 713990277Sobrien { 714090277Sobrien const char *arg; 714190277Sobrien int len = e - this_arg; 714290277Sobrien 714390277Sobrien if (*q == '\0') 714490277Sobrien abort (); 714590277Sobrien 714690277Sobrien arg = q; 714790277Sobrien 714890277Sobrien while (*q != ' ' && *q != ';') 714990277Sobrien { 715090277Sobrien if (*q == '\0') 715190277Sobrien abort (); 715290277Sobrien ++q; 715390277Sobrien } 715490277Sobrien 715590277Sobrien if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) || 715690277Sobrien default_arg (this_arg, e - this_arg)) 715790277Sobrien { 715890277Sobrien mp = 1; 715990277Sobrien break; 716090277Sobrien } 716190277Sobrien 716290277Sobrien if (*q == ' ') 716390277Sobrien ++q; 716490277Sobrien } 716590277Sobrien 716690277Sobrien if (! mp) 716790277Sobrien m = 0; 716890277Sobrien 716990277Sobrien if (*e == ' ') 717090277Sobrien ++e; 717190277Sobrien } 717290277Sobrien 717390277Sobrien if (m) 717490277Sobrien { 717590277Sobrien skip = 1; 717690277Sobrien break; 717790277Sobrien } 717890277Sobrien 717990277Sobrien if (*e != '\0') 718090277Sobrien ++e; 718190277Sobrien } 718290277Sobrien } 718390277Sobrien 718490277Sobrien if (! skip) 718590277Sobrien { 718690277Sobrien /* If this is a duplicate, skip it. */ 718790277Sobrien skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len 718890277Sobrien && ! strncmp (last_path, this_path, last_path_len)); 718990277Sobrien 719090277Sobrien last_path = this_path; 719190277Sobrien last_path_len = p - this_path; 719290277Sobrien } 719390277Sobrien 719418334Speter /* If this directory requires any default arguments, we can skip 719518334Speter it. We will already have printed a directory identical to 719618334Speter this one which does not require that default argument. */ 719718334Speter if (! skip) 719818334Speter { 719990277Sobrien const char *q; 720018334Speter 720118334Speter q = p + 1; 720218334Speter while (*q != ';') 720318334Speter { 720490277Sobrien const char *arg; 720518334Speter 720618334Speter if (*q == '\0') 720718334Speter abort (); 720818334Speter 720918334Speter if (*q == '!') 721018334Speter arg = NULL; 721118334Speter else 721218334Speter arg = q; 721318334Speter 721418334Speter while (*q != ' ' && *q != ';') 721518334Speter { 721618334Speter if (*q == '\0') 721718334Speter abort (); 721818334Speter ++q; 721918334Speter } 722018334Speter 722118334Speter if (arg != NULL 722218334Speter && default_arg (arg, q - arg)) 722318334Speter { 722418334Speter skip = 1; 722518334Speter break; 722618334Speter } 722718334Speter 722818334Speter if (*q == ' ') 722918334Speter ++q; 723018334Speter } 723118334Speter } 723218334Speter 723318334Speter if (! skip) 723418334Speter { 723590277Sobrien const char *p1; 723618334Speter 7237104763Skan for (p1 = last_path; p1 < p && *p1 != ':'; p1++) 723818334Speter putchar (*p1); 723918334Speter putchar (';'); 724018334Speter } 724118334Speter 724218334Speter ++p; 724318334Speter while (*p != ';') 724418334Speter { 724518334Speter int use_arg; 724618334Speter 724718334Speter if (*p == '\0') 724818334Speter abort (); 724918334Speter 725018334Speter if (skip) 725118334Speter { 725218334Speter ++p; 725318334Speter continue; 725418334Speter } 725518334Speter 725618334Speter use_arg = *p != '!'; 725718334Speter 725818334Speter if (use_arg) 725918334Speter putchar ('@'); 726018334Speter 726118334Speter while (*p != ' ' && *p != ';') 726218334Speter { 726318334Speter if (*p == '\0') 726418334Speter abort (); 726518334Speter if (use_arg) 726618334Speter putchar (*p); 726718334Speter ++p; 726818334Speter } 726918334Speter 727018334Speter if (*p == ' ') 727118334Speter ++p; 727218334Speter } 727318334Speter 727418334Speter if (! skip) 727550599Sobrien { 727690277Sobrien /* If there are extra options, print them now. */ 727750599Sobrien if (multilib_extra && *multilib_extra) 727850599Sobrien { 727950599Sobrien int print_at = TRUE; 728090277Sobrien const char *q; 728118334Speter 728250599Sobrien for (q = multilib_extra; *q != '\0'; q++) 728350599Sobrien { 728450599Sobrien if (*q == ' ') 728550599Sobrien print_at = TRUE; 728650599Sobrien else 728750599Sobrien { 728850599Sobrien if (print_at) 728950599Sobrien putchar ('@'); 729050599Sobrien putchar (*q); 729150599Sobrien print_at = FALSE; 729250599Sobrien } 729350599Sobrien } 729450599Sobrien } 729590277Sobrien 729650599Sobrien putchar ('\n'); 729750599Sobrien } 729850599Sobrien 729918334Speter ++p; 730018334Speter } 730118334Speter} 7302117413Skan 7303117413Skan/* if-exists built-in spec function. 7304117413Skan 7305117413Skan Checks to see if the file specified by the absolute pathname in 7306117413Skan ARGS exists. Returns that pathname if found. 7307117413Skan 7308117413Skan The usual use for this function is to check for a library file 7309117413Skan (whose name has been expanded with %s). */ 7310117413Skan 7311117413Skanstatic const char * 7312117413Skanif_exists_spec_function (argc, argv) 7313117413Skan int argc; 7314117413Skan const char **argv; 7315117413Skan{ 7316117413Skan /* Must have only one argument. */ 7317117413Skan if (argc == 1 && IS_ABSOLUTE_PATHNAME (argv[0]) && ! access (argv[0], R_OK)) 7318117413Skan return argv[0]; 7319117413Skan 7320117413Skan return NULL; 7321117413Skan} 7322117413Skan 7323117413Skan/* if-exists-else built-in spec function. 7324117413Skan 7325117413Skan This is like if-exists, but takes an additional argument which 7326117413Skan is returned if the first argument does not exist. */ 7327117413Skan 7328117413Skanstatic const char * 7329117413Skanif_exists_else_spec_function (argc, argv) 7330117413Skan int argc; 7331117413Skan const char **argv; 7332117413Skan{ 7333117413Skan /* Must have exactly two arguments. */ 7334117413Skan if (argc != 2) 7335117413Skan return NULL; 7336117413Skan 7337117413Skan if (IS_ABSOLUTE_PATHNAME (argv[0]) && ! access (argv[0], R_OK)) 7338117413Skan return argv[0]; 7339117413Skan 7340117413Skan return argv[1]; 7341117413Skan} 7342