gcc.c revision 90277
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 90277 2002-02-06 02:53:38Z obrien $ */ 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 9850599Sobrien#else 9990277Sobrien#undef TARGET_EXECUTABLE_SUFFIX 10090277Sobrien#define TARGET_EXECUTABLE_SUFFIX "" 10118334Speter#endif 10218334Speter 10390277Sobrien/* By default there is no special suffix for host executables. */ 10490277Sobrien#ifdef HOST_EXECUTABLE_SUFFIX 10590277Sobrien#define HAVE_HOST_EXECUTABLE_SUFFIX 10618334Speter#else 10790277Sobrien#define HOST_EXECUTABLE_SUFFIX "" 10818334Speter#endif 10918334Speter 11090277Sobrien/* By default, the suffix for target object files is ".o". */ 11190277Sobrien#ifdef TARGET_OBJECT_SUFFIX 11290277Sobrien#define HAVE_TARGET_OBJECT_SUFFIX 11390277Sobrien#else 11490277Sobrien#define TARGET_OBJECT_SUFFIX ".o" 11518334Speter#endif 11618334Speter 11790277Sobrien#ifndef VMS 11890277Sobrien/* FIXME: the location independence code for VMS is hairier than this, 11990277Sobrien and hasn't been written. */ 12090277Sobrien#ifndef DIR_UP 12190277Sobrien#define DIR_UP ".." 12290277Sobrien#endif /* DIR_UP */ 12390277Sobrien#endif /* VMS */ 12418334Speter 12590277Sobrienstatic const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; 12652520Sobrien 12718334Speter#define obstack_chunk_alloc xmalloc 12818334Speter#define obstack_chunk_free free 12918334Speter 13052520Sobrien#ifndef GET_ENV_PATH_LIST 13152520Sobrien#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0) 13218334Speter#endif 13318334Speter 13490277Sobrien/* Most every one is fine with LIBRARY_PATH. For some, it conflicts. */ 13590277Sobrien#ifndef LIBRARY_PATH_ENV 13690277Sobrien#define LIBRARY_PATH_ENV "LIBRARY_PATH" 13790277Sobrien#endif 13890277Sobrien 13950599Sobrien#ifndef HAVE_KILL 14050599Sobrien#define kill(p,s) raise(s) 14118334Speter#endif 14218334Speter 14318334Speter/* If a stage of compilation returns an exit status >= 1, 14418334Speter compilation of that file ceases. */ 14518334Speter 14618334Speter#define MIN_FATAL_STATUS 1 14718334Speter 14890277Sobrien/* Flag set by cppspec.c to 1. */ 14990277Sobrienint is_cpp_driver; 15090277Sobrien 15190277Sobrien/* Flag saying to pass the greatest exit code returned by a sub-process 15290277Sobrien to the calling program. */ 15390277Sobrienstatic int pass_exit_codes; 15490277Sobrien 15590277Sobrien/* Definition of string containing the arguments given to configure. */ 15690277Sobrien#include "configargs.h" 15790277Sobrien 15818334Speter/* Flag saying to print the directories gcc will search through looking for 15918334Speter programs, libraries, etc. */ 16018334Speter 16118334Speterstatic int print_search_dirs; 16218334Speter 16318334Speter/* Flag saying to print the full filename of this file 16418334Speter as found through our usual search mechanism. */ 16518334Speter 16652520Sobrienstatic const char *print_file_name = NULL; 16718334Speter 16850599Sobrien/* As print_file_name, but search for executable file. */ 16918334Speter 17052520Sobrienstatic const char *print_prog_name = NULL; 17118334Speter 17218334Speter/* Flag saying to print the relative path we'd use to 17318334Speter find libgcc.a given the current compiler flags. */ 17418334Speter 17518334Speterstatic int print_multi_directory; 17618334Speter 17718334Speter/* Flag saying to print the list of subdirectories and 17818334Speter compiler flags used to select them in a standard form. */ 17918334Speter 18018334Speterstatic int print_multi_lib; 18118334Speter 18250599Sobrien/* Flag saying to print the command line options understood by gcc and its 18350599Sobrien sub-processes. */ 18450599Sobrien 18550599Sobrienstatic int print_help_list; 18650599Sobrien 18718334Speter/* Flag indicating whether we should print the command and arguments */ 18818334Speter 18918334Speterstatic int verbose_flag; 19018334Speter 19190277Sobrien/* Flag indicating whether we should ONLY print the command and 19290277Sobrien arguments (like verbose_flag) without executing the command. 19390277Sobrien Displayed arguments are quoted so that the generated command 19490277Sobrien line is suitable for execution. This is intended for use in 19590277Sobrien shell scripts to capture the driver-generated command line. */ 19690277Sobrienstatic int verbose_only_flag; 19790277Sobrien 19890277Sobrien/* Flag indicating to print target specific command line options. */ 19990277Sobrien 20090277Sobrienstatic int target_help_flag; 20190277Sobrien 20290277Sobrien/* Flag indicating whether we should report subprocess execution times 20390277Sobrien (if this is supported by the system - see pexecute.c). */ 20490277Sobrien 20590277Sobrienstatic int report_times; 20690277Sobrien 20718334Speter/* Nonzero means write "temp" files in source directory 20818334Speter and use the source file's name in them, and don't delete them. */ 20918334Speter 21018334Speterstatic int save_temps_flag; 21118334Speter 21218334Speter/* The compiler version. */ 21318334Speter 21490277Sobrienstatic const char *compiler_version; 21518334Speter 21618334Speter/* The target version specified with -V */ 21718334Speter 21890277Sobrienstatic const char *spec_version = DEFAULT_TARGET_VERSION; 21918334Speter 22018334Speter/* The target machine specified with -b. */ 22118334Speter 22252520Sobrienstatic const char *spec_machine = DEFAULT_TARGET_MACHINE; 22318334Speter 22418334Speter/* Nonzero if cross-compiling. 22518334Speter When -b is used, the value comes from the `specs' file. */ 22618334Speter 22718334Speter#ifdef CROSS_COMPILE 22890277Sobrienstatic const char *cross_compile = "1"; 22918334Speter#else 23090277Sobrienstatic const char *cross_compile = "0"; 23118334Speter#endif 23218334Speter 23390277Sobrien#ifdef MODIFY_TARGET_NAME 23490277Sobrien 23590277Sobrien/* Information on how to alter the target name based on a command-line 23690277Sobrien switch. The only case we support now is simply appending or deleting a 23790277Sobrien string to or from the end of the first part of the configuration name. */ 23890277Sobrien 23990277Sobrienstatic const struct modify_target 24090277Sobrien{ 24190277Sobrien const char *const sw; 24290277Sobrien const enum add_del {ADD, DELETE} add_del; 24390277Sobrien const char *const str; 24490277Sobrien} 24590277Sobrienmodify_target[] = MODIFY_TARGET_NAME; 24690277Sobrien#endif 24790277Sobrien 24818334Speter/* The number of errors that have occurred; the link phase will not be 24918334Speter run if this is non-zero. */ 25018334Speterstatic int error_count = 0; 25118334Speter 25290277Sobrien/* Greatest exit code of sub-processes that has been encountered up to 25390277Sobrien now. */ 25490277Sobrienstatic int greatest_status = 1; 25590277Sobrien 25618334Speter/* This is the obstack which we use to allocate many strings. */ 25718334Speter 25818334Speterstatic struct obstack obstack; 25918334Speter 26018334Speter/* This is the obstack to build an environment variable to pass to 26118334Speter collect2 that describes all of the relevant switches of what to 26218334Speter pass the compiler in building the list of pointers to constructors 26318334Speter and destructors. */ 26418334Speter 26518334Speterstatic struct obstack collect_obstack; 26618334Speter 26790277Sobrien/* These structs are used to collect resource usage information for 26890277Sobrien subprocesses. */ 26990277Sobrien#ifdef HAVE_GETRUSAGE 27090277Sobrienstatic struct rusage rus, prus; 27190277Sobrien#endif 27218334Speter 27318334Speter/* Forward declaration for prototypes. */ 27418334Speterstruct path_prefix; 27518334Speter 27690277Sobrienstatic void init_spec PARAMS ((void)); 27790277Sobrien#ifndef VMS 27890277Sobrienstatic char **split_directories PARAMS ((const char *, int *)); 27990277Sobrienstatic void free_split_directories PARAMS ((char **)); 28090277Sobrienstatic char *make_relative_prefix PARAMS ((const char *, const char *, const char *)); 28190277Sobrien#endif /* VMS */ 28290277Sobrienstatic void store_arg PARAMS ((const char *, int, int)); 28390277Sobrienstatic char *load_specs PARAMS ((const char *)); 28490277Sobrienstatic void read_specs PARAMS ((const char *, int)); 28590277Sobrienstatic void set_spec PARAMS ((const char *, const char *)); 28690277Sobrienstatic struct compiler *lookup_compiler PARAMS ((const char *, size_t, const char *)); 28790277Sobrienstatic char *build_search_list PARAMS ((struct path_prefix *, const char *, int)); 28890277Sobrienstatic void putenv_from_prefixes PARAMS ((struct path_prefix *, const char *)); 28990277Sobrienstatic int access_check PARAMS ((const char *, int)); 29090277Sobrienstatic char *find_a_file PARAMS ((struct path_prefix *, const char *, int)); 29190277Sobrienstatic void add_prefix PARAMS ((struct path_prefix *, const char *, 29290277Sobrien const char *, int, int, int *)); 29390277Sobrienstatic void translate_options PARAMS ((int *, const char *const **)); 29490277Sobrienstatic char *skip_whitespace PARAMS ((char *)); 29590277Sobrienstatic void delete_if_ordinary PARAMS ((const char *)); 29690277Sobrienstatic void delete_temp_files PARAMS ((void)); 29790277Sobrienstatic void delete_failure_queue PARAMS ((void)); 29890277Sobrienstatic void clear_failure_queue PARAMS ((void)); 29990277Sobrienstatic int check_live_switch PARAMS ((int, int)); 30090277Sobrienstatic const char *handle_braces PARAMS ((const char *)); 30190277Sobrienstatic char *save_string PARAMS ((const char *, int)); 30290277Sobrienstatic void set_collect_gcc_options PARAMS ((void)); 30390277Sobrienstatic int do_spec_1 PARAMS ((const char *, int, const char *)); 30490277Sobrienstatic const char *find_file PARAMS ((const char *)); 30590277Sobrienstatic int is_directory PARAMS ((const char *, const char *, int)); 30690277Sobrienstatic void validate_switches PARAMS ((const char *)); 30790277Sobrienstatic void validate_all_switches PARAMS ((void)); 30890277Sobrienstatic void give_switch PARAMS ((int, int, int)); 30990277Sobrienstatic int used_arg PARAMS ((const char *, int)); 31090277Sobrienstatic int default_arg PARAMS ((const char *, int)); 31190277Sobrienstatic void set_multilib_dir PARAMS ((void)); 31290277Sobrienstatic void print_multilib_info PARAMS ((void)); 31390277Sobrienstatic void perror_with_name PARAMS ((const char *)); 31490277Sobrienstatic void pfatal_pexecute PARAMS ((const char *, const char *)) 31552520Sobrien ATTRIBUTE_NORETURN; 31690277Sobrienstatic void notice PARAMS ((const char *, ...)) 31752520Sobrien ATTRIBUTE_PRINTF_1; 31890277Sobrienstatic void display_help PARAMS ((void)); 31990277Sobrienstatic void add_preprocessor_option PARAMS ((const char *, int)); 32090277Sobrienstatic void add_assembler_option PARAMS ((const char *, int)); 32190277Sobrienstatic void add_linker_option PARAMS ((const char *, int)); 32290277Sobrienstatic void process_command PARAMS ((int, const char *const *)); 32390277Sobrienstatic int execute PARAMS ((void)); 32490277Sobrienstatic void clear_args PARAMS ((void)); 32590277Sobrienstatic void fatal_error PARAMS ((int)); 32690277Sobrien#ifdef ENABLE_SHARED_LIBGCC 32790277Sobrienstatic void init_gcc_specs PARAMS ((struct obstack *, 32890277Sobrien const char *, const char *, 32990277Sobrien const char *)); 33090277Sobrien#endif 33190277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 33290277Sobrienstatic const char *convert_filename PARAMS ((const char *, int, int)); 33390277Sobrien#endif 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. 42590277Sobrien %nSTR Print STR as an 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. 45018334Speter %c process SIGNED_CHAR_SPEC as a spec. 45190277Sobrien %C process CPP_SPEC as a spec. 45218334Speter %1 process CC1_SPEC as a spec. 45318334Speter %2 process CC1PLUS_SPEC as a spec. 45418334Speter %| output "-" if the input for the current command is coming from a pipe. 45518334Speter %* substitute the variable part of a matched option. (See below.) 45618334Speter Note that each comma in the substituted string is replaced by 45718334Speter a single space. 45818334Speter %{S} substitutes the -S switch, if that switch was given to CC. 45918334Speter If that switch was not specified, this substitutes nothing. 46018334Speter Here S is a metasyntactic variable. 46118334Speter %{S*} substitutes all the switches specified to CC whose names start 46290277Sobrien with -S. This is used for -o, -I, etc; switches that take 46318334Speter arguments. CC considers `-o foo' as being one switch whose 46418334Speter name starts with `o'. %{o*} would substitute this text, 46518334Speter including the space; thus, two arguments would be generated. 46650599Sobrien %{^S*} likewise, but don't put a blank between a switch and any args. 46790277Sobrien %{S*&T*} likewise, but preserve order of S and T options (the order 46890277Sobrien of S and T in the spec is not significant). Can be any number 46990277Sobrien of ampersand-separated variables; for each the wild card is 47090277Sobrien optional. Useful for CPP as %{D*&U*&A*}. 47118334Speter %{S*:X} substitutes X if one or more switches whose names start with -S are 47218334Speter specified to CC. Note that the tail part of the -S option 47318334Speter (i.e. the part matched by the `*') will be substituted for each 47418334Speter occurrence of %* within X. 47590277Sobrien %{<S} remove all occurrences of -S from the command line. 47690277Sobrien Note - this option is position dependent. % commands in the 47790277Sobrien spec string before this option will see -S, % commands in the 47890277Sobrien spec string after this option will not. 47918334Speter %{S:X} substitutes X, but only if the -S switch was given to CC. 48018334Speter %{!S:X} substitutes X, but only if the -S switch was NOT given to CC. 48118334Speter %{|S:X} like %{S:X}, but if no S switch, substitute `-'. 48218334Speter %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'. 48318334Speter %{.S:X} substitutes X, but only if processing a file with suffix S. 48418334Speter %{!.S:X} substitutes X, but only if NOT processing a file with suffix S. 48550599Sobrien %{S|P:X} substitutes X if either -S or -P was given to CC. This may be 48650599Sobrien combined with ! and . as above binding stronger than the OR. 48718334Speter %(Spec) processes a specification defined in a specs file as *Spec: 48818334Speter %[Spec] as above, but put __ around -D arguments 48918334Speter 49018334SpeterThe conditional text X in a %{S:X} or %{!S:X} construct may contain 49118334Speterother nested % constructs or spaces, or even newlines. They are 49218334Speterprocessed as usual, as described above. 49318334Speter 49418334SpeterThe -O, -f, -m, and -W switches are handled specifically in these 49518334Speterconstructs. If another value of -O or the negated form of a -f, -m, or 49618334Speter-W switch is found later in the command line, the earlier switch 49718334Spetervalue is ignored, except with {S*} where S is just one letter; this 49818334Speterpasses all matching options. 49918334Speter 50050599SobrienThe character | at the beginning of the predicate text is used to indicate 50150599Sobrienthat a command should be piped to the following command, but only if -pipe 50250599Sobrienis specified. 50318334Speter 50418334SpeterNote that it is built into CC which switches take arguments and which 50518334Speterdo not. You might think it would be useful to generalize this to 50618334Speterallow each compiler's spec to say which switches take arguments. But 50718334Speterthis cannot be done in a consistent fashion. CC cannot even decide 50818334Speterwhich input files have been specified without knowing which switches 50918334Spetertake arguments, and it must know which input files to compile in order 51018334Speterto tell which compilers to run. 51118334Speter 51218334SpeterCC also knows implicitly that arguments starting in `-l' are to be 51318334Spetertreated as compiler output files, and passed to the linker in their 51418334Speterproper position among the other output files. */ 51518334Speter 51618334Speter/* Define the macros used for specs %a, %l, %L, %S, %c, %C, %1. */ 51718334Speter 51818334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler 51918334Speter or extra switch-translations. */ 52018334Speter#ifndef ASM_SPEC 52118334Speter#define ASM_SPEC "" 52218334Speter#endif 52318334Speter 52418334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after 52518334Speter the assembler has run. */ 52618334Speter#ifndef ASM_FINAL_SPEC 52718334Speter#define ASM_FINAL_SPEC "" 52818334Speter#endif 52918334Speter 53018334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor 53118334Speter or extra switch-translations. */ 53218334Speter#ifndef CPP_SPEC 53318334Speter#define CPP_SPEC "" 53418334Speter#endif 53518334Speter 53618334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus 53718334Speter or extra switch-translations. */ 53818334Speter#ifndef CC1_SPEC 53918334Speter#define CC1_SPEC "" 54018334Speter#endif 54118334Speter 54218334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus 54318334Speter or extra switch-translations. */ 54418334Speter#ifndef CC1PLUS_SPEC 54518334Speter#define CC1PLUS_SPEC "" 54618334Speter#endif 54718334Speter 54818334Speter/* config.h can define LINK_SPEC to provide extra args to the linker 54918334Speter or extra switch-translations. */ 55018334Speter#ifndef LINK_SPEC 55118334Speter#define LINK_SPEC "" 55218334Speter#endif 55318334Speter 55418334Speter/* config.h can define LIB_SPEC to override the default libraries. */ 55518334Speter#ifndef LIB_SPEC 55618334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}" 55718334Speter#endif 55818334Speter 55918334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is 56018334Speter included. */ 56118334Speter#ifndef LIBGCC_SPEC 56218334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1) 56318334Speter/* Have gcc do the search for libgcc.a. */ 56450599Sobrien#define LIBGCC_SPEC "libgcc.a%s" 56518334Speter#else 56650599Sobrien#define LIBGCC_SPEC "-lgcc" 56718334Speter#endif 56818334Speter#endif 56918334Speter 57018334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files. */ 57118334Speter#ifndef STARTFILE_SPEC 57218334Speter#define STARTFILE_SPEC \ 57318334Speter "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}" 57418334Speter#endif 57518334Speter 57650599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options 57750599Sobrien require spaces between the option and the argument. */ 57818334Speter#ifndef SWITCHES_NEED_SPACES 57918334Speter#define SWITCHES_NEED_SPACES "" 58018334Speter#endif 58118334Speter 58218334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files. */ 58318334Speter#ifndef ENDFILE_SPEC 58418334Speter#define ENDFILE_SPEC "" 58518334Speter#endif 58618334Speter 58718334Speter/* This spec is used for telling cpp whether char is signed or not. */ 58818334Speter#ifndef SIGNED_CHAR_SPEC 58918334Speter/* Use #if rather than ?: 59018334Speter because MIPS C compiler rejects like ?: in initializers. */ 59118334Speter#if DEFAULT_SIGNED_CHAR 59218334Speter#define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}" 59318334Speter#else 59418334Speter#define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}" 59518334Speter#endif 59618334Speter#endif 59718334Speter 59850599Sobrien#ifndef LINKER_NAME 59950599Sobrien#define LINKER_NAME "collect2" 60018334Speter#endif 60118334Speter 60290277Sobrien/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g' 60390277Sobrien to the assembler. */ 60490277Sobrien#ifndef ASM_DEBUG_SPEC 60590277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \ 60690277Sobrien && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) 60790277Sobrien# define ASM_DEBUG_SPEC \ 60890277Sobrien (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \ 60990277Sobrien ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" \ 61090277Sobrien : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}") 61190277Sobrien# else 61290277Sobrien# if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) 61390277Sobrien# define ASM_DEBUG_SPEC "%{g*:--gstabs}" 61490277Sobrien# endif 61590277Sobrien# if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) 61690277Sobrien# define ASM_DEBUG_SPEC "%{g*:--gdwarf2}" 61790277Sobrien# endif 61890277Sobrien# endif 61990277Sobrien#endif 62090277Sobrien#ifndef ASM_DEBUG_SPEC 62190277Sobrien# define ASM_DEBUG_SPEC "" 62290277Sobrien#endif 62318334Speter 62490277Sobrien/* Here is the spec for running the linker, after compiling all files. */ 62590277Sobrien 62690277Sobrien/* -u* was put back because both BSD and SysV seem to support it. */ 62790277Sobrien/* %{static:} simply prevents an error message if the target machine 62890277Sobrien doesn't handle -static. */ 62990277Sobrien/* We want %{T*} after %{L*} and %D so that it can be used to specify linker 63090277Sobrien scripts which exist in user specified directories, or in standard 63190277Sobrien directories. */ 63290277Sobrien#ifndef LINK_COMMAND_SPEC 63390277Sobrien#define LINK_COMMAND_SPEC "\ 63490277Sobrien%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\ 63590277Sobrien %(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r} %{s} %{t}\ 63690277Sobrien %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ 63790277Sobrien %{static:} %{L*} %(link_libgcc) %o %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\ 63890277Sobrien %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}" 63990277Sobrien#endif 64090277Sobrien 64190277Sobrien#ifndef LINK_LIBGCC_SPEC 64290277Sobrien# ifdef LINK_LIBGCC_SPECIAL 64390277Sobrien/* Don't generate -L options for startfile prefix list. */ 64490277Sobrien# define LINK_LIBGCC_SPEC "" 64590277Sobrien# else 64690277Sobrien/* Do generate them. */ 64790277Sobrien# define LINK_LIBGCC_SPEC "%D" 64890277Sobrien# endif 64990277Sobrien#endif 65090277Sobrien 65190277Sobrienstatic const char *asm_debug = ASM_DEBUG_SPEC; 65290277Sobrienstatic const char *cpp_spec = CPP_SPEC; 65390277Sobrienstatic const char *cpp_predefines = CPP_PREDEFINES; 65490277Sobrienstatic const char *cc1_spec = CC1_SPEC; 65590277Sobrienstatic const char *cc1plus_spec = CC1PLUS_SPEC; 65690277Sobrienstatic const char *signed_char_spec = SIGNED_CHAR_SPEC; 65790277Sobrienstatic const char *asm_spec = ASM_SPEC; 65890277Sobrienstatic const char *asm_final_spec = ASM_FINAL_SPEC; 65990277Sobrienstatic const char *link_spec = LINK_SPEC; 66090277Sobrienstatic const char *lib_spec = LIB_SPEC; 66190277Sobrienstatic const char *libgcc_spec = LIBGCC_SPEC; 66290277Sobrienstatic const char *endfile_spec = ENDFILE_SPEC; 66390277Sobrienstatic const char *startfile_spec = STARTFILE_SPEC; 66490277Sobrienstatic const char *switches_need_spaces = SWITCHES_NEED_SPACES; 66590277Sobrienstatic const char *linker_name_spec = LINKER_NAME; 66690277Sobrienstatic const char *link_command_spec = LINK_COMMAND_SPEC; 66790277Sobrienstatic const char *link_libgcc_spec = LINK_LIBGCC_SPEC; 66890277Sobrien 66990277Sobrien/* Standard options to cpp, cc1, and as, to reduce duplication in specs. 67090277Sobrien There should be no need to override these in target dependent files, 67190277Sobrien but we need to copy them to the specs file so that newer versions 67290277Sobrien of the GCC driver can correctly drive older tool chains with the 67390277Sobrien appropriate -B options. */ 67490277Sobrien 67590277Sobrienstatic const char *trad_capable_cpp = 67690277Sobrien"%{traditional|ftraditional|traditional-cpp:trad}cpp0"; 67790277Sobrien 67890277Sobrienstatic const char *cpp_unique_options = 67990277Sobrien"%{C:%{!E:%eGNU C does not support -C without using -E}}\ 68090277Sobrien %{nostdinc*} %{C} %{v} %{I*} %{P} %{$} %I\ 68190277Sobrien %{MD:-M -MF %W{!o: %b.d}%W{o*:%.d%*}}\ 68290277Sobrien %{MMD:-MM -MF %W{!o: %b.d}%W{o*:%.d%*}}\ 68390277Sobrien %{M} %{MM} %W{MF*} %{MG} %{MP} %{MQ*} %{MT*} %{M|MD|MM|MMD:%{o*:-MQ %*}}\ 68490277Sobrien %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\ 68590277Sobrien %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\ 68690277Sobrien %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\ 68790277Sobrien %{fno-inline|O0|!O*:-D__NO_INLINE__} %{ffast-math:-D__FAST_MATH__}\ 68890277Sobrien %{fshort-wchar:-U__WCHAR_TYPE__ -D__WCHAR_TYPE__=short\\ unsigned\\ int}\ 68990277Sobrien %{ffreestanding:-D__STDC_HOSTED__=0} %{fno-hosted:-D__STDC_HOSTED__=0}\ 69090277Sobrien %{!ffreestanding:%{!fno-hosted:-D__STDC_HOSTED__=1}} %{remap}\ 69190277Sobrien %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\ 69290277Sobrien %{E:%{!M*:%W{o*}}}"; 69390277Sobrien 69490277Sobrien/* This contains cpp options which are common with cc1_options and are passed 69590277Sobrien only when preprocessing only to avoid duplication. */ 69690277Sobrienstatic const char *cpp_options = 69790277Sobrien"%(cpp_unique_options) %{std*} %{d*} %{W*} %{w} %{pedantic*}\ 69890277Sobrien %{fshow-column} %{fno-show-column}\ 69990277Sobrien %{fleading-underscore} %{fno-leading-underscore}\ 70090277Sobrien %{fno-operator-names} %{ftabstop=*}"; 70190277Sobrien 70290277Sobrien/* NB: This is shared amongst all front-ends. */ 70390277Sobrienstatic const char *cc1_options = 70490277Sobrien"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 70590277Sobrien %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\ 70690277Sobrien %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*} %{ansi}\ 70790277Sobrien %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\ 70890277Sobrien %{Qn:-fno-ident} %{--help:--help}\ 70990277Sobrien %{--target-help:--target-help}\ 71090277Sobrien %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\ 71190277Sobrien %{fsyntax-only:-o %j} %{-param*}"; 71290277Sobrien 71390277Sobrienstatic const char *asm_options = 71490277Sobrien"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}"; 71590277Sobrien 71690277Sobrienstatic const char *invoke_as = 71790277Sobrien"%{!S:-o %{|!pipe:%g.s} |\n as %(asm_options) %{!pipe:%g.s} %A }"; 71890277Sobrien 71950599Sobrien/* Some compilers have limits on line lengths, and the multilib_select 72050599Sobrien and/or multilib_matches strings can be very long, so we build them at 72150599Sobrien run time. */ 72250599Sobrienstatic struct obstack multilib_obstack; 72390277Sobrienstatic const char *multilib_select; 72490277Sobrienstatic const char *multilib_matches; 72590277Sobrienstatic const char *multilib_defaults; 72690277Sobrienstatic const char *multilib_exclusions; 72750599Sobrien#include "multilib.h" 72850599Sobrien 72950599Sobrien/* Check whether a particular argument is a default argument. */ 73050599Sobrien 73150599Sobrien#ifndef MULTILIB_DEFAULTS 73250599Sobrien#define MULTILIB_DEFAULTS { "" } 73350599Sobrien#endif 73450599Sobrien 73590277Sobrienstatic const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS; 73650599Sobrien 73790277Sobrienstruct user_specs 73890277Sobrien{ 73950599Sobrien struct user_specs *next; 74052520Sobrien const char *filename; 74150599Sobrien}; 74250599Sobrien 74350599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail; 74450599Sobrien 74518334Speter/* This defines which switch letters take arguments. */ 74618334Speter 74750599Sobrien#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \ 74818334Speter ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \ 74918334Speter || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \ 75018334Speter || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \ 75150599Sobrien || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \ 75250599Sobrien || (CHAR) == 'B' || (CHAR) == 'b') 75350599Sobrien 75450599Sobrien#ifndef SWITCH_TAKES_ARG 75550599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR) 75618334Speter#endif 75718334Speter 75818334Speter/* This defines which multi-letter switches take arguments. */ 75918334Speter 76018334Speter#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \ 76118334Speter (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ 76218334Speter || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \ 76318334Speter || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \ 76418334Speter || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \ 76518334Speter || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \ 76690277Sobrien || !strcmp (STR, "isystem") || !strcmp (STR, "-param") \ 76790277Sobrien || !strcmp (STR, "specs") \ 76890277Sobrien || !strcmp (STR, "MF") || !strcmp (STR, "MT") || !strcmp (STR, "MQ")) 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 {".ch", "#Chill", 0}, {".chi", "#Chill", 0}, 83290277Sobrien {".java", "#Java", 0}, {".class", "#Java", 0}, 83390277Sobrien {".zip", "#Java", 0}, {".jar", "#Java", 0}, 83450599Sobrien /* Next come the entries for C. */ 83590277Sobrien {".c", "@c", 0}, 83618334Speter {"@c", 83790277Sobrien /* cc1 has an integrated ISO C preprocessor. We should invoke the 83890277Sobrien external preprocessor if -save-temps or -traditional is given. */ 83990277Sobrien "%{E|M|MM:%(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)}\ 84090277Sobrien %{!E:%{!M:%{!MM:\ 84190277Sobrien %{save-temps:%(trad_capable_cpp) -lang-c %{ansi:-std=c89}\ 84290277Sobrien %(cpp_options) %b.i \n\ 84390277Sobrien cc1 -fpreprocessed %b.i %(cc1_options)}\ 84490277Sobrien %{!save-temps:\ 84590277Sobrien %{traditional|ftraditional|traditional-cpp:\ 84690277Sobrien tradcpp0 -lang-c %{ansi:-std=c89} %(cpp_options) %{!pipe:%g.i} |\n\ 84790277Sobrien cc1 -fpreprocessed %{!pipe:%g.i} %(cc1_options)}\ 84890277Sobrien %{!traditional:%{!ftraditional:%{!traditional-cpp:\ 84990277Sobrien cc1 -lang-c %{ansi:-std=c89} %(cpp_unique_options) %(cc1_options)}}}}\ 85090277Sobrien %{!fsyntax-only:%(invoke_as)}}}}", 0}, 85118334Speter {"-", 85290277Sobrien "%{!E:%e-E required when input is from standard input}\ 85390277Sobrien %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)", 0}, 85490277Sobrien {".h", "@c-header", 0}, 85518334Speter {"@c-header", 85690277Sobrien "%{!E:%ecompilation of header file requested} \ 85790277Sobrien %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)", 0}, 85890277Sobrien {".i", "@cpp-output", 0}, 85918334Speter {"@cpp-output", 86090277Sobrien "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0}, 86190277Sobrien {".s", "@assembler", 0}, 86218334Speter {"@assembler", 86390277Sobrien "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0}, 86490277Sobrien {".S", "@assembler-with-cpp", 0}, 86518334Speter {"@assembler-with-cpp", 86690277Sobrien "%(trad_capable_cpp) -lang-asm %(cpp_options)\ 86790277Sobrien %{!M:%{!MM:%{!E:%{!S:-o %{|!pipe:%g.s} |\n\ 86890277Sobrien as %(asm_debug) %(asm_options) %{!pipe:%g.s} %A }}}}", 0}, 86918334Speter#include "specs.h" 87018334Speter /* Mark end of table */ 87190277Sobrien {0, 0, 0} 87218334Speter}; 87318334Speter 87418334Speter/* Number of elements in default_compilers, not counting the terminator. */ 87518334Speter 87618334Speterstatic int n_default_compilers 87718334Speter = (sizeof default_compilers / sizeof (struct compiler)) - 1; 87818334Speter 87918334Speter/* A vector of options to give to the linker. 88018334Speter These options are accumulated by %x, 88118334Speter and substituted into the linker command with %X. */ 88218334Speterstatic int n_linker_options; 88318334Speterstatic char **linker_options; 88418334Speter 88518334Speter/* A vector of options to give to the assembler. 88618334Speter These options are accumulated by -Wa, 88718334Speter and substituted into the assembler command with %Y. */ 88818334Speterstatic int n_assembler_options; 88918334Speterstatic char **assembler_options; 89018334Speter 89118334Speter/* A vector of options to give to the preprocessor. 89218334Speter These options are accumulated by -Wp, 89318334Speter and substituted into the preprocessor command with %Z. */ 89418334Speterstatic int n_preprocessor_options; 89518334Speterstatic char **preprocessor_options; 89618334Speter 89718334Speter/* Define how to map long options into short ones. */ 89818334Speter 89918334Speter/* This structure describes one mapping. */ 90018334Speterstruct option_map 90118334Speter{ 90218334Speter /* The long option's name. */ 90390277Sobrien const char *const name; 90418334Speter /* The equivalent short option. */ 90590277Sobrien const char *const equivalent; 90618334Speter /* Argument info. A string of flag chars; NULL equals no options. 90718334Speter a => argument required. 90818334Speter o => argument optional. 90918334Speter j => join argument to equivalent, making one word. 91018334Speter * => require other text after NAME as an argument. */ 91190277Sobrien const char *const arg_info; 91218334Speter}; 91318334Speter 91418334Speter/* This is the table of mappings. Mappings are tried sequentially 91518334Speter for each option encountered; the first one that matches, wins. */ 91618334Speter 91790277Sobrienstatic const struct option_map option_map[] = 91818334Speter { 91918334Speter {"--all-warnings", "-Wall", 0}, 92018334Speter {"--ansi", "-ansi", 0}, 92118334Speter {"--assemble", "-S", 0}, 92218334Speter {"--assert", "-A", "a"}, 92352520Sobrien {"--classpath", "-fclasspath=", "aj"}, 92452520Sobrien {"--CLASSPATH", "-fCLASSPATH=", "aj"}, 92518334Speter {"--comments", "-C", 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"}, 95018334Speter {"--no-line-commands", "-P", 0}, 95118334Speter {"--no-precompiled-includes", "-noprecomp", 0}, 95218334Speter {"--no-standard-includes", "-nostdinc", 0}, 95318334Speter {"--no-standard-libraries", "-nostdlib", 0}, 95418334Speter {"--no-warnings", "-w", 0}, 95518334Speter {"--optimize", "-O", "oj"}, 95618334Speter {"--output", "-o", "a"}, 95752520Sobrien {"--output-class-directory", "-foutput-class-dir=", "ja"}, 95890277Sobrien {"--param", "--param", "a"}, 95918334Speter {"--pedantic", "-pedantic", 0}, 96018334Speter {"--pedantic-errors", "-pedantic-errors", 0}, 96118334Speter {"--pipe", "-pipe", 0}, 96218334Speter {"--prefix", "-B", "a"}, 96318334Speter {"--preprocess", "-E", 0}, 96418334Speter {"--print-search-dirs", "-print-search-dirs", 0}, 96518334Speter {"--print-file-name", "-print-file-name=", "aj"}, 96618334Speter {"--print-libgcc-file-name", "-print-libgcc-file-name", 0}, 96718334Speter {"--print-missing-file-dependencies", "-MG", 0}, 96818334Speter {"--print-multi-lib", "-print-multi-lib", 0}, 96918334Speter {"--print-multi-directory", "-print-multi-directory", 0}, 97018334Speter {"--print-prog-name", "-print-prog-name=", "aj"}, 97118334Speter {"--profile", "-p", 0}, 97218334Speter {"--profile-blocks", "-a", 0}, 97318334Speter {"--quiet", "-q", 0}, 97418334Speter {"--save-temps", "-save-temps", 0}, 97518334Speter {"--shared", "-shared", 0}, 97618334Speter {"--silent", "-q", 0}, 97750599Sobrien {"--specs", "-specs=", "aj"}, 97818334Speter {"--static", "-static", 0}, 97952520Sobrien {"--std", "-std=", "aj"}, 98018334Speter {"--symbolic", "-symbolic", 0}, 98118334Speter {"--target", "-b", "a"}, 98290277Sobrien {"--time", "-time", 0}, 98318334Speter {"--trace-includes", "-H", 0}, 98418334Speter {"--traditional", "-traditional", 0}, 98518334Speter {"--traditional-cpp", "-traditional-cpp", 0}, 98618334Speter {"--trigraphs", "-trigraphs", 0}, 98750599Sobrien {"--undefine-macro", "-U", "aj"}, 98818334Speter {"--use-version", "-V", "a"}, 98918334Speter {"--user-dependencies", "-MM", 0}, 99018334Speter {"--verbose", "-v", 0}, 99118334Speter {"--warn-", "-W", "*j"}, 99218334Speter {"--write-dependencies", "-MD", 0}, 99318334Speter {"--write-user-dependencies", "-MMD", 0}, 99418334Speter {"--", "-f", "*j"} 99518334Speter }; 99618334Speter 99790277Sobrien 99890277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE 99990277Sobrienstatic const struct { 100090277Sobrien const char *const option_found; 100190277Sobrien const char *const replacements; 100290277Sobrien} target_option_translations[] = 100390277Sobrien{ 100490277Sobrien TARGET_OPTION_TRANSLATE_TABLE, 100590277Sobrien { 0, 0 } 100690277Sobrien}; 100790277Sobrien#endif 100890277Sobrien 100918334Speter/* Translate the options described by *ARGCP and *ARGVP. 101018334Speter Make a new vector and store it back in *ARGVP, 101118334Speter and store its length in *ARGVC. */ 101218334Speter 101318334Speterstatic void 101418334Spetertranslate_options (argcp, argvp) 101518334Speter int *argcp; 101690277Sobrien const char *const **argvp; 101718334Speter{ 101852520Sobrien int i; 101918334Speter int argc = *argcp; 102090277Sobrien const char *const *argv = *argvp; 102190277Sobrien int newvsize = (argc + 2) * 2 * sizeof (const char *); 102252520Sobrien const char **newv = 102390277Sobrien (const char **) xmalloc (newvsize); 102418334Speter int newindex = 0; 102518334Speter 102618334Speter i = 0; 102718334Speter newv[newindex++] = argv[i++]; 102818334Speter 102918334Speter while (i < argc) 103018334Speter { 103190277Sobrien#ifdef TARGET_OPTION_TRANSLATE_TABLE 103290277Sobrien int tott_idx; 103390277Sobrien 103490277Sobrien for (tott_idx = 0; 103590277Sobrien target_option_translations[tott_idx].option_found; 103690277Sobrien tott_idx++) 103790277Sobrien { 103890277Sobrien if (strcmp (target_option_translations[tott_idx].option_found, 103990277Sobrien argv[i]) == 0) 104090277Sobrien { 104190277Sobrien int spaces = 1; 104290277Sobrien const char *sp; 104390277Sobrien char *np; 104490277Sobrien 104590277Sobrien for (sp = target_option_translations[tott_idx].replacements; 104690277Sobrien *sp; sp++) 104790277Sobrien { 104890277Sobrien if (*sp == ' ') 104990277Sobrien spaces ++; 105090277Sobrien } 105190277Sobrien 105290277Sobrien newvsize += spaces * sizeof (const char *); 105390277Sobrien newv = (const char **) xrealloc (newv, newvsize); 105490277Sobrien 105590277Sobrien sp = target_option_translations[tott_idx].replacements; 105690277Sobrien np = xstrdup (sp); 105790277Sobrien 105890277Sobrien while (1) 105990277Sobrien { 106090277Sobrien while (*np == ' ') 106190277Sobrien np++; 106290277Sobrien if (*np == 0) 106390277Sobrien break; 106490277Sobrien newv[newindex++] = np; 106590277Sobrien while (*np != ' ' && *np) 106690277Sobrien np++; 106790277Sobrien if (*np == 0) 106890277Sobrien break; 106990277Sobrien *np++ = 0; 107090277Sobrien } 107190277Sobrien 107290277Sobrien i ++; 107390277Sobrien break; 107490277Sobrien } 107590277Sobrien } 107690277Sobrien if (target_option_translations[tott_idx].option_found) 107790277Sobrien continue; 107890277Sobrien#endif 107990277Sobrien 108018334Speter /* Translate -- options. */ 108118334Speter if (argv[i][0] == '-' && argv[i][1] == '-') 108218334Speter { 108352520Sobrien size_t j; 108418334Speter /* Find a mapping that applies to this option. */ 108590277Sobrien for (j = 0; j < ARRAY_SIZE (option_map); j++) 108618334Speter { 108750599Sobrien size_t optlen = strlen (option_map[j].name); 108850599Sobrien size_t arglen = strlen (argv[i]); 108950599Sobrien size_t complen = arglen > optlen ? optlen : arglen; 109052520Sobrien const char *arginfo = option_map[j].arg_info; 109118334Speter 109218334Speter if (arginfo == 0) 109318334Speter arginfo = ""; 109418334Speter 109518334Speter if (!strncmp (argv[i], option_map[j].name, complen)) 109618334Speter { 109752520Sobrien const char *arg = 0; 109818334Speter 109918334Speter if (arglen < optlen) 110018334Speter { 110152520Sobrien size_t k; 110290277Sobrien for (k = j + 1; k < ARRAY_SIZE (option_map); k++) 110318334Speter if (strlen (option_map[k].name) >= arglen 110418334Speter && !strncmp (argv[i], option_map[k].name, arglen)) 110518334Speter { 110690277Sobrien error ("ambiguous abbreviation %s", argv[i]); 110718334Speter break; 110818334Speter } 110918334Speter 111090277Sobrien if (k != ARRAY_SIZE (option_map)) 111118334Speter break; 111218334Speter } 111318334Speter 111418334Speter if (arglen > optlen) 111518334Speter { 111618334Speter /* If the option has an argument, accept that. */ 111718334Speter if (argv[i][optlen] == '=') 111818334Speter arg = argv[i] + optlen + 1; 111918334Speter 112018334Speter /* If this mapping requires extra text at end of name, 112118334Speter accept that as "argument". */ 112290277Sobrien else if (strchr (arginfo, '*') != 0) 112318334Speter arg = argv[i] + optlen; 112418334Speter 112518334Speter /* Otherwise, extra text at end means mismatch. 112618334Speter Try other mappings. */ 112718334Speter else 112818334Speter continue; 112918334Speter } 113018334Speter 113190277Sobrien else if (strchr (arginfo, '*') != 0) 113218334Speter { 113390277Sobrien error ("incomplete `%s' option", option_map[j].name); 113418334Speter break; 113518334Speter } 113618334Speter 113718334Speter /* Handle arguments. */ 113890277Sobrien if (strchr (arginfo, 'a') != 0) 113918334Speter { 114018334Speter if (arg == 0) 114118334Speter { 114218334Speter if (i + 1 == argc) 114318334Speter { 114490277Sobrien error ("missing argument to `%s' option", 114518334Speter option_map[j].name); 114618334Speter break; 114718334Speter } 114818334Speter 114918334Speter arg = argv[++i]; 115018334Speter } 115118334Speter } 115290277Sobrien else if (strchr (arginfo, '*') != 0) 115318334Speter ; 115490277Sobrien else if (strchr (arginfo, 'o') == 0) 115518334Speter { 115618334Speter if (arg != 0) 115790277Sobrien error ("extraneous argument to `%s' option", 115818334Speter option_map[j].name); 115918334Speter arg = 0; 116018334Speter } 116118334Speter 116218334Speter /* Store the translation as one argv elt or as two. */ 116390277Sobrien if (arg != 0 && strchr (arginfo, 'j') != 0) 116450599Sobrien newv[newindex++] = concat (option_map[j].equivalent, arg, 116590277Sobrien NULL); 116618334Speter else if (arg != 0) 116718334Speter { 116818334Speter newv[newindex++] = option_map[j].equivalent; 116918334Speter newv[newindex++] = arg; 117018334Speter } 117118334Speter else 117218334Speter newv[newindex++] = option_map[j].equivalent; 117318334Speter 117418334Speter break; 117518334Speter } 117618334Speter } 117718334Speter i++; 117818334Speter } 117918334Speter 118018334Speter /* Handle old-fashioned options--just copy them through, 118118334Speter with their arguments. */ 118218334Speter else if (argv[i][0] == '-') 118318334Speter { 118452520Sobrien const char *p = argv[i] + 1; 118518334Speter int c = *p; 118618334Speter int nskip = 1; 118718334Speter 118818334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 118918334Speter nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0); 119018334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 119118334Speter nskip += WORD_SWITCH_TAKES_ARG (p); 119218334Speter else if ((c == 'B' || c == 'b' || c == 'V' || c == 'x') 119318334Speter && p[1] == 0) 119418334Speter nskip += 1; 119518334Speter else if (! strcmp (p, "Xlinker")) 119618334Speter nskip += 1; 119718334Speter 119818334Speter /* Watch out for an option at the end of the command line that 119918334Speter is missing arguments, and avoid skipping past the end of the 120018334Speter command line. */ 120118334Speter if (nskip + i > argc) 120218334Speter nskip = argc - i; 120318334Speter 120418334Speter while (nskip > 0) 120518334Speter { 120618334Speter newv[newindex++] = argv[i++]; 120718334Speter nskip--; 120818334Speter } 120918334Speter } 121018334Speter else 121118334Speter /* Ordinary operands, or +e options. */ 121218334Speter newv[newindex++] = argv[i++]; 121318334Speter } 121418334Speter 121518334Speter newv[newindex] = 0; 121618334Speter 121718334Speter *argvp = newv; 121818334Speter *argcp = newindex; 121918334Speter} 122018334Speter 122118334Speterstatic char * 122218334Speterskip_whitespace (p) 122318334Speter char *p; 122418334Speter{ 122518334Speter while (1) 122618334Speter { 122718334Speter /* A fully-blank line is a delimiter in the SPEC file and shouldn't 122818334Speter be considered whitespace. */ 122918334Speter if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n') 123018334Speter return p + 1; 123118334Speter else if (*p == '\n' || *p == ' ' || *p == '\t') 123218334Speter p++; 123318334Speter else if (*p == '#') 123418334Speter { 123590277Sobrien while (*p != '\n') 123690277Sobrien p++; 123718334Speter p++; 123818334Speter } 123918334Speter else 124018334Speter break; 124118334Speter } 124218334Speter 124318334Speter return p; 124418334Speter} 124590277Sobrien/* Structures to keep track of prefixes to try when looking for files. */ 124690277Sobrien 124790277Sobrienstruct prefix_list 124890277Sobrien{ 124990277Sobrien const char *prefix; /* String to prepend to the path. */ 125090277Sobrien struct prefix_list *next; /* Next in linked list. */ 125190277Sobrien int require_machine_suffix; /* Don't use without machine_suffix. */ 125290277Sobrien /* 2 means try both machine_suffix and just_machine_suffix. */ 125390277Sobrien int *used_flag_ptr; /* 1 if a file was found with this prefix. */ 125490277Sobrien int priority; /* Sort key - priority within list */ 125590277Sobrien}; 125690277Sobrien 125790277Sobrienstruct path_prefix 125890277Sobrien{ 125990277Sobrien struct prefix_list *plist; /* List of prefixes to try */ 126090277Sobrien int max_len; /* Max length of a prefix in PLIST */ 126190277Sobrien const char *name; /* Name of this list (used in config stuff) */ 126290277Sobrien}; 126390277Sobrien 126490277Sobrien/* List of prefixes to try when looking for executables. */ 126590277Sobrien 126690277Sobrienstatic struct path_prefix exec_prefixes = { 0, 0, "exec" }; 126790277Sobrien 126890277Sobrien/* List of prefixes to try when looking for startup (crt0) files. */ 126990277Sobrien 127090277Sobrienstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" }; 127190277Sobrien 127290277Sobrien/* List of prefixes to try when looking for include files. */ 127390277Sobrien 127490277Sobrienstatic struct path_prefix include_prefixes = { 0, 0, "include" }; 127590277Sobrien 127690277Sobrien/* Suffix to attach to directories searched for commands. 127790277Sobrien This looks like `MACHINE/VERSION/'. */ 127890277Sobrien 127990277Sobrienstatic const char *machine_suffix = 0; 128090277Sobrien 128190277Sobrien/* Suffix to attach to directories searched for commands. 128290277Sobrien This is just `MACHINE/'. */ 128390277Sobrien 128490277Sobrienstatic const char *just_machine_suffix = 0; 128590277Sobrien 128690277Sobrien/* Adjusted value of GCC_EXEC_PREFIX envvar. */ 128790277Sobrien 128890277Sobrienstatic const char *gcc_exec_prefix; 128990277Sobrien 129090277Sobrien/* Default prefixes to attach to command names. */ 129190277Sobrien 129290277Sobrien#ifdef CROSS_COMPILE /* Don't use these prefixes for a cross compiler. */ 129390277Sobrien#undef MD_EXEC_PREFIX 129490277Sobrien#undef MD_STARTFILE_PREFIX 129590277Sobrien#undef MD_STARTFILE_PREFIX_1 129690277Sobrien#endif 129790277Sobrien 129890277Sobrien/* If no prefixes defined, use the null string, which will disable them. */ 129990277Sobrien#ifndef MD_EXEC_PREFIX 130090277Sobrien#define MD_EXEC_PREFIX "" 130190277Sobrien#endif 130290277Sobrien#ifndef MD_STARTFILE_PREFIX 130390277Sobrien#define MD_STARTFILE_PREFIX "" 130490277Sobrien#endif 130590277Sobrien#ifndef MD_STARTFILE_PREFIX_1 130690277Sobrien#define MD_STARTFILE_PREFIX_1 "" 130790277Sobrien#endif 130890277Sobrien 130990277Sobrien/* Supply defaults for the standard prefixes. */ 131090277Sobrien 131190277Sobrien#ifndef STANDARD_EXEC_PREFIX 131290277Sobrien#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/" 131390277Sobrien#endif 131490277Sobrien#ifndef STANDARD_STARTFILE_PREFIX 131590277Sobrien#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/" 131690277Sobrien#endif 131790277Sobrien#ifndef TOOLDIR_BASE_PREFIX 131890277Sobrien#define TOOLDIR_BASE_PREFIX "/usr/local/" 131990277Sobrien#endif 132090277Sobrien#ifndef STANDARD_BINDIR_PREFIX 132190277Sobrien#define STANDARD_BINDIR_PREFIX "/usr/local/bin" 132290277Sobrien#endif 132390277Sobrien 132490277Sobrienstatic const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX; 132590277Sobrienstatic const char *const standard_exec_prefix_1 = "/usr/lib/gcc/"; 132690277Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX; 132790277Sobrien 132890277Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX; 132990277Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1; 133090277Sobrienstatic const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; 133190277Sobrienstatic const char *const standard_startfile_prefix_1 = "/lib/"; 133290277Sobrienstatic const char *const standard_startfile_prefix_2 = "/usr/lib/"; 133390277Sobrien 133490277Sobrienstatic const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX; 133590277Sobrienstatic const char *tooldir_prefix; 133690277Sobrien 133790277Sobrienstatic const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX; 133890277Sobrien 133990277Sobrien/* Subdirectory to use for locating libraries. Set by 134090277Sobrien set_multilib_dir based on the compilation options. */ 134190277Sobrien 134290277Sobrienstatic const char *multilib_dir; 134318334Speter 134450599Sobrien/* Structure to keep track of the specs that have been defined so far. 134550599Sobrien These are accessed using %(specname) or %[specname] in a compiler 134650599Sobrien or link spec. */ 134718334Speter 134818334Speterstruct spec_list 134918334Speter{ 135050599Sobrien /* The following 2 fields must be first */ 135150599Sobrien /* to allow EXTRA_SPECS to be initialized */ 135290277Sobrien const char *name; /* name of the spec. */ 135390277Sobrien const char *ptr; /* available ptr if no static pointer */ 135450599Sobrien 135550599Sobrien /* The following fields are not initialized */ 135650599Sobrien /* by EXTRA_SPECS */ 135790277Sobrien const char **ptr_spec; /* pointer to the spec itself. */ 135850599Sobrien struct spec_list *next; /* Next spec in linked list. */ 135950599Sobrien int name_len; /* length of the name */ 136050599Sobrien int alloc_p; /* whether string was allocated */ 136118334Speter}; 136218334Speter 136350599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \ 136490277Sobrien{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 } 136518334Speter 136690277Sobrien/* List of statically defined specs. */ 136790277Sobrienstatic struct spec_list static_specs[] = 136890277Sobrien{ 136950599Sobrien INIT_STATIC_SPEC ("asm", &asm_spec), 137090277Sobrien INIT_STATIC_SPEC ("asm_debug", &asm_debug), 137150599Sobrien INIT_STATIC_SPEC ("asm_final", &asm_final_spec), 137290277Sobrien INIT_STATIC_SPEC ("asm_options", &asm_options), 137390277Sobrien INIT_STATIC_SPEC ("invoke_as", &invoke_as), 137450599Sobrien INIT_STATIC_SPEC ("cpp", &cpp_spec), 137590277Sobrien INIT_STATIC_SPEC ("cpp_options", &cpp_options), 137690277Sobrien INIT_STATIC_SPEC ("cpp_unique_options", &cpp_unique_options), 137790277Sobrien INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp), 137850599Sobrien INIT_STATIC_SPEC ("cc1", &cc1_spec), 137990277Sobrien INIT_STATIC_SPEC ("cc1_options", &cc1_options), 138050599Sobrien INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec), 138150599Sobrien INIT_STATIC_SPEC ("endfile", &endfile_spec), 138250599Sobrien INIT_STATIC_SPEC ("link", &link_spec), 138350599Sobrien INIT_STATIC_SPEC ("lib", &lib_spec), 138450599Sobrien INIT_STATIC_SPEC ("libgcc", &libgcc_spec), 138550599Sobrien INIT_STATIC_SPEC ("startfile", &startfile_spec), 138650599Sobrien INIT_STATIC_SPEC ("switches_need_spaces", &switches_need_spaces), 138750599Sobrien INIT_STATIC_SPEC ("signed_char", &signed_char_spec), 138850599Sobrien INIT_STATIC_SPEC ("predefines", &cpp_predefines), 138950599Sobrien INIT_STATIC_SPEC ("cross_compile", &cross_compile), 139050599Sobrien INIT_STATIC_SPEC ("version", &compiler_version), 139150599Sobrien INIT_STATIC_SPEC ("multilib", &multilib_select), 139250599Sobrien INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults), 139350599Sobrien INIT_STATIC_SPEC ("multilib_extra", &multilib_extra), 139450599Sobrien INIT_STATIC_SPEC ("multilib_matches", &multilib_matches), 139590277Sobrien INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions), 139650599Sobrien INIT_STATIC_SPEC ("linker", &linker_name_spec), 139790277Sobrien INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec), 139890277Sobrien INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix), 139990277Sobrien INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix), 140090277Sobrien INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1), 140150599Sobrien}; 140250599Sobrien 140350599Sobrien#ifdef EXTRA_SPECS /* additional specs needed */ 140452520Sobrien/* Structure to keep track of just the first two args of a spec_list. 140590277Sobrien That is all that the EXTRA_SPECS macro gives us. */ 140652520Sobrienstruct spec_list_1 140752520Sobrien{ 140890277Sobrien const char *const name; 140990277Sobrien const char *const ptr; 141052520Sobrien}; 141152520Sobrien 141290277Sobrienstatic const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS }; 141390277Sobrienstatic struct spec_list *extra_specs = (struct spec_list *) 0; 141450599Sobrien#endif 141550599Sobrien 141650599Sobrien/* List of dynamically allocates specs that have been defined so far. */ 141750599Sobrien 141890277Sobrienstatic struct spec_list *specs = (struct spec_list *) 0; 141990277Sobrien 142090277Sobrien/* Add appropriate libgcc specs to OBSTACK, taking into account 142190277Sobrien various permutations of -shared-libgcc, -shared, and such. */ 142250599Sobrien 142390277Sobrien#ifdef ENABLE_SHARED_LIBGCC 142490277Sobrienstatic void 142590277Sobrieninit_gcc_specs (obstack, shared_name, static_name, eh_name) 142690277Sobrien struct obstack *obstack; 142790277Sobrien const char *shared_name; 142890277Sobrien const char *static_name; 142990277Sobrien const char *eh_name; 143090277Sobrien{ 143190277Sobrien char buffer[128]; 143290277Sobrien const char *p; 143390277Sobrien 143490277Sobrien /* If we see -shared-libgcc, then use the shared version. */ 143590277Sobrien sprintf (buffer, "%%{shared-libgcc:%s %s}", shared_name, static_name); 143690277Sobrien obstack_grow (obstack, buffer, strlen (buffer)); 143790277Sobrien /* If we see -static-libgcc, then use the static version. */ 143890277Sobrien sprintf (buffer, "%%{static-libgcc:%s %s}", static_name, eh_name); 143990277Sobrien obstack_grow (obstack, buffer, strlen (buffer)); 144090277Sobrien /* Otherwise, if we see -shared, then use the shared version 144190277Sobrien if using EH registration routines or static version without 144290277Sobrien exception handling routines otherwise. */ 144390277Sobrien p = "%{!shared-libgcc:%{!static-libgcc:%{shared:"; 144490277Sobrien obstack_grow (obstack, p, strlen (p)); 144590277Sobrien#ifdef LINK_EH_SPEC 144690277Sobrien sprintf (buffer, "%s}}}", static_name); 144790277Sobrien#else 144890277Sobrien sprintf (buffer, "%s}}}", shared_name); 144990277Sobrien#endif 145090277Sobrien obstack_grow (obstack, buffer, strlen (buffer)); 145190277Sobrien /* Otherwise, use the static version. */ 145290277Sobrien sprintf (buffer, 145390277Sobrien "%%{!shared-libgcc:%%{!static-libgcc:%%{!shared:%s %s}}}", 145490277Sobrien static_name, eh_name); 145590277Sobrien obstack_grow (obstack, buffer, strlen (buffer)); 145690277Sobrien} 145790277Sobrien#endif /* ENABLE_SHARED_LIBGCC */ 145890277Sobrien 145950599Sobrien/* Initialize the specs lookup routines. */ 146050599Sobrien 146150599Sobrienstatic void 146250599Sobrieninit_spec () 146350599Sobrien{ 146490277Sobrien struct spec_list *next = (struct spec_list *) 0; 146590277Sobrien struct spec_list *sl = (struct spec_list *) 0; 146650599Sobrien int i; 146750599Sobrien 146850599Sobrien if (specs) 146990277Sobrien return; /* Already initialized. */ 147050599Sobrien 147150599Sobrien if (verbose_flag) 147290277Sobrien notice ("Using built-in specs.\n"); 147350599Sobrien 147450599Sobrien#ifdef EXTRA_SPECS 147552520Sobrien extra_specs = (struct spec_list *) 147690277Sobrien xcalloc (sizeof (struct spec_list), ARRAY_SIZE (extra_specs_1)); 147790277Sobrien 147890277Sobrien for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--) 147950599Sobrien { 148050599Sobrien sl = &extra_specs[i]; 148152520Sobrien sl->name = extra_specs_1[i].name; 148252520Sobrien sl->ptr = extra_specs_1[i].ptr; 148350599Sobrien sl->next = next; 148450599Sobrien sl->name_len = strlen (sl->name); 148550599Sobrien sl->ptr_spec = &sl->ptr; 148650599Sobrien next = sl; 148750599Sobrien } 148850599Sobrien#endif 148950599Sobrien 149090277Sobrien for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) 149150599Sobrien { 149250599Sobrien sl = &static_specs[i]; 149350599Sobrien sl->next = next; 149450599Sobrien next = sl; 149550599Sobrien } 149650599Sobrien 149790277Sobrien#ifdef ENABLE_SHARED_LIBGCC 149890277Sobrien /* ??? If neither -shared-libgcc nor --static-libgcc was 149990277Sobrien seen, then we should be making an educated guess. Some proposed 150090277Sobrien heuristics for ELF include: 150190277Sobrien 150290277Sobrien (1) If "-Wl,--export-dynamic", then it's a fair bet that the 150390277Sobrien program will be doing dynamic loading, which will likely 150490277Sobrien need the shared libgcc. 150590277Sobrien 150690277Sobrien (2) If "-ldl", then it's also a fair bet that we're doing 150790277Sobrien dynamic loading. 150890277Sobrien 150990277Sobrien (3) For each ET_DYN we're linking against (either through -lfoo 151090277Sobrien or /some/path/foo.so), check to see whether it or one of 151190277Sobrien its dependencies depends on a shared libgcc. 151290277Sobrien 151390277Sobrien (4) If "-shared" 151490277Sobrien 151590277Sobrien If the runtime is fixed to look for program headers instead 151690277Sobrien of calling __register_frame_info at all, for each object, 151790277Sobrien use the shared libgcc if any EH symbol referenced. 151890277Sobrien 151990277Sobrien If crtstuff is fixed to not invoke __register_frame_info 152090277Sobrien automatically, for each object, use the shared libgcc if 152190277Sobrien any non-empty unwind section found. 152290277Sobrien 152390277Sobrien Doing any of this probably requires invoking an external program to 152490277Sobrien do the actual object file scanning. */ 152590277Sobrien { 152690277Sobrien const char *p = libgcc_spec; 152790277Sobrien int in_sep = 1; 152890277Sobrien 152990277Sobrien /* Transform the extant libgcc_spec into one that uses the shared libgcc 153090277Sobrien when given the proper command line arguments. */ 153190277Sobrien while (*p) 153290277Sobrien { 153390277Sobrien if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0) 153490277Sobrien { 153590277Sobrien init_gcc_specs (&obstack, 153690277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB 153790277Sobrien "-lgcc_s" 153890277Sobrien#else 153990277Sobrien "-lgcc_s%M" 154090277Sobrien#endif 154190277Sobrien , 154290277Sobrien "-lgcc", 154390277Sobrien "-lgcc_eh"); 154490277Sobrien p += 5; 154590277Sobrien in_sep = 0; 154690277Sobrien } 154790277Sobrien else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0) 154890277Sobrien { 154990277Sobrien /* Ug. We don't know shared library extensions. Hope that 155090277Sobrien systems that use this form don't do shared libraries. */ 155190277Sobrien init_gcc_specs (&obstack, 155290277Sobrien#ifdef NO_SHARED_LIBGCC_MULTILIB 155390277Sobrien "-lgcc_s" 155490277Sobrien#else 155590277Sobrien "-lgcc_s%M" 155690277Sobrien#endif 155790277Sobrien , 155890277Sobrien "libgcc.a%s", 155990277Sobrien "libgcc_eh.a%s"); 156090277Sobrien p += 10; 156190277Sobrien in_sep = 0; 156290277Sobrien } 156390277Sobrien else 156490277Sobrien { 156590277Sobrien obstack_1grow (&obstack, *p); 156690277Sobrien in_sep = (*p == ' '); 156790277Sobrien p += 1; 156890277Sobrien } 156990277Sobrien } 157090277Sobrien 157190277Sobrien obstack_1grow (&obstack, '\0'); 157290277Sobrien libgcc_spec = obstack_finish (&obstack); 157390277Sobrien } 157490277Sobrien#endif 157590277Sobrien#ifdef USE_AS_TRADITIONAL_FORMAT 157690277Sobrien /* Prepend "--traditional-format" to whatever asm_spec we had before. */ 157790277Sobrien { 157890277Sobrien static const char tf[] = "--traditional-format "; 157990277Sobrien obstack_grow (&obstack, tf, sizeof(tf) - 1); 158090277Sobrien obstack_grow0 (&obstack, asm_spec, strlen (asm_spec)); 158190277Sobrien asm_spec = obstack_finish (&obstack); 158290277Sobrien } 158390277Sobrien#endif 158490277Sobrien#ifdef LINK_EH_SPEC 158590277Sobrien /* Prepend LINK_EH_SPEC to whatever link_spec we had before. */ 158690277Sobrien obstack_grow (&obstack, LINK_EH_SPEC, sizeof(LINK_EH_SPEC) - 1); 158790277Sobrien obstack_grow0 (&obstack, link_spec, strlen (link_spec)); 158890277Sobrien link_spec = obstack_finish (&obstack); 158990277Sobrien#endif 159090277Sobrien 159150599Sobrien specs = sl; 159250599Sobrien} 159350599Sobrien 159418334Speter/* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is 159518334Speter removed; If the spec starts with a + then SPEC is added to the end of the 159650599Sobrien current spec. */ 159718334Speter 159818334Speterstatic void 159918334Speterset_spec (name, spec) 160052520Sobrien const char *name; 160152520Sobrien const char *spec; 160218334Speter{ 160318334Speter struct spec_list *sl; 160490277Sobrien const char *old_spec; 160550599Sobrien int name_len = strlen (name); 160650599Sobrien int i; 160718334Speter 160890277Sobrien /* If this is the first call, initialize the statically allocated specs. */ 160950599Sobrien if (!specs) 161050599Sobrien { 161190277Sobrien struct spec_list *next = (struct spec_list *) 0; 161290277Sobrien for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) 161350599Sobrien { 161450599Sobrien sl = &static_specs[i]; 161550599Sobrien sl->next = next; 161650599Sobrien next = sl; 161750599Sobrien } 161850599Sobrien specs = sl; 161950599Sobrien } 162050599Sobrien 162190277Sobrien /* See if the spec already exists. */ 162218334Speter for (sl = specs; sl; sl = sl->next) 162350599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, name)) 162418334Speter break; 162518334Speter 162618334Speter if (!sl) 162718334Speter { 162890277Sobrien /* Not found - make it. */ 162918334Speter sl = (struct spec_list *) xmalloc (sizeof (struct spec_list)); 163090277Sobrien sl->name = xstrdup (name); 163150599Sobrien sl->name_len = name_len; 163250599Sobrien sl->ptr_spec = &sl->ptr; 163350599Sobrien sl->alloc_p = 0; 163450599Sobrien *(sl->ptr_spec) = ""; 163518334Speter sl->next = specs; 163618334Speter specs = sl; 163718334Speter } 163818334Speter 163950599Sobrien old_spec = *(sl->ptr_spec); 164052520Sobrien *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1])) 164190277Sobrien ? concat (old_spec, spec + 1, NULL) 164290277Sobrien : xstrdup (spec)); 164318334Speter 164450599Sobrien#ifdef DEBUG_SPECS 164550599Sobrien if (verbose_flag) 164652520Sobrien notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec)); 164750599Sobrien#endif 164850599Sobrien 164990277Sobrien /* Free the old spec. */ 165050599Sobrien if (old_spec && sl->alloc_p) 165190277Sobrien free ((PTR) old_spec); 165250599Sobrien 165350599Sobrien sl->alloc_p = 1; 165418334Speter} 165518334Speter 165618334Speter/* Accumulate a command (program name and args), and run it. */ 165718334Speter 165818334Speter/* Vector of pointers to arguments in the current line of specifications. */ 165918334Speter 166090277Sobrienstatic const char **argbuf; 166118334Speter 166218334Speter/* Number of elements allocated in argbuf. */ 166318334Speter 166418334Speterstatic int argbuf_length; 166518334Speter 166618334Speter/* Number of elements in argbuf currently in use (containing args). */ 166718334Speter 166818334Speterstatic int argbuf_index; 166918334Speter 167090277Sobrien/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated 167190277Sobrien temp file. If the HOST_BIT_BUCKET is used for %j, no entry is made for 167290277Sobrien it here. */ 167350599Sobrien 167418334Speterstatic struct temp_name { 167552520Sobrien const char *suffix; /* suffix associated with the code. */ 167618334Speter int length; /* strlen (suffix). */ 167718334Speter int unique; /* Indicates whether %g or %u/%U was used. */ 167852520Sobrien const char *filename; /* associated filename. */ 167918334Speter int filename_length; /* strlen (filename). */ 168018334Speter struct temp_name *next; 168118334Speter} *temp_names; 168218334Speter 168318334Speter/* Number of commands executed so far. */ 168418334Speter 168518334Speterstatic int execution_count; 168618334Speter 168718334Speter/* Number of commands that exited with a signal. */ 168818334Speter 168918334Speterstatic int signal_count; 169018334Speter 169118334Speter/* Name with which this program was invoked. */ 169218334Speter 169352520Sobrienstatic const char *programname; 169418334Speter 169518334Speter/* Clear out the vector of arguments (after a command is executed). */ 169618334Speter 169718334Speterstatic void 169818334Speterclear_args () 169918334Speter{ 170018334Speter argbuf_index = 0; 170118334Speter} 170218334Speter 170318334Speter/* Add one argument to the vector at the end. 170418334Speter This is done when a space is seen or at the end of the line. 170518334Speter If DELETE_ALWAYS is nonzero, the arg is a filename 170618334Speter and the file should be deleted eventually. 170718334Speter If DELETE_FAILURE is nonzero, the arg is a filename 170818334Speter and the file should be deleted if this compilation fails. */ 170918334Speter 171018334Speterstatic void 171118334Speterstore_arg (arg, delete_always, delete_failure) 171290277Sobrien const char *arg; 171318334Speter int delete_always, delete_failure; 171418334Speter{ 171518334Speter if (argbuf_index + 1 == argbuf_length) 171650599Sobrien argbuf 171790277Sobrien = (const char **) xrealloc (argbuf, 171890277Sobrien (argbuf_length *= 2) * sizeof (const char *)); 171918334Speter 172018334Speter argbuf[argbuf_index++] = arg; 172118334Speter argbuf[argbuf_index] = 0; 172218334Speter 172318334Speter if (delete_always || delete_failure) 172418334Speter record_temp_file (arg, delete_always, delete_failure); 172518334Speter} 172618334Speter 172790277Sobrien/* Load specs from a file name named FILENAME, replacing occurrences of 172890277Sobrien various different types of line-endings, \r\n, \n\r and just \r, with 172990277Sobrien a single \n. */ 173050599Sobrien 173190277Sobrienstatic char * 173290277Sobrienload_specs (filename) 173352520Sobrien const char *filename; 173450599Sobrien{ 173550599Sobrien int desc; 173650599Sobrien int readlen; 173750599Sobrien struct stat statbuf; 173850599Sobrien char *buffer; 173990277Sobrien char *buffer_p; 174090277Sobrien char *specs; 174190277Sobrien char *specs_p; 174250599Sobrien 174350599Sobrien if (verbose_flag) 174452520Sobrien notice ("Reading specs from %s\n", filename); 174550599Sobrien 174650599Sobrien /* Open and stat the file. */ 174750599Sobrien desc = open (filename, O_RDONLY, 0); 174850599Sobrien if (desc < 0) 174950599Sobrien pfatal_with_name (filename); 175050599Sobrien if (stat (filename, &statbuf) < 0) 175150599Sobrien pfatal_with_name (filename); 175250599Sobrien 175350599Sobrien /* Read contents of file into BUFFER. */ 175450599Sobrien buffer = xmalloc ((unsigned) statbuf.st_size + 1); 175550599Sobrien readlen = read (desc, buffer, (unsigned) statbuf.st_size); 175650599Sobrien if (readlen < 0) 175750599Sobrien pfatal_with_name (filename); 175850599Sobrien buffer[readlen] = 0; 175950599Sobrien close (desc); 176050599Sobrien 176190277Sobrien specs = xmalloc (readlen + 1); 176290277Sobrien specs_p = specs; 176390277Sobrien for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++) 176490277Sobrien { 176590277Sobrien int skip = 0; 176690277Sobrien char c = *buffer_p; 176790277Sobrien if (c == '\r') 176890277Sobrien { 176990277Sobrien if (buffer_p > buffer && *(buffer_p - 1) == '\n') /* \n\r */ 177090277Sobrien skip = 1; 177190277Sobrien else if (*(buffer_p + 1) == '\n') /* \r\n */ 177290277Sobrien skip = 1; 177390277Sobrien else /* \r */ 177490277Sobrien c = '\n'; 177590277Sobrien } 177690277Sobrien if (! skip) 177790277Sobrien *specs_p++ = c; 177890277Sobrien } 177990277Sobrien *specs_p = '\0'; 178090277Sobrien 178190277Sobrien free (buffer); 178290277Sobrien return (specs); 178390277Sobrien} 178490277Sobrien 178590277Sobrien/* Read compilation specs from a file named FILENAME, 178690277Sobrien replacing the default ones. 178790277Sobrien 178890277Sobrien A suffix which starts with `*' is a definition for 178990277Sobrien one of the machine-specific sub-specs. The "suffix" should be 179090277Sobrien *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc. 179190277Sobrien The corresponding spec is stored in asm_spec, etc., 179290277Sobrien rather than in the `compilers' vector. 179390277Sobrien 179490277Sobrien Anything invalid in the file is a fatal error. */ 179590277Sobrien 179690277Sobrienstatic void 179790277Sobrienread_specs (filename, main_p) 179890277Sobrien const char *filename; 179990277Sobrien int main_p; 180090277Sobrien{ 180190277Sobrien char *buffer; 180290277Sobrien char *p; 180390277Sobrien 180490277Sobrien buffer = load_specs (filename); 180590277Sobrien 180650599Sobrien /* Scan BUFFER for specs, putting them in the vector. */ 180750599Sobrien p = buffer; 180850599Sobrien while (1) 180950599Sobrien { 181050599Sobrien char *suffix; 181150599Sobrien char *spec; 181250599Sobrien char *in, *out, *p1, *p2, *p3; 181350599Sobrien 181450599Sobrien /* Advance P in BUFFER to the next nonblank nocomment line. */ 181550599Sobrien p = skip_whitespace (p); 181650599Sobrien if (*p == 0) 181750599Sobrien break; 181850599Sobrien 181950599Sobrien /* Is this a special command that starts with '%'? */ 182050599Sobrien /* Don't allow this for the main specs file, since it would 182150599Sobrien encourage people to overwrite it. */ 182250599Sobrien if (*p == '%' && !main_p) 182350599Sobrien { 182450599Sobrien p1 = p; 182550599Sobrien while (*p && *p != '\n') 182650599Sobrien p++; 182750599Sobrien 182890277Sobrien /* Skip '\n'. */ 182990277Sobrien p++; 183050599Sobrien 183190277Sobrien if (!strncmp (p1, "%include", sizeof ("%include") - 1) 183250599Sobrien && (p1[sizeof "%include" - 1] == ' ' 183350599Sobrien || p1[sizeof "%include" - 1] == '\t')) 183450599Sobrien { 183550599Sobrien char *new_filename; 183650599Sobrien 183750599Sobrien p1 += sizeof ("%include"); 183850599Sobrien while (*p1 == ' ' || *p1 == '\t') 183950599Sobrien p1++; 184050599Sobrien 184150599Sobrien if (*p1++ != '<' || p[-2] != '>') 184252520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 184352520Sobrien (long) (p1 - buffer + 1)); 184450599Sobrien 184550599Sobrien p[-2] = '\0'; 184650599Sobrien new_filename = find_a_file (&startfile_prefixes, p1, R_OK); 184750599Sobrien read_specs (new_filename ? new_filename : p1, FALSE); 184850599Sobrien continue; 184950599Sobrien } 185050599Sobrien else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1) 185150599Sobrien && (p1[sizeof "%include_noerr" - 1] == ' ' 185250599Sobrien || p1[sizeof "%include_noerr" - 1] == '\t')) 185350599Sobrien { 185450599Sobrien char *new_filename; 185550599Sobrien 185650599Sobrien p1 += sizeof "%include_noerr"; 185790277Sobrien while (*p1 == ' ' || *p1 == '\t') 185890277Sobrien p1++; 185950599Sobrien 186050599Sobrien if (*p1++ != '<' || p[-2] != '>') 186152520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 186252520Sobrien (long) (p1 - buffer + 1)); 186350599Sobrien 186450599Sobrien p[-2] = '\0'; 186550599Sobrien new_filename = find_a_file (&startfile_prefixes, p1, R_OK); 186650599Sobrien if (new_filename) 186750599Sobrien read_specs (new_filename, FALSE); 186850599Sobrien else if (verbose_flag) 186990277Sobrien notice ("could not find specs file %s\n", p1); 187050599Sobrien continue; 187150599Sobrien } 187250599Sobrien else if (!strncmp (p1, "%rename", sizeof "%rename" - 1) 187350599Sobrien && (p1[sizeof "%rename" - 1] == ' ' 187450599Sobrien || p1[sizeof "%rename" - 1] == '\t')) 187550599Sobrien { 187650599Sobrien int name_len; 187750599Sobrien struct spec_list *sl; 187850599Sobrien 187950599Sobrien /* Get original name */ 188050599Sobrien p1 += sizeof "%rename"; 188150599Sobrien while (*p1 == ' ' || *p1 == '\t') 188250599Sobrien p1++; 188350599Sobrien 188490277Sobrien if (! ISALPHA ((unsigned char) *p1)) 188552520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 188652520Sobrien (long) (p1 - buffer)); 188750599Sobrien 188850599Sobrien p2 = p1; 188990277Sobrien while (*p2 && !ISSPACE ((unsigned char) *p2)) 189050599Sobrien p2++; 189150599Sobrien 189250599Sobrien if (*p2 != ' ' && *p2 != '\t') 189352520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 189452520Sobrien (long) (p2 - buffer)); 189550599Sobrien 189650599Sobrien name_len = p2 - p1; 189750599Sobrien *p2++ = '\0'; 189850599Sobrien while (*p2 == ' ' || *p2 == '\t') 189950599Sobrien p2++; 190050599Sobrien 190190277Sobrien if (! ISALPHA ((unsigned char) *p2)) 190252520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 190352520Sobrien (long) (p2 - buffer)); 190450599Sobrien 190590277Sobrien /* Get new spec name. */ 190650599Sobrien p3 = p2; 190790277Sobrien while (*p3 && !ISSPACE ((unsigned char) *p3)) 190850599Sobrien p3++; 190950599Sobrien 191090277Sobrien if (p3 != p - 1) 191152520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 191252520Sobrien (long) (p3 - buffer)); 191350599Sobrien *p3 = '\0'; 191450599Sobrien 191550599Sobrien for (sl = specs; sl; sl = sl->next) 191650599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, p1)) 191750599Sobrien break; 191850599Sobrien 191950599Sobrien if (!sl) 192050599Sobrien fatal ("specs %s spec was not found to be renamed", p1); 192150599Sobrien 192250599Sobrien if (strcmp (p1, p2) == 0) 192350599Sobrien continue; 192450599Sobrien 192550599Sobrien if (verbose_flag) 192650599Sobrien { 192752520Sobrien notice ("rename spec %s to %s\n", p1, p2); 192850599Sobrien#ifdef DEBUG_SPECS 192952520Sobrien notice ("spec is '%s'\n\n", *(sl->ptr_spec)); 193050599Sobrien#endif 193150599Sobrien } 193250599Sobrien 193350599Sobrien set_spec (p2, *(sl->ptr_spec)); 193450599Sobrien if (sl->alloc_p) 193590277Sobrien free ((PTR) *(sl->ptr_spec)); 193650599Sobrien 193750599Sobrien *(sl->ptr_spec) = ""; 193850599Sobrien sl->alloc_p = 0; 193950599Sobrien continue; 194050599Sobrien } 194150599Sobrien else 194252520Sobrien fatal ("specs unknown %% command after %ld characters", 194352520Sobrien (long) (p1 - buffer)); 194450599Sobrien } 194550599Sobrien 194650599Sobrien /* Find the colon that should end the suffix. */ 194750599Sobrien p1 = p; 194850599Sobrien while (*p1 && *p1 != ':' && *p1 != '\n') 194950599Sobrien p1++; 195050599Sobrien 195150599Sobrien /* The colon shouldn't be missing. */ 195250599Sobrien if (*p1 != ':') 195352520Sobrien fatal ("specs file malformed after %ld characters", 195452520Sobrien (long) (p1 - buffer)); 195550599Sobrien 195650599Sobrien /* Skip back over trailing whitespace. */ 195750599Sobrien p2 = p1; 195850599Sobrien while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) 195950599Sobrien p2--; 196050599Sobrien 196150599Sobrien /* Copy the suffix to a string. */ 196250599Sobrien suffix = save_string (p, p2 - p); 196350599Sobrien /* Find the next line. */ 196450599Sobrien p = skip_whitespace (p1 + 1); 196550599Sobrien if (p[1] == 0) 196652520Sobrien fatal ("specs file malformed after %ld characters", 196752520Sobrien (long) (p - buffer)); 196850599Sobrien 196950599Sobrien p1 = p; 197050599Sobrien /* Find next blank line or end of string. */ 197150599Sobrien while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0'))) 197250599Sobrien p1++; 197350599Sobrien 197450599Sobrien /* Specs end at the blank line and do not include the newline. */ 197550599Sobrien spec = save_string (p, p1 - p); 197650599Sobrien p = p1; 197750599Sobrien 197850599Sobrien /* Delete backslash-newline sequences from the spec. */ 197950599Sobrien in = spec; 198050599Sobrien out = spec; 198150599Sobrien while (*in != 0) 198250599Sobrien { 198350599Sobrien if (in[0] == '\\' && in[1] == '\n') 198450599Sobrien in += 2; 198550599Sobrien else if (in[0] == '#') 198650599Sobrien while (*in && *in != '\n') 198750599Sobrien in++; 198850599Sobrien 198950599Sobrien else 199050599Sobrien *out++ = *in++; 199150599Sobrien } 199250599Sobrien *out = 0; 199350599Sobrien 199450599Sobrien if (suffix[0] == '*') 199550599Sobrien { 199650599Sobrien if (! strcmp (suffix, "*link_command")) 199750599Sobrien link_command_spec = spec; 199850599Sobrien else 199950599Sobrien set_spec (suffix + 1, spec); 200050599Sobrien } 200150599Sobrien else 200250599Sobrien { 200350599Sobrien /* Add this pair to the vector. */ 200450599Sobrien compilers 200550599Sobrien = ((struct compiler *) 200650599Sobrien xrealloc (compilers, 200750599Sobrien (n_compilers + 2) * sizeof (struct compiler))); 200850599Sobrien 200950599Sobrien compilers[n_compilers].suffix = suffix; 201090277Sobrien compilers[n_compilers].spec = spec; 201150599Sobrien n_compilers++; 201290277Sobrien memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]); 201350599Sobrien } 201450599Sobrien 201550599Sobrien if (*suffix == 0) 201650599Sobrien link_command_spec = spec; 201750599Sobrien } 201850599Sobrien 201950599Sobrien if (link_command_spec == 0) 202050599Sobrien fatal ("spec file has no spec for linking"); 202150599Sobrien} 202250599Sobrien 202318334Speter/* Record the names of temporary files we tell compilers to write, 202418334Speter and delete them at the end of the run. */ 202518334Speter 202618334Speter/* This is the common prefix we use to make temp file names. 202718334Speter It is chosen once for each run of this program. 202890277Sobrien It is substituted into a spec by %g or %j. 202918334Speter Thus, all temp file names contain this prefix. 203018334Speter In practice, all temp file names start with this prefix. 203118334Speter 203218334Speter This prefix comes from the envvar TMPDIR if it is defined; 203318334Speter otherwise, from the P_tmpdir macro if that is defined; 203450599Sobrien otherwise, in /usr/tmp or /tmp; 203550599Sobrien or finally the current directory if all else fails. */ 203618334Speter 203752520Sobrienstatic const char *temp_filename; 203818334Speter 203918334Speter/* Length of the prefix. */ 204018334Speter 204118334Speterstatic int temp_filename_length; 204218334Speter 204318334Speter/* Define the list of temporary files to delete. */ 204418334Speter 204518334Speterstruct temp_file 204618334Speter{ 204752520Sobrien const char *name; 204818334Speter struct temp_file *next; 204918334Speter}; 205018334Speter 205118334Speter/* Queue of files to delete on success or failure of compilation. */ 205218334Speterstatic struct temp_file *always_delete_queue; 205318334Speter/* Queue of files to delete on failure of compilation. */ 205418334Speterstatic struct temp_file *failure_delete_queue; 205518334Speter 205618334Speter/* Record FILENAME as a file to be deleted automatically. 205718334Speter ALWAYS_DELETE nonzero means delete it if all compilation succeeds; 205818334Speter otherwise delete it in any case. 205918334Speter FAIL_DELETE nonzero means delete it if a compilation step fails; 206018334Speter otherwise delete it in any case. */ 206118334Speter 206290277Sobrienvoid 206318334Speterrecord_temp_file (filename, always_delete, fail_delete) 206452520Sobrien const char *filename; 206518334Speter int always_delete; 206618334Speter int fail_delete; 206718334Speter{ 206890277Sobrien char *const name = xstrdup (filename); 206918334Speter 207018334Speter if (always_delete) 207118334Speter { 207290277Sobrien struct temp_file *temp; 207318334Speter for (temp = always_delete_queue; temp; temp = temp->next) 207418334Speter if (! strcmp (name, temp->name)) 207518334Speter goto already1; 207650599Sobrien 207718334Speter temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); 207818334Speter temp->next = always_delete_queue; 207918334Speter temp->name = name; 208018334Speter always_delete_queue = temp; 208150599Sobrien 208218334Speter already1:; 208318334Speter } 208418334Speter 208518334Speter if (fail_delete) 208618334Speter { 208790277Sobrien struct temp_file *temp; 208818334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 208918334Speter if (! strcmp (name, temp->name)) 209018334Speter goto already2; 209150599Sobrien 209218334Speter temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); 209318334Speter temp->next = failure_delete_queue; 209418334Speter temp->name = name; 209518334Speter failure_delete_queue = temp; 209650599Sobrien 209718334Speter already2:; 209818334Speter } 209918334Speter} 210018334Speter 210118334Speter/* Delete all the temporary files whose names we previously recorded. */ 210218334Speter 210318334Speterstatic void 210418334Speterdelete_if_ordinary (name) 210552520Sobrien const char *name; 210618334Speter{ 210718334Speter struct stat st; 210818334Speter#ifdef DEBUG 210918334Speter int i, c; 211018334Speter 211118334Speter printf ("Delete %s? (y or n) ", name); 211218334Speter fflush (stdout); 211318334Speter i = getchar (); 211418334Speter if (i != '\n') 211550599Sobrien while ((c = getchar ()) != '\n' && c != EOF) 211650599Sobrien ; 211750599Sobrien 211818334Speter if (i == 'y' || i == 'Y') 211918334Speter#endif /* DEBUG */ 212018334Speter if (stat (name, &st) >= 0 && S_ISREG (st.st_mode)) 212118334Speter if (unlink (name) < 0) 212218334Speter if (verbose_flag) 212318334Speter perror_with_name (name); 212418334Speter} 212518334Speter 212618334Speterstatic void 212718334Speterdelete_temp_files () 212818334Speter{ 212990277Sobrien struct temp_file *temp; 213018334Speter 213118334Speter for (temp = always_delete_queue; temp; temp = temp->next) 213218334Speter delete_if_ordinary (temp->name); 213318334Speter always_delete_queue = 0; 213418334Speter} 213518334Speter 213618334Speter/* Delete all the files to be deleted on error. */ 213718334Speter 213818334Speterstatic void 213918334Speterdelete_failure_queue () 214018334Speter{ 214190277Sobrien struct temp_file *temp; 214218334Speter 214318334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 214418334Speter delete_if_ordinary (temp->name); 214518334Speter} 214618334Speter 214718334Speterstatic void 214818334Speterclear_failure_queue () 214918334Speter{ 215018334Speter failure_delete_queue = 0; 215118334Speter} 215218334Speter 215318334Speter/* Build a list of search directories from PATHS. 215418334Speter PREFIX is a string to prepend to the list. 215518334Speter If CHECK_DIR_P is non-zero we ensure the directory exists. 215618334Speter This is used mostly by putenv_from_prefixes so we use `collect_obstack'. 215718334Speter It is also used by the --print-search-dirs flag. */ 215818334Speter 215918334Speterstatic char * 216018334Speterbuild_search_list (paths, prefix, check_dir_p) 216118334Speter struct path_prefix *paths; 216252520Sobrien const char *prefix; 216318334Speter int check_dir_p; 216418334Speter{ 216518334Speter int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0; 216618334Speter int just_suffix_len 216718334Speter = (just_machine_suffix) ? strlen (just_machine_suffix) : 0; 216818334Speter int first_time = TRUE; 216918334Speter struct prefix_list *pprefix; 217018334Speter 217118334Speter obstack_grow (&collect_obstack, prefix, strlen (prefix)); 217290277Sobrien obstack_1grow (&collect_obstack, '='); 217318334Speter 217418334Speter for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next) 217518334Speter { 217618334Speter int len = strlen (pprefix->prefix); 217718334Speter 217818334Speter if (machine_suffix 217950599Sobrien && (! check_dir_p 218018334Speter || is_directory (pprefix->prefix, machine_suffix, 0))) 218118334Speter { 218218334Speter if (!first_time) 218318334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 218490277Sobrien 218518334Speter first_time = FALSE; 218618334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 218718334Speter obstack_grow (&collect_obstack, machine_suffix, suffix_len); 218818334Speter } 218918334Speter 219018334Speter if (just_machine_suffix 219118334Speter && pprefix->require_machine_suffix == 2 219250599Sobrien && (! check_dir_p 219318334Speter || is_directory (pprefix->prefix, just_machine_suffix, 0))) 219418334Speter { 219550599Sobrien if (! first_time) 219618334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 219790277Sobrien 219818334Speter first_time = FALSE; 219918334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 220018334Speter obstack_grow (&collect_obstack, just_machine_suffix, 220118334Speter just_suffix_len); 220218334Speter } 220318334Speter 220450599Sobrien if (! pprefix->require_machine_suffix) 220518334Speter { 220650599Sobrien if (! first_time) 220718334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 220818334Speter 220918334Speter first_time = FALSE; 221018334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 221118334Speter } 221218334Speter } 221350599Sobrien 221418334Speter obstack_1grow (&collect_obstack, '\0'); 221518334Speter return obstack_finish (&collect_obstack); 221618334Speter} 221718334Speter 221850599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 221950599Sobrien for collect. */ 222018334Speter 222118334Speterstatic void 222218334Speterputenv_from_prefixes (paths, env_var) 222318334Speter struct path_prefix *paths; 222452520Sobrien const char *env_var; 222518334Speter{ 222618334Speter putenv (build_search_list (paths, env_var, 1)); 222718334Speter} 222818334Speter 222990277Sobrien#ifndef VMS 223090277Sobrien 223190277Sobrien/* FIXME: the location independence code for VMS is hairier than this, 223290277Sobrien and hasn't been written. */ 223390277Sobrien 223490277Sobrien/* Split a filename into component directories. */ 223590277Sobrien 223690277Sobrienstatic char ** 223790277Sobriensplit_directories (name, ptr_num_dirs) 223890277Sobrien const char *name; 223990277Sobrien int *ptr_num_dirs; 224090277Sobrien{ 224190277Sobrien int num_dirs = 0; 224290277Sobrien char **dirs; 224390277Sobrien const char *p, *q; 224490277Sobrien int ch; 224590277Sobrien 224690277Sobrien /* Count the number of directories. Special case MSDOS disk names as part 224790277Sobrien of the initial directory. */ 224890277Sobrien p = name; 224990277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 225090277Sobrien if (name[1] == ':' && IS_DIR_SEPARATOR (name[2])) 225190277Sobrien { 225290277Sobrien p += 3; 225390277Sobrien num_dirs++; 225490277Sobrien } 225590277Sobrien#endif /* HAVE_DOS_BASED_FILE_SYSTEM */ 225690277Sobrien 225790277Sobrien while ((ch = *p++) != '\0') 225890277Sobrien { 225990277Sobrien if (IS_DIR_SEPARATOR (ch)) 226090277Sobrien { 226190277Sobrien num_dirs++; 226290277Sobrien while (IS_DIR_SEPARATOR (*p)) 226390277Sobrien p++; 226490277Sobrien } 226590277Sobrien } 226690277Sobrien 226790277Sobrien dirs = (char **) xmalloc (sizeof (char *) * (num_dirs + 2)); 226890277Sobrien 226990277Sobrien /* Now copy the directory parts. */ 227090277Sobrien num_dirs = 0; 227190277Sobrien p = name; 227290277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 227390277Sobrien if (name[1] == ':' && IS_DIR_SEPARATOR (name[2])) 227490277Sobrien { 227590277Sobrien dirs[num_dirs++] = save_string (p, 3); 227690277Sobrien p += 3; 227790277Sobrien } 227890277Sobrien#endif /* HAVE_DOS_BASED_FILE_SYSTEM */ 227990277Sobrien 228090277Sobrien q = p; 228190277Sobrien while ((ch = *p++) != '\0') 228290277Sobrien { 228390277Sobrien if (IS_DIR_SEPARATOR (ch)) 228490277Sobrien { 228590277Sobrien while (IS_DIR_SEPARATOR (*p)) 228690277Sobrien p++; 228790277Sobrien 228890277Sobrien dirs[num_dirs++] = save_string (q, p - q); 228990277Sobrien q = p; 229090277Sobrien } 229190277Sobrien } 229290277Sobrien 229390277Sobrien if (p - 1 - q > 0) 229490277Sobrien dirs[num_dirs++] = save_string (q, p - 1 - q); 229590277Sobrien 229690277Sobrien dirs[num_dirs] = NULL; 229790277Sobrien if (ptr_num_dirs) 229890277Sobrien *ptr_num_dirs = num_dirs; 229990277Sobrien 230090277Sobrien return dirs; 230190277Sobrien} 230290277Sobrien 230390277Sobrien/* Release storage held by split directories. */ 230490277Sobrien 230590277Sobrienstatic void 230690277Sobrienfree_split_directories (dirs) 230790277Sobrien char **dirs; 230890277Sobrien{ 230990277Sobrien int i = 0; 231090277Sobrien 231190277Sobrien while (dirs[i] != NULL) 231290277Sobrien free (dirs[i++]); 231390277Sobrien 231490277Sobrien free ((char *) dirs); 231590277Sobrien} 231690277Sobrien 231790277Sobrien/* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string that gets 231890277Sobrien to PREFIX starting with the directory portion of PROGNAME and a relative 231990277Sobrien pathname of the difference between BIN_PREFIX and PREFIX. 232090277Sobrien 232190277Sobrien For example, if BIN_PREFIX is /alpha/beta/gamma/gcc/delta, PREFIX is 232290277Sobrien /alpha/beta/gamma/omega/, and PROGNAME is /red/green/blue/gcc, then this 232390277Sobrien function will return /red/green/blue/../omega. 232490277Sobrien 232590277Sobrien If no relative prefix can be found, return NULL. */ 232690277Sobrien 232790277Sobrienstatic char * 232890277Sobrienmake_relative_prefix (progname, bin_prefix, prefix) 232990277Sobrien const char *progname; 233090277Sobrien const char *bin_prefix; 233190277Sobrien const char *prefix; 233290277Sobrien{ 233390277Sobrien char **prog_dirs, **bin_dirs, **prefix_dirs; 233490277Sobrien int prog_num, bin_num, prefix_num, std_loc_p; 233590277Sobrien int i, n, common; 233690277Sobrien 233790277Sobrien prog_dirs = split_directories (progname, &prog_num); 233890277Sobrien bin_dirs = split_directories (bin_prefix, &bin_num); 233990277Sobrien 234090277Sobrien /* If there is no full pathname, try to find the program by checking in each 234190277Sobrien of the directories specified in the PATH environment variable. */ 234290277Sobrien if (prog_num == 1) 234390277Sobrien { 234490277Sobrien char *temp; 234590277Sobrien 234690277Sobrien GET_ENV_PATH_LIST (temp, "PATH"); 234790277Sobrien if (temp) 234890277Sobrien { 234990277Sobrien char *startp, *endp, *nstore; 235090277Sobrien size_t prefixlen = strlen (temp) + 1; 235190277Sobrien if (prefixlen < 2) 235290277Sobrien prefixlen = 2; 235390277Sobrien 235490277Sobrien nstore = (char *) alloca (prefixlen + strlen (progname) + 1); 235590277Sobrien 235690277Sobrien startp = endp = temp; 235790277Sobrien while (1) 235890277Sobrien { 235990277Sobrien if (*endp == PATH_SEPARATOR || *endp == 0) 236090277Sobrien { 236190277Sobrien if (endp == startp) 236290277Sobrien { 236390277Sobrien nstore[0] = '.'; 236490277Sobrien nstore[1] = DIR_SEPARATOR; 236590277Sobrien nstore[2] = '\0'; 236690277Sobrien } 236790277Sobrien else 236890277Sobrien { 236990277Sobrien strncpy (nstore, startp, endp - startp); 237090277Sobrien if (! IS_DIR_SEPARATOR (endp[-1])) 237190277Sobrien { 237290277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 237390277Sobrien nstore[endp - startp + 1] = 0; 237490277Sobrien } 237590277Sobrien else 237690277Sobrien nstore[endp - startp] = 0; 237790277Sobrien } 237890277Sobrien strcat (nstore, progname); 237990277Sobrien if (! access (nstore, X_OK) 238090277Sobrien#ifdef HAVE_HOST_EXECUTABLE_SUFFIX 238190277Sobrien || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK) 238290277Sobrien#endif 238390277Sobrien ) 238490277Sobrien { 238590277Sobrien free_split_directories (prog_dirs); 238690277Sobrien progname = nstore; 238790277Sobrien prog_dirs = split_directories (progname, &prog_num); 238890277Sobrien break; 238990277Sobrien } 239090277Sobrien 239190277Sobrien if (*endp == 0) 239290277Sobrien break; 239390277Sobrien endp = startp = endp + 1; 239490277Sobrien } 239590277Sobrien else 239690277Sobrien endp++; 239790277Sobrien } 239890277Sobrien } 239990277Sobrien } 240090277Sobrien 240190277Sobrien /* Remove the program name from comparison of directory names. */ 240290277Sobrien prog_num--; 240390277Sobrien 240490277Sobrien /* Determine if the compiler is installed in the standard location, and if 240590277Sobrien so, we don't need to specify relative directories. Also, if argv[0] 240690277Sobrien doesn't contain any directory specifiers, there is not much we can do. */ 240790277Sobrien std_loc_p = 0; 240890277Sobrien if (prog_num == bin_num) 240990277Sobrien { 241090277Sobrien for (i = 0; i < bin_num; i++) 241190277Sobrien { 241290277Sobrien if (strcmp (prog_dirs[i], bin_dirs[i]) != 0) 241390277Sobrien break; 241490277Sobrien } 241590277Sobrien 241690277Sobrien if (prog_num <= 0 || i == bin_num) 241790277Sobrien { 241890277Sobrien std_loc_p = 1; 241990277Sobrien free_split_directories (prog_dirs); 242090277Sobrien free_split_directories (bin_dirs); 242190277Sobrien prog_dirs = bin_dirs = (char **) 0; 242290277Sobrien return NULL; 242390277Sobrien } 242490277Sobrien } 242590277Sobrien 242690277Sobrien prefix_dirs = split_directories (prefix, &prefix_num); 242790277Sobrien 242890277Sobrien /* Find how many directories are in common between bin_prefix & prefix. */ 242990277Sobrien n = (prefix_num < bin_num) ? prefix_num : bin_num; 243090277Sobrien for (common = 0; common < n; common++) 243190277Sobrien { 243290277Sobrien if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0) 243390277Sobrien break; 243490277Sobrien } 243590277Sobrien 243690277Sobrien /* If there are no common directories, there can be no relative prefix. */ 243790277Sobrien if (common == 0) 243890277Sobrien { 243990277Sobrien free_split_directories (prog_dirs); 244090277Sobrien free_split_directories (bin_dirs); 244190277Sobrien free_split_directories (prefix_dirs); 244290277Sobrien return NULL; 244390277Sobrien } 244490277Sobrien 244590277Sobrien /* Build up the pathnames in argv[0]. */ 244690277Sobrien for (i = 0; i < prog_num; i++) 244790277Sobrien obstack_grow (&obstack, prog_dirs[i], strlen (prog_dirs[i])); 244890277Sobrien 244990277Sobrien /* Now build up the ..'s. */ 245090277Sobrien for (i = common; i < n; i++) 245190277Sobrien { 245290277Sobrien obstack_grow (&obstack, DIR_UP, sizeof (DIR_UP) - 1); 245390277Sobrien obstack_1grow (&obstack, DIR_SEPARATOR); 245490277Sobrien } 245590277Sobrien 245690277Sobrien /* Put in directories to move over to prefix. */ 245790277Sobrien for (i = common; i < prefix_num; i++) 245890277Sobrien obstack_grow (&obstack, prefix_dirs[i], strlen (prefix_dirs[i])); 245990277Sobrien 246090277Sobrien free_split_directories (prog_dirs); 246190277Sobrien free_split_directories (bin_dirs); 246290277Sobrien free_split_directories (prefix_dirs); 246390277Sobrien 246490277Sobrien obstack_1grow (&obstack, '\0'); 246590277Sobrien return obstack_finish (&obstack); 246690277Sobrien} 246790277Sobrien#endif /* VMS */ 246890277Sobrien 246990277Sobrien/* Check whether NAME can be accessed in MODE. This is like access, 247090277Sobrien except that it never considers directories to be executable. */ 247190277Sobrien 247290277Sobrienstatic int 247390277Sobrienaccess_check (name, mode) 247490277Sobrien const char *name; 247590277Sobrien int mode; 247690277Sobrien{ 247790277Sobrien if (mode == X_OK) 247890277Sobrien { 247990277Sobrien struct stat st; 248090277Sobrien 248190277Sobrien if (stat (name, &st) < 0 248290277Sobrien || S_ISDIR (st.st_mode)) 248390277Sobrien return -1; 248490277Sobrien } 248590277Sobrien 248690277Sobrien return access (name, mode); 248790277Sobrien} 248890277Sobrien 248918334Speter/* Search for NAME using the prefix list PREFIXES. MODE is passed to 249018334Speter access to check permissions. 249150599Sobrien Return 0 if not found, otherwise return its name, allocated with malloc. */ 249218334Speter 249318334Speterstatic char * 249418334Speterfind_a_file (pprefix, name, mode) 249518334Speter struct path_prefix *pprefix; 249652520Sobrien const char *name; 249718334Speter int mode; 249818334Speter{ 249918334Speter char *temp; 250090277Sobrien const char *const file_suffix = 250190277Sobrien ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : ""); 250218334Speter struct prefix_list *pl; 250318334Speter int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1; 250418334Speter 250552520Sobrien#ifdef DEFAULT_ASSEMBLER 250690277Sobrien if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) 250790277Sobrien return xstrdup (DEFAULT_ASSEMBLER); 250852520Sobrien#endif 250952520Sobrien 251052520Sobrien#ifdef DEFAULT_LINKER 251190277Sobrien if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) 251290277Sobrien return xstrdup (DEFAULT_LINKER); 251352520Sobrien#endif 251452520Sobrien 251518334Speter if (machine_suffix) 251618334Speter len += strlen (machine_suffix); 251718334Speter 251818334Speter temp = xmalloc (len); 251918334Speter 252018334Speter /* Determine the filename to execute (special case for absolute paths). */ 252118334Speter 252290277Sobrien if (IS_ABSOLUTE_PATHNAME (name)) 252318334Speter { 252452520Sobrien if (access (name, mode) == 0) 252518334Speter { 252618334Speter strcpy (temp, name); 252718334Speter return temp; 252818334Speter } 252918334Speter } 253018334Speter else 253118334Speter for (pl = pprefix->plist; pl; pl = pl->next) 253218334Speter { 253318334Speter if (machine_suffix) 253418334Speter { 253518334Speter /* Some systems have a suffix for executable files. 253618334Speter So try appending that first. */ 253718334Speter if (file_suffix[0] != 0) 253818334Speter { 253918334Speter strcpy (temp, pl->prefix); 254018334Speter strcat (temp, machine_suffix); 254118334Speter strcat (temp, name); 254218334Speter strcat (temp, file_suffix); 254390277Sobrien if (access_check (temp, mode) == 0) 254418334Speter { 254518334Speter if (pl->used_flag_ptr != 0) 254618334Speter *pl->used_flag_ptr = 1; 254718334Speter return temp; 254818334Speter } 254918334Speter } 255018334Speter 255118334Speter /* Now try just the name. */ 255218334Speter strcpy (temp, pl->prefix); 255318334Speter strcat (temp, machine_suffix); 255418334Speter strcat (temp, name); 255590277Sobrien if (access_check (temp, mode) == 0) 255618334Speter { 255718334Speter if (pl->used_flag_ptr != 0) 255818334Speter *pl->used_flag_ptr = 1; 255918334Speter return temp; 256018334Speter } 256118334Speter } 256218334Speter 256318334Speter /* Certain prefixes are tried with just the machine type, 256418334Speter not the version. This is used for finding as, ld, etc. */ 256518334Speter if (just_machine_suffix && pl->require_machine_suffix == 2) 256618334Speter { 256718334Speter /* Some systems have a suffix for executable files. 256818334Speter So try appending that first. */ 256918334Speter if (file_suffix[0] != 0) 257018334Speter { 257118334Speter strcpy (temp, pl->prefix); 257218334Speter strcat (temp, just_machine_suffix); 257318334Speter strcat (temp, name); 257418334Speter strcat (temp, file_suffix); 257590277Sobrien if (access_check (temp, mode) == 0) 257618334Speter { 257718334Speter if (pl->used_flag_ptr != 0) 257818334Speter *pl->used_flag_ptr = 1; 257918334Speter return temp; 258018334Speter } 258118334Speter } 258218334Speter 258318334Speter strcpy (temp, pl->prefix); 258418334Speter strcat (temp, just_machine_suffix); 258518334Speter strcat (temp, name); 258690277Sobrien if (access_check (temp, mode) == 0) 258718334Speter { 258818334Speter if (pl->used_flag_ptr != 0) 258918334Speter *pl->used_flag_ptr = 1; 259018334Speter return temp; 259118334Speter } 259218334Speter } 259318334Speter 259418334Speter /* Certain prefixes can't be used without the machine suffix 259518334Speter when the machine or version is explicitly specified. */ 259650599Sobrien if (! pl->require_machine_suffix) 259718334Speter { 259818334Speter /* Some systems have a suffix for executable files. 259918334Speter So try appending that first. */ 260018334Speter if (file_suffix[0] != 0) 260118334Speter { 260218334Speter strcpy (temp, pl->prefix); 260318334Speter strcat (temp, name); 260418334Speter strcat (temp, file_suffix); 260590277Sobrien if (access_check (temp, mode) == 0) 260618334Speter { 260718334Speter if (pl->used_flag_ptr != 0) 260818334Speter *pl->used_flag_ptr = 1; 260918334Speter return temp; 261018334Speter } 261118334Speter } 261218334Speter 261318334Speter strcpy (temp, pl->prefix); 261418334Speter strcat (temp, name); 261590277Sobrien if (access_check (temp, mode) == 0) 261618334Speter { 261718334Speter if (pl->used_flag_ptr != 0) 261818334Speter *pl->used_flag_ptr = 1; 261918334Speter return temp; 262018334Speter } 262118334Speter } 262218334Speter } 262318334Speter 262418334Speter free (temp); 262518334Speter return 0; 262618334Speter} 262718334Speter 262890277Sobrien/* Ranking of prefixes in the sort list. -B prefixes are put before 262990277Sobrien all others. */ 263018334Speter 263190277Sobrienenum path_prefix_priority 263290277Sobrien{ 263390277Sobrien PREFIX_PRIORITY_B_OPT, 263490277Sobrien PREFIX_PRIORITY_LAST 263590277Sobrien}; 263690277Sobrien 263790277Sobrien/* Add an entry for PREFIX in PLIST. The PLIST is kept in assending 263890277Sobrien order according to PRIORITY. Within each PRIORITY, new entries are 263990277Sobrien appended. 264090277Sobrien 264118334Speter If WARN is nonzero, we will warn if no file is found 264218334Speter through this prefix. WARN should point to an int 264318334Speter which will be set to 1 if this entry is used. 264418334Speter 264550599Sobrien COMPONENT is the value to be passed to update_path. 264650599Sobrien 264718334Speter REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without 264818334Speter the complete value of machine_suffix. 264918334Speter 2 means try both machine_suffix and just_machine_suffix. */ 265018334Speter 265118334Speterstatic void 265290277Sobrienadd_prefix (pprefix, prefix, component, priority, require_machine_suffix, warn) 265318334Speter struct path_prefix *pprefix; 265452520Sobrien const char *prefix; 265552520Sobrien const char *component; 265690277Sobrien /* enum prefix_priority */ int priority; 265718334Speter int require_machine_suffix; 265818334Speter int *warn; 265918334Speter{ 266018334Speter struct prefix_list *pl, **prev; 266118334Speter int len; 266218334Speter 266390277Sobrien for (prev = &pprefix->plist; 266490277Sobrien (*prev) != NULL && (*prev)->priority <= priority; 266590277Sobrien prev = &(*prev)->next) 266690277Sobrien ; 266718334Speter 266818334Speter /* Keep track of the longest prefix */ 266918334Speter 267050599Sobrien prefix = update_path (prefix, component); 267118334Speter len = strlen (prefix); 267218334Speter if (len > pprefix->max_len) 267318334Speter pprefix->max_len = len; 267418334Speter 267518334Speter pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list)); 267690277Sobrien pl->prefix = prefix; 267718334Speter pl->require_machine_suffix = require_machine_suffix; 267818334Speter pl->used_flag_ptr = warn; 267990277Sobrien pl->priority = priority; 268018334Speter if (warn) 268118334Speter *warn = 0; 268218334Speter 268390277Sobrien /* Insert after PREV */ 268490277Sobrien pl->next = (*prev); 268590277Sobrien (*prev) = pl; 268618334Speter} 268718334Speter 268818334Speter/* Execute the command specified by the arguments on the current line of spec. 268918334Speter When using pipes, this includes several piped-together commands 269018334Speter with `|' between them. 269118334Speter 269218334Speter Return 0 if successful, -1 if failed. */ 269318334Speter 269418334Speterstatic int 269518334Speterexecute () 269618334Speter{ 269718334Speter int i; 269818334Speter int n_commands; /* # of command. */ 269918334Speter char *string; 270018334Speter struct command 270190277Sobrien { 270290277Sobrien const char *prog; /* program name. */ 270390277Sobrien const char **argv; /* vector of args. */ 270490277Sobrien int pid; /* pid of process for this command. */ 270590277Sobrien }; 270618334Speter 270718334Speter struct command *commands; /* each command buffer with above info. */ 270818334Speter 270918334Speter /* Count # of piped commands. */ 271018334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 271118334Speter if (strcmp (argbuf[i], "|") == 0) 271218334Speter n_commands++; 271318334Speter 271418334Speter /* Get storage for each command. */ 271590277Sobrien commands = (struct command *) alloca (n_commands * sizeof (struct command)); 271618334Speter 271718334Speter /* Split argbuf into its separate piped processes, 271818334Speter and record info about each one. 271918334Speter Also search for the programs that are to be run. */ 272018334Speter 272118334Speter commands[0].prog = argbuf[0]; /* first command. */ 272218334Speter commands[0].argv = &argbuf[0]; 272318334Speter string = find_a_file (&exec_prefixes, commands[0].prog, X_OK); 272450599Sobrien 272518334Speter if (string) 272618334Speter commands[0].argv[0] = string; 272718334Speter 272818334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 272918334Speter if (strcmp (argbuf[i], "|") == 0) 273018334Speter { /* each command. */ 273152520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS) 273290277Sobrien fatal ("-pipe not supported"); 273318334Speter#endif 273418334Speter argbuf[i] = 0; /* termination of command args. */ 273518334Speter commands[n_commands].prog = argbuf[i + 1]; 273618334Speter commands[n_commands].argv = &argbuf[i + 1]; 273718334Speter string = find_a_file (&exec_prefixes, commands[n_commands].prog, X_OK); 273818334Speter if (string) 273918334Speter commands[n_commands].argv[0] = string; 274018334Speter n_commands++; 274118334Speter } 274218334Speter 274318334Speter argbuf[argbuf_index] = 0; 274418334Speter 274518334Speter /* If -v, print what we are about to do, and maybe query. */ 274618334Speter 274718334Speter if (verbose_flag) 274818334Speter { 274950599Sobrien /* For help listings, put a blank line between sub-processes. */ 275050599Sobrien if (print_help_list) 275150599Sobrien fputc ('\n', stderr); 275290277Sobrien 275318334Speter /* Print each piped command as a separate line. */ 275490277Sobrien for (i = 0; i < n_commands; i++) 275518334Speter { 275690277Sobrien const char *const *j; 275718334Speter 275890277Sobrien if (verbose_only_flag) 275990277Sobrien { 276090277Sobrien for (j = commands[i].argv; *j; j++) 276190277Sobrien { 276290277Sobrien const char *p; 276390277Sobrien fprintf (stderr, " \""); 276490277Sobrien for (p = *j; *p; ++p) 276590277Sobrien { 276690277Sobrien if (*p == '"' || *p == '\\' || *p == '$') 276790277Sobrien fputc ('\\', stderr); 276890277Sobrien fputc (*p, stderr); 276990277Sobrien } 277090277Sobrien fputc ('"', stderr); 277190277Sobrien } 277290277Sobrien } 277390277Sobrien else 277490277Sobrien for (j = commands[i].argv; *j; j++) 277590277Sobrien fprintf (stderr, " %s", *j); 277618334Speter 277718334Speter /* Print a pipe symbol after all but the last command. */ 277818334Speter if (i + 1 != n_commands) 277918334Speter fprintf (stderr, " |"); 278018334Speter fprintf (stderr, "\n"); 278118334Speter } 278218334Speter fflush (stderr); 278390277Sobrien if (verbose_only_flag != 0) 278490277Sobrien return 0; 278518334Speter#ifdef DEBUG 278652520Sobrien notice ("\nGo ahead? (y or n) "); 278718334Speter fflush (stderr); 278818334Speter i = getchar (); 278918334Speter if (i != '\n') 279050599Sobrien while (getchar () != '\n') 279150599Sobrien ; 279250599Sobrien 279318334Speter if (i != 'y' && i != 'Y') 279418334Speter return 0; 279518334Speter#endif /* DEBUG */ 279618334Speter } 279718334Speter 279818334Speter /* Run each piped subprocess. */ 279918334Speter 280018334Speter for (i = 0; i < n_commands; i++) 280118334Speter { 280250599Sobrien char *errmsg_fmt, *errmsg_arg; 280390277Sobrien const char *string = commands[i].argv[0]; 280418334Speter 280590277Sobrien /* For some bizarre reason, the second argument of execvp() is 280690277Sobrien char *const *, not const char *const *. */ 280790277Sobrien commands[i].pid = pexecute (string, (char *const *) commands[i].argv, 280850599Sobrien programname, temp_filename, 280950599Sobrien &errmsg_fmt, &errmsg_arg, 281050599Sobrien ((i == 0 ? PEXECUTE_FIRST : 0) 281150599Sobrien | (i + 1 == n_commands ? PEXECUTE_LAST : 0) 281250599Sobrien | (string == commands[i].prog 281350599Sobrien ? PEXECUTE_SEARCH : 0) 281450599Sobrien | (verbose_flag ? PEXECUTE_VERBOSE : 0))); 281518334Speter 281650599Sobrien if (commands[i].pid == -1) 281750599Sobrien pfatal_pexecute (errmsg_fmt, errmsg_arg); 281850599Sobrien 281918334Speter if (string != commands[i].prog) 282090277Sobrien free ((PTR) string); 282118334Speter } 282218334Speter 282318334Speter execution_count++; 282418334Speter 282518334Speter /* Wait for all the subprocesses to finish. 282618334Speter We don't care what order they finish in; 282718334Speter we know that N_COMMANDS waits will get them all. 282818334Speter Ignore subprocesses that we don't know about, 282918334Speter since they can be spawned by the process that exec'ed us. */ 283018334Speter 283118334Speter { 283218334Speter int ret_code = 0; 283390277Sobrien#ifdef HAVE_GETRUSAGE 283490277Sobrien struct timeval d; 283590277Sobrien double ut = 0.0, st = 0.0; 283690277Sobrien#endif 283718334Speter 283890277Sobrien for (i = 0; i < n_commands;) 283918334Speter { 284018334Speter int j; 284118334Speter int status; 284218334Speter int pid; 284318334Speter 284450599Sobrien pid = pwait (commands[i].pid, &status, 0); 284518334Speter if (pid < 0) 284618334Speter abort (); 284718334Speter 284890277Sobrien#ifdef HAVE_GETRUSAGE 284990277Sobrien if (report_times) 285090277Sobrien { 285190277Sobrien /* getrusage returns the total resource usage of all children 285290277Sobrien up to now. Copy the previous values into prus, get the 285390277Sobrien current statistics, then take the difference. */ 285490277Sobrien 285590277Sobrien prus = rus; 285690277Sobrien getrusage (RUSAGE_CHILDREN, &rus); 285790277Sobrien d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec; 285890277Sobrien d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec; 285990277Sobrien ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6; 286090277Sobrien 286190277Sobrien d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec; 286290277Sobrien d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec; 286390277Sobrien st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6; 286490277Sobrien } 286590277Sobrien#endif 286690277Sobrien 286718334Speter for (j = 0; j < n_commands; j++) 286818334Speter if (commands[j].pid == pid) 286918334Speter { 287018334Speter i++; 287190277Sobrien if (WIFSIGNALED (status)) 287218334Speter { 287390277Sobrien#ifdef SIGPIPE 287490277Sobrien /* SIGPIPE is a special case. It happens in -pipe mode 287590277Sobrien when the compiler dies before the preprocessor is 287690277Sobrien done, or the assembler dies before the compiler is 287790277Sobrien done. There's generally been an error already, and 287890277Sobrien this is just fallout. So don't generate another error 287990277Sobrien unless we would otherwise have succeeded. */ 288090277Sobrien if (WTERMSIG (status) == SIGPIPE 288190277Sobrien && (signal_count || greatest_status >= MIN_FATAL_STATUS)) 288290277Sobrien ; 288390277Sobrien else 288490277Sobrien#endif 288590277Sobrien fatal ("\ 288690277SobrienInternal error: %s (program %s)\n\ 288790277SobrienPlease submit a full bug report.\n\ 288890277SobrienSee %s for instructions.", 288990277Sobrien strsignal (WTERMSIG (status)), commands[j].prog, 289090277Sobrien GCCBUGURL); 289190277Sobrien signal_count++; 289290277Sobrien ret_code = -1; 289318334Speter } 289490277Sobrien else if (WIFEXITED (status) 289590277Sobrien && WEXITSTATUS (status) >= MIN_FATAL_STATUS) 289690277Sobrien { 289790277Sobrien if (WEXITSTATUS (status) > greatest_status) 289890277Sobrien greatest_status = WEXITSTATUS (status); 289990277Sobrien ret_code = -1; 290090277Sobrien } 290190277Sobrien#ifdef HAVE_GETRUSAGE 290290277Sobrien if (report_times && ut + st != 0) 290390277Sobrien notice ("# %s %.2f %.2f\n", commands[j].prog, ut, st); 290490277Sobrien#endif 290518334Speter break; 290618334Speter } 290718334Speter } 290818334Speter return ret_code; 290918334Speter } 291018334Speter} 291118334Speter 291218334Speter/* Find all the switches given to us 291318334Speter and make a vector describing them. 291418334Speter The elements of the vector are strings, one per switch given. 291518334Speter If a switch uses following arguments, then the `part1' field 291618334Speter is the switch itself and the `args' field 291718334Speter is a null-terminated vector containing the following arguments. 291890277Sobrien The `live_cond' field is: 291990277Sobrien 0 when initialized 292090277Sobrien 1 if the switch is true in a conditional spec, 292190277Sobrien -1 if false (overridden by a later switch) 292290277Sobrien -2 if this switch should be ignored (used in %{<S}) 292352520Sobrien The `validated' field is nonzero if any spec has looked at this switch; 292418334Speter if it remains zero at the end of the run, it must be meaningless. */ 292518334Speter 292690277Sobrien#define SWITCH_OK 0 292790277Sobrien#define SWITCH_FALSE -1 292890277Sobrien#define SWITCH_IGNORE -2 292990277Sobrien#define SWITCH_LIVE 1 293090277Sobrien 293118334Speterstruct switchstr 293218334Speter{ 293352520Sobrien const char *part1; 293490277Sobrien const char **args; 293518334Speter int live_cond; 293690277Sobrien unsigned char validated; 293790277Sobrien unsigned char ordering; 293818334Speter}; 293918334Speter 294018334Speterstatic struct switchstr *switches; 294118334Speter 294218334Speterstatic int n_switches; 294318334Speter 294418334Speterstruct infile 294518334Speter{ 294652520Sobrien const char *name; 294752520Sobrien const char *language; 294818334Speter}; 294918334Speter 295018334Speter/* Also a vector of input files specified. */ 295118334Speter 295218334Speterstatic struct infile *infiles; 295318334Speter 295490277Sobrienint n_infiles; 295518334Speter 295652520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that 295750599Sobrien we can tell if there were any user supplied any files or libraries. */ 295850599Sobrien 295950599Sobrienstatic int added_libraries; 296050599Sobrien 296118334Speter/* And a vector of corresponding output files is made up later. */ 296218334Speter 296390277Sobrienconst char **outfiles; 296418334Speter 296550599Sobrien/* Used to track if none of the -B paths are used. */ 296650599Sobrienstatic int warn_B; 296750599Sobrien 296850599Sobrien/* Used to track if standard path isn't used and -b or -V is specified. */ 296950599Sobrienstatic int warn_std; 297050599Sobrien 297150599Sobrien/* Gives value to pass as "warn" to add_prefix for standard prefixes. */ 297250599Sobrienstatic int *warn_std_ptr = 0; 297350599Sobrien 297490277Sobrien 297553878Sobrien#if defined(FREEBSD_NATIVE) 297653878Sobrien#include <objformat.h> 297753878Sobrien 297853878Sobrientypedef enum { OBJFMT_UNKNOWN, OBJFMT_AOUT, OBJFMT_ELF } objf_t; 297953878Sobrien 298053878Sobrienstatic objf_t objformat = OBJFMT_UNKNOWN; 298150599Sobrien#endif 298290277Sobrien 298390277Sobrien 298450599Sobrien 298590277Sobrien#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 298650599Sobrien 298750599Sobrien/* Convert NAME to a new name if it is the standard suffix. DO_EXE 298890277Sobrien is true if we should look for an executable suffix. DO_OBJ 298990277Sobrien is true if we should look for an object suffix. */ 299050599Sobrien 299190277Sobrienstatic const char * 299290277Sobrienconvert_filename (name, do_exe, do_obj) 299390277Sobrien const char *name; 299490277Sobrien int do_exe ATTRIBUTE_UNUSED; 299590277Sobrien int do_obj ATTRIBUTE_UNUSED; 299650599Sobrien{ 299790277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 299850599Sobrien int i; 299990277Sobrien#endif 300052520Sobrien int len; 300150599Sobrien 300252520Sobrien if (name == NULL) 300352520Sobrien return NULL; 300490277Sobrien 300552520Sobrien len = strlen (name); 300652520Sobrien 300790277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX 300890277Sobrien /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj". */ 300990277Sobrien if (do_obj && len > 2 301050599Sobrien && name[len - 2] == '.' 301150599Sobrien && name[len - 1] == 'o') 301250599Sobrien { 301350599Sobrien obstack_grow (&obstack, name, len - 2); 301490277Sobrien obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); 301550599Sobrien name = obstack_finish (&obstack); 301650599Sobrien } 301750599Sobrien#endif 301850599Sobrien 301990277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 302050599Sobrien /* If there is no filetype, make it the executable suffix (which includes 302150599Sobrien the "."). But don't get confused if we have just "-o". */ 302290277Sobrien if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-')) 302350599Sobrien return name; 302450599Sobrien 302550599Sobrien for (i = len - 1; i >= 0; i--) 302652520Sobrien if (IS_DIR_SEPARATOR (name[i])) 302750599Sobrien break; 302850599Sobrien 302950599Sobrien for (i++; i < len; i++) 303050599Sobrien if (name[i] == '.') 303150599Sobrien return name; 303250599Sobrien 303350599Sobrien obstack_grow (&obstack, name, len); 303490277Sobrien obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX, 303590277Sobrien strlen (TARGET_EXECUTABLE_SUFFIX)); 303650599Sobrien name = obstack_finish (&obstack); 303750599Sobrien#endif 303850599Sobrien 303950599Sobrien return name; 304050599Sobrien} 304150599Sobrien#endif 304250599Sobrien 304350599Sobrien/* Display the command line switches accepted by gcc. */ 304450599Sobrienstatic void 304550599Sobriendisplay_help () 304650599Sobrien{ 304790277Sobrien printf (_("Usage: %s [options] file...\n"), programname); 304890277Sobrien fputs (_("Options:\n"), stdout); 304950599Sobrien 305090277Sobrien fputs (_(" -pass-exit-codes Exit with highest error code from a phase\n"), stdout); 305190277Sobrien fputs (_(" --help Display this information\n"), stdout); 305290277Sobrien fputs (_(" --target-help Display target specific command line options\n"), stdout); 305350599Sobrien if (! verbose_flag) 305490277Sobrien fputs (_(" (Use '-v --help' to display command line options of sub-processes)\n"), stdout); 305590277Sobrien fputs (_(" -dumpspecs Display all of the built in spec strings\n"), stdout); 305690277Sobrien fputs (_(" -dumpversion Display the version of the compiler\n"), stdout); 305790277Sobrien fputs (_(" -dumpmachine Display the compiler's target processor\n"), stdout); 305890277Sobrien fputs (_(" -print-search-dirs Display the directories in the compiler's search path\n"), stdout); 305990277Sobrien fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library\n"), stdout); 306090277Sobrien fputs (_(" -print-file-name=<lib> Display the full path to library <lib>\n"), stdout); 306190277Sobrien fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>\n"), stdout); 306290277Sobrien fputs (_(" -print-multi-directory Display the root directory for versions of libgcc\n"), stdout); 306390277Sobrien fputs (_("\ 306490277Sobrien -print-multi-lib Display the mapping between command line options and\n\ 306590277Sobrien multiple library search directories\n"), stdout); 306690277Sobrien fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler\n"), stdout); 306790277Sobrien fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout); 306890277Sobrien fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker\n"), stdout); 306990277Sobrien fputs (_(" -Xlinker <arg> Pass <arg> on to the linker\n"), stdout); 307090277Sobrien fputs (_(" -save-temps Do not delete intermediate files\n"), stdout); 307190277Sobrien fputs (_(" -pipe Use pipes rather than intermediate files\n"), stdout); 307290277Sobrien fputs (_(" -time Time the execution of each subprocess\n"), stdout); 307390277Sobrien fputs (_(" -specs=<file> Override built-in specs with the contents of <file>\n"), stdout); 307490277Sobrien fputs (_(" -std=<standard> Assume that the input sources are for <standard>\n"), stdout); 307590277Sobrien fputs (_(" -B <directory> Add <directory> to the compiler's search paths\n"), stdout); 307690277Sobrien fputs (_(" -b <machine> Run gcc for target <machine>, if installed\n"), stdout); 307790277Sobrien fputs (_(" -V <version> Run gcc version number <version>, if installed\n"), stdout); 307890277Sobrien fputs (_(" -v Display the programs invoked by the compiler\n"), stdout); 307990277Sobrien fputs (_(" -### Like -v but options quoted and commands not executed\n"), stdout); 308090277Sobrien fputs (_(" -E Preprocess only; do not compile, assemble or link\n"), stdout); 308190277Sobrien fputs (_(" -S Compile only; do not assemble or link\n"), stdout); 308290277Sobrien fputs (_(" -c Compile and assemble, but do not link\n"), stdout); 308390277Sobrien fputs (_(" -o <file> Place the output into <file>\n"), stdout); 308490277Sobrien fputs (_("\ 308590277Sobrien -x <language> Specify the language of the following input files\n\ 308690277Sobrien Permissable languages include: c c++ assembler none\n\ 308790277Sobrien 'none' means revert to the default behavior of\n\ 308890277Sobrien guessing the language based on the file's extension\n\ 308990277Sobrien"), stdout); 309050599Sobrien 309190277Sobrien printf (_("\ 309290277Sobrien\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\ 309390277Sobrien passed on to the various sub-processes invoked by %s. In order to pass\n\ 309490277Sobrien other options on to these processes the -W<letter> options must be used.\n\ 309590277Sobrien"), programname); 309650599Sobrien 309750599Sobrien /* The rest of the options are displayed by invocations of the various 309850599Sobrien sub-processes. */ 309950599Sobrien} 310050599Sobrien 310190277Sobrienstatic void 310290277Sobrienadd_preprocessor_option (option, len) 310390277Sobrien const char *option; 310452520Sobrien int len; 310590277Sobrien{ 310652520Sobrien n_preprocessor_options++; 310790277Sobrien 310852520Sobrien if (! preprocessor_options) 310952520Sobrien preprocessor_options 311052520Sobrien = (char **) xmalloc (n_preprocessor_options * sizeof (char *)); 311152520Sobrien else 311252520Sobrien preprocessor_options 311352520Sobrien = (char **) xrealloc (preprocessor_options, 311452520Sobrien n_preprocessor_options * sizeof (char *)); 311590277Sobrien 311652520Sobrien preprocessor_options [n_preprocessor_options - 1] = 311752520Sobrien save_string (option, len); 311850599Sobrien} 311990277Sobrien 312090277Sobrienstatic void 312190277Sobrienadd_assembler_option (option, len) 312290277Sobrien const char *option; 312352520Sobrien int len; 312452520Sobrien{ 312552520Sobrien n_assembler_options++; 312652520Sobrien 312752520Sobrien if (! assembler_options) 312852520Sobrien assembler_options 312952520Sobrien = (char **) xmalloc (n_assembler_options * sizeof (char *)); 313052520Sobrien else 313152520Sobrien assembler_options 313252520Sobrien = (char **) xrealloc (assembler_options, 313352520Sobrien n_assembler_options * sizeof (char *)); 313452520Sobrien 313552520Sobrien assembler_options [n_assembler_options - 1] = save_string (option, len); 313650599Sobrien} 313790277Sobrien 313890277Sobrienstatic void 313990277Sobrienadd_linker_option (option, len) 314090277Sobrien const char *option; 314190277Sobrien int len; 314252520Sobrien{ 314352520Sobrien n_linker_options++; 314452520Sobrien 314552520Sobrien if (! linker_options) 314652520Sobrien linker_options 314752520Sobrien = (char **) xmalloc (n_linker_options * sizeof (char *)); 314852520Sobrien else 314952520Sobrien linker_options 315052520Sobrien = (char **) xrealloc (linker_options, 315152520Sobrien n_linker_options * sizeof (char *)); 315252520Sobrien 315352520Sobrien linker_options [n_linker_options - 1] = save_string (option, len); 315450599Sobrien} 315550599Sobrien 315618334Speter/* Create the vector `switches' and its contents. 315718334Speter Store its length in `n_switches'. */ 315818334Speter 315918334Speterstatic void 316018334Speterprocess_command (argc, argv) 316118334Speter int argc; 316290277Sobrien const char *const *argv; 316318334Speter{ 316490277Sobrien int i; 316552520Sobrien const char *temp; 316652520Sobrien char *temp1; 316790277Sobrien const char *spec_lang = 0; 316818334Speter int last_language_n_infiles; 316950599Sobrien int have_c = 0; 317050599Sobrien int have_o = 0; 317150599Sobrien int lang_n_infiles = 0; 317290277Sobrien#ifdef MODIFY_TARGET_NAME 317390277Sobrien int is_modify_target_name; 317490277Sobrien int j; 317590277Sobrien#endif 317618334Speter 317752520Sobrien GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX"); 317818334Speter 317918334Speter n_switches = 0; 318018334Speter n_infiles = 0; 318150599Sobrien added_libraries = 0; 318218334Speter 318318334Speter /* Figure compiler version from version string. */ 318418334Speter 318590277Sobrien compiler_version = temp1 = xstrdup (version_string); 318690277Sobrien 318752520Sobrien for (; *temp1; ++temp1) 318818334Speter { 318952520Sobrien if (*temp1 == ' ') 319018334Speter { 319152520Sobrien *temp1 = '\0'; 319218334Speter break; 319318334Speter } 319418334Speter } 319518334Speter 319690277Sobrien /* Set up the default search paths. If there is no GCC_EXEC_PREFIX, 319790277Sobrien see if we can create it from the pathname specified in argv[0]. */ 319818334Speter 319990277Sobrien#ifndef VMS 320090277Sobrien /* FIXME: make_relative_prefix doesn't yet work for VMS. */ 320190277Sobrien if (!gcc_exec_prefix) 320290277Sobrien { 320390277Sobrien gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix, 320490277Sobrien standard_exec_prefix); 320590277Sobrien if (gcc_exec_prefix) 320690277Sobrien putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL)); 320790277Sobrien } 320890277Sobrien#endif 320990277Sobrien 321018334Speter if (gcc_exec_prefix) 321118334Speter { 321250599Sobrien int len = strlen (gcc_exec_prefix); 321390277Sobrien 321490277Sobrien if (len > (int) sizeof ("/lib/gcc-lib/") - 1 321552520Sobrien && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1]))) 321650599Sobrien { 321750599Sobrien temp = gcc_exec_prefix + len - sizeof ("/lib/gcc-lib/") + 1; 321852520Sobrien if (IS_DIR_SEPARATOR (*temp) 321990277Sobrien && strncmp (temp + 1, "lib", 3) == 0 322052520Sobrien && IS_DIR_SEPARATOR (temp[4]) 322190277Sobrien && strncmp (temp + 5, "gcc-lib", 7) == 0) 322250599Sobrien len -= sizeof ("/lib/gcc-lib/") - 1; 322350599Sobrien } 322450599Sobrien 322550599Sobrien set_std_prefix (gcc_exec_prefix, len); 322690277Sobrien add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC", 322790277Sobrien PREFIX_PRIORITY_LAST, 0, NULL); 322890277Sobrien add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 322990277Sobrien PREFIX_PRIORITY_LAST, 0, NULL); 323018334Speter } 323118334Speter 323218334Speter /* COMPILER_PATH and LIBRARY_PATH have values 323318334Speter that are lists of directory names with colons. */ 323418334Speter 323552520Sobrien GET_ENV_PATH_LIST (temp, "COMPILER_PATH"); 323618334Speter if (temp) 323718334Speter { 323852520Sobrien const char *startp, *endp; 323918334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 324018334Speter 324118334Speter startp = endp = temp; 324218334Speter while (1) 324318334Speter { 324418334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 324518334Speter { 324690277Sobrien strncpy (nstore, startp, endp - startp); 324718334Speter if (endp == startp) 324890277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 324952520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 325018334Speter { 325190277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 325290277Sobrien nstore[endp - startp + 1] = 0; 325318334Speter } 325418334Speter else 325590277Sobrien nstore[endp - startp] = 0; 325690277Sobrien add_prefix (&exec_prefixes, nstore, 0, 325790277Sobrien PREFIX_PRIORITY_LAST, 0, NULL); 325850599Sobrien add_prefix (&include_prefixes, 325990277Sobrien concat (nstore, "include", NULL), 326090277Sobrien 0, PREFIX_PRIORITY_LAST, 0, NULL); 326118334Speter if (*endp == 0) 326218334Speter break; 326318334Speter endp = startp = endp + 1; 326418334Speter } 326518334Speter else 326618334Speter endp++; 326718334Speter } 326818334Speter } 326918334Speter 327090277Sobrien GET_ENV_PATH_LIST (temp, LIBRARY_PATH_ENV); 327155220Sobrien if (temp) 327218334Speter { 327352520Sobrien const char *startp, *endp; 327418334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 327518334Speter 327618334Speter startp = endp = temp; 327718334Speter while (1) 327818334Speter { 327918334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 328018334Speter { 328190277Sobrien strncpy (nstore, startp, endp - startp); 328218334Speter if (endp == startp) 328390277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 328452520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 328518334Speter { 328690277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 328790277Sobrien nstore[endp - startp + 1] = 0; 328818334Speter } 328918334Speter else 329090277Sobrien nstore[endp - startp] = 0; 329190277Sobrien add_prefix (&startfile_prefixes, nstore, NULL, 329290277Sobrien PREFIX_PRIORITY_LAST, 0, NULL); 329318334Speter if (*endp == 0) 329418334Speter break; 329518334Speter endp = startp = endp + 1; 329618334Speter } 329718334Speter else 329818334Speter endp++; 329918334Speter } 330018334Speter } 330118334Speter 330218334Speter /* Use LPATH like LIBRARY_PATH (for the CMU build program). */ 330352520Sobrien GET_ENV_PATH_LIST (temp, "LPATH"); 330450599Sobrien if (temp && *cross_compile == '0') 330518334Speter { 330652520Sobrien const char *startp, *endp; 330718334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 330818334Speter 330918334Speter startp = endp = temp; 331018334Speter while (1) 331118334Speter { 331218334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 331318334Speter { 331490277Sobrien strncpy (nstore, startp, endp - startp); 331518334Speter if (endp == startp) 331690277Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL)); 331752520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 331818334Speter { 331990277Sobrien nstore[endp - startp] = DIR_SEPARATOR; 332090277Sobrien nstore[endp - startp + 1] = 0; 332118334Speter } 332218334Speter else 332390277Sobrien nstore[endp - startp] = 0; 332490277Sobrien add_prefix (&startfile_prefixes, nstore, NULL, 332590277Sobrien PREFIX_PRIORITY_LAST, 0, NULL); 332618334Speter if (*endp == 0) 332718334Speter break; 332818334Speter endp = startp = endp + 1; 332918334Speter } 333018334Speter else 333118334Speter endp++; 333218334Speter } 333318334Speter } 333418334Speter 333553878Sobrien#if defined(FREEBSD_NATIVE) 333634229Speter { 333753878Sobrien char buf[64]; 333853878Sobrien if (getobjformat (buf, sizeof buf, &argc, argv)) 333953878Sobrien if (strcmp (buf, "aout") == 0) 334053878Sobrien objformat = OBJFMT_AOUT; 334153878Sobrien else if (strcmp (buf, "elf") == 0) 334253878Sobrien objformat = OBJFMT_ELF; 334334229Speter else 334453878Sobrien fprintf(stderr, "Unrecognized object format: %s\n", buf); 334534229Speter } 334634229Speter#endif 334750599Sobrien 334877389Sobrien /* Options specified as if they appeared on the command line. */ 334977389Sobrien temp = getenv ("GCC_OPTIONS"); 335077389Sobrien if ((temp) && (strlen (temp) > 0)) 335177389Sobrien { 335277389Sobrien int len; 335377389Sobrien int optc = 1; 335477389Sobrien int new_argc; 335577389Sobrien char **new_argv; 335677389Sobrien char *envopts; 335777389Sobrien 335877389Sobrien while (isspace (*temp)) 335977389Sobrien temp++; 336077389Sobrien len = strlen (temp); 336177389Sobrien envopts = (char *) xmalloc (len + 1); 336277389Sobrien strcpy (envopts, temp); 336377389Sobrien 336477389Sobrien for (i = 0; i < (len - 1); i++) 336577389Sobrien if ((isspace (envopts[i])) && ! (isspace (envopts[i+1]))) 336677389Sobrien optc++; 336777389Sobrien 336877389Sobrien new_argv = (char **) alloca ((optc + argc) * sizeof(char *)); 336977389Sobrien 337077389Sobrien for (i = 0, new_argc = 1; new_argc <= optc; new_argc++) 337177389Sobrien { 337277389Sobrien while (isspace (envopts[i])) 337377389Sobrien i++; 337477389Sobrien new_argv[new_argc] = envopts + i; 337577389Sobrien while (!isspace (envopts[i]) && (envopts[i] != '\0')) 337677389Sobrien i++; 337777389Sobrien envopts[i++] = '\0'; 337877389Sobrien } 337977389Sobrien for (i = 1; i < argc; i++) 338077389Sobrien new_argv[new_argc++] = argv[i]; 338177389Sobrien 338277389Sobrien argv = new_argv; 338377389Sobrien argc = new_argc; 338477389Sobrien } 338577389Sobrien 338618334Speter /* Convert new-style -- options to old-style. */ 338718334Speter translate_options (&argc, &argv); 338818334Speter 338950599Sobrien /* Do language-specific adjustment/addition of flags. */ 339090277Sobrien lang_specific_driver (&argc, &argv, &added_libraries); 339150599Sobrien 339218334Speter /* Scan argv twice. Here, the first time, just count how many switches 339318334Speter there will be in their vector, and how many input files in theirs. 339490277Sobrien Also parse any switches that determine the configuration name, such as -b. 339518334Speter Here we also parse the switches that cc itself uses (e.g. -v). */ 339618334Speter 339718334Speter for (i = 1; i < argc; i++) 339818334Speter { 339918334Speter if (! strcmp (argv[i], "-dumpspecs")) 340018334Speter { 340150599Sobrien struct spec_list *sl; 340250599Sobrien init_spec (); 340350599Sobrien for (sl = specs; sl; sl = sl->next) 340450599Sobrien printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec)); 340590277Sobrien if (link_command_spec) 340690277Sobrien printf ("*link_command:\n%s\n\n", link_command_spec); 340718334Speter exit (0); 340818334Speter } 340918334Speter else if (! strcmp (argv[i], "-dumpversion")) 341018334Speter { 341150599Sobrien printf ("%s\n", spec_version); 341218334Speter exit (0); 341318334Speter } 341418334Speter else if (! strcmp (argv[i], "-dumpmachine")) 341518334Speter { 341618334Speter printf ("%s\n", spec_machine); 341790277Sobrien exit (0); 341818334Speter } 341990277Sobrien else if (strcmp (argv[i], "-fversion") == 0) 342090277Sobrien { 342190277Sobrien /* translate_options () has turned --version into -fversion. */ 342290277Sobrien printf (_("%s (GCC) %s\n"), programname, version_string); 342390277Sobrien fputs (_("Copyright (C) 2002 Free Software Foundation, Inc.\n"), 342490277Sobrien stdout); 342590277Sobrien fputs (_("This is free software; see the source for copying conditions. There is NO\n\ 342690277Sobrienwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"), 342790277Sobrien stdout); 342890277Sobrien exit (0); 342990277Sobrien } 343050599Sobrien else if (strcmp (argv[i], "-fhelp") == 0) 343150599Sobrien { 343250599Sobrien /* translate_options () has turned --help into -fhelp. */ 343350599Sobrien print_help_list = 1; 343450599Sobrien 343550599Sobrien /* We will be passing a dummy file on to the sub-processes. */ 343650599Sobrien n_infiles++; 343750599Sobrien n_switches++; 343890277Sobrien 343990277Sobrien /* CPP driver cannot obtain switch from cc1_options. */ 344090277Sobrien if (is_cpp_driver) 344190277Sobrien add_preprocessor_option ("--help", 6); 344250599Sobrien add_assembler_option ("--help", 6); 344350599Sobrien add_linker_option ("--help", 6); 344450599Sobrien } 344590277Sobrien else if (strcmp (argv[i], "-ftarget-help") == 0) 344690277Sobrien { 344790277Sobrien /* translate_options() has turned --target-help into -ftarget-help. */ 344890277Sobrien target_help_flag = 1; 344990277Sobrien 345090277Sobrien /* We will be passing a dummy file on to the sub-processes. */ 345190277Sobrien n_infiles++; 345290277Sobrien n_switches++; 345390277Sobrien 345490277Sobrien /* CPP driver cannot obtain switch from cc1_options. */ 345590277Sobrien if (is_cpp_driver) 345690277Sobrien add_preprocessor_option ("--target-help", 13); 345790277Sobrien add_assembler_option ("--target-help", 13); 345890277Sobrien add_linker_option ("--target-help", 13); 345990277Sobrien } 346090277Sobrien else if (! strcmp (argv[i], "-pass-exit-codes")) 346190277Sobrien { 346290277Sobrien pass_exit_codes = 1; 346390277Sobrien n_switches++; 346490277Sobrien } 346518334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 346618334Speter print_search_dirs = 1; 346718334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 346818334Speter print_file_name = "libgcc.a"; 346918334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 347018334Speter print_file_name = argv[i] + 17; 347118334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 347218334Speter print_prog_name = argv[i] + 17; 347318334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 347418334Speter print_multi_lib = 1; 347518334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 347618334Speter print_multi_directory = 1; 347718334Speter else if (! strncmp (argv[i], "-Wa,", 4)) 347818334Speter { 347918334Speter int prev, j; 348018334Speter /* Pass the rest of this option to the assembler. */ 348118334Speter 348218334Speter /* Split the argument at commas. */ 348318334Speter prev = 4; 348418334Speter for (j = 4; argv[i][j]; j++) 348518334Speter if (argv[i][j] == ',') 348618334Speter { 348750599Sobrien add_assembler_option (argv[i] + prev, j - prev); 348818334Speter prev = j + 1; 348918334Speter } 349090277Sobrien 349118334Speter /* Record the part after the last comma. */ 349250599Sobrien add_assembler_option (argv[i] + prev, j - prev); 349318334Speter } 349418334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 349518334Speter { 349618334Speter int prev, j; 349718334Speter /* Pass the rest of this option to the preprocessor. */ 349818334Speter 349918334Speter /* Split the argument at commas. */ 350018334Speter prev = 4; 350118334Speter for (j = 4; argv[i][j]; j++) 350218334Speter if (argv[i][j] == ',') 350318334Speter { 350450599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 350518334Speter prev = j + 1; 350618334Speter } 350790277Sobrien 350818334Speter /* Record the part after the last comma. */ 350950599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 351018334Speter } 351118334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 351218334Speter /* The +e options to the C++ front-end. */ 351318334Speter n_switches++; 351418334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 351518334Speter { 351618334Speter int j; 351718334Speter /* Split the argument at commas. */ 351818334Speter for (j = 3; argv[i][j]; j++) 351918334Speter n_infiles += (argv[i][j] == ','); 352018334Speter } 352118334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 352218334Speter { 352318334Speter if (i + 1 == argc) 352418334Speter fatal ("argument to `-Xlinker' is missing"); 352518334Speter 352618334Speter n_infiles++; 352718334Speter i++; 352818334Speter } 352977389Sobrien else if (strcmp (argv[i], "-l") == 0) 353077389Sobrien { 353177389Sobrien if (i + 1 == argc) 353277389Sobrien fatal ("argument to `-l' is missing"); 353377389Sobrien 353477389Sobrien n_infiles++; 353577389Sobrien i++; 353677389Sobrien } 353718334Speter else if (strncmp (argv[i], "-l", 2) == 0) 353818334Speter n_infiles++; 353950599Sobrien else if (strcmp (argv[i], "-save-temps") == 0) 354050599Sobrien { 354150599Sobrien save_temps_flag = 1; 354250599Sobrien n_switches++; 354350599Sobrien } 354450599Sobrien else if (strcmp (argv[i], "-specs") == 0) 354550599Sobrien { 354650599Sobrien struct user_specs *user = (struct user_specs *) 354750599Sobrien xmalloc (sizeof (struct user_specs)); 354850599Sobrien if (++i >= argc) 354950599Sobrien fatal ("argument to `-specs' is missing"); 355050599Sobrien 355190277Sobrien user->next = (struct user_specs *) 0; 355250599Sobrien user->filename = argv[i]; 355350599Sobrien if (user_specs_tail) 355450599Sobrien user_specs_tail->next = user; 355550599Sobrien else 355650599Sobrien user_specs_head = user; 355750599Sobrien user_specs_tail = user; 355850599Sobrien } 355950599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 356050599Sobrien { 356150599Sobrien struct user_specs *user = (struct user_specs *) 356250599Sobrien xmalloc (sizeof (struct user_specs)); 356350599Sobrien if (strlen (argv[i]) == 7) 356450599Sobrien fatal ("argument to `-specs=' is missing"); 356550599Sobrien 356690277Sobrien user->next = (struct user_specs *) 0; 356790277Sobrien user->filename = argv[i] + 7; 356850599Sobrien if (user_specs_tail) 356950599Sobrien user_specs_tail->next = user; 357050599Sobrien else 357150599Sobrien user_specs_head = user; 357250599Sobrien user_specs_tail = user; 357350599Sobrien } 357490277Sobrien else if (strcmp (argv[i], "-time") == 0) 357590277Sobrien report_times = 1; 357690277Sobrien else if (strcmp (argv[i], "-###") == 0) 357790277Sobrien { 357890277Sobrien /* This is similar to -v except that there is no execution 357990277Sobrien of the commands and the echoed arguments are quoted. It 358090277Sobrien is intended for use in shell scripts to capture the 358190277Sobrien driver-generated command line. */ 358290277Sobrien verbose_only_flag++; 358390277Sobrien verbose_flag++; 358490277Sobrien } 358518334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 358618334Speter { 358790277Sobrien const char *p = &argv[i][1]; 358890277Sobrien int c = *p; 358918334Speter 359018334Speter switch (c) 359118334Speter { 359218334Speter case 'b': 359390277Sobrien n_switches++; 359418334Speter if (p[1] == 0 && i + 1 == argc) 359518334Speter fatal ("argument to `-b' is missing"); 359618334Speter if (p[1] == 0) 359718334Speter spec_machine = argv[++i]; 359818334Speter else 359918334Speter spec_machine = p + 1; 360050599Sobrien 360150599Sobrien warn_std_ptr = &warn_std; 360218334Speter break; 360318334Speter 360418334Speter case 'B': 360518334Speter { 360690277Sobrien const char *value; 360790277Sobrien int len; 360890277Sobrien 360918334Speter if (p[1] == 0 && i + 1 == argc) 361018334Speter fatal ("argument to `-B' is missing"); 361118334Speter if (p[1] == 0) 361218334Speter value = argv[++i]; 361318334Speter else 361418334Speter value = p + 1; 361518334Speter 361690277Sobrien len = strlen (value); 361790277Sobrien 361890277Sobrien /* Catch the case where the user has forgotten to append a 361990277Sobrien directory separator to the path. Note, they may be using 362090277Sobrien -B to add an executable name prefix, eg "i386-elf-", in 362190277Sobrien order to distinguish between multiple installations of 362290277Sobrien GCC in the same directory. Hence we must check to see 362390277Sobrien if appending a directory separator actually makes a 362490277Sobrien valid directory name. */ 362590277Sobrien if (! IS_DIR_SEPARATOR (value [len - 1]) 362690277Sobrien && is_directory (value, "", 0)) 362790277Sobrien { 362890277Sobrien char *tmp = xmalloc (len + 2); 362990277Sobrien strcpy (tmp, value); 363090277Sobrien tmp[len] = DIR_SEPARATOR; 363190277Sobrien tmp[++ len] = 0; 363290277Sobrien value = tmp; 363390277Sobrien } 363490277Sobrien 363590277Sobrien /* As a kludge, if the arg is "[foo/]stageN/", just 363690277Sobrien add "[foo/]include" to the include prefix. */ 363790277Sobrien if ((len == 7 363890277Sobrien || (len > 7 363990277Sobrien && (IS_DIR_SEPARATOR (value[len - 8])))) 364090277Sobrien && strncmp (value + len - 7, "stage", 5) == 0 364190277Sobrien && ISDIGIT (value[len - 2]) 364290277Sobrien && (IS_DIR_SEPARATOR (value[len - 1]))) 364390277Sobrien { 364490277Sobrien if (len == 7) 364590277Sobrien add_prefix (&include_prefixes, "include", NULL, 364690277Sobrien PREFIX_PRIORITY_B_OPT, 0, NULL); 364790277Sobrien else 364890277Sobrien { 364990277Sobrien char * string = xmalloc (len + 1); 365090277Sobrien 365190277Sobrien strncpy (string, value, len - 7); 365290277Sobrien strcpy (string + len - 7, "include"); 365390277Sobrien add_prefix (&include_prefixes, string, NULL, 365490277Sobrien PREFIX_PRIORITY_B_OPT, 0, NULL); 365590277Sobrien } 365690277Sobrien } 365790277Sobrien 365890277Sobrien add_prefix (&exec_prefixes, value, NULL, 365990277Sobrien PREFIX_PRIORITY_B_OPT, 0, &warn_B); 366090277Sobrien add_prefix (&startfile_prefixes, value, NULL, 366190277Sobrien PREFIX_PRIORITY_B_OPT, 0, &warn_B); 366290277Sobrien add_prefix (&include_prefixes, concat (value, "include", NULL), 366390277Sobrien NULL, PREFIX_PRIORITY_B_OPT, 0, NULL); 366490277Sobrien n_switches++; 366518334Speter } 366618334Speter break; 366718334Speter 366818334Speter case 'v': /* Print our subcommands and print versions. */ 366918334Speter n_switches++; 367018334Speter /* If they do anything other than exactly `-v', don't set 367118334Speter verbose_flag; rather, continue on to give the error. */ 367218334Speter if (p[1] != 0) 367318334Speter break; 367418334Speter verbose_flag++; 367518334Speter break; 367618334Speter 367718334Speter case 'V': 367850599Sobrien n_switches++; 367918334Speter if (p[1] == 0 && i + 1 == argc) 368018334Speter fatal ("argument to `-V' is missing"); 368118334Speter if (p[1] == 0) 368218334Speter spec_version = argv[++i]; 368318334Speter else 368418334Speter spec_version = p + 1; 368518334Speter compiler_version = spec_version; 368650599Sobrien warn_std_ptr = &warn_std; 368750599Sobrien 368850599Sobrien /* Validate the version number. Use the same checks 368950599Sobrien done when inserting it into a spec. 369050599Sobrien 369150599Sobrien The format of the version string is 369250599Sobrien ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */ 369350599Sobrien { 369452520Sobrien const char *v = compiler_version; 369550599Sobrien 369650599Sobrien /* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */ 369750599Sobrien while (! ISDIGIT (*v)) 369850599Sobrien v++; 369950599Sobrien 370050599Sobrien if (v > compiler_version && v[-1] != '-') 370150599Sobrien fatal ("invalid version number format"); 370250599Sobrien 370350599Sobrien /* Set V after the first period. */ 370450599Sobrien while (ISDIGIT (*v)) 370550599Sobrien v++; 370650599Sobrien 370750599Sobrien if (*v != '.') 370850599Sobrien fatal ("invalid version number format"); 370950599Sobrien 371050599Sobrien v++; 371150599Sobrien while (ISDIGIT (*v)) 371250599Sobrien v++; 371350599Sobrien 371450599Sobrien if (*v != 0 && *v != ' ' && *v != '.' && *v != '-') 371550599Sobrien fatal ("invalid version number format"); 371650599Sobrien } 371718334Speter break; 371818334Speter 371950599Sobrien case 'S': 372050599Sobrien case 'c': 372150599Sobrien if (p[1] == 0) 372218334Speter { 372350599Sobrien have_c = 1; 372418334Speter n_switches++; 372518334Speter break; 372618334Speter } 372750599Sobrien goto normal_switch; 372850599Sobrien 372950599Sobrien case 'o': 373050599Sobrien have_o = 1; 373190277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) 373250599Sobrien if (! have_c) 373350599Sobrien { 373450599Sobrien int skip; 373590277Sobrien 373650599Sobrien /* Forward scan, just in case -S or -c is specified 373750599Sobrien after -o. */ 373850599Sobrien int j = i + 1; 373950599Sobrien if (p[1] == 0) 374050599Sobrien ++j; 374150599Sobrien while (j < argc) 374250599Sobrien { 374350599Sobrien if (argv[j][0] == '-') 374450599Sobrien { 374550599Sobrien if (SWITCH_CURTAILS_COMPILATION (argv[j][1]) 374650599Sobrien && argv[j][2] == 0) 374750599Sobrien { 374850599Sobrien have_c = 1; 374950599Sobrien break; 375050599Sobrien } 375190277Sobrien else if ((skip = SWITCH_TAKES_ARG (argv[j][1]))) 375250599Sobrien j += skip - (argv[j][2] != 0); 375390277Sobrien else if ((skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1))) 375450599Sobrien j += skip; 375550599Sobrien } 375650599Sobrien j++; 375750599Sobrien } 375850599Sobrien } 375950599Sobrien#endif 376090277Sobrien#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX) 376150599Sobrien if (p[1] == 0) 376290277Sobrien argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0); 376350599Sobrien else 376490277Sobrien argv[i] = convert_filename (argv[i], ! have_c, 0); 376550599Sobrien#endif 376650599Sobrien goto normal_switch; 376750599Sobrien 376818334Speter default: 376950599Sobrien normal_switch: 377090277Sobrien 377190277Sobrien#ifdef MODIFY_TARGET_NAME 377290277Sobrien is_modify_target_name = 0; 377390277Sobrien 377490277Sobrien for (j = 0; 377590277Sobrien j < sizeof modify_target / sizeof modify_target[0]; j++) 377690277Sobrien if (! strcmp (argv[i], modify_target[j].sw)) 377790277Sobrien { 377890277Sobrien char *new_name 377990277Sobrien = (char *) xmalloc (strlen (modify_target[j].str) 378090277Sobrien + strlen (spec_machine)); 378190277Sobrien const char *p, *r; 378290277Sobrien char *q; 378390277Sobrien int made_addition = 0; 378490277Sobrien 378590277Sobrien is_modify_target_name = 1; 378690277Sobrien for (p = spec_machine, q = new_name; *p != 0; ) 378790277Sobrien { 378890277Sobrien if (modify_target[j].add_del == DELETE 378990277Sobrien && (! strncmp (q, modify_target[j].str, 379090277Sobrien strlen (modify_target[j].str)))) 379190277Sobrien p += strlen (modify_target[j].str); 379290277Sobrien else if (modify_target[j].add_del == ADD 379390277Sobrien && ! made_addition && *p == '-') 379490277Sobrien { 379590277Sobrien for (r = modify_target[j].str; *r != 0; ) 379690277Sobrien *q++ = *r++; 379790277Sobrien made_addition = 1; 379890277Sobrien } 379990277Sobrien 380090277Sobrien *q++ = *p++; 380190277Sobrien } 380290277Sobrien 380390277Sobrien spec_machine = new_name; 380490277Sobrien } 380590277Sobrien 380690277Sobrien if (is_modify_target_name) 380790277Sobrien break; 380890277Sobrien#endif 380990277Sobrien 381018334Speter n_switches++; 381118334Speter 381218334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 381318334Speter i += SWITCH_TAKES_ARG (c) - (p[1] != 0); 381418334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 381518334Speter i += WORD_SWITCH_TAKES_ARG (p); 381618334Speter } 381718334Speter } 381818334Speter else 381950599Sobrien { 382050599Sobrien n_infiles++; 382150599Sobrien lang_n_infiles++; 382250599Sobrien } 382318334Speter } 382418334Speter 382550599Sobrien if (have_c && have_o && lang_n_infiles > 1) 382650599Sobrien fatal ("cannot specify -o with -c or -S and multiple compilations"); 382750599Sobrien 382818334Speter /* Set up the search paths before we go looking for config files. */ 382918334Speter 383018334Speter /* These come before the md prefixes so that we will find gcc's subcommands 383118334Speter (such as cpp) rather than those of the host system. */ 383218334Speter /* Use 2 as fourth arg meaning try just the machine as a suffix, 383318334Speter as well as trying the machine and the version. */ 383418346Speter#ifdef FREEBSD_NATIVE 383553878Sobrien switch (objformat) 383653878Sobrien { 383753878Sobrien case OBJFMT_AOUT: 383853878Sobrien n_switches++; /* add implied -maout */ 383955220Sobrien add_prefix (&exec_prefixes, PREFIX"/libexec/aout/", "BINUTILS", 384053878Sobrien 0, 0, NULL_PTR); 384153878Sobrien break; 384253878Sobrien case OBJFMT_ELF: 384355220Sobrien add_prefix (&exec_prefixes, PREFIX"/libexec/elf/", "BINUTILS", 384453878Sobrien 0, 0, NULL_PTR); 384553878Sobrien break; 384654778Sobrien case OBJFMT_UNKNOWN: 384754778Sobrien fatal ("object format unknown"); 384853878Sobrien } 384918346Speter#else /* not FREEBSD_NATIVE */ 385018334Speter#ifndef OS2 385190277Sobrien add_prefix (&exec_prefixes, standard_exec_prefix, "GCC", 385290277Sobrien PREFIX_PRIORITY_LAST, 1, warn_std_ptr); 385350599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", 385490277Sobrien PREFIX_PRIORITY_LAST, 2, warn_std_ptr); 385550599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS", 385690277Sobrien PREFIX_PRIORITY_LAST, 2, warn_std_ptr); 385718334Speter#endif 385818334Speter 385950599Sobrien add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", 386090277Sobrien PREFIX_PRIORITY_LAST, 1, warn_std_ptr); 386150599Sobrien add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS", 386290277Sobrien PREFIX_PRIORITY_LAST, 1, warn_std_ptr); 386318346Speter#endif /* FREEBSD_NATIVE */ 386418334Speter 386590277Sobrien tooldir_prefix = concat (tooldir_base_prefix, spec_machine, 386690277Sobrien dir_separator_str, NULL); 386718334Speter 386818334Speter /* If tooldir is relative, base it on exec_prefixes. A relative 386918334Speter tooldir lets us move the installed tree as a unit. 387018334Speter 387118334Speter If GCC_EXEC_PREFIX is defined, then we want to add two relative 387218334Speter directories, so that we can search both the user specified directory 387318334Speter and the standard place. */ 387418334Speter 387590277Sobrien if (!IS_ABSOLUTE_PATHNAME (tooldir_prefix)) 387618334Speter { 387718334Speter if (gcc_exec_prefix) 387818334Speter { 387918334Speter char *gcc_exec_tooldir_prefix 388050599Sobrien = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 388190277Sobrien spec_version, dir_separator_str, tooldir_prefix, NULL); 388218334Speter 388318334Speter add_prefix (&exec_prefixes, 388490277Sobrien concat (gcc_exec_tooldir_prefix, "bin", 388590277Sobrien dir_separator_str, NULL), 388690277Sobrien NULL, PREFIX_PRIORITY_LAST, 0, NULL); 388718334Speter add_prefix (&startfile_prefixes, 388890277Sobrien concat (gcc_exec_tooldir_prefix, "lib", 388990277Sobrien dir_separator_str, NULL), 389090277Sobrien NULL, PREFIX_PRIORITY_LAST, 0, NULL); 389118334Speter } 389218334Speter 389350599Sobrien tooldir_prefix = concat (standard_exec_prefix, spec_machine, 389490277Sobrien dir_separator_str, spec_version, 389590277Sobrien dir_separator_str, tooldir_prefix, NULL); 389618334Speter } 389718334Speter 389818346Speter#ifndef FREEBSD_NATIVE 389990277Sobrien add_prefix (&exec_prefixes, 390090277Sobrien concat (tooldir_prefix, "bin", dir_separator_str, NULL), 390190277Sobrien "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL); 390218334Speter add_prefix (&startfile_prefixes, 390390277Sobrien concat (tooldir_prefix, "lib", dir_separator_str, NULL), 390490277Sobrien "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL); 390518346Speter#endif /* FREEBSD_NATIVE */ 390618334Speter 390718334Speter /* More prefixes are enabled in main, after we read the specs file 390818334Speter and determine whether this is cross-compilation or not. */ 390918334Speter 391018334Speter /* Then create the space for the vectors and scan again. */ 391118334Speter 391218334Speter switches = ((struct switchstr *) 391318334Speter xmalloc ((n_switches + 1) * sizeof (struct switchstr))); 391418334Speter infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile)); 391518334Speter n_switches = 0; 391618334Speter n_infiles = 0; 391718334Speter last_language_n_infiles = -1; 391818334Speter 391918334Speter /* This, time, copy the text of each switch and store a pointer 392018334Speter to the copy in the vector of switches. 392118334Speter Store all the infiles in their vector. */ 392218334Speter 392353878Sobrien#if defined(FREEBSD_NATIVE) 392453878Sobrien switch (objformat) 392553878Sobrien { 392653878Sobrien case OBJFMT_AOUT: 392753878Sobrien switches[n_switches].part1 = "maout"; 392853878Sobrien switches[n_switches].args = 0; 392953878Sobrien switches[n_switches].live_cond = 0; 393053878Sobrien switches[n_switches].validated = 0; 393153878Sobrien n_switches++; 393253878Sobrien putenv("OBJFORMAT=aout"); 393353878Sobrien break; 393453878Sobrien case OBJFMT_ELF: 393553878Sobrien putenv("OBJFORMAT=elf"); 393653878Sobrien break; 393754778Sobrien case OBJFMT_UNKNOWN: 393854778Sobrien fatal ("object format unknown"); 393953878Sobrien } 394034229Speter#endif 394134229Speter 394218334Speter for (i = 1; i < argc; i++) 394318334Speter { 394418334Speter /* Just skip the switches that were handled by the preceding loop. */ 394590277Sobrien#ifdef MODIFY_TARGET_NAME 394690277Sobrien is_modify_target_name = 0; 394790277Sobrien 394890277Sobrien for (j = 0; j < sizeof modify_target / sizeof modify_target[0]; j++) 394990277Sobrien if (! strcmp (argv[i], modify_target[j].sw)) 395090277Sobrien is_modify_target_name = 1; 395190277Sobrien 395290277Sobrien if (is_modify_target_name) 395390277Sobrien ; 395490277Sobrien else 395590277Sobrien#endif 395618334Speter if (! strncmp (argv[i], "-Wa,", 4)) 395718334Speter ; 395818334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 395918334Speter ; 396090277Sobrien else if (! strcmp (argv[i], "-pass-exit-codes")) 396190277Sobrien ; 396218334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 396318334Speter ; 396418334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 396518334Speter ; 396618334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 396718334Speter ; 396818334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 396918334Speter ; 397018334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 397118334Speter ; 397218334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 397318334Speter ; 397490277Sobrien else if (! strcmp (argv[i], "-ftarget-help")) 397590277Sobrien ; 397690277Sobrien else if (! strcmp (argv[i], "-fhelp")) 397790277Sobrien ; 397818334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 397918334Speter { 398018334Speter /* Compensate for the +e options to the C++ front-end; 398118334Speter they're there simply for cfront call-compatibility. We do 398218334Speter some magic in default_compilers to pass them down properly. 398318334Speter Note we deliberately start at the `+' here, to avoid passing 398418334Speter -e0 or -e1 down into the linker. */ 398518334Speter switches[n_switches].part1 = &argv[i][0]; 398618334Speter switches[n_switches].args = 0; 398790277Sobrien switches[n_switches].live_cond = SWITCH_OK; 398852520Sobrien switches[n_switches].validated = 0; 398918334Speter n_switches++; 399018334Speter } 399118334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 399218334Speter { 399318334Speter int prev, j; 399418334Speter /* Split the argument at commas. */ 399518334Speter prev = 4; 399618334Speter for (j = 4; argv[i][j]; j++) 399718334Speter if (argv[i][j] == ',') 399818334Speter { 399950599Sobrien infiles[n_infiles].language = "*"; 400018334Speter infiles[n_infiles++].name 400118334Speter = save_string (argv[i] + prev, j - prev); 400218334Speter prev = j + 1; 400318334Speter } 400418334Speter /* Record the part after the last comma. */ 400550599Sobrien infiles[n_infiles].language = "*"; 400618334Speter infiles[n_infiles++].name = argv[i] + prev; 400718334Speter } 400818334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 400918334Speter { 401050599Sobrien infiles[n_infiles].language = "*"; 401118334Speter infiles[n_infiles++].name = argv[++i]; 401218334Speter } 401377389Sobrien else if (strcmp (argv[i], "-l") == 0) 401477389Sobrien { /* POSIX allows separation of -l and the lib arg; 401577389Sobrien canonicalize by concatenating -l with its arg */ 401677389Sobrien infiles[n_infiles].language = "*"; 401777389Sobrien infiles[n_infiles++].name = concat ("-l", argv[++i], NULL); 401877389Sobrien } 401918334Speter else if (strncmp (argv[i], "-l", 2) == 0) 402018334Speter { 402150599Sobrien infiles[n_infiles].language = "*"; 402218334Speter infiles[n_infiles++].name = argv[i]; 402318334Speter } 402450599Sobrien else if (strcmp (argv[i], "-specs") == 0) 402550599Sobrien i++; 402650599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 402750599Sobrien ; 402890277Sobrien else if (strcmp (argv[i], "-time") == 0) 402990277Sobrien ; 403090277Sobrien else if ((save_temps_flag || report_times) 403190277Sobrien && strcmp (argv[i], "-pipe") == 0) 403290277Sobrien { 403390277Sobrien /* -save-temps overrides -pipe, so that temp files are produced */ 403490277Sobrien if (save_temps_flag) 403590277Sobrien error ("warning: -pipe ignored because -save-temps specified"); 403690277Sobrien /* -time overrides -pipe because we can't get correct stats when 403790277Sobrien multiple children are running at once. */ 403890277Sobrien else if (report_times) 403990277Sobrien error ("warning: -pipe ignored because -time specified"); 404090277Sobrien } 404190277Sobrien else if (strcmp (argv[i], "-###") == 0) 404290277Sobrien ; 404318334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 404418334Speter { 404590277Sobrien const char *p = &argv[i][1]; 404690277Sobrien int c = *p; 404718334Speter 404818334Speter if (c == 'x') 404918334Speter { 405018334Speter if (p[1] == 0 && i + 1 == argc) 405118334Speter fatal ("argument to `-x' is missing"); 405218334Speter if (p[1] == 0) 405318334Speter spec_lang = argv[++i]; 405418334Speter else 405518334Speter spec_lang = p + 1; 405618334Speter if (! strcmp (spec_lang, "none")) 405718334Speter /* Suppress the warning if -xnone comes after the last input 405818334Speter file, because alternate command interfaces like g++ might 405918334Speter find it useful to place -xnone after each input file. */ 406018334Speter spec_lang = 0; 406118334Speter else 406218334Speter last_language_n_infiles = n_infiles; 406318334Speter continue; 406418334Speter } 406518334Speter switches[n_switches].part1 = p; 406618334Speter /* Deal with option arguments in separate argv elements. */ 406718334Speter if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) 406818334Speter || WORD_SWITCH_TAKES_ARG (p)) 406918334Speter { 407018334Speter int j = 0; 407118334Speter int n_args = WORD_SWITCH_TAKES_ARG (p); 407218334Speter 407318334Speter if (n_args == 0) 407418334Speter { 407518334Speter /* Count only the option arguments in separate argv elements. */ 407618334Speter n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); 407718334Speter } 407818334Speter if (i + n_args >= argc) 407918334Speter fatal ("argument to `-%s' is missing", p); 408018334Speter switches[n_switches].args 408190277Sobrien = (const char **) xmalloc ((n_args + 1) * sizeof(const char *)); 408218334Speter while (j < n_args) 408318334Speter switches[n_switches].args[j++] = argv[++i]; 408418334Speter /* Null-terminate the vector. */ 408518334Speter switches[n_switches].args[j] = 0; 408618334Speter } 408790277Sobrien else if (strchr (switches_need_spaces, c)) 408818334Speter { 408950599Sobrien /* On some systems, ld cannot handle some options without 409050599Sobrien a space. So split the option from its argument. */ 409150599Sobrien char *part1 = (char *) xmalloc (2); 409250599Sobrien part1[0] = c; 409350599Sobrien part1[1] = '\0'; 409490277Sobrien 409550599Sobrien switches[n_switches].part1 = part1; 409690277Sobrien switches[n_switches].args 409790277Sobrien = (const char **) xmalloc (2 * sizeof (const char *)); 409890277Sobrien switches[n_switches].args[0] = xstrdup (p+1); 409918334Speter switches[n_switches].args[1] = 0; 410018334Speter } 410118334Speter else 410218334Speter switches[n_switches].args = 0; 410318334Speter 410490277Sobrien switches[n_switches].live_cond = SWITCH_OK; 410552520Sobrien switches[n_switches].validated = 0; 410690277Sobrien switches[n_switches].ordering = 0; 410790277Sobrien /* These are always valid, since gcc.c itself understands it. */ 410890277Sobrien if (!strcmp (p, "save-temps") 410990277Sobrien || !strcmp (p, "static-libgcc") 411090277Sobrien || !strcmp (p, "shared-libgcc")) 411152520Sobrien switches[n_switches].validated = 1; 411290277Sobrien else 411390277Sobrien { 411490277Sobrien char ch = switches[n_switches].part1[0]; 411590277Sobrien if (ch == 'V' || ch == 'b' || ch == 'B') 411690277Sobrien switches[n_switches].validated = 1; 411790277Sobrien } 411818334Speter n_switches++; 411918334Speter } 412018334Speter else 412118334Speter { 412290277Sobrien#ifdef HAVE_TARGET_OBJECT_SUFFIX 412390277Sobrien argv[i] = convert_filename (argv[i], 0, access (argv[i], F_OK)); 412418334Speter#endif 412518334Speter 412690277Sobrien if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0) 412718334Speter { 412818334Speter perror_with_name (argv[i]); 412918334Speter error_count++; 413018334Speter } 413118334Speter else 413218334Speter { 413318334Speter infiles[n_infiles].language = spec_lang; 413418334Speter infiles[n_infiles++].name = argv[i]; 413518334Speter } 413618334Speter } 413718334Speter } 413818334Speter 413918334Speter if (n_infiles == last_language_n_infiles && spec_lang != 0) 414090277Sobrien error ("warning: `-x %s' after last input file has no effect", spec_lang); 414118334Speter 414290277Sobrien /* Ensure we only invoke each subprocess once. */ 414390277Sobrien if (target_help_flag || print_help_list) 414490277Sobrien { 414590277Sobrien n_infiles = 1; 414690277Sobrien 414790277Sobrien /* Create a dummy input file, so that we can pass --target-help on to 414890277Sobrien the various sub-processes. */ 414990277Sobrien infiles[0].language = "c"; 415090277Sobrien infiles[0].name = "help-dummy"; 415190277Sobrien 415290277Sobrien if (target_help_flag) 415390277Sobrien { 415490277Sobrien switches[n_switches].part1 = "--target-help"; 415590277Sobrien switches[n_switches].args = 0; 415690277Sobrien switches[n_switches].live_cond = SWITCH_OK; 415790277Sobrien switches[n_switches].validated = 0; 415890277Sobrien 415990277Sobrien n_switches++; 416090277Sobrien } 416190277Sobrien 416290277Sobrien if (print_help_list) 416390277Sobrien { 416490277Sobrien switches[n_switches].part1 = "--help"; 416590277Sobrien switches[n_switches].args = 0; 416690277Sobrien switches[n_switches].live_cond = SWITCH_OK; 416790277Sobrien switches[n_switches].validated = 0; 416890277Sobrien 416990277Sobrien n_switches++; 417090277Sobrien } 417190277Sobrien } 417290277Sobrien 417318334Speter switches[n_switches].part1 = 0; 417418334Speter infiles[n_infiles].name = 0; 417518334Speter} 417690277Sobrien 417790277Sobrien/* Store switches not filtered out by %{<S} in spec in COLLECT_GCC_OPTIONS 417890277Sobrien and place that in the environment. */ 417990277Sobrien 418090277Sobrienstatic void 418190277Sobrienset_collect_gcc_options () 418290277Sobrien{ 418390277Sobrien int i; 418490277Sobrien int first_time; 418590277Sobrien 418690277Sobrien /* Build COLLECT_GCC_OPTIONS to have all of the options specified to 418790277Sobrien the compiler. */ 418890277Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=", 418990277Sobrien sizeof ("COLLECT_GCC_OPTIONS=") - 1); 419090277Sobrien 419190277Sobrien first_time = TRUE; 419290277Sobrien for (i = 0; (int) i < n_switches; i++) 419390277Sobrien { 419490277Sobrien const char *const *args; 419590277Sobrien const char *p, *q; 419690277Sobrien if (!first_time) 419790277Sobrien obstack_grow (&collect_obstack, " ", 1); 419890277Sobrien 419990277Sobrien first_time = FALSE; 420090277Sobrien 420190277Sobrien /* Ignore elided switches. */ 420290277Sobrien if (switches[i].live_cond == SWITCH_IGNORE) 420390277Sobrien continue; 420490277Sobrien 420590277Sobrien obstack_grow (&collect_obstack, "'-", 2); 420690277Sobrien q = switches[i].part1; 420790277Sobrien while ((p = strchr (q, '\''))) 420890277Sobrien { 420990277Sobrien obstack_grow (&collect_obstack, q, p - q); 421090277Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 421190277Sobrien q = ++p; 421290277Sobrien } 421390277Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 421490277Sobrien obstack_grow (&collect_obstack, "'", 1); 421590277Sobrien 421690277Sobrien for (args = switches[i].args; args && *args; args++) 421790277Sobrien { 421890277Sobrien obstack_grow (&collect_obstack, " '", 2); 421990277Sobrien q = *args; 422090277Sobrien while ((p = strchr (q, '\''))) 422190277Sobrien { 422290277Sobrien obstack_grow (&collect_obstack, q, p - q); 422390277Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 422490277Sobrien q = ++p; 422590277Sobrien } 422690277Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 422790277Sobrien obstack_grow (&collect_obstack, "'", 1); 422890277Sobrien } 422990277Sobrien } 423090277Sobrien obstack_grow (&collect_obstack, "\0", 1); 423190277Sobrien putenv (obstack_finish (&collect_obstack)); 423290277Sobrien} 423318334Speter 423418334Speter/* Process a spec string, accumulating and running commands. */ 423518334Speter 423618334Speter/* These variables describe the input file name. 423718334Speter input_file_number is the index on outfiles of this file, 423818334Speter so that the output file name can be stored for later use by %o. 423918334Speter input_basename is the start of the part of the input file 424018334Speter sans all directory names, and basename_length is the number 424118334Speter of characters starting there excluding the suffix .c or whatever. */ 424218334Speter 424352520Sobrienconst char *input_filename; 424418334Speterstatic int input_file_number; 424550599Sobriensize_t input_filename_length; 424618334Speterstatic int basename_length; 424790277Sobrienstatic int suffixed_basename_length; 424852520Sobrienstatic const char *input_basename; 424952520Sobrienstatic const char *input_suffix; 425090277Sobrienstatic struct stat input_stat; 425190277Sobrienstatic int input_stat_set; 425218334Speter 425390277Sobrien/* The compiler used to process the current input file. */ 425490277Sobrienstatic struct compiler *input_file_compiler; 425590277Sobrien 425618334Speter/* These are variables used within do_spec and do_spec_1. */ 425718334Speter 425818334Speter/* Nonzero if an arg has been started and not yet terminated 425918334Speter (with space, tab or newline). */ 426018334Speterstatic int arg_going; 426118334Speter 426218334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated 426318334Speter is a temporary file name. */ 426418334Speterstatic int delete_this_arg; 426518334Speter 426618334Speter/* Nonzero means %w has been seen; the next arg to be terminated 426718334Speter is the output file name of this compilation. */ 426818334Speterstatic int this_is_output_file; 426918334Speter 427018334Speter/* Nonzero means %s has been seen; the next arg to be terminated 427118334Speter is the name of a library file and we should try the standard 427218334Speter search dirs for it. */ 427318334Speterstatic int this_is_library_file; 427418334Speter 427518334Speter/* Nonzero means that the input of this command is coming from a pipe. */ 427618334Speterstatic int input_from_pipe; 427718334Speter 427890277Sobrien/* Nonnull means substitute this for any suffix when outputting a switches 427990277Sobrien arguments. */ 428090277Sobrienstatic const char *suffix_subst; 428190277Sobrien 428218334Speter/* Process the spec SPEC and run the commands specified therein. 428318334Speter Returns 0 if the spec is successfully processed; -1 if failed. */ 428418334Speter 428550599Sobrienint 428618334Speterdo_spec (spec) 428752520Sobrien const char *spec; 428818334Speter{ 428918334Speter int value; 429018334Speter 429118334Speter clear_args (); 429218334Speter arg_going = 0; 429318334Speter delete_this_arg = 0; 429418334Speter this_is_output_file = 0; 429518334Speter this_is_library_file = 0; 429618334Speter input_from_pipe = 0; 429790277Sobrien suffix_subst = NULL; 429818334Speter 429990277Sobrien value = do_spec_1 (spec, 0, NULL); 430018334Speter 430118334Speter /* Force out any unfinished command. 430218334Speter If -pipe, this forces out the last command if it ended in `|'. */ 430318334Speter if (value == 0) 430418334Speter { 430518334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 430618334Speter argbuf_index--; 430718334Speter 430890277Sobrien set_collect_gcc_options (); 430990277Sobrien 431018334Speter if (argbuf_index > 0) 431118334Speter value = execute (); 431218334Speter } 431318334Speter 431418334Speter return value; 431518334Speter} 431618334Speter 431718334Speter/* Process the sub-spec SPEC as a portion of a larger spec. 431818334Speter This is like processing a whole spec except that we do 431918334Speter not initialize at the beginning and we do not supply a 432018334Speter newline by default at the end. 432118334Speter INSWITCH nonzero means don't process %-sequences in SPEC; 432218334Speter in this case, % is treated as an ordinary character. 432318334Speter This is used while substituting switches. 432418334Speter INSWITCH nonzero also causes SPC not to terminate an argument. 432518334Speter 432618334Speter Value is zero unless a line was finished 432718334Speter and the command on that line reported an error. */ 432818334Speter 432918334Speterstatic int 433018334Speterdo_spec_1 (spec, inswitch, soft_matched_part) 433152520Sobrien const char *spec; 433218334Speter int inswitch; 433352520Sobrien const char *soft_matched_part; 433418334Speter{ 433590277Sobrien const char *p = spec; 433690277Sobrien int c; 433718334Speter int i; 433852520Sobrien const char *string; 433918334Speter int value; 434018334Speter 434150599Sobrien while ((c = *p++)) 434218334Speter /* If substituting a switch, treat all chars like letters. 434318334Speter Otherwise, NL, SPC, TAB and % are special. */ 434418334Speter switch (inswitch ? 'a' : c) 434518334Speter { 434618334Speter case '\n': 434718334Speter /* End of line: finish any pending argument, 434818334Speter then run the pending command if one has been started. */ 434918334Speter if (arg_going) 435018334Speter { 435118334Speter obstack_1grow (&obstack, 0); 435218334Speter string = obstack_finish (&obstack); 435318334Speter if (this_is_library_file) 435418334Speter string = find_file (string); 435518334Speter store_arg (string, delete_this_arg, this_is_output_file); 435618334Speter if (this_is_output_file) 435718334Speter outfiles[input_file_number] = string; 435818334Speter } 435918334Speter arg_going = 0; 436018334Speter 436118334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 436218334Speter { 436318334Speter for (i = 0; i < n_switches; i++) 436418334Speter if (!strcmp (switches[i].part1, "pipe")) 436518334Speter break; 436618334Speter 436718334Speter /* A `|' before the newline means use a pipe here, 436818334Speter but only if -pipe was specified. 436918334Speter Otherwise, execute now and don't pass the `|' as an arg. */ 437018334Speter if (i < n_switches) 437118334Speter { 437218334Speter input_from_pipe = 1; 437352520Sobrien switches[i].validated = 1; 437418334Speter break; 437518334Speter } 437618334Speter else 437718334Speter argbuf_index--; 437818334Speter } 437918334Speter 438090277Sobrien set_collect_gcc_options (); 438190277Sobrien 438218334Speter if (argbuf_index > 0) 438318334Speter { 438418334Speter value = execute (); 438518334Speter if (value) 438618334Speter return value; 438718334Speter } 438818334Speter /* Reinitialize for a new command, and for a new argument. */ 438918334Speter clear_args (); 439018334Speter arg_going = 0; 439118334Speter delete_this_arg = 0; 439218334Speter this_is_output_file = 0; 439318334Speter this_is_library_file = 0; 439418334Speter input_from_pipe = 0; 439518334Speter break; 439618334Speter 439718334Speter case '|': 439818334Speter /* End any pending argument. */ 439918334Speter if (arg_going) 440018334Speter { 440118334Speter obstack_1grow (&obstack, 0); 440218334Speter string = obstack_finish (&obstack); 440318334Speter if (this_is_library_file) 440418334Speter string = find_file (string); 440518334Speter store_arg (string, delete_this_arg, this_is_output_file); 440618334Speter if (this_is_output_file) 440718334Speter outfiles[input_file_number] = string; 440818334Speter } 440918334Speter 441018334Speter /* Use pipe */ 441118334Speter obstack_1grow (&obstack, c); 441218334Speter arg_going = 1; 441318334Speter break; 441418334Speter 441518334Speter case '\t': 441618334Speter case ' ': 441718334Speter /* Space or tab ends an argument if one is pending. */ 441818334Speter if (arg_going) 441918334Speter { 442018334Speter obstack_1grow (&obstack, 0); 442118334Speter string = obstack_finish (&obstack); 442218334Speter if (this_is_library_file) 442318334Speter string = find_file (string); 442418334Speter store_arg (string, delete_this_arg, this_is_output_file); 442518334Speter if (this_is_output_file) 442618334Speter outfiles[input_file_number] = string; 442718334Speter } 442818334Speter /* Reinitialize for a new argument. */ 442918334Speter arg_going = 0; 443018334Speter delete_this_arg = 0; 443118334Speter this_is_output_file = 0; 443218334Speter this_is_library_file = 0; 443318334Speter break; 443418334Speter 443518334Speter case '%': 443618334Speter switch (c = *p++) 443718334Speter { 443818334Speter case 0: 443990277Sobrien fatal ("invalid specification! Bug in cc"); 444018334Speter 444118334Speter case 'b': 444218334Speter obstack_grow (&obstack, input_basename, basename_length); 444318334Speter arg_going = 1; 444418334Speter break; 444518334Speter 444690277Sobrien case 'B': 444790277Sobrien obstack_grow (&obstack, input_basename, suffixed_basename_length); 444890277Sobrien arg_going = 1; 444990277Sobrien break; 445090277Sobrien 445118334Speter case 'd': 445218334Speter delete_this_arg = 2; 445318334Speter break; 445418334Speter 445518334Speter /* Dump out the directories specified with LIBRARY_PATH, 445618334Speter followed by the absolute directories 445718334Speter that we search for startfiles. */ 445818334Speter case 'D': 445918334Speter { 446018334Speter struct prefix_list *pl = startfile_prefixes.plist; 446150599Sobrien size_t bufsize = 100; 446218334Speter char *buffer = (char *) xmalloc (bufsize); 446318334Speter int idx; 446418334Speter 446518334Speter for (; pl; pl = pl->next) 446618334Speter { 446718334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR 446818334Speter /* Used on systems which record the specified -L dirs 446918334Speter and use them to search for dynamic linking. */ 447018334Speter /* Relative directories always come from -B, 447118334Speter and it is better not to use them for searching 447290277Sobrien at run time. In particular, stage1 loses. */ 447390277Sobrien if (!IS_ABSOLUTE_PATHNAME (pl->prefix)) 447418334Speter continue; 447518334Speter#endif 447618334Speter /* Try subdirectory if there is one. */ 447718334Speter if (multilib_dir != NULL) 447818334Speter { 447918334Speter if (machine_suffix) 448018334Speter { 448118334Speter if (strlen (pl->prefix) + strlen (machine_suffix) 448218334Speter >= bufsize) 448318334Speter bufsize = (strlen (pl->prefix) 448418334Speter + strlen (machine_suffix)) * 2 + 1; 448518334Speter buffer = (char *) xrealloc (buffer, bufsize); 448618334Speter strcpy (buffer, pl->prefix); 448718334Speter strcat (buffer, machine_suffix); 448818334Speter if (is_directory (buffer, multilib_dir, 1)) 448918334Speter { 449090277Sobrien do_spec_1 ("-L", 0, NULL); 449118334Speter#ifdef SPACE_AFTER_L_OPTION 449290277Sobrien do_spec_1 (" ", 0, NULL); 449318334Speter#endif 449490277Sobrien do_spec_1 (buffer, 1, NULL); 449590277Sobrien do_spec_1 (multilib_dir, 1, NULL); 449618334Speter /* Make this a separate argument. */ 449790277Sobrien do_spec_1 (" ", 0, NULL); 449818334Speter } 449918334Speter } 450018334Speter if (!pl->require_machine_suffix) 450118334Speter { 450218334Speter if (is_directory (pl->prefix, multilib_dir, 1)) 450318334Speter { 450490277Sobrien do_spec_1 ("-L", 0, NULL); 450518334Speter#ifdef SPACE_AFTER_L_OPTION 450690277Sobrien do_spec_1 (" ", 0, NULL); 450718334Speter#endif 450890277Sobrien do_spec_1 (pl->prefix, 1, NULL); 450990277Sobrien do_spec_1 (multilib_dir, 1, NULL); 451018334Speter /* Make this a separate argument. */ 451190277Sobrien do_spec_1 (" ", 0, NULL); 451218334Speter } 451318334Speter } 451418334Speter } 451518334Speter if (machine_suffix) 451618334Speter { 451718334Speter if (is_directory (pl->prefix, machine_suffix, 1)) 451818334Speter { 451990277Sobrien do_spec_1 ("-L", 0, NULL); 452018334Speter#ifdef SPACE_AFTER_L_OPTION 452190277Sobrien do_spec_1 (" ", 0, NULL); 452218334Speter#endif 452390277Sobrien do_spec_1 (pl->prefix, 1, NULL); 452418334Speter /* Remove slash from machine_suffix. */ 452518334Speter if (strlen (machine_suffix) >= bufsize) 452618334Speter bufsize = strlen (machine_suffix) * 2 + 1; 452718334Speter buffer = (char *) xrealloc (buffer, bufsize); 452818334Speter strcpy (buffer, machine_suffix); 452918334Speter idx = strlen (buffer); 453052520Sobrien if (IS_DIR_SEPARATOR (buffer[idx - 1])) 453118334Speter buffer[idx - 1] = 0; 453290277Sobrien do_spec_1 (buffer, 1, NULL); 453318334Speter /* Make this a separate argument. */ 453490277Sobrien do_spec_1 (" ", 0, NULL); 453518334Speter } 453618334Speter } 453718334Speter if (!pl->require_machine_suffix) 453818334Speter { 453918334Speter if (is_directory (pl->prefix, "", 1)) 454018334Speter { 454190277Sobrien do_spec_1 ("-L", 0, NULL); 454218334Speter#ifdef SPACE_AFTER_L_OPTION 454390277Sobrien do_spec_1 (" ", 0, NULL); 454418334Speter#endif 454518334Speter /* Remove slash from pl->prefix. */ 454618334Speter if (strlen (pl->prefix) >= bufsize) 454718334Speter bufsize = strlen (pl->prefix) * 2 + 1; 454818334Speter buffer = (char *) xrealloc (buffer, bufsize); 454918334Speter strcpy (buffer, pl->prefix); 455018334Speter idx = strlen (buffer); 455152520Sobrien if (IS_DIR_SEPARATOR (buffer[idx - 1])) 455218334Speter buffer[idx - 1] = 0; 455390277Sobrien do_spec_1 (buffer, 1, NULL); 455418334Speter /* Make this a separate argument. */ 455590277Sobrien do_spec_1 (" ", 0, NULL); 455618334Speter } 455718334Speter } 455818334Speter } 455918334Speter free (buffer); 456018334Speter } 456118334Speter break; 456218334Speter 456318334Speter case 'e': 456452520Sobrien /* %efoo means report an error with `foo' as error message 456518334Speter and don't execute any more commands for this file. */ 456618334Speter { 456752520Sobrien const char *q = p; 456818334Speter char *buf; 456990277Sobrien while (*p != 0 && *p != '\n') 457090277Sobrien p++; 457118334Speter buf = (char *) alloca (p - q + 1); 457218334Speter strncpy (buf, q, p - q); 457318334Speter buf[p - q] = 0; 457490277Sobrien error ("%s", buf); 457518334Speter return -1; 457618334Speter } 457718334Speter break; 457890277Sobrien case 'n': 457990277Sobrien /* %nfoo means report an notice with `foo' on stderr. */ 458090277Sobrien { 458190277Sobrien const char *q = p; 458290277Sobrien char *buf; 458390277Sobrien while (*p != 0 && *p != '\n') 458490277Sobrien p++; 458590277Sobrien buf = (char *) alloca (p - q + 1); 458690277Sobrien strncpy (buf, q, p - q); 458790277Sobrien buf[p - q] = 0; 458890277Sobrien notice ("%s\n", buf); 458990277Sobrien if (*p) 459090277Sobrien p++; 459190277Sobrien } 459290277Sobrien break; 459318334Speter 459490277Sobrien case 'j': 459590277Sobrien { 459690277Sobrien struct stat st; 459790277Sobrien 459890277Sobrien /* If save_temps_flag is off, and the HOST_BIT_BUCKET is defined, 459990277Sobrien and it is not a directory, and it is writable, use it. 460090277Sobrien Otherwise, fall through and treat this like any other 460190277Sobrien temporary file. */ 460290277Sobrien 460390277Sobrien if ((!save_temps_flag) 460490277Sobrien && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode)) 460590277Sobrien && (access (HOST_BIT_BUCKET, W_OK) == 0)) 460690277Sobrien { 460790277Sobrien obstack_grow (&obstack, HOST_BIT_BUCKET, 460890277Sobrien strlen (HOST_BIT_BUCKET)); 460990277Sobrien delete_this_arg = 0; 461090277Sobrien arg_going = 1; 461190277Sobrien break; 461290277Sobrien } 461390277Sobrien } 461418334Speter case 'g': 461518334Speter case 'u': 461618334Speter case 'U': 461718334Speter { 461818334Speter struct temp_name *t; 461950599Sobrien int suffix_length; 462052520Sobrien const char *suffix = p; 462190277Sobrien char *saved_suffix = NULL; 462218334Speter 462390277Sobrien while (*p == '.' || ISALPHA ((unsigned char) *p)) 462490277Sobrien p++; 462590277Sobrien suffix_length = p - suffix; 462650599Sobrien if (p[0] == '%' && p[1] == 'O') 462750599Sobrien { 462850599Sobrien p += 2; 462950599Sobrien /* We don't support extra suffix characters after %O. */ 463090277Sobrien if (*p == '.' || ISALPHA ((unsigned char) *p)) 463150599Sobrien abort (); 463290277Sobrien if (suffix_length == 0) 463390277Sobrien suffix = TARGET_OBJECT_SUFFIX; 463490277Sobrien else 463590277Sobrien { 463690277Sobrien saved_suffix 463790277Sobrien = (char *) xmalloc (suffix_length 463890277Sobrien + strlen (TARGET_OBJECT_SUFFIX)); 463990277Sobrien strncpy (saved_suffix, suffix, suffix_length); 464090277Sobrien strcpy (saved_suffix + suffix_length, 464190277Sobrien TARGET_OBJECT_SUFFIX); 464290277Sobrien } 464390277Sobrien suffix_length += strlen (TARGET_OBJECT_SUFFIX); 464450599Sobrien } 464590277Sobrien 464690277Sobrien /* If the input_filename has the same suffix specified 464790277Sobrien for the %g, %u, or %U, and -save-temps is specified, 464890277Sobrien we could end up using that file as an intermediate 464990277Sobrien thus clobbering the user's source file (.e.g., 465090277Sobrien gcc -save-temps foo.s would clobber foo.s with the 465190277Sobrien output of cpp0). So check for this condition and 465290277Sobrien generate a temp file as the intermediate. */ 465390277Sobrien 465490277Sobrien if (save_temps_flag) 465550599Sobrien { 465690277Sobrien temp_filename_length = basename_length + suffix_length; 465790277Sobrien temp_filename = alloca (temp_filename_length + 1); 465890277Sobrien strncpy ((char *) temp_filename, input_basename, basename_length); 465990277Sobrien strncpy ((char *) temp_filename + basename_length, suffix, 466090277Sobrien suffix_length); 466190277Sobrien *((char *) temp_filename + temp_filename_length) = '\0'; 466290277Sobrien if (strcmp (temp_filename, input_filename) != 0) 466390277Sobrien { 466490277Sobrien struct stat st_temp; 466590277Sobrien 466690277Sobrien /* Note, set_input() resets input_stat_set to 0. */ 466790277Sobrien if (input_stat_set == 0) 466890277Sobrien { 466990277Sobrien input_stat_set = stat (input_filename, &input_stat); 467090277Sobrien if (input_stat_set >= 0) 467190277Sobrien input_stat_set = 1; 467290277Sobrien } 467390277Sobrien 467490277Sobrien /* If we have the stat for the input_filename 467590277Sobrien and we can do the stat for the temp_filename 467690277Sobrien then the they could still refer to the same 467790277Sobrien file if st_dev/st_ino's are the same. */ 467890277Sobrien 467990277Sobrien if (input_stat_set != 1 468090277Sobrien || stat (temp_filename, &st_temp) < 0 468190277Sobrien || input_stat.st_dev != st_temp.st_dev 468290277Sobrien || input_stat.st_ino != st_temp.st_ino) 468390277Sobrien { 468490277Sobrien temp_filename = save_string (temp_filename, 468590277Sobrien temp_filename_length + 1); 468690277Sobrien obstack_grow (&obstack, temp_filename, 468790277Sobrien temp_filename_length); 468890277Sobrien arg_going = 1; 468990277Sobrien break; 469090277Sobrien } 469190277Sobrien } 469250599Sobrien } 469350599Sobrien 469418334Speter /* See if we already have an association of %g/%u/%U and 469518334Speter suffix. */ 469618334Speter for (t = temp_names; t; t = t->next) 469750599Sobrien if (t->length == suffix_length 469850599Sobrien && strncmp (t->suffix, suffix, suffix_length) == 0 469918334Speter && t->unique == (c != 'g')) 470018334Speter break; 470118334Speter 470290277Sobrien /* Make a new association if needed. %u and %j 470390277Sobrien require one. */ 470490277Sobrien if (t == 0 || c == 'u' || c == 'j') 470518334Speter { 470618334Speter if (t == 0) 470718334Speter { 470818334Speter t = (struct temp_name *) xmalloc (sizeof (struct temp_name)); 470918334Speter t->next = temp_names; 471018334Speter temp_names = t; 471118334Speter } 471250599Sobrien t->length = suffix_length; 471390277Sobrien if (saved_suffix) 471490277Sobrien { 471590277Sobrien t->suffix = saved_suffix; 471690277Sobrien saved_suffix = NULL; 471790277Sobrien } 471890277Sobrien else 471990277Sobrien t->suffix = save_string (suffix, suffix_length); 472018334Speter t->unique = (c != 'g'); 472150599Sobrien temp_filename = make_temp_file (t->suffix); 472250599Sobrien temp_filename_length = strlen (temp_filename); 472318334Speter t->filename = temp_filename; 472418334Speter t->filename_length = temp_filename_length; 472518334Speter } 472618334Speter 472790277Sobrien if (saved_suffix) 472890277Sobrien free (saved_suffix); 472990277Sobrien 473018334Speter obstack_grow (&obstack, t->filename, t->filename_length); 473118334Speter delete_this_arg = 1; 473218334Speter } 473318334Speter arg_going = 1; 473418334Speter break; 473518334Speter 473618334Speter case 'i': 473718334Speter obstack_grow (&obstack, input_filename, input_filename_length); 473818334Speter arg_going = 1; 473918334Speter break; 474018334Speter 474118334Speter case 'I': 474218334Speter { 474318334Speter struct prefix_list *pl = include_prefixes.plist; 474418334Speter 474518334Speter if (gcc_exec_prefix) 474618334Speter { 474790277Sobrien do_spec_1 ("-iprefix", 1, NULL); 474818334Speter /* Make this a separate argument. */ 474990277Sobrien do_spec_1 (" ", 0, NULL); 475090277Sobrien do_spec_1 (gcc_exec_prefix, 1, NULL); 475190277Sobrien do_spec_1 (" ", 0, NULL); 475218334Speter } 475318334Speter 475418334Speter for (; pl; pl = pl->next) 475518334Speter { 475690277Sobrien do_spec_1 ("-isystem", 1, NULL); 475718334Speter /* Make this a separate argument. */ 475890277Sobrien do_spec_1 (" ", 0, NULL); 475990277Sobrien do_spec_1 (pl->prefix, 1, NULL); 476090277Sobrien do_spec_1 (" ", 0, NULL); 476118334Speter } 476218334Speter } 476318334Speter break; 476418334Speter 476518334Speter case 'o': 476652520Sobrien { 476752520Sobrien int max = n_infiles; 476852520Sobrien max += lang_specific_extra_outfiles; 476918334Speter 477052520Sobrien for (i = 0; i < max; i++) 477152520Sobrien if (outfiles[i]) 477252520Sobrien store_arg (outfiles[i], 0, 0); 477352520Sobrien break; 477452520Sobrien } 477552520Sobrien 477618334Speter case 'O': 477790277Sobrien obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX)); 477818334Speter arg_going = 1; 477918334Speter break; 478018334Speter 478118334Speter case 's': 478218334Speter this_is_library_file = 1; 478318334Speter break; 478418334Speter 478518334Speter case 'w': 478618334Speter this_is_output_file = 1; 478718334Speter break; 478818334Speter 478918334Speter case 'W': 479018334Speter { 479150599Sobrien int cur_index = argbuf_index; 479218334Speter /* Handle the {...} following the %W. */ 479318334Speter if (*p != '{') 479418334Speter abort (); 479518334Speter p = handle_braces (p + 1); 479618334Speter if (p == 0) 479718334Speter return -1; 479818334Speter /* If any args were output, mark the last one for deletion 479918334Speter on failure. */ 480050599Sobrien if (argbuf_index != cur_index) 480118334Speter record_temp_file (argbuf[argbuf_index - 1], 0, 1); 480218334Speter break; 480318334Speter } 480418334Speter 480518334Speter /* %x{OPTION} records OPTION for %X to output. */ 480618334Speter case 'x': 480718334Speter { 480852520Sobrien const char *p1 = p; 480918334Speter char *string; 481018334Speter 481118334Speter /* Skip past the option value and make a copy. */ 481218334Speter if (*p != '{') 481318334Speter abort (); 481418334Speter while (*p++ != '}') 481518334Speter ; 481618334Speter string = save_string (p1 + 1, p - p1 - 2); 481718334Speter 481818334Speter /* See if we already recorded this option. */ 481918334Speter for (i = 0; i < n_linker_options; i++) 482018334Speter if (! strcmp (string, linker_options[i])) 482118334Speter { 482218334Speter free (string); 482318334Speter return 0; 482418334Speter } 482518334Speter 482618334Speter /* This option is new; add it. */ 482750599Sobrien add_linker_option (string, strlen (string)); 482818334Speter } 482918334Speter break; 483018334Speter 483118334Speter /* Dump out the options accumulated previously using %x. */ 483218334Speter case 'X': 483318334Speter for (i = 0; i < n_linker_options; i++) 483418334Speter { 483590277Sobrien do_spec_1 (linker_options[i], 1, NULL); 483618334Speter /* Make each accumulated option a separate argument. */ 483790277Sobrien do_spec_1 (" ", 0, NULL); 483818334Speter } 483918334Speter break; 484018334Speter 484118334Speter /* Dump out the options accumulated previously using -Wa,. */ 484218334Speter case 'Y': 484318334Speter for (i = 0; i < n_assembler_options; i++) 484418334Speter { 484590277Sobrien do_spec_1 (assembler_options[i], 1, NULL); 484618334Speter /* Make each accumulated option a separate argument. */ 484790277Sobrien do_spec_1 (" ", 0, NULL); 484818334Speter } 484918334Speter break; 485018334Speter 485118334Speter /* Dump out the options accumulated previously using -Wp,. */ 485218334Speter case 'Z': 485318334Speter for (i = 0; i < n_preprocessor_options; i++) 485418334Speter { 485590277Sobrien do_spec_1 (preprocessor_options[i], 1, NULL); 485618334Speter /* Make each accumulated option a separate argument. */ 485790277Sobrien do_spec_1 (" ", 0, NULL); 485818334Speter } 485918334Speter break; 486018334Speter 486118334Speter /* Here are digits and numbers that just process 486218334Speter a certain constant string as a spec. */ 486318334Speter 486418334Speter case '1': 486590277Sobrien value = do_spec_1 (cc1_spec, 0, NULL); 486618334Speter if (value != 0) 486718334Speter return value; 486818334Speter break; 486918334Speter 487018334Speter case '2': 487190277Sobrien value = do_spec_1 (cc1plus_spec, 0, NULL); 487218334Speter if (value != 0) 487318334Speter return value; 487418334Speter break; 487518334Speter 487618334Speter case 'a': 487790277Sobrien value = do_spec_1 (asm_spec, 0, NULL); 487818334Speter if (value != 0) 487918334Speter return value; 488018334Speter break; 488118334Speter 488218334Speter case 'A': 488390277Sobrien value = do_spec_1 (asm_final_spec, 0, NULL); 488418334Speter if (value != 0) 488518334Speter return value; 488618334Speter break; 488718334Speter 488818334Speter case 'c': 488990277Sobrien value = do_spec_1 (signed_char_spec, 0, NULL); 489018334Speter if (value != 0) 489118334Speter return value; 489218334Speter break; 489318334Speter 489418334Speter case 'C': 489590277Sobrien { 489690277Sobrien const char *const spec 489790277Sobrien = (input_file_compiler->cpp_spec 489890277Sobrien ? input_file_compiler->cpp_spec 489990277Sobrien : cpp_spec); 490090277Sobrien value = do_spec_1 (spec, 0, NULL); 490190277Sobrien if (value != 0) 490290277Sobrien return value; 490390277Sobrien } 490418334Speter break; 490518334Speter 490618334Speter case 'E': 490790277Sobrien value = do_spec_1 (endfile_spec, 0, NULL); 490818334Speter if (value != 0) 490918334Speter return value; 491018334Speter break; 491118334Speter 491218334Speter case 'l': 491390277Sobrien value = do_spec_1 (link_spec, 0, NULL); 491418334Speter if (value != 0) 491518334Speter return value; 491618334Speter break; 491718334Speter 491818334Speter case 'L': 491990277Sobrien value = do_spec_1 (lib_spec, 0, NULL); 492018334Speter if (value != 0) 492118334Speter return value; 492218334Speter break; 492318334Speter 492418334Speter case 'G': 492590277Sobrien value = do_spec_1 (libgcc_spec, 0, NULL); 492618334Speter if (value != 0) 492718334Speter return value; 492818334Speter break; 492918334Speter 493090277Sobrien case 'M': 493190277Sobrien if (multilib_dir && strcmp (multilib_dir, ".") != 0) 493290277Sobrien { 493390277Sobrien char *p; 493490277Sobrien const char *q; 493590277Sobrien size_t len; 493690277Sobrien 493790277Sobrien len = strlen (multilib_dir); 493890277Sobrien obstack_blank (&obstack, len + 1); 493990277Sobrien p = obstack_next_free (&obstack) - (len + 1); 494090277Sobrien 494190277Sobrien *p++ = '_'; 494290277Sobrien for (q = multilib_dir; *q ; ++q, ++p) 494390277Sobrien *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q); 494490277Sobrien } 494590277Sobrien break; 494690277Sobrien 494718334Speter case 'p': 494818334Speter { 494918334Speter char *x = (char *) alloca (strlen (cpp_predefines) + 1); 495018334Speter char *buf = x; 495190277Sobrien const char *y; 495218334Speter 495318334Speter /* Copy all of the -D options in CPP_PREDEFINES into BUF. */ 495418334Speter y = cpp_predefines; 495518334Speter while (*y != 0) 495618334Speter { 495718334Speter if (! strncmp (y, "-D", 2)) 495818334Speter /* Copy the whole option. */ 495918334Speter while (*y && *y != ' ' && *y != '\t') 496018334Speter *x++ = *y++; 496118334Speter else if (*y == ' ' || *y == '\t') 496218334Speter /* Copy whitespace to the result. */ 496318334Speter *x++ = *y++; 496418334Speter /* Don't copy other options. */ 496518334Speter else 496618334Speter y++; 496718334Speter } 496818334Speter 496918334Speter *x = 0; 497018334Speter 497190277Sobrien value = do_spec_1 (buf, 0, NULL); 497218334Speter if (value != 0) 497318334Speter return value; 497418334Speter } 497518334Speter break; 497618334Speter 497718334Speter case 'P': 497818334Speter { 497918334Speter char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1); 498018334Speter char *buf = x; 498190277Sobrien const char *y; 498218334Speter 498318334Speter /* Copy all of CPP_PREDEFINES into BUF, 498490277Sobrien but force them all into the reserved name space if they 498590277Sobrien aren't already there. The reserved name space is all 498690277Sobrien identifiers beginning with two underscores or with one 498790277Sobrien underscore and a capital letter. We do the forcing by 498890277Sobrien adding up to two underscores to the beginning and end 498990277Sobrien of each symbol. e.g. mips, _mips, mips_, and _mips_ all 499090277Sobrien become __mips__. */ 499118334Speter y = cpp_predefines; 499218334Speter while (*y != 0) 499318334Speter { 499418334Speter if (! strncmp (y, "-D", 2)) 499518334Speter { 499618334Speter int flag = 0; 499718334Speter 499818334Speter *x++ = *y++; 499918334Speter *x++ = *y++; 500018334Speter 500118334Speter if (*y != '_' 500290277Sobrien || (*(y + 1) != '_' 500390277Sobrien && ! ISUPPER ((unsigned char) *(y + 1)))) 500490277Sobrien { 500518334Speter /* Stick __ at front of macro name. */ 500690277Sobrien if (*y != '_') 500790277Sobrien *x++ = '_'; 500818334Speter *x++ = '_'; 500918334Speter /* Arrange to stick __ at the end as well. */ 501018334Speter flag = 1; 501118334Speter } 501218334Speter 501318334Speter /* Copy the macro name. */ 501418334Speter while (*y && *y != '=' && *y != ' ' && *y != '\t') 501518334Speter *x++ = *y++; 501618334Speter 501718334Speter if (flag) 501890277Sobrien { 501990277Sobrien if (x[-1] != '_') 502090277Sobrien { 502190277Sobrien if (x[-2] != '_') 502290277Sobrien *x++ = '_'; 502390277Sobrien *x++ = '_'; 502490277Sobrien } 502518334Speter } 502618334Speter 502718334Speter /* Copy the value given, if any. */ 502818334Speter while (*y && *y != ' ' && *y != '\t') 502918334Speter *x++ = *y++; 503018334Speter } 503118334Speter else if (*y == ' ' || *y == '\t') 503218334Speter /* Copy whitespace to the result. */ 503318334Speter *x++ = *y++; 503418334Speter /* Don't copy -A options */ 503518334Speter else 503618334Speter y++; 503718334Speter } 503818334Speter *x++ = ' '; 503918334Speter 504018334Speter /* Copy all of CPP_PREDEFINES into BUF, 504118334Speter but put __ after every -D. */ 504218334Speter y = cpp_predefines; 504318334Speter while (*y != 0) 504418334Speter { 504518334Speter if (! strncmp (y, "-D", 2)) 504618334Speter { 504718334Speter y += 2; 504818334Speter 504918334Speter if (*y != '_' 505090277Sobrien || (*(y + 1) != '_' 505190277Sobrien && ! ISUPPER ((unsigned char) *(y + 1)))) 505290277Sobrien { 505318334Speter /* Stick -D__ at front of macro name. */ 505418334Speter *x++ = '-'; 505518334Speter *x++ = 'D'; 505690277Sobrien if (*y != '_') 505790277Sobrien *x++ = '_'; 505818334Speter *x++ = '_'; 505918334Speter 506018334Speter /* Copy the macro name. */ 506118334Speter while (*y && *y != '=' && *y != ' ' && *y != '\t') 506218334Speter *x++ = *y++; 506318334Speter 506418334Speter /* Copy the value given, if any. */ 506518334Speter while (*y && *y != ' ' && *y != '\t') 506618334Speter *x++ = *y++; 506718334Speter } 506818334Speter else 506918334Speter { 507018334Speter /* Do not copy this macro - we have just done it before */ 507118334Speter while (*y && *y != ' ' && *y != '\t') 507218334Speter y++; 507318334Speter } 507418334Speter } 507518334Speter else if (*y == ' ' || *y == '\t') 507618334Speter /* Copy whitespace to the result. */ 507718334Speter *x++ = *y++; 507890277Sobrien /* Don't copy -A options. */ 507918334Speter else 508018334Speter y++; 508118334Speter } 508218334Speter *x++ = ' '; 508318334Speter 508418334Speter /* Copy all of the -A options in CPP_PREDEFINES into BUF. */ 508518334Speter y = cpp_predefines; 508618334Speter while (*y != 0) 508718334Speter { 508818334Speter if (! strncmp (y, "-A", 2)) 508918334Speter /* Copy the whole option. */ 509018334Speter while (*y && *y != ' ' && *y != '\t') 509118334Speter *x++ = *y++; 509218334Speter else if (*y == ' ' || *y == '\t') 509318334Speter /* Copy whitespace to the result. */ 509418334Speter *x++ = *y++; 509518334Speter /* Don't copy other options. */ 509618334Speter else 509718334Speter y++; 509818334Speter } 509918334Speter 510018334Speter *x = 0; 510118334Speter 510290277Sobrien value = do_spec_1 (buf, 0, NULL); 510318334Speter if (value != 0) 510418334Speter return value; 510518334Speter } 510618334Speter break; 510718334Speter 510818334Speter case 'S': 510990277Sobrien value = do_spec_1 (startfile_spec, 0, NULL); 511018334Speter if (value != 0) 511118334Speter return value; 511218334Speter break; 511318334Speter 511418334Speter /* Here we define characters other than letters and digits. */ 511518334Speter 511618334Speter case '{': 511718334Speter p = handle_braces (p); 511818334Speter if (p == 0) 511918334Speter return -1; 512018334Speter break; 512118334Speter 512218334Speter case '%': 512318334Speter obstack_1grow (&obstack, '%'); 512418334Speter break; 512518334Speter 512690277Sobrien case '.': 512790277Sobrien { 512890277Sobrien unsigned len = 0; 512990277Sobrien 513090277Sobrien while (p[len] && p[len] != ' ' && p[len] != '%') 513190277Sobrien len++; 513290277Sobrien suffix_subst = save_string (p - 1, len + 1); 513390277Sobrien p += len; 513490277Sobrien } 513590277Sobrien break; 513690277Sobrien 513718334Speter case '*': 513890277Sobrien if (soft_matched_part) 513990277Sobrien { 514090277Sobrien do_spec_1 (soft_matched_part, 1, NULL); 514190277Sobrien do_spec_1 (" ", 0, NULL); 514290277Sobrien } 514390277Sobrien else 514490277Sobrien /* Catch the case where a spec string contains something like 514590277Sobrien '%{foo:%*}'. ie there is no * in the pattern on the left 514690277Sobrien hand side of the :. */ 514790277Sobrien error ("spec failure: '%%*' has not been initialized by pattern match"); 514818334Speter break; 514918334Speter 515018334Speter /* Process a string found as the value of a spec given by name. 515118334Speter This feature allows individual machine descriptions 515218334Speter to add and use their own specs. 515318334Speter %[...] modifies -D options the way %P does; 515418334Speter %(...) uses the spec unmodified. */ 515550599Sobrien case '[': 515690277Sobrien error ("warning: use of obsolete %%[ operator in specs"); 515718334Speter case '(': 515818334Speter { 515952520Sobrien const char *name = p; 516018334Speter struct spec_list *sl; 516118334Speter int len; 516218334Speter 516318334Speter /* The string after the S/P is the name of a spec that is to be 516450599Sobrien processed. */ 516518334Speter while (*p && *p != ')' && *p != ']') 516618334Speter p++; 516718334Speter 516890277Sobrien /* See if it's in the list. */ 516918334Speter for (len = p - name, sl = specs; sl; sl = sl->next) 517050599Sobrien if (sl->name_len == len && !strncmp (sl->name, name, len)) 517118334Speter { 517250599Sobrien name = *(sl->ptr_spec); 517350599Sobrien#ifdef DEBUG_SPECS 517452520Sobrien notice ("Processing spec %c%s%c, which is '%s'\n", 517552520Sobrien c, sl->name, (c == '(') ? ')' : ']', name); 517650599Sobrien#endif 517718334Speter break; 517818334Speter } 517918334Speter 518018334Speter if (sl) 518118334Speter { 518218334Speter if (c == '(') 518318334Speter { 518490277Sobrien value = do_spec_1 (name, 0, NULL); 518518334Speter if (value != 0) 518618334Speter return value; 518718334Speter } 518818334Speter else 518918334Speter { 519018334Speter char *x = (char *) alloca (strlen (name) * 2 + 1); 519118334Speter char *buf = x; 519252520Sobrien const char *y = name; 519350599Sobrien int flag = 0; 519418334Speter 519518334Speter /* Copy all of NAME into BUF, but put __ after 519690277Sobrien every -D and at the end of each arg. */ 519718334Speter while (1) 519818334Speter { 519918334Speter if (! strncmp (y, "-D", 2)) 520018334Speter { 520118334Speter *x++ = '-'; 520218334Speter *x++ = 'D'; 520318334Speter *x++ = '_'; 520418334Speter *x++ = '_'; 520518334Speter y += 2; 520650599Sobrien flag = 1; 520750599Sobrien continue; 520818334Speter } 520990277Sobrien else if (flag 521090277Sobrien && (*y == ' ' || *y == '\t' || *y == '=' 521190277Sobrien || *y == '}' || *y == 0)) 521218334Speter { 521318334Speter *x++ = '_'; 521418334Speter *x++ = '_'; 521550599Sobrien flag = 0; 521618334Speter } 521790277Sobrien if (*y == 0) 521850599Sobrien break; 521918334Speter else 522018334Speter *x++ = *y++; 522118334Speter } 522218334Speter *x = 0; 522318334Speter 522490277Sobrien value = do_spec_1 (buf, 0, NULL); 522518334Speter if (value != 0) 522618334Speter return value; 522718334Speter } 522818334Speter } 522918334Speter 523018334Speter /* Discard the closing paren or bracket. */ 523118334Speter if (*p) 523218334Speter p++; 523318334Speter } 523418334Speter break; 523518334Speter 523618334Speter case 'v': 523718334Speter { 523818334Speter int c1 = *p++; /* Select first or second version number. */ 523990277Sobrien const char *v = compiler_version; 524090277Sobrien const char *q; 524190277Sobrien static const char zeroc = '0'; 524250599Sobrien 524350599Sobrien /* The format of the version string is 524450599Sobrien ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */ 524550599Sobrien 524650599Sobrien /* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */ 524750599Sobrien while (! ISDIGIT (*v)) 524850599Sobrien v++; 524950599Sobrien if (v > compiler_version && v[-1] != '-') 525050599Sobrien abort (); 525150599Sobrien 525218334Speter /* If desired, advance to second version number. */ 525390277Sobrien if (c1 >= '2') 525418334Speter { 525550599Sobrien /* Set V after the first period. */ 525650599Sobrien while (ISDIGIT (*v)) 525718334Speter v++; 525850599Sobrien if (*v != '.') 525950599Sobrien abort (); 526050599Sobrien v++; 526118334Speter } 526250599Sobrien 526390277Sobrien /* If desired, advance to third version number. 526490277Sobrien But don't complain if it's not present */ 526590277Sobrien if (c1 == '3') 526690277Sobrien { 526790277Sobrien /* Set V after the second period. */ 526890277Sobrien while (ISDIGIT (*v)) 526990277Sobrien v++; 527090277Sobrien if ((*v != 0) && (*v != ' ') && (*v != '.') && (*v != '-')) 527190277Sobrien abort (); 527290277Sobrien if (*v != 0) 527390277Sobrien v++; 527490277Sobrien } 527590277Sobrien 527618334Speter /* Set Q at the next period or at the end. */ 527718334Speter q = v; 527850599Sobrien while (ISDIGIT (*q)) 527918334Speter q++; 528090277Sobrien if (*q != 0 && q > v && *q != ' ' && *q != '.' && *q != '-') 528150599Sobrien abort (); 528250599Sobrien 528390277Sobrien if (q > v) 528490277Sobrien /* Put that part into the command. */ 528590277Sobrien obstack_grow (&obstack, v, q - v); 528690277Sobrien else 528790277Sobrien /* Default to "0" */ 528890277Sobrien obstack_grow (&obstack, &zeroc, 1); 528918334Speter arg_going = 1; 529018334Speter } 529118334Speter break; 529218334Speter 529318334Speter case '|': 529418334Speter if (input_from_pipe) 529590277Sobrien do_spec_1 ("-", 0, NULL); 529618334Speter break; 529718334Speter 529818334Speter default: 529990277Sobrien error ("spec failure: unrecognized spec option '%c'", c); 530090277Sobrien break; 530118334Speter } 530218334Speter break; 530318334Speter 530418334Speter case '\\': 530518334Speter /* Backslash: treat next character as ordinary. */ 530618334Speter c = *p++; 530718334Speter 530818334Speter /* fall through */ 530918334Speter default: 531018334Speter /* Ordinary character: put it into the current argument. */ 531118334Speter obstack_1grow (&obstack, c); 531218334Speter arg_going = 1; 531318334Speter } 531418334Speter 531590277Sobrien /* End of string. */ 531690277Sobrien return 0; 531718334Speter} 531818334Speter 531918334Speter/* Return 0 if we call do_spec_1 and that returns -1. */ 532018334Speter 532152520Sobrienstatic const char * 532218334Speterhandle_braces (p) 532390277Sobrien const char *p; 532418334Speter{ 532552520Sobrien const char *filter, *body = NULL, *endbody = NULL; 532650599Sobrien int pipe_p = 0; 532790277Sobrien int true_once = 0; /* If, in %{a|b:d}, at least one of a,b was seen. */ 532850599Sobrien int negate; 532950599Sobrien int suffix; 533050599Sobrien int include_blanks = 1; 533190277Sobrien int elide_switch = 0; 533290277Sobrien int ordered = 0; 533318334Speter 533450599Sobrien if (*p == '^') 533590277Sobrien { 533690277Sobrien /* A '^' after the open-brace means to not give blanks before args. */ 533790277Sobrien include_blanks = 0; 533890277Sobrien ++p; 533990277Sobrien } 534050599Sobrien 534118334Speter if (*p == '|') 534290277Sobrien { 534390277Sobrien /* A `|' after the open-brace means, 534490277Sobrien if the test fails, output a single minus sign rather than nothing. 534590277Sobrien This is used in %{|!pipe:...}. */ 534690277Sobrien pipe_p = 1; 534790277Sobrien ++p; 534890277Sobrien } 534918334Speter 535090277Sobrien if (*p == '<') 535190277Sobrien { 535290277Sobrien /* A `<' after the open-brace means that the switch should be 535390277Sobrien removed from the command-line. */ 535490277Sobrien elide_switch = 1; 535590277Sobrien ++p; 535690277Sobrien } 535790277Sobrien 535850599Sobriennext_member: 535950599Sobrien negate = suffix = 0; 536050599Sobrien 536118334Speter if (*p == '!') 536218334Speter /* A `!' after the open-brace negates the condition: 536318334Speter succeed if the specified switch is not present. */ 536418334Speter negate = 1, ++p; 536518334Speter 536618334Speter if (*p == '.') 536718334Speter /* A `.' after the open-brace means test against the current suffix. */ 536818334Speter { 536950599Sobrien if (pipe_p) 537018334Speter abort (); 537118334Speter 537218334Speter suffix = 1; 537318334Speter ++p; 537418334Speter } 537518334Speter 537690277Sobrien if (elide_switch && (negate || pipe_p || suffix)) 537790277Sobrien { 537890277Sobrien /* It doesn't make sense to mix elision with other flags. We 537990277Sobrien could fatal() here, but the standard seems to be to abort. */ 538090277Sobrien abort (); 538190277Sobrien } 538290277Sobrien 538390277Sobrien next_ampersand: 538418334Speter filter = p; 538590277Sobrien while (*p != ':' && *p != '}' && *p != '|' && *p != '&') 538690277Sobrien p++; 538750599Sobrien 538890277Sobrien if (*p == '|' && (pipe_p || ordered)) 538950599Sobrien abort (); 539050599Sobrien 539150599Sobrien if (!body) 539218334Speter { 539390277Sobrien if (*p != '}' && *p != '&') 539490277Sobrien { 539590277Sobrien int count = 1; 539690277Sobrien const char *q = p; 539750599Sobrien 539890277Sobrien while (*q++ != ':') 539990277Sobrien continue; 540050599Sobrien body = q; 540190277Sobrien 540250599Sobrien while (count > 0) 540350599Sobrien { 540450599Sobrien if (*q == '{') 540590277Sobrien count++; 540650599Sobrien else if (*q == '}') 540790277Sobrien count--; 540850599Sobrien else if (*q == 0) 540990277Sobrien fatal ("mismatched braces in specs"); 541050599Sobrien q++; 541150599Sobrien } 541250599Sobrien endbody = q; 541318334Speter } 541450599Sobrien else 541590277Sobrien body = p, endbody = p + 1; 541618334Speter } 541718334Speter 541818334Speter if (suffix) 541918334Speter { 542018334Speter int found = (input_suffix != 0 542190277Sobrien && (long) strlen (input_suffix) == (long) (p - filter) 542218334Speter && strncmp (input_suffix, filter, p - filter) == 0); 542318334Speter 542450599Sobrien if (body[0] == '}') 542518334Speter abort (); 542618334Speter 542718334Speter if (negate != found 542890277Sobrien && do_spec_1 (save_string (body, endbody-body-1), 0, NULL) < 0) 542918334Speter return 0; 543018334Speter } 543190277Sobrien else if (p[-1] == '*' && (p[0] == '}' || p[0] == '&')) 543218334Speter { 543318334Speter /* Substitute all matching switches as separate args. */ 543490277Sobrien int i; 543590277Sobrien 543618334Speter for (i = 0; i < n_switches; i++) 543790277Sobrien if (!strncmp (switches[i].part1, filter, p - 1 - filter) 543890277Sobrien && check_live_switch (i, p - 1 - filter)) 543990277Sobrien { 544090277Sobrien if (elide_switch) 544190277Sobrien { 544290277Sobrien switches[i].live_cond = SWITCH_IGNORE; 544390277Sobrien switches[i].validated = 1; 544490277Sobrien } 544590277Sobrien else 544690277Sobrien ordered = 1, switches[i].ordering = 1; 544790277Sobrien } 544818334Speter } 544918334Speter else 545018334Speter { 545118334Speter /* Test for presence of the specified switch. */ 545290277Sobrien int i; 545318334Speter int present = 0; 545418334Speter 545518334Speter /* If name specified ends in *, as in {x*:...}, 545618334Speter check for %* and handle that case. */ 545718334Speter if (p[-1] == '*' && !negate) 545818334Speter { 545918334Speter int substitution; 546052520Sobrien const char *r = body; 546118334Speter 546218334Speter /* First see whether we have %*. */ 546318334Speter substitution = 0; 546450599Sobrien while (r < endbody) 546518334Speter { 546618334Speter if (*r == '%' && r[1] == '*') 546718334Speter substitution = 1; 546818334Speter r++; 546918334Speter } 547018334Speter /* If we do, handle that case. */ 547118334Speter if (substitution) 547218334Speter { 547318334Speter /* Substitute all matching switches as separate args. 547418334Speter But do this by substituting for %* 547518334Speter in the text that follows the colon. */ 547618334Speter 547718334Speter unsigned hard_match_len = p - filter - 1; 547850599Sobrien char *string = save_string (body, endbody - body - 1); 547918334Speter 548018334Speter for (i = 0; i < n_switches; i++) 548118334Speter if (!strncmp (switches[i].part1, filter, hard_match_len) 548218334Speter && check_live_switch (i, -1)) 548318334Speter { 548418334Speter do_spec_1 (string, 0, &switches[i].part1[hard_match_len]); 548518334Speter /* Pass any arguments this switch has. */ 548650599Sobrien give_switch (i, 1, 1); 548790277Sobrien suffix_subst = NULL; 548818334Speter } 548918334Speter 549050599Sobrien /* We didn't match. Try again. */ 549150599Sobrien if (*p++ == '|') 549250599Sobrien goto next_member; 549350599Sobrien return endbody; 549418334Speter } 549518334Speter } 549618334Speter 549718334Speter /* If name specified ends in *, as in {x*:...}, 549818334Speter check for presence of any switch name starting with x. */ 549918334Speter if (p[-1] == '*') 550018334Speter { 550118334Speter for (i = 0; i < n_switches; i++) 550218334Speter { 550318334Speter unsigned hard_match_len = p - filter - 1; 550418334Speter 550518334Speter if (!strncmp (switches[i].part1, filter, hard_match_len) 550618334Speter && check_live_switch (i, hard_match_len)) 550718334Speter { 550818334Speter present = 1; 550990277Sobrien break; 551018334Speter } 551118334Speter } 551218334Speter } 551318334Speter /* Otherwise, check for presence of exact name specified. */ 551418334Speter else 551518334Speter { 551618334Speter for (i = 0; i < n_switches; i++) 551718334Speter { 551818334Speter if (!strncmp (switches[i].part1, filter, p - filter) 551918334Speter && switches[i].part1[p - filter] == 0 552018334Speter && check_live_switch (i, -1)) 552118334Speter { 552218334Speter present = 1; 552318334Speter break; 552418334Speter } 552518334Speter } 552618334Speter } 552718334Speter 552850599Sobrien /* If it is as desired (present for %{s...}, absent for %{!s...}) 552918334Speter then substitute either the switch or the specified 553018334Speter conditional text. */ 553118334Speter if (present != negate) 553218334Speter { 553390277Sobrien if (elide_switch) 553418334Speter { 553590277Sobrien switches[i].live_cond = SWITCH_IGNORE; 553690277Sobrien switches[i].validated = 1; 553718334Speter } 553890277Sobrien else if (ordered || *p == '&') 553990277Sobrien ordered = 1, switches[i].ordering = 1; 554090277Sobrien else if (*p == '}') 554190277Sobrien give_switch (i, 0, include_blanks); 554218334Speter else 554390277Sobrien /* Even if many alternatives are matched, only output once. */ 554490277Sobrien true_once = 1; 554518334Speter } 554650599Sobrien else if (pipe_p) 554718334Speter { 554818334Speter /* Here if a %{|...} conditional fails: output a minus sign, 554918334Speter which means "standard output" or "standard input". */ 555090277Sobrien do_spec_1 ("-", 0, NULL); 555150599Sobrien return endbody; 555218334Speter } 555318334Speter } 555418334Speter 555550599Sobrien /* We didn't match; try again. */ 555650599Sobrien if (*p++ == '|') 555750599Sobrien goto next_member; 555850599Sobrien 555990277Sobrien if (p[-1] == '&') 556090277Sobrien { 556190277Sobrien body = 0; 556290277Sobrien goto next_ampersand; 556390277Sobrien } 556490277Sobrien 556590277Sobrien if (ordered) 556690277Sobrien { 556790277Sobrien int i; 556890277Sobrien /* Doing this set of switches later preserves their command-line 556990277Sobrien ordering. This is needed for e.g. -U, -D and -A. */ 557090277Sobrien for (i = 0; i < n_switches; i++) 557190277Sobrien if (switches[i].ordering == 1) 557290277Sobrien { 557390277Sobrien switches[i].ordering = 0; 557490277Sobrien give_switch (i, 0, include_blanks); 557590277Sobrien } 557690277Sobrien } 557790277Sobrien /* Process the spec just once, regardless of match count. */ 557890277Sobrien else if (true_once) 557990277Sobrien { 558090277Sobrien if (do_spec_1 (save_string (body, endbody - body - 1), 558190277Sobrien 0, NULL) < 0) 558290277Sobrien return 0; 558390277Sobrien } 558490277Sobrien 558550599Sobrien return endbody; 558618334Speter} 558718334Speter 558818334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch 558918334Speter on the command line. PREFIX_LENGTH is the length of XXX in an {XXX*} 559018334Speter spec, or -1 if either exact match or %* is used. 559118334Speter 559218334Speter A -O switch is obsoleted by a later -O switch. A -f, -m, or -W switch 559318334Speter whose value does not begin with "no-" is obsoleted by the same value 559418334Speter with the "no-", similarly for a switch with the "no-" prefix. */ 559518334Speter 559618334Speterstatic int 559718334Spetercheck_live_switch (switchnum, prefix_length) 559818334Speter int switchnum; 559918334Speter int prefix_length; 560018334Speter{ 560152520Sobrien const char *name = switches[switchnum].part1; 560218334Speter int i; 560318334Speter 560418334Speter /* In the common case of {<at-most-one-letter>*}, a negating 560518334Speter switch would always match, so ignore that case. We will just 560618334Speter send the conflicting switches to the compiler phase. */ 560718334Speter if (prefix_length >= 0 && prefix_length <= 1) 560818334Speter return 1; 560918334Speter 561018334Speter /* If we already processed this switch and determined if it was 561118334Speter live or not, return our past determination. */ 561218334Speter if (switches[switchnum].live_cond != 0) 561318334Speter return switches[switchnum].live_cond > 0; 561418334Speter 561518334Speter /* Now search for duplicate in a manner that depends on the name. */ 561618334Speter switch (*name) 561718334Speter { 561818334Speter case 'O': 561990277Sobrien for (i = switchnum + 1; i < n_switches; i++) 562090277Sobrien if (switches[i].part1[0] == 'O') 562190277Sobrien { 562290277Sobrien switches[switchnum].validated = 1; 562390277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 562490277Sobrien return 0; 562590277Sobrien } 562618334Speter break; 562718334Speter 562818334Speter case 'W': case 'f': case 'm': 562918334Speter if (! strncmp (name + 1, "no-", 3)) 563018334Speter { 563150599Sobrien /* We have Xno-YYY, search for XYYY. */ 563218334Speter for (i = switchnum + 1; i < n_switches; i++) 563318334Speter if (switches[i].part1[0] == name[0] 563418334Speter && ! strcmp (&switches[i].part1[1], &name[4])) 563590277Sobrien { 563690277Sobrien switches[switchnum].validated = 1; 563790277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 563890277Sobrien return 0; 563990277Sobrien } 564018334Speter } 564118334Speter else 564218334Speter { 564318334Speter /* We have XYYY, search for Xno-YYY. */ 564418334Speter for (i = switchnum + 1; i < n_switches; i++) 564518334Speter if (switches[i].part1[0] == name[0] 564618334Speter && switches[i].part1[1] == 'n' 564718334Speter && switches[i].part1[2] == 'o' 564818334Speter && switches[i].part1[3] == '-' 564918334Speter && !strcmp (&switches[i].part1[4], &name[1])) 565090277Sobrien { 565190277Sobrien switches[switchnum].validated = 1; 565290277Sobrien switches[switchnum].live_cond = SWITCH_FALSE; 565390277Sobrien return 0; 565490277Sobrien } 565518334Speter } 565618334Speter break; 565718334Speter } 565818334Speter 565918334Speter /* Otherwise the switch is live. */ 566090277Sobrien switches[switchnum].live_cond = SWITCH_LIVE; 566118334Speter return 1; 566218334Speter} 566318334Speter 566418334Speter/* Pass a switch to the current accumulating command 566518334Speter in the same form that we received it. 566618334Speter SWITCHNUM identifies the switch; it is an index into 566718334Speter the vector of switches gcc received, which is `switches'. 566818334Speter This cannot fail since it never finishes a command line. 566918334Speter 567050599Sobrien If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. 567118334Speter 567250599Sobrien If INCLUDE_BLANKS is nonzero, then we include blanks before each argument 567350599Sobrien of the switch. */ 567450599Sobrien 567518334Speterstatic void 567650599Sobriengive_switch (switchnum, omit_first_word, include_blanks) 567718334Speter int switchnum; 567818334Speter int omit_first_word; 567950599Sobrien int include_blanks; 568018334Speter{ 568190277Sobrien if (switches[switchnum].live_cond == SWITCH_IGNORE) 568290277Sobrien return; 568390277Sobrien 568418334Speter if (!omit_first_word) 568518334Speter { 568690277Sobrien do_spec_1 ("-", 0, NULL); 568790277Sobrien do_spec_1 (switches[switchnum].part1, 1, NULL); 568818334Speter } 568950599Sobrien 569018334Speter if (switches[switchnum].args != 0) 569118334Speter { 569290277Sobrien const char **p; 569318334Speter for (p = switches[switchnum].args; *p; p++) 569418334Speter { 569590277Sobrien const char *arg = *p; 569690277Sobrien 569750599Sobrien if (include_blanks) 569890277Sobrien do_spec_1 (" ", 0, NULL); 569990277Sobrien if (suffix_subst) 570090277Sobrien { 570190277Sobrien unsigned length = strlen (arg); 570290277Sobrien int dot = 0; 570390277Sobrien 570490277Sobrien while (length-- && !IS_DIR_SEPARATOR (arg[length])) 570590277Sobrien if (arg[length] == '.') 570690277Sobrien { 570790277Sobrien ((char *)arg)[length] = 0; 570890277Sobrien dot = 1; 570990277Sobrien break; 571090277Sobrien } 571190277Sobrien do_spec_1 (arg, 1, NULL); 571290277Sobrien if (dot) 571390277Sobrien ((char *)arg)[length] = '.'; 571490277Sobrien do_spec_1 (suffix_subst, 1, NULL); 571590277Sobrien } 571690277Sobrien else 571790277Sobrien do_spec_1 (arg, 1, NULL); 571818334Speter } 571918334Speter } 572050599Sobrien 572190277Sobrien do_spec_1 (" ", 0, NULL); 572252520Sobrien switches[switchnum].validated = 1; 572318334Speter} 572418334Speter 572518334Speter/* Search for a file named NAME trying various prefixes including the 572618334Speter user's -B prefix and some standard ones. 572718334Speter Return the absolute file name found. If nothing is found, return NAME. */ 572818334Speter 572952520Sobrienstatic const char * 573018334Speterfind_file (name) 573152520Sobrien const char *name; 573218334Speter{ 573318334Speter char *newname; 573418334Speter 573518334Speter /* Try multilib_dir if it is defined. */ 573618334Speter if (multilib_dir != NULL) 573718334Speter { 573890277Sobrien const char *const try = ACONCAT ((multilib_dir, dir_separator_str, name, NULL)); 573918334Speter 574018334Speter newname = find_a_file (&startfile_prefixes, try, R_OK); 574118334Speter 574218334Speter /* If we don't find it in the multi library dir, then fall 574318334Speter through and look for it in the normal places. */ 574418334Speter if (newname != NULL) 574518334Speter return newname; 574618334Speter } 574718334Speter 574818334Speter newname = find_a_file (&startfile_prefixes, name, R_OK); 574918334Speter return newname ? newname : name; 575018334Speter} 575118334Speter 575218334Speter/* Determine whether a directory exists. If LINKER, return 0 for 575318334Speter certain fixed names not needed by the linker. If not LINKER, it is 575418334Speter only important to return 0 if the host machine has a small ARG_MAX 575518334Speter limit. */ 575618334Speter 575718334Speterstatic int 575818334Speteris_directory (path1, path2, linker) 575952520Sobrien const char *path1; 576052520Sobrien const char *path2; 576118334Speter int linker; 576218334Speter{ 576318334Speter int len1 = strlen (path1); 576418334Speter int len2 = strlen (path2); 576518334Speter char *path = (char *) alloca (3 + len1 + len2); 576618334Speter char *cp; 576718334Speter struct stat st; 576818334Speter 576918334Speter#ifndef SMALL_ARG_MAX 577018334Speter if (! linker) 577118334Speter return 1; 577218334Speter#endif 577318334Speter 577418334Speter /* Construct the path from the two parts. Ensure the string ends with "/.". 577518334Speter The resulting path will be a directory even if the given path is a 577618334Speter symbolic link. */ 577752520Sobrien memcpy (path, path1, len1); 577852520Sobrien memcpy (path + len1, path2, len2); 577918334Speter cp = path + len1 + len2; 578052520Sobrien if (!IS_DIR_SEPARATOR (cp[-1])) 578118334Speter *cp++ = DIR_SEPARATOR; 578218334Speter *cp++ = '.'; 578318334Speter *cp = '\0'; 578418334Speter 578551232Sbde#ifndef FREEBSD_NATIVE 578618334Speter /* Exclude directories that the linker is known to search. */ 578718334Speter if (linker 578818334Speter && ((cp - path == 6 578990277Sobrien && strcmp (path, concat (dir_separator_str, "lib", 579090277Sobrien dir_separator_str, ".", NULL)) == 0) 579118334Speter || (cp - path == 10 579290277Sobrien && strcmp (path, concat (dir_separator_str, "usr", 579390277Sobrien dir_separator_str, "lib", 579490277Sobrien dir_separator_str, ".", NULL)) == 0))) 579518334Speter return 0; 579651232Sbde#endif /* FREEBSD_NATIVE */ 579718334Speter 579818334Speter return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode)); 579918334Speter} 580090277Sobrien 580190277Sobrien/* Set up the various global variables to indicate that we're processing 580290277Sobrien the input file named FILENAME. */ 580390277Sobrien 580490277Sobrienvoid 580590277Sobrienset_input (filename) 580690277Sobrien const char *filename; 580790277Sobrien{ 580890277Sobrien const char *p; 580990277Sobrien 581090277Sobrien input_filename = filename; 581190277Sobrien input_filename_length = strlen (input_filename); 581290277Sobrien 581390277Sobrien input_basename = input_filename; 581490277Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 581590277Sobrien /* Skip drive name so 'x:foo' is handled properly. */ 581690277Sobrien if (input_basename[1] == ':') 581790277Sobrien input_basename += 2; 581890277Sobrien#endif 581990277Sobrien for (p = input_basename; *p; p++) 582090277Sobrien if (IS_DIR_SEPARATOR (*p)) 582190277Sobrien input_basename = p + 1; 582290277Sobrien 582390277Sobrien /* Find a suffix starting with the last period, 582490277Sobrien and set basename_length to exclude that suffix. */ 582590277Sobrien basename_length = strlen (input_basename); 582690277Sobrien suffixed_basename_length = basename_length; 582790277Sobrien p = input_basename + basename_length; 582890277Sobrien while (p != input_basename && *p != '.') 582990277Sobrien --p; 583090277Sobrien if (*p == '.' && p != input_basename) 583190277Sobrien { 583290277Sobrien basename_length = p - input_basename; 583390277Sobrien input_suffix = p + 1; 583490277Sobrien } 583590277Sobrien else 583690277Sobrien input_suffix = ""; 583790277Sobrien 583890277Sobrien /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then 583990277Sobrien we will need to do a stat on the input_filename. The 584090277Sobrien INPUT_STAT_SET signals that the stat is needed. */ 584190277Sobrien input_stat_set = 0; 584290277Sobrien} 584318334Speter 584418334Speter/* On fatal signals, delete all the temporary files. */ 584518334Speter 584618334Speterstatic void 584718334Speterfatal_error (signum) 584818334Speter int signum; 584918334Speter{ 585018334Speter signal (signum, SIG_DFL); 585118334Speter delete_failure_queue (); 585218334Speter delete_temp_files (); 585318334Speter /* Get the same signal again, this time not handled, 585418334Speter so its normal effect occurs. */ 585518334Speter kill (getpid (), signum); 585618334Speter} 585718334Speter 585890277Sobrienextern int main PARAMS ((int, const char *const *)); 585990277Sobrien 586018334Speterint 586118334Spetermain (argc, argv) 586218334Speter int argc; 586390277Sobrien const char *const *argv; 586418334Speter{ 586590277Sobrien size_t i; 586618334Speter int value; 586718334Speter int linker_was_run = 0; 586818334Speter char *explicit_link_files; 586918334Speter char *specs_file; 587052520Sobrien const char *p; 587150599Sobrien struct user_specs *uptr; 587218334Speter 587318334Speter p = argv[0] + strlen (argv[0]); 587452520Sobrien while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) 587552520Sobrien --p; 587618334Speter programname = p; 587718334Speter 587890277Sobrien xmalloc_set_program_name (programname); 587990277Sobrien 588090277Sobrien#ifdef GCC_DRIVER_HOST_INITIALIZATION 588190277Sobrien /* Perform host dependent initialization when needed. */ 588290277Sobrien GCC_DRIVER_HOST_INITIALIZATION; 588352520Sobrien#endif 588452520Sobrien 588590277Sobrien gcc_init_libintl (); 588690277Sobrien 588718334Speter if (signal (SIGINT, SIG_IGN) != SIG_IGN) 588818334Speter signal (SIGINT, fatal_error); 588918334Speter#ifdef SIGHUP 589018334Speter if (signal (SIGHUP, SIG_IGN) != SIG_IGN) 589118334Speter signal (SIGHUP, fatal_error); 589218334Speter#endif 589318334Speter if (signal (SIGTERM, SIG_IGN) != SIG_IGN) 589418334Speter signal (SIGTERM, fatal_error); 589518334Speter#ifdef SIGPIPE 589618334Speter if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) 589718334Speter signal (SIGPIPE, fatal_error); 589818334Speter#endif 589990277Sobrien#ifdef SIGCHLD 590090277Sobrien /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will 590190277Sobrien receive the signal. A different setting is inheritable */ 590290277Sobrien signal (SIGCHLD, SIG_DFL); 590390277Sobrien#endif 590418334Speter 590518334Speter argbuf_length = 10; 590690277Sobrien argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *)); 590718334Speter 590818334Speter obstack_init (&obstack); 590918334Speter 591050599Sobrien /* Build multilib_select, et. al from the separate lines that make up each 591150599Sobrien multilib selection. */ 591250599Sobrien { 591390277Sobrien const char *const *q = multilib_raw; 591450599Sobrien int need_space; 591550599Sobrien 591650599Sobrien obstack_init (&multilib_obstack); 591750599Sobrien while ((p = *q++) != (char *) 0) 591850599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 591950599Sobrien 592050599Sobrien obstack_1grow (&multilib_obstack, 0); 592150599Sobrien multilib_select = obstack_finish (&multilib_obstack); 592250599Sobrien 592350599Sobrien q = multilib_matches_raw; 592450599Sobrien while ((p = *q++) != (char *) 0) 592550599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 592650599Sobrien 592750599Sobrien obstack_1grow (&multilib_obstack, 0); 592850599Sobrien multilib_matches = obstack_finish (&multilib_obstack); 592950599Sobrien 593090277Sobrien q = multilib_exclusions_raw; 593190277Sobrien while ((p = *q++) != (char *) 0) 593290277Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 593390277Sobrien 593490277Sobrien obstack_1grow (&multilib_obstack, 0); 593590277Sobrien multilib_exclusions = obstack_finish (&multilib_obstack); 593690277Sobrien 593750599Sobrien need_space = FALSE; 593890277Sobrien for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++) 593950599Sobrien { 594050599Sobrien if (need_space) 594150599Sobrien obstack_1grow (&multilib_obstack, ' '); 594250599Sobrien obstack_grow (&multilib_obstack, 594350599Sobrien multilib_defaults_raw[i], 594450599Sobrien strlen (multilib_defaults_raw[i])); 594550599Sobrien need_space = TRUE; 594650599Sobrien } 594750599Sobrien 594850599Sobrien obstack_1grow (&multilib_obstack, 0); 594950599Sobrien multilib_defaults = obstack_finish (&multilib_obstack); 595050599Sobrien } 595150599Sobrien 595218334Speter /* Set up to remember the pathname of gcc and any options 595318334Speter needed for collect. We use argv[0] instead of programname because 595418334Speter we need the complete pathname. */ 595518334Speter obstack_init (&collect_obstack); 595690277Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1); 595790277Sobrien obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1); 595818334Speter putenv (obstack_finish (&collect_obstack)); 595918334Speter 596018334Speter#ifdef INIT_ENVIRONMENT 596118334Speter /* Set up any other necessary machine specific environment variables. */ 596218334Speter putenv (INIT_ENVIRONMENT); 596318334Speter#endif 596418334Speter 596518334Speter /* Make a table of what switches there are (switches, n_switches). 596618334Speter Make a table of specified input files (infiles, n_infiles). 596718334Speter Decode switches that are handled locally. */ 596818334Speter 596918334Speter process_command (argc, argv); 597018334Speter 597118334Speter /* Initialize the vector of specs to just the default. 597218334Speter This means one element containing 0s, as a terminator. */ 597318334Speter 597418334Speter compilers = (struct compiler *) xmalloc (sizeof default_compilers); 597590277Sobrien memcpy ((char *) compilers, (char *) default_compilers, 597690277Sobrien sizeof default_compilers); 597718334Speter n_compilers = n_default_compilers; 597818334Speter 597918334Speter /* Read specs from a file if there is one. */ 598018334Speter 598118346Speter#ifndef FREEBSD_NATIVE 598250599Sobrien machine_suffix = concat (spec_machine, dir_separator_str, 598390277Sobrien spec_version, dir_separator_str, NULL); 598490277Sobrien just_machine_suffix = concat (spec_machine, dir_separator_str, NULL); 598550599Sobrien#else /* FREEBSD_NATIVE */ 598650599Sobrien just_machine_suffix = ""; 598750599Sobrien#endif /* FREEBSD_NATIVE */ 598818334Speter 598918334Speter specs_file = find_a_file (&startfile_prefixes, "specs", R_OK); 599018334Speter /* Read the specs file unless it is a default one. */ 599118334Speter if (specs_file != 0 && strcmp (specs_file, "specs")) 599250599Sobrien read_specs (specs_file, TRUE); 599350599Sobrien else 599450599Sobrien init_spec (); 599518334Speter 599650599Sobrien /* We need to check standard_exec_prefix/just_machine_suffix/specs 599790277Sobrien for any override of as, ld and libraries. */ 599850599Sobrien specs_file = (char *) alloca (strlen (standard_exec_prefix) 599950599Sobrien + strlen (just_machine_suffix) 600050599Sobrien + sizeof ("specs")); 600150599Sobrien 600250599Sobrien strcpy (specs_file, standard_exec_prefix); 600350599Sobrien strcat (specs_file, just_machine_suffix); 600450599Sobrien strcat (specs_file, "specs"); 600550599Sobrien if (access (specs_file, R_OK) == 0) 600650599Sobrien read_specs (specs_file, TRUE); 600790277Sobrien 600818334Speter /* If not cross-compiling, look for startfiles in the standard places. */ 600950599Sobrien if (*cross_compile == '0') 601018334Speter { 601190277Sobrien if (*md_exec_prefix) 601290277Sobrien { 601390277Sobrien add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 601490277Sobrien PREFIX_PRIORITY_LAST, 0, NULL); 601590277Sobrien add_prefix (&startfile_prefixes, md_exec_prefix, "GCC", 601690277Sobrien PREFIX_PRIORITY_LAST, 0, NULL); 601790277Sobrien } 601818334Speter 601990277Sobrien if (*md_startfile_prefix) 602090277Sobrien add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC", 602190277Sobrien PREFIX_PRIORITY_LAST, 0, NULL); 602218334Speter 602390277Sobrien if (*md_startfile_prefix_1) 602490277Sobrien add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC", 602590277Sobrien PREFIX_PRIORITY_LAST, 0, NULL); 602618334Speter 602718334Speter /* If standard_startfile_prefix is relative, base it on 602818334Speter standard_exec_prefix. This lets us move the installed tree 602918334Speter as a unit. If GCC_EXEC_PREFIX is defined, base 603018334Speter standard_startfile_prefix on that as well. */ 603190277Sobrien if (IS_ABSOLUTE_PATHNAME (standard_startfile_prefix)) 603250599Sobrien add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS", 603390277Sobrien PREFIX_PRIORITY_LAST, 0, NULL); 603418334Speter else 603518334Speter { 603618334Speter if (gcc_exec_prefix) 603718334Speter add_prefix (&startfile_prefixes, 603850599Sobrien concat (gcc_exec_prefix, machine_suffix, 603990277Sobrien standard_startfile_prefix, NULL), 604090277Sobrien NULL, PREFIX_PRIORITY_LAST, 0, NULL); 604118334Speter add_prefix (&startfile_prefixes, 604250599Sobrien concat (standard_exec_prefix, 604350599Sobrien machine_suffix, 604490277Sobrien standard_startfile_prefix, NULL), 604590277Sobrien NULL, PREFIX_PRIORITY_LAST, 0, NULL); 604690277Sobrien } 604718334Speter 604818346Speter#ifndef FREEBSD_NATIVE 604950599Sobrien add_prefix (&startfile_prefixes, standard_startfile_prefix_1, 605090277Sobrien "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL); 605150599Sobrien add_prefix (&startfile_prefixes, standard_startfile_prefix_2, 605290277Sobrien "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL); 605318334Speter#if 0 /* Can cause surprises, and one can use -B./ instead. */ 605490277Sobrien add_prefix (&startfile_prefixes, "./", NULL, 605590277Sobrien PREFIX_PRIORITY_LAST, 1, NULL); 605618334Speter#endif 605718346Speter#endif /* FREEBSD_NATIVE */ 605818334Speter } 605918334Speter else 606018334Speter { 606190277Sobrien if (!IS_ABSOLUTE_PATHNAME (standard_startfile_prefix) 606290277Sobrien && gcc_exec_prefix) 606318334Speter add_prefix (&startfile_prefixes, 606450599Sobrien concat (gcc_exec_prefix, machine_suffix, 606590277Sobrien standard_startfile_prefix, NULL), 606690277Sobrien "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL); 606718334Speter } 606818334Speter 606952520Sobrien /* Process any user specified specs in the order given on the command 607052520Sobrien line. */ 607152520Sobrien for (uptr = user_specs_head; uptr; uptr = uptr->next) 607252520Sobrien { 607352520Sobrien char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK); 607452520Sobrien read_specs (filename ? filename : uptr->filename, FALSE); 607552520Sobrien } 607652520Sobrien 607718334Speter /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */ 607818334Speter if (gcc_exec_prefix) 607990277Sobrien gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 608090277Sobrien spec_version, dir_separator_str, NULL); 608118334Speter 608218334Speter /* Now we have the specs. 608318334Speter Set the `valid' bits for switches that match anything in any spec. */ 608418334Speter 608518334Speter validate_all_switches (); 608618334Speter 608718334Speter /* Now that we have the switches and the specs, set 608818334Speter the subdirectory based on the options. */ 608918334Speter set_multilib_dir (); 609018334Speter 609118334Speter /* Warn about any switches that no pass was interested in. */ 609218334Speter 609390277Sobrien for (i = 0; (int) i < n_switches; i++) 609452520Sobrien if (! switches[i].validated) 609518334Speter error ("unrecognized option `-%s'", switches[i].part1); 609618334Speter 609718334Speter /* Obey some of the options. */ 609818334Speter 609918334Speter if (print_search_dirs) 610018334Speter { 610190277Sobrien printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix); 610290277Sobrien printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0)); 610390277Sobrien printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0)); 610490277Sobrien return (0); 610518334Speter } 610618334Speter 610718334Speter if (print_file_name) 610818334Speter { 610918334Speter printf ("%s\n", find_file (print_file_name)); 611090277Sobrien return (0); 611118334Speter } 611218334Speter 611318334Speter if (print_prog_name) 611418334Speter { 611518334Speter char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK); 611618334Speter printf ("%s\n", (newname ? newname : print_prog_name)); 611790277Sobrien return (0); 611818334Speter } 611918334Speter 612018334Speter if (print_multi_lib) 612118334Speter { 612218334Speter print_multilib_info (); 612390277Sobrien return (0); 612418334Speter } 612518334Speter 612618334Speter if (print_multi_directory) 612718334Speter { 612818334Speter if (multilib_dir == NULL) 612918334Speter printf (".\n"); 613018334Speter else 613118334Speter printf ("%s\n", multilib_dir); 613290277Sobrien return (0); 613318334Speter } 613418334Speter 613590277Sobrien if (target_help_flag) 613690277Sobrien { 613790277Sobrien /* Print if any target specific options. */ 613890277Sobrien 613990277Sobrien /* We do not exit here. Instead we have created a fake input file 614090277Sobrien called 'target-dummy' which needs to be compiled, and we pass this 614190277Sobrien on to the various sub-processes, along with the --target-help 614290277Sobrien switch. */ 614390277Sobrien } 614490277Sobrien 614550599Sobrien if (print_help_list) 614650599Sobrien { 614750599Sobrien display_help (); 614850599Sobrien 614950599Sobrien if (! verbose_flag) 615050599Sobrien { 615190277Sobrien printf (_("\nFor bug reporting instructions, please see:\n")); 615257849Sobrien printf ("%s.\n", GCCBUGURL); 615390277Sobrien 615490277Sobrien return (0); 615550599Sobrien } 615650599Sobrien 615750599Sobrien /* We do not exit here. Instead we have created a fake input file 615850599Sobrien called 'help-dummy' which needs to be compiled, and we pass this 615990277Sobrien on the various sub-processes, along with the --help switch. */ 616050599Sobrien } 616190277Sobrien 616218334Speter if (verbose_flag) 616318334Speter { 616450599Sobrien int n; 616590277Sobrien const char *thrmod; 616650599Sobrien 616790277Sobrien notice ("Configured with: %s\n", configuration_arguments); 616890277Sobrien 616990277Sobrien#ifdef THREAD_MODEL_SPEC 617090277Sobrien /* We could have defined THREAD_MODEL_SPEC to "%*" by default, 617190277Sobrien but there's no point in doing all this processing just to get 617290277Sobrien thread_model back. */ 617390277Sobrien obstack_init (&obstack); 617490277Sobrien do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); 617590277Sobrien obstack_1grow (&obstack, '\0'); 617690277Sobrien thrmod = obstack_finish (&obstack); 617790277Sobrien#else 617890277Sobrien thrmod = thread_model; 617990277Sobrien#endif 618090277Sobrien 618190277Sobrien notice ("Thread model: %s\n", thrmod); 618290277Sobrien 618350599Sobrien /* compiler_version is truncated at the first space when initialized 618450599Sobrien from version string, so truncate version_string at the first space 618550599Sobrien before comparing. */ 618650599Sobrien for (n = 0; version_string[n]; n++) 618750599Sobrien if (version_string[n] == ' ') 618850599Sobrien break; 618950599Sobrien 619050599Sobrien if (! strncmp (version_string, compiler_version, n) 619150599Sobrien && compiler_version[n] == 0) 619252520Sobrien notice ("gcc version %s\n", version_string); 619318334Speter else 619452520Sobrien notice ("gcc driver version %s executing gcc version %s\n", 619552520Sobrien version_string, compiler_version); 619618334Speter 619718334Speter if (n_infiles == 0) 619890277Sobrien return (0); 619918334Speter } 620018334Speter 620150599Sobrien if (n_infiles == added_libraries) 620218346Speter fatal ("No input files specified"); 620318334Speter 620418334Speter /* Make a place to record the compiler output file names 620518334Speter that correspond to the input files. */ 620618334Speter 620750599Sobrien i = n_infiles; 620850599Sobrien i += lang_specific_extra_outfiles; 620990277Sobrien outfiles = (const char **) xcalloc (i, sizeof (char *)); 621018334Speter 621118334Speter /* Record which files were specified explicitly as link input. */ 621218334Speter 621390277Sobrien explicit_link_files = xcalloc (1, n_infiles); 621418334Speter 621590277Sobrien for (i = 0; (int) i < n_infiles; i++) 621618334Speter { 621718334Speter int this_file_error = 0; 621818334Speter 621918334Speter /* Tell do_spec what to substitute for %i. */ 622018334Speter 622118334Speter input_file_number = i; 622290277Sobrien set_input (infiles[i].name); 622318334Speter 622418334Speter /* Use the same thing in %o, unless cp->spec says otherwise. */ 622518334Speter 622618334Speter outfiles[i] = input_filename; 622718334Speter 622818334Speter /* Figure out which compiler from the file's suffix. */ 622918334Speter 623090277Sobrien input_file_compiler 623190277Sobrien = lookup_compiler (infiles[i].name, input_filename_length, 623290277Sobrien infiles[i].language); 623390277Sobrien 623490277Sobrien if (input_file_compiler) 623518334Speter { 623618334Speter /* Ok, we found an applicable compiler. Run its spec. */ 623718334Speter 623890277Sobrien if (input_file_compiler->spec[0] == '#') 623918334Speter { 624090277Sobrien error ("%s: %s compiler not installed on this system", 624190277Sobrien input_filename, &input_file_compiler->spec[1]); 624290277Sobrien this_file_error = 1; 624318334Speter } 624418334Speter else 624590277Sobrien { 624690277Sobrien value = do_spec (input_file_compiler->spec); 624790277Sobrien if (value < 0) 624890277Sobrien this_file_error = 1; 624990277Sobrien } 625018334Speter } 625118334Speter 625218334Speter /* If this file's name does not contain a recognized suffix, 625318334Speter record it as explicit linker input. */ 625418334Speter 625518334Speter else 625618334Speter explicit_link_files[i] = 1; 625718334Speter 625818334Speter /* Clear the delete-on-failure queue, deleting the files in it 625918334Speter if this compilation failed. */ 626018334Speter 626118334Speter if (this_file_error) 626218334Speter { 626318334Speter delete_failure_queue (); 626418334Speter error_count++; 626518334Speter } 626618334Speter /* If this compilation succeeded, don't delete those files later. */ 626718334Speter clear_failure_queue (); 626818334Speter } 626918334Speter 627090277Sobrien /* Reset the output file name to the first input file name, for use 627190277Sobrien with %b in LINK_SPEC on a target that prefers not to emit a.out 627290277Sobrien by default. */ 627390277Sobrien if (n_infiles > 0) 627490277Sobrien set_input (infiles[0].name); 627590277Sobrien 627652520Sobrien if (error_count == 0) 627752520Sobrien { 627852520Sobrien /* Make sure INPUT_FILE_NUMBER points to first available open 627952520Sobrien slot. */ 628052520Sobrien input_file_number = n_infiles; 628152520Sobrien if (lang_specific_pre_link ()) 628252520Sobrien error_count++; 628352520Sobrien } 628450599Sobrien 628518334Speter /* Run ld to link all the compiler output files. */ 628618334Speter 628718334Speter if (error_count == 0) 628818334Speter { 628918334Speter int tmp = execution_count; 629018334Speter 629190277Sobrien /* We'll use ld if we can't find collect2. */ 629250599Sobrien if (! strcmp (linker_name_spec, "collect2")) 629350599Sobrien { 629450599Sobrien char *s = find_a_file (&exec_prefixes, "collect2", X_OK); 629550599Sobrien if (s == NULL) 629650599Sobrien linker_name_spec = "ld"; 629750599Sobrien } 629818334Speter /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 629918334Speter for collect. */ 630090277Sobrien putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH"); 630190277Sobrien putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV); 630218334Speter 630318334Speter value = do_spec (link_command_spec); 630418334Speter if (value < 0) 630518334Speter error_count = 1; 630618334Speter linker_was_run = (tmp != execution_count); 630718334Speter } 630818334Speter 630918334Speter /* If options said don't run linker, 631018334Speter complain about input files to be given to the linker. */ 631118334Speter 631218334Speter if (! linker_was_run && error_count == 0) 631390277Sobrien for (i = 0; (int) i < n_infiles; i++) 631418334Speter if (explicit_link_files[i]) 631590277Sobrien error ("%s: linker input file unused because linking not done", 631618334Speter outfiles[i]); 631718334Speter 631818334Speter /* Delete some or all of the temporary files we made. */ 631918334Speter 632018334Speter if (error_count) 632118334Speter delete_failure_queue (); 632218334Speter delete_temp_files (); 632318334Speter 632450599Sobrien if (print_help_list) 632550599Sobrien { 632690277Sobrien printf (("\nFor bug reporting instructions, please see:\n")); 632757849Sobrien printf ("%s\n", GCCBUGURL); 632850599Sobrien } 632990277Sobrien 633090277Sobrien return (signal_count != 0 ? 2 633190277Sobrien : error_count > 0 ? (pass_exit_codes ? greatest_status : 1) 633290277Sobrien : 0); 633318334Speter} 633418334Speter 633518334Speter/* Find the proper compilation spec for the file name NAME, 633618334Speter whose length is LENGTH. LANGUAGE is the specified language, 633750599Sobrien or 0 if this file is to be passed to the linker. */ 633818334Speter 633918334Speterstatic struct compiler * 634018334Speterlookup_compiler (name, length, language) 634152520Sobrien const char *name; 634250599Sobrien size_t length; 634352520Sobrien const char *language; 634418334Speter{ 634518334Speter struct compiler *cp; 634618334Speter 634790277Sobrien /* If this was specified by the user to be a linker input, indicate that. */ 634850599Sobrien if (language != 0 && language[0] == '*') 634950599Sobrien return 0; 635050599Sobrien 635150599Sobrien /* Otherwise, look for the language, if one is spec'd. */ 635218334Speter if (language != 0) 635318334Speter { 635418334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 635550599Sobrien if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language)) 635650599Sobrien return cp; 635750599Sobrien 635818334Speter error ("language %s not recognized", language); 635950599Sobrien return 0; 636018334Speter } 636118334Speter 636218334Speter /* Look for a suffix. */ 636318334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 636418334Speter { 636518334Speter if (/* The suffix `-' matches only the file name `-'. */ 636618334Speter (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 636750599Sobrien || (strlen (cp->suffix) < length 636850599Sobrien /* See if the suffix matches the end of NAME. */ 636950599Sobrien && !strcmp (cp->suffix, 637050599Sobrien name + length - strlen (cp->suffix)) 637150599Sobrien )) 637290277Sobrien break; 637390277Sobrien } 637450599Sobrien 637590277Sobrien#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM) 637690277Sobrien /* look again, but case-insensitively this time. */ 637790277Sobrien if (cp < compilers) 637890277Sobrien for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 637990277Sobrien { 638090277Sobrien if (/* The suffix `-' matches only the file name `-'. */ 638190277Sobrien (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 638290277Sobrien || (strlen (cp->suffix) < length 638390277Sobrien /* See if the suffix matches the end of NAME. */ 638490277Sobrien && ((!strcmp (cp->suffix, 638590277Sobrien name + length - strlen (cp->suffix)) 638690277Sobrien || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) 638790277Sobrien && !strcasecmp (cp->suffix, 638890277Sobrien name + length - strlen (cp->suffix))) 638990277Sobrien )) 639090277Sobrien break; 639190277Sobrien } 639290277Sobrien#endif 639350599Sobrien 639490277Sobrien if (cp >= compilers) 639590277Sobrien { 639690277Sobrien if (cp->spec[0] != '@') 639790277Sobrien /* A non-alias entry: return it. */ 639890277Sobrien return cp; 639990277Sobrien 640090277Sobrien /* An alias entry maps a suffix to a language. 640190277Sobrien Search for the language; pass 0 for NAME and LENGTH 640290277Sobrien to avoid infinite recursion if language not found. */ 640390277Sobrien return lookup_compiler (NULL, 0, cp->spec + 1); 640418334Speter } 640518334Speter return 0; 640618334Speter} 640718334Speter 640818334Speterstatic char * 640918334Spetersave_string (s, len) 641090277Sobrien const char *s; 641190277Sobrien int len; 641218334Speter{ 641390277Sobrien char *result = xmalloc (len + 1); 641418334Speter 641590277Sobrien memcpy (result, s, len); 641618334Speter result[len] = 0; 641718334Speter return result; 641818334Speter} 641918334Speter 642090277Sobrienvoid 642118334Speterpfatal_with_name (name) 642252520Sobrien const char *name; 642318334Speter{ 642452520Sobrien perror_with_name (name); 642552520Sobrien delete_temp_files (); 642652520Sobrien exit (1); 642718334Speter} 642818334Speter 642918334Speterstatic void 643018334Speterperror_with_name (name) 643152520Sobrien const char *name; 643218334Speter{ 643352520Sobrien error ("%s: %s", name, xstrerror (errno)); 643418334Speter} 643518334Speter 643618334Speterstatic void 643750599Sobrienpfatal_pexecute (errmsg_fmt, errmsg_arg) 643852520Sobrien const char *errmsg_fmt; 643952520Sobrien const char *errmsg_arg; 644018334Speter{ 644150599Sobrien if (errmsg_arg) 644250599Sobrien { 644352520Sobrien int save_errno = errno; 644452520Sobrien 644550599Sobrien /* Space for trailing '\0' is in %s. */ 644650599Sobrien char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg)); 644750599Sobrien sprintf (msg, errmsg_fmt, errmsg_arg); 644850599Sobrien errmsg_fmt = msg; 644952520Sobrien 645052520Sobrien errno = save_errno; 645150599Sobrien } 645250599Sobrien 645352520Sobrien pfatal_with_name (errmsg_fmt); 645418334Speter} 645518334Speter 645690277Sobrien/* Output an error message and exit */ 645718334Speter 645818334Spetervoid 645918334Speterfancy_abort () 646018334Speter{ 646190277Sobrien fatal ("internal gcc abort"); 646218334Speter} 646318334Speter 646418334Speter/* Output an error message and exit */ 646518334Speter 646652520Sobrienvoid 646790277Sobrienfatal VPARAMS ((const char *msgid, ...)) 646818334Speter{ 646990277Sobrien VA_OPEN (ap, msgid); 647090277Sobrien VA_FIXEDARG (ap, const char *, msgid); 647118334Speter 647218334Speter fprintf (stderr, "%s: ", programname); 647352520Sobrien vfprintf (stderr, _(msgid), ap); 647490277Sobrien VA_CLOSE (ap); 647518334Speter fprintf (stderr, "\n"); 647618334Speter delete_temp_files (); 647718334Speter exit (1); 647818334Speter} 647918334Speter 648090277Sobrienvoid 648190277Sobrienerror VPARAMS ((const char *msgid, ...)) 648218334Speter{ 648390277Sobrien VA_OPEN (ap, msgid); 648490277Sobrien VA_FIXEDARG (ap, const char *, msgid); 648518334Speter 648618334Speter fprintf (stderr, "%s: ", programname); 648752520Sobrien vfprintf (stderr, _(msgid), ap); 648890277Sobrien VA_CLOSE (ap); 648918334Speter 649018334Speter fprintf (stderr, "\n"); 649118334Speter} 649252520Sobrien 649352520Sobrienstatic void 649490277Sobriennotice VPARAMS ((const char *msgid, ...)) 649552520Sobrien{ 649690277Sobrien VA_OPEN (ap, msgid); 649790277Sobrien VA_FIXEDARG (ap, const char *, msgid); 649852520Sobrien 649952520Sobrien vfprintf (stderr, _(msgid), ap); 650090277Sobrien VA_CLOSE (ap); 650152520Sobrien} 650218334Speter 650318334Speterstatic void 650418334Spetervalidate_all_switches () 650518334Speter{ 650618334Speter struct compiler *comp; 650790277Sobrien const char *p; 650890277Sobrien char c; 650918334Speter struct spec_list *spec; 651018334Speter 651190277Sobrien for (comp = compilers; comp->spec; comp++) 651218334Speter { 651390277Sobrien p = comp->spec; 651490277Sobrien while ((c = *p++)) 651590277Sobrien if (c == '%' && *p == '{') 651690277Sobrien /* We have a switch spec. */ 651790277Sobrien validate_switches (p + 1); 651818334Speter } 651918334Speter 652090277Sobrien /* Look through the linked list of specs read from the specs file. */ 652190277Sobrien for (spec = specs; spec; spec = spec->next) 652218334Speter { 652350599Sobrien p = *(spec->ptr_spec); 652450599Sobrien while ((c = *p++)) 652518334Speter if (c == '%' && *p == '{') 652618334Speter /* We have a switch spec. */ 652718334Speter validate_switches (p + 1); 652818334Speter } 652918334Speter 653018334Speter p = link_command_spec; 653150599Sobrien while ((c = *p++)) 653218334Speter if (c == '%' && *p == '{') 653318334Speter /* We have a switch spec. */ 653418334Speter validate_switches (p + 1); 653518334Speter} 653618334Speter 653718334Speter/* Look at the switch-name that comes after START 653818334Speter and mark as valid all supplied switches that match it. */ 653918334Speter 654018334Speterstatic void 654118334Spetervalidate_switches (start) 654252520Sobrien const char *start; 654318334Speter{ 654490277Sobrien const char *p = start; 654552520Sobrien const char *filter; 654690277Sobrien int i; 654790277Sobrien int suffix; 654818334Speter 654918334Speter if (*p == '|') 655018334Speter ++p; 655118334Speter 655290277Sobriennext_member: 655318334Speter if (*p == '!') 655418334Speter ++p; 655518334Speter 655690277Sobrien suffix = 0; 655718334Speter if (*p == '.') 655818334Speter suffix = 1, ++p; 655918334Speter 656018334Speter filter = p; 656190277Sobrien while (*p != ':' && *p != '}' && *p != '|' && *p != '&') 656290277Sobrien p++; 656318334Speter 656418334Speter if (suffix) 656518334Speter ; 656618334Speter else if (p[-1] == '*') 656718334Speter { 656818334Speter /* Mark all matching switches as valid. */ 656918334Speter for (i = 0; i < n_switches; i++) 657090277Sobrien if (!strncmp (switches[i].part1, filter, p - filter - 1)) 657152520Sobrien switches[i].validated = 1; 657218334Speter } 657318334Speter else 657418334Speter { 657518334Speter /* Mark an exact matching switch as valid. */ 657618334Speter for (i = 0; i < n_switches; i++) 657718334Speter { 657818334Speter if (!strncmp (switches[i].part1, filter, p - filter) 657918334Speter && switches[i].part1[p - filter] == 0) 658052520Sobrien switches[i].validated = 1; 658118334Speter } 658218334Speter } 658390277Sobrien 658490277Sobrien if (*p++ == '|' || p[-1] == '&') 658590277Sobrien goto next_member; 658618334Speter} 658718334Speter 658850599Sobrien/* Check whether a particular argument was used. The first time we 658950599Sobrien canonicalize the switches to keep only the ones we care about. */ 659018334Speter 659118334Speterstatic int 659218334Speterused_arg (p, len) 659352520Sobrien const char *p; 659418334Speter int len; 659518334Speter{ 659690277Sobrien struct mswitchstr 659790277Sobrien { 659890277Sobrien const char *str; 659990277Sobrien const char *replace; 660050599Sobrien int len; 660150599Sobrien int rep_len; 660250599Sobrien }; 660318334Speter 660450599Sobrien static struct mswitchstr *mswitches; 660550599Sobrien static int n_mswitches; 660650599Sobrien int i, j; 660750599Sobrien 660850599Sobrien if (!mswitches) 660950599Sobrien { 661050599Sobrien struct mswitchstr *matches; 661190277Sobrien const char *q; 661250599Sobrien int cnt = 0; 661350599Sobrien 661490277Sobrien /* Break multilib_matches into the component strings of string 661590277Sobrien and replacement string. */ 661650599Sobrien for (q = multilib_matches; *q != '\0'; q++) 661750599Sobrien if (*q == ';') 661850599Sobrien cnt++; 661950599Sobrien 662090277Sobrien matches = 662190277Sobrien (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt); 662250599Sobrien i = 0; 662350599Sobrien q = multilib_matches; 662450599Sobrien while (*q != '\0') 662550599Sobrien { 662650599Sobrien matches[i].str = q; 662750599Sobrien while (*q != ' ') 662850599Sobrien { 662950599Sobrien if (*q == '\0') 663050599Sobrien abort (); 663150599Sobrien q++; 663250599Sobrien } 663350599Sobrien matches[i].len = q - matches[i].str; 663450599Sobrien 663550599Sobrien matches[i].replace = ++q; 663650599Sobrien while (*q != ';' && *q != '\0') 663750599Sobrien { 663850599Sobrien if (*q == ' ') 663950599Sobrien abort (); 664050599Sobrien q++; 664150599Sobrien } 664250599Sobrien matches[i].rep_len = q - matches[i].replace; 664350599Sobrien i++; 664450599Sobrien if (*q == ';') 664590277Sobrien q++; 664650599Sobrien } 664750599Sobrien 664850599Sobrien /* Now build a list of the replacement string for switches that we care 664950599Sobrien about. Make sure we allocate at least one entry. This prevents 665050599Sobrien xmalloc from calling fatal, and prevents us from re-executing this 665150599Sobrien block of code. */ 665250599Sobrien mswitches 665350599Sobrien = (struct mswitchstr *) xmalloc ((sizeof (struct mswitchstr)) 665450599Sobrien * (n_switches ? n_switches : 1)); 665550599Sobrien for (i = 0; i < n_switches; i++) 665650599Sobrien { 665750599Sobrien int xlen = strlen (switches[i].part1); 665850599Sobrien for (j = 0; j < cnt; j++) 665990277Sobrien if (xlen == matches[j].len 666090277Sobrien && ! strncmp (switches[i].part1, matches[j].str, xlen)) 666150599Sobrien { 666250599Sobrien mswitches[n_mswitches].str = matches[j].replace; 666350599Sobrien mswitches[n_mswitches].len = matches[j].rep_len; 666490277Sobrien mswitches[n_mswitches].replace = (char *) 0; 666550599Sobrien mswitches[n_mswitches].rep_len = 0; 666650599Sobrien n_mswitches++; 666750599Sobrien break; 666850599Sobrien } 666950599Sobrien } 667050599Sobrien } 667150599Sobrien 667250599Sobrien for (i = 0; i < n_mswitches; i++) 667350599Sobrien if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len)) 667418334Speter return 1; 667550599Sobrien 667618334Speter return 0; 667718334Speter} 667818334Speter 667918334Speterstatic int 668018334Speterdefault_arg (p, len) 668152520Sobrien const char *p; 668218334Speter int len; 668318334Speter{ 668490277Sobrien const char *start, *end; 668518334Speter 668690277Sobrien for (start = multilib_defaults; *start != '\0'; start = end + 1) 668750599Sobrien { 668850599Sobrien while (*start == ' ' || *start == '\t') 668950599Sobrien start++; 669018334Speter 669150599Sobrien if (*start == '\0') 669250599Sobrien break; 669350599Sobrien 669490277Sobrien for (end = start + 1; *end != ' ' && *end != '\t' && *end != '\0'; end++) 669550599Sobrien ; 669650599Sobrien 669750599Sobrien if ((end - start) == len && strncmp (p, start, len) == 0) 669850599Sobrien return 1; 669950599Sobrien 670050599Sobrien if (*end == '\0') 670150599Sobrien break; 670250599Sobrien } 670350599Sobrien 670418334Speter return 0; 670518334Speter} 670618334Speter 670790277Sobrien/* Work out the subdirectory to use based on the options. The format of 670890277Sobrien multilib_select is a list of elements. Each element is a subdirectory 670990277Sobrien name followed by a list of options followed by a semicolon. The format 671090277Sobrien of multilib_exclusions is the same, but without the preceding 671190277Sobrien directory. First gcc will check the exclusions, if none of the options 671290277Sobrien beginning with an exclamation point are present, and all of the other 671390277Sobrien options are present, then we will ignore this completely. Passing 671490277Sobrien that, gcc will consider each multilib_select in turn using the same 671590277Sobrien rules for matching the options. If a match is found, that subdirectory 671690277Sobrien will be used. */ 671718334Speter 671818334Speterstatic void 671918334Speterset_multilib_dir () 672018334Speter{ 672190277Sobrien const char *p; 672290277Sobrien unsigned int this_path_len; 672390277Sobrien const char *this_path, *this_arg; 672418334Speter int not_arg; 672518334Speter int ok; 672618334Speter 672790277Sobrien p = multilib_exclusions; 672818334Speter while (*p != '\0') 672918334Speter { 673018334Speter /* Ignore newlines. */ 673118334Speter if (*p == '\n') 673218334Speter { 673318334Speter ++p; 673418334Speter continue; 673518334Speter } 673618334Speter 673790277Sobrien /* Check the arguments. */ 673890277Sobrien ok = 1; 673990277Sobrien while (*p != ';') 674090277Sobrien { 674190277Sobrien if (*p == '\0') 674290277Sobrien abort (); 674390277Sobrien 674490277Sobrien if (! ok) 674590277Sobrien { 674690277Sobrien ++p; 674790277Sobrien continue; 674890277Sobrien } 674990277Sobrien 675090277Sobrien this_arg = p; 675190277Sobrien while (*p != ' ' && *p != ';') 675290277Sobrien { 675390277Sobrien if (*p == '\0') 675490277Sobrien abort (); 675590277Sobrien ++p; 675690277Sobrien } 675790277Sobrien 675890277Sobrien if (*this_arg != '!') 675990277Sobrien not_arg = 0; 676090277Sobrien else 676190277Sobrien { 676290277Sobrien not_arg = 1; 676390277Sobrien ++this_arg; 676490277Sobrien } 676590277Sobrien 676690277Sobrien ok = used_arg (this_arg, p - this_arg); 676790277Sobrien if (not_arg) 676890277Sobrien ok = ! ok; 676990277Sobrien 677090277Sobrien if (*p == ' ') 677190277Sobrien ++p; 677290277Sobrien } 677390277Sobrien 677490277Sobrien if (ok) 677590277Sobrien return; 677690277Sobrien 677790277Sobrien ++p; 677890277Sobrien } 677990277Sobrien 678090277Sobrien p = multilib_select; 678190277Sobrien while (*p != '\0') 678290277Sobrien { 678390277Sobrien /* Ignore newlines. */ 678490277Sobrien if (*p == '\n') 678590277Sobrien { 678690277Sobrien ++p; 678790277Sobrien continue; 678890277Sobrien } 678990277Sobrien 679018334Speter /* Get the initial path. */ 679118334Speter this_path = p; 679218334Speter while (*p != ' ') 679318334Speter { 679418334Speter if (*p == '\0') 679518334Speter abort (); 679618334Speter ++p; 679718334Speter } 679818334Speter this_path_len = p - this_path; 679918334Speter 680018334Speter /* Check the arguments. */ 680118334Speter ok = 1; 680218334Speter ++p; 680318334Speter while (*p != ';') 680418334Speter { 680518334Speter if (*p == '\0') 680618334Speter abort (); 680718334Speter 680818334Speter if (! ok) 680918334Speter { 681018334Speter ++p; 681118334Speter continue; 681218334Speter } 681318334Speter 681418334Speter this_arg = p; 681518334Speter while (*p != ' ' && *p != ';') 681618334Speter { 681718334Speter if (*p == '\0') 681818334Speter abort (); 681918334Speter ++p; 682018334Speter } 682118334Speter 682218334Speter if (*this_arg != '!') 682318334Speter not_arg = 0; 682418334Speter else 682518334Speter { 682618334Speter not_arg = 1; 682718334Speter ++this_arg; 682818334Speter } 682918334Speter 683018334Speter /* If this is a default argument, we can just ignore it. 683118334Speter This is true even if this_arg begins with '!'. Beginning 683218334Speter with '!' does not mean that this argument is necessarily 683318334Speter inappropriate for this library: it merely means that 683418334Speter there is a more specific library which uses this 683518334Speter argument. If this argument is a default, we need not 683618334Speter consider that more specific library. */ 683718334Speter if (! default_arg (this_arg, p - this_arg)) 683818334Speter { 683918334Speter ok = used_arg (this_arg, p - this_arg); 684018334Speter if (not_arg) 684118334Speter ok = ! ok; 684218334Speter } 684318334Speter 684418334Speter if (*p == ' ') 684518334Speter ++p; 684618334Speter } 684718334Speter 684818334Speter if (ok) 684918334Speter { 685018334Speter if (this_path_len != 1 685118334Speter || this_path[0] != '.') 685218334Speter { 685390277Sobrien char *new_multilib_dir = xmalloc (this_path_len + 1); 685452520Sobrien strncpy (new_multilib_dir, this_path, this_path_len); 685552520Sobrien new_multilib_dir[this_path_len] = '\0'; 685652520Sobrien multilib_dir = new_multilib_dir; 685718334Speter } 685818334Speter break; 685918334Speter } 686018334Speter 686118334Speter ++p; 686290277Sobrien } 686318334Speter} 686418334Speter 686518334Speter/* Print out the multiple library subdirectory selection 686618334Speter information. This prints out a series of lines. Each line looks 686718334Speter like SUBDIRECTORY;@OPTION@OPTION, with as many options as is 686818334Speter required. Only the desired options are printed out, the negative 686918334Speter matches. The options are print without a leading dash. There are 687018334Speter no spaces to make it easy to use the information in the shell. 687118334Speter Each subdirectory is printed only once. This assumes the ordering 687290277Sobrien generated by the genmultilib script. Also, we leave out ones that match 687390277Sobrien the exclusions. */ 687418334Speter 687518334Speterstatic void 687618334Speterprint_multilib_info () 687718334Speter{ 687890277Sobrien const char *p = multilib_select; 687990277Sobrien const char *last_path = 0, *this_path; 688018334Speter int skip; 688190277Sobrien unsigned int last_path_len = 0; 688218334Speter 688318334Speter while (*p != '\0') 688418334Speter { 688590277Sobrien skip = 0; 688618334Speter /* Ignore newlines. */ 688718334Speter if (*p == '\n') 688818334Speter { 688918334Speter ++p; 689018334Speter continue; 689118334Speter } 689218334Speter 689318334Speter /* Get the initial path. */ 689418334Speter this_path = p; 689518334Speter while (*p != ' ') 689618334Speter { 689718334Speter if (*p == '\0') 689818334Speter abort (); 689918334Speter ++p; 690018334Speter } 690118334Speter 690290277Sobrien /* Check for matches with the multilib_exclusions. We don't bother 690390277Sobrien with the '!' in either list. If any of the exclusion rules match 690490277Sobrien all of its options with the select rule, we skip it. */ 690590277Sobrien { 690690277Sobrien const char *e = multilib_exclusions; 690790277Sobrien const char *this_arg; 690818334Speter 690990277Sobrien while (*e != '\0') 691090277Sobrien { 691190277Sobrien int m = 1; 691290277Sobrien /* Ignore newlines. */ 691390277Sobrien if (*e == '\n') 691490277Sobrien { 691590277Sobrien ++e; 691690277Sobrien continue; 691790277Sobrien } 691818334Speter 691990277Sobrien /* Check the arguments. */ 692090277Sobrien while (*e != ';') 692190277Sobrien { 692290277Sobrien const char *q; 692390277Sobrien int mp = 0; 692490277Sobrien 692590277Sobrien if (*e == '\0') 692690277Sobrien abort (); 692790277Sobrien 692890277Sobrien if (! m) 692990277Sobrien { 693090277Sobrien ++e; 693190277Sobrien continue; 693290277Sobrien } 693390277Sobrien 693490277Sobrien this_arg = e; 693590277Sobrien 693690277Sobrien while (*e != ' ' && *e != ';') 693790277Sobrien { 693890277Sobrien if (*e == '\0') 693990277Sobrien abort (); 694090277Sobrien ++e; 694190277Sobrien } 694290277Sobrien 694390277Sobrien q = p + 1; 694490277Sobrien while (*q != ';') 694590277Sobrien { 694690277Sobrien const char *arg; 694790277Sobrien int len = e - this_arg; 694890277Sobrien 694990277Sobrien if (*q == '\0') 695090277Sobrien abort (); 695190277Sobrien 695290277Sobrien arg = q; 695390277Sobrien 695490277Sobrien while (*q != ' ' && *q != ';') 695590277Sobrien { 695690277Sobrien if (*q == '\0') 695790277Sobrien abort (); 695890277Sobrien ++q; 695990277Sobrien } 696090277Sobrien 696190277Sobrien if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) || 696290277Sobrien default_arg (this_arg, e - this_arg)) 696390277Sobrien { 696490277Sobrien mp = 1; 696590277Sobrien break; 696690277Sobrien } 696790277Sobrien 696890277Sobrien if (*q == ' ') 696990277Sobrien ++q; 697090277Sobrien } 697190277Sobrien 697290277Sobrien if (! mp) 697390277Sobrien m = 0; 697490277Sobrien 697590277Sobrien if (*e == ' ') 697690277Sobrien ++e; 697790277Sobrien } 697890277Sobrien 697990277Sobrien if (m) 698090277Sobrien { 698190277Sobrien skip = 1; 698290277Sobrien break; 698390277Sobrien } 698490277Sobrien 698590277Sobrien if (*e != '\0') 698690277Sobrien ++e; 698790277Sobrien } 698890277Sobrien } 698990277Sobrien 699090277Sobrien if (! skip) 699190277Sobrien { 699290277Sobrien /* If this is a duplicate, skip it. */ 699390277Sobrien skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len 699490277Sobrien && ! strncmp (last_path, this_path, last_path_len)); 699590277Sobrien 699690277Sobrien last_path = this_path; 699790277Sobrien last_path_len = p - this_path; 699890277Sobrien } 699990277Sobrien 700018334Speter /* If this directory requires any default arguments, we can skip 700118334Speter it. We will already have printed a directory identical to 700218334Speter this one which does not require that default argument. */ 700318334Speter if (! skip) 700418334Speter { 700590277Sobrien const char *q; 700618334Speter 700718334Speter q = p + 1; 700818334Speter while (*q != ';') 700918334Speter { 701090277Sobrien const char *arg; 701118334Speter 701218334Speter if (*q == '\0') 701318334Speter abort (); 701418334Speter 701518334Speter if (*q == '!') 701618334Speter arg = NULL; 701718334Speter else 701818334Speter arg = q; 701918334Speter 702018334Speter while (*q != ' ' && *q != ';') 702118334Speter { 702218334Speter if (*q == '\0') 702318334Speter abort (); 702418334Speter ++q; 702518334Speter } 702618334Speter 702718334Speter if (arg != NULL 702818334Speter && default_arg (arg, q - arg)) 702918334Speter { 703018334Speter skip = 1; 703118334Speter break; 703218334Speter } 703318334Speter 703418334Speter if (*q == ' ') 703518334Speter ++q; 703618334Speter } 703718334Speter } 703818334Speter 703918334Speter if (! skip) 704018334Speter { 704190277Sobrien const char *p1; 704218334Speter 704318334Speter for (p1 = last_path; p1 < p; p1++) 704418334Speter putchar (*p1); 704518334Speter putchar (';'); 704618334Speter } 704718334Speter 704818334Speter ++p; 704918334Speter while (*p != ';') 705018334Speter { 705118334Speter int use_arg; 705218334Speter 705318334Speter if (*p == '\0') 705418334Speter abort (); 705518334Speter 705618334Speter if (skip) 705718334Speter { 705818334Speter ++p; 705918334Speter continue; 706018334Speter } 706118334Speter 706218334Speter use_arg = *p != '!'; 706318334Speter 706418334Speter if (use_arg) 706518334Speter putchar ('@'); 706618334Speter 706718334Speter while (*p != ' ' && *p != ';') 706818334Speter { 706918334Speter if (*p == '\0') 707018334Speter abort (); 707118334Speter if (use_arg) 707218334Speter putchar (*p); 707318334Speter ++p; 707418334Speter } 707518334Speter 707618334Speter if (*p == ' ') 707718334Speter ++p; 707818334Speter } 707918334Speter 708018334Speter if (! skip) 708150599Sobrien { 708290277Sobrien /* If there are extra options, print them now. */ 708350599Sobrien if (multilib_extra && *multilib_extra) 708450599Sobrien { 708550599Sobrien int print_at = TRUE; 708690277Sobrien const char *q; 708718334Speter 708850599Sobrien for (q = multilib_extra; *q != '\0'; q++) 708950599Sobrien { 709050599Sobrien if (*q == ' ') 709150599Sobrien print_at = TRUE; 709250599Sobrien else 709350599Sobrien { 709450599Sobrien if (print_at) 709550599Sobrien putchar ('@'); 709650599Sobrien putchar (*q); 709750599Sobrien print_at = FALSE; 709850599Sobrien } 709950599Sobrien } 710050599Sobrien } 710190277Sobrien 710250599Sobrien putchar ('\n'); 710350599Sobrien } 710450599Sobrien 710518334Speter ++p; 710618334Speter } 710718334Speter} 7108