gcc.c revision 57849
118334Speter/* Compiler driver program that can handle many languages. 252520Sobrien Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc. 318334Speter 418334SpeterThis file is part of GNU CC. 518334Speter 618334SpeterGNU CC is free software; you can redistribute it and/or modify 718334Speterit under the terms of the GNU General Public License as published by 818334Speterthe Free Software Foundation; either version 2, or (at your option) 918334Speterany later version. 1018334Speter 1118334SpeterGNU CC is distributed in the hope that it will be useful, 1218334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1318334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1418334SpeterGNU General Public License for more details. 1518334Speter 1618334SpeterYou should have received a copy of the GNU General Public License 1718334Speteralong with GNU CC; see the file COPYING. If not, write to 1818334Speterthe Free Software Foundation, 59 Temple Place - Suite 330, 1918334SpeterBoston, MA 02111-1307, USA. 2018334Speter 2118334SpeterThis paragraph is here to try to keep Sun CC from dying. 2218334SpeterThe number of chars here seems crucial!!!! */ 2318334Speter 2451232Sbde/* $FreeBSD: head/contrib/gcc/gcc.c 57849 2000-03-09 10:11:08Z obrien $ */ 2551232Sbde 2618334Speter/* This program is the user interface to the C compiler and possibly to 2718334Speterother compilers. It is used because compilation is a complicated procedure 2818334Speterwhich involves running several programs and passing temporary files between 2918334Speterthem, forwarding the users switches to those programs selectively, 3018334Speterand deleting the temporary files at the end. 3118334Speter 3218334SpeterCC recognizes how to compile each input file by suffixes in the file names. 3318334SpeterOnce it knows which kind of compilation to perform, the procedure for 3418334Spetercompilation is specified by a string called a "spec". */ 3518334Speter 3650599Sobrien#include "config.h" 3750599Sobrien#include "system.h" 3850599Sobrien#include <signal.h> 3918334Speter 4050599Sobrien#include "obstack.h" 4152520Sobrien#include "intl.h" 4252520Sobrien#include "prefix.h" 4318334Speter 4450599Sobrien#ifdef VMS 4550599Sobrien#define exit __posix_exit 4618334Speter#endif 4718334Speter 4818334Speter/* By default there is no special suffix for executables. */ 4950599Sobrien#ifdef EXECUTABLE_SUFFIX 5050599Sobrien#define HAVE_EXECUTABLE_SUFFIX 5150599Sobrien#else 5218334Speter#define EXECUTABLE_SUFFIX "" 5318334Speter#endif 5418334Speter 5550599Sobrien/* By default, the suffix for object files is ".o". */ 5618334Speter#ifdef OBJECT_SUFFIX 5718334Speter#define HAVE_OBJECT_SUFFIX 5818334Speter#else 5918334Speter#define OBJECT_SUFFIX ".o" 6018334Speter#endif 6118334Speter 6218334Speter/* By default, colon separates directories in a path. */ 6318334Speter#ifndef PATH_SEPARATOR 6418334Speter#define PATH_SEPARATOR ':' 6518334Speter#endif 6618334Speter 6718334Speter#ifndef DIR_SEPARATOR 6818334Speter#define DIR_SEPARATOR '/' 6918334Speter#endif 7018334Speter 7152520Sobrien/* Define IS_DIR_SEPARATOR. */ 7252520Sobrien#ifndef DIR_SEPARATOR_2 7352520Sobrien# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) 7452520Sobrien#else /* DIR_SEPARATOR_2 */ 7552520Sobrien# define IS_DIR_SEPARATOR(ch) \ 7652520Sobrien (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) 7752520Sobrien#endif /* DIR_SEPARATOR_2 */ 7852520Sobrien 7918334Speterstatic char dir_separator_str[] = {DIR_SEPARATOR, 0}; 8018334Speter 8118334Speter#define obstack_chunk_alloc xmalloc 8218334Speter#define obstack_chunk_free free 8318334Speter 8452520Sobrien#ifndef GET_ENV_PATH_LIST 8552520Sobrien#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0) 8618334Speter#endif 8718334Speter 8850599Sobrien#ifndef HAVE_KILL 8950599Sobrien#define kill(p,s) raise(s) 9018334Speter#endif 9118334Speter 9218334Speter/* If a stage of compilation returns an exit status >= 1, 9318334Speter compilation of that file ceases. */ 9418334Speter 9518334Speter#define MIN_FATAL_STATUS 1 9618334Speter 9718334Speter/* Flag saying to print the directories gcc will search through looking for 9818334Speter programs, libraries, etc. */ 9918334Speter 10018334Speterstatic int print_search_dirs; 10118334Speter 10218334Speter/* Flag saying to print the full filename of this file 10318334Speter as found through our usual search mechanism. */ 10418334Speter 10552520Sobrienstatic const char *print_file_name = NULL; 10618334Speter 10750599Sobrien/* As print_file_name, but search for executable file. */ 10818334Speter 10952520Sobrienstatic const char *print_prog_name = NULL; 11018334Speter 11118334Speter/* Flag saying to print the relative path we'd use to 11218334Speter find libgcc.a given the current compiler flags. */ 11318334Speter 11418334Speterstatic int print_multi_directory; 11518334Speter 11618334Speter/* Flag saying to print the list of subdirectories and 11718334Speter compiler flags used to select them in a standard form. */ 11818334Speter 11918334Speterstatic int print_multi_lib; 12018334Speter 12150599Sobrien/* Flag saying to print the command line options understood by gcc and its 12250599Sobrien sub-processes. */ 12350599Sobrien 12450599Sobrienstatic int print_help_list; 12550599Sobrien 12618334Speter/* Flag indicating whether we should print the command and arguments */ 12718334Speter 12818334Speterstatic int verbose_flag; 12918334Speter 13018334Speter/* Nonzero means write "temp" files in source directory 13118334Speter and use the source file's name in them, and don't delete them. */ 13218334Speter 13318334Speterstatic int save_temps_flag; 13418334Speter 13518334Speter/* The compiler version. */ 13618334Speter 13718334Speterstatic char *compiler_version; 13818334Speter 13918334Speter/* The target version specified with -V */ 14018334Speter 14118334Speterstatic char *spec_version = DEFAULT_TARGET_VERSION; 14218334Speter 14318334Speter/* The target machine specified with -b. */ 14418334Speter 14552520Sobrienstatic const char *spec_machine = DEFAULT_TARGET_MACHINE; 14618334Speter 14718334Speter/* Nonzero if cross-compiling. 14818334Speter When -b is used, the value comes from the `specs' file. */ 14918334Speter 15018334Speter#ifdef CROSS_COMPILE 15150599Sobrienstatic char *cross_compile = "1"; 15218334Speter#else 15350599Sobrienstatic char *cross_compile = "0"; 15418334Speter#endif 15518334Speter 15618334Speter/* The number of errors that have occurred; the link phase will not be 15718334Speter run if this is non-zero. */ 15818334Speterstatic int error_count = 0; 15918334Speter 16018334Speter/* This is the obstack which we use to allocate many strings. */ 16118334Speter 16218334Speterstatic struct obstack obstack; 16318334Speter 16418334Speter/* This is the obstack to build an environment variable to pass to 16518334Speter collect2 that describes all of the relevant switches of what to 16618334Speter pass the compiler in building the list of pointers to constructors 16718334Speter and destructors. */ 16818334Speter 16918334Speterstatic struct obstack collect_obstack; 17018334Speter 17118334Speterextern char *version_string; 17218334Speter 17318334Speter/* Forward declaration for prototypes. */ 17418334Speterstruct path_prefix; 17518334Speter 17650599Sobrienstatic void init_spec PROTO((void)); 17752520Sobrienstatic void read_specs PROTO((const char *, int)); 17852520Sobrienstatic void set_spec PROTO((const char *, const char *)); 17952520Sobrienstatic struct compiler *lookup_compiler PROTO((const char *, size_t, const char *)); 18052520Sobrienstatic char *build_search_list PROTO((struct path_prefix *, const char *, int)); 18152520Sobrienstatic void putenv_from_prefixes PROTO((struct path_prefix *, const char *)); 18252520Sobrienstatic char *find_a_file PROTO((struct path_prefix *, const char *, int)); 18352520Sobrienstatic void add_prefix PROTO((struct path_prefix *, const char *, 18452520Sobrien const char *, int, int, int *)); 18518334Speterstatic char *skip_whitespace PROTO((char *)); 18652520Sobrienstatic void record_temp_file PROTO((const char *, int, int)); 18752520Sobrienstatic void delete_if_ordinary PROTO((const char *)); 18818334Speterstatic void delete_temp_files PROTO((void)); 18918334Speterstatic void delete_failure_queue PROTO((void)); 19018334Speterstatic void clear_failure_queue PROTO((void)); 19118334Speterstatic int check_live_switch PROTO((int, int)); 19252520Sobrienstatic const char *handle_braces PROTO((const char *)); 19352520Sobrienstatic char *save_string PROTO((const char *, int)); 19452520Sobrienextern int do_spec PROTO((const char *)); 19552520Sobrienstatic int do_spec_1 PROTO((const char *, int, const char *)); 19652520Sobrienstatic const char *find_file PROTO((const char *)); 19752520Sobrienstatic int is_directory PROTO((const char *, const char *, int)); 19852520Sobrienstatic void validate_switches PROTO((const char *)); 19918334Speterstatic void validate_all_switches PROTO((void)); 20050599Sobrienstatic void give_switch PROTO((int, int, int)); 20152520Sobrienstatic int used_arg PROTO((const char *, int)); 20252520Sobrienstatic int default_arg PROTO((const char *, int)); 20318334Speterstatic void set_multilib_dir PROTO((void)); 20418334Speterstatic void print_multilib_info PROTO((void)); 20552520Sobrienstatic void pfatal_with_name PROTO((const char *)) ATTRIBUTE_NORETURN; 20652520Sobrienstatic void perror_with_name PROTO((const char *)); 20752520Sobrienstatic void pfatal_pexecute PROTO((const char *, const char *)) 20852520Sobrien ATTRIBUTE_NORETURN; 20952520Sobrienstatic void error PVPROTO((const char *, ...)) 21052520Sobrien ATTRIBUTE_PRINTF_1; 21152520Sobrienstatic void notice PVPROTO((const char *, ...)) 21252520Sobrien ATTRIBUTE_PRINTF_1; 21350599Sobrienstatic void display_help PROTO((void)); 21452520Sobrienstatic void add_preprocessor_option PROTO ((const char *, int)); 21552520Sobrienstatic void add_assembler_option PROTO ((const char *, int)); 21652520Sobrienstatic void add_linker_option PROTO ((const char *, int)); 21752520Sobrienstatic void process_command PROTO ((int, char **)); 21852520Sobrienstatic int execute PROTO ((void)); 21952520Sobrienstatic void unused_prefix_warnings PROTO ((struct path_prefix *)); 22052520Sobrienstatic void clear_args PROTO ((void)); 22152520Sobrienstatic void fatal_error PROTO ((int)); 22218334Speter 22352520Sobrienvoid fancy_abort PROTO((void)) ATTRIBUTE_NORETURN; 22450599Sobrien 22550599Sobrien/* Called before processing to change/add/remove arguments. */ 22652520Sobrienextern void lang_specific_driver PROTO ((void (*) PVPROTO((const char *, ...)), 22752520Sobrien int *, char ***, int *)); 22850599Sobrien 22950599Sobrien/* Called before linking. Returns 0 on success and -1 on failure. */ 23050599Sobrienextern int lang_specific_pre_link (); 23150599Sobrien 23250599Sobrien/* Number of extra output files that lang_specific_pre_link may generate. */ 23350599Sobrienextern int lang_specific_extra_outfiles; 23418334Speter 23518334Speter/* Specs are strings containing lines, each of which (if not blank) 23618334Speteris made up of a program name, and arguments separated by spaces. 23718334SpeterThe program name must be exact and start from root, since no path 23818334Speteris searched and it is unreliable to depend on the current working directory. 23918334SpeterRedirection of input or output is not supported; the subprograms must 24018334Speteraccept filenames saying what files to read and write. 24118334Speter 24218334SpeterIn addition, the specs can contain %-sequences to substitute variable text 24318334Speteror for conditional text. Here is a table of all defined %-sequences. 24418334SpeterNote that spaces are not generated automatically around the results of 24518334Speterexpanding these sequences; therefore, you can concatenate them together 24618334Speteror with constant text in a single argument. 24718334Speter 24818334Speter %% substitute one % into the program name or argument. 24918334Speter %i substitute the name of the input file being processed. 25018334Speter %b substitute the basename of the input file being processed. 25118334Speter This is the substring up to (and not including) the last period 25218334Speter and not including the directory. 25350599Sobrien %gSUFFIX 25450599Sobrien substitute a file name that has suffix SUFFIX and is chosen 25550599Sobrien once per compilation, and mark the argument a la %d. To reduce 25650599Sobrien exposure to denial-of-service attacks, the file name is now 25750599Sobrien chosen in a way that is hard to predict even when previously 25850599Sobrien chosen file names are known. For example, `%g.s ... %g.o ... %g.s' 25950599Sobrien might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'. SUFFIX matches 26050599Sobrien the regexp "[.A-Za-z]*" or the special string "%O", which is 26150599Sobrien treated exactly as if %O had been pre-processed. Previously, %g 26250599Sobrien was simply substituted with a file name chosen once per compilation, 26350599Sobrien without regard to any appended suffix (which was therefore treated 26450599Sobrien just like ordinary text), making such attacks more likely to succeed. 26550599Sobrien %uSUFFIX 26650599Sobrien like %g, but generates a new temporary file name even if %uSUFFIX 26750599Sobrien was already seen. 26850599Sobrien %USUFFIX 26950599Sobrien substitutes the last file name generated with %uSUFFIX, generating a 27050599Sobrien new one if there is no such last file name. In the absence of any 27150599Sobrien %uSUFFIX, this is just like %gSUFFIX, except they don't share 27250599Sobrien the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s' 27350599Sobrien would involve the generation of two distinct file names, one 27450599Sobrien for each `%g.s' and another for each `%U.s'. Previously, %U was 27550599Sobrien simply substituted with a file name chosen for the previous %u, 27650599Sobrien without regard to any appended suffix. 27718334Speter %d marks the argument containing or following the %d as a 27818334Speter temporary file name, so that that file will be deleted if CC exits 27918334Speter successfully. Unlike %g, this contributes no text to the argument. 28018334Speter %w marks the argument containing or following the %w as the 28118334Speter "output file" of this compilation. This puts the argument 28218334Speter into the sequence of arguments that %o will substitute later. 28318334Speter %W{...} 28418334Speter like %{...} but mark last argument supplied within 28518334Speter as a file to be deleted on failure. 28618334Speter %o substitutes the names of all the output files, with spaces 28718334Speter automatically placed around them. You should write spaces 28818334Speter around the %o as well or the results are undefined. 28918334Speter %o is for use in the specs for running the linker. 29018334Speter Input files whose names have no recognized suffix are not compiled 29118334Speter at all, but they are included among the output files, so they will 29218334Speter be linked. 29350599Sobrien %O substitutes the suffix for object files. Note that this is 29450599Sobrien handled specially when it immediately follows %g, %u, or %U, 29550599Sobrien because of the need for those to form complete file names. The 29650599Sobrien handling is such that %O is treated exactly as if it had already 29750599Sobrien been substituted, except that %g, %u, and %U do not currently 29850599Sobrien support additional SUFFIX characters following %O as they would 29950599Sobrien following, for example, `.o'. 30018334Speter %p substitutes the standard macro predefinitions for the 30118334Speter current target machine. Use this when running cpp. 30218334Speter %P like %p, but puts `__' before and after the name of each macro. 30318334Speter (Except macros that already have __.) 30418334Speter This is for ANSI C. 30518334Speter %I Substitute a -iprefix option made from GCC_EXEC_PREFIX. 30618334Speter %s current argument is the name of a library or startup file of some sort. 30718334Speter Search for that file in a standard list of directories 30818334Speter and substitute the full name found. 30918334Speter %eSTR Print STR as an error message. STR is terminated by a newline. 31018334Speter Use this when inconsistent options are detected. 31118334Speter %x{OPTION} Accumulate an option for %X. 31218334Speter %X Output the accumulated linker options specified by compilations. 31318334Speter %Y Output the accumulated assembler options specified by compilations. 31418334Speter %Z Output the accumulated preprocessor options specified by compilations. 31518334Speter %v1 Substitute the major version number of GCC. 31618334Speter (For version 2.5.n, this is 2.) 31718334Speter %v2 Substitute the minor version number of GCC. 31818334Speter (For version 2.5.n, this is 5.) 31918334Speter %a process ASM_SPEC as a spec. 32018334Speter This allows config.h to specify part of the spec for running as. 32118334Speter %A process ASM_FINAL_SPEC as a spec. A capital A is actually 32218334Speter used here. This can be used to run a post-processor after the 32350599Sobrien assembler has done its job. 32418334Speter %D Dump out a -L option for each directory in startfile_prefixes. 32518334Speter If multilib_dir is set, extra entries are generated with it affixed. 32618334Speter %l process LINK_SPEC as a spec. 32718334Speter %L process LIB_SPEC as a spec. 32818334Speter %G process LIBGCC_SPEC as a spec. 32918334Speter %S process STARTFILE_SPEC as a spec. A capital S is actually used here. 33018334Speter %E process ENDFILE_SPEC as a spec. A capital E is actually used here. 33118334Speter %c process SIGNED_CHAR_SPEC as a spec. 33218334Speter %C process CPP_SPEC as a spec. A capital C is actually used here. 33318334Speter %1 process CC1_SPEC as a spec. 33418334Speter %2 process CC1PLUS_SPEC as a spec. 33518334Speter %| output "-" if the input for the current command is coming from a pipe. 33618334Speter %* substitute the variable part of a matched option. (See below.) 33718334Speter Note that each comma in the substituted string is replaced by 33818334Speter a single space. 33918334Speter %{S} substitutes the -S switch, if that switch was given to CC. 34018334Speter If that switch was not specified, this substitutes nothing. 34118334Speter Here S is a metasyntactic variable. 34218334Speter %{S*} substitutes all the switches specified to CC whose names start 34318334Speter with -S. This is used for -o, -D, -I, etc; switches that take 34418334Speter arguments. CC considers `-o foo' as being one switch whose 34518334Speter name starts with `o'. %{o*} would substitute this text, 34618334Speter including the space; thus, two arguments would be generated. 34750599Sobrien %{^S*} likewise, but don't put a blank between a switch and any args. 34818334Speter %{S*:X} substitutes X if one or more switches whose names start with -S are 34918334Speter specified to CC. Note that the tail part of the -S option 35018334Speter (i.e. the part matched by the `*') will be substituted for each 35118334Speter occurrence of %* within X. 35218334Speter %{S:X} substitutes X, but only if the -S switch was given to CC. 35318334Speter %{!S:X} substitutes X, but only if the -S switch was NOT given to CC. 35418334Speter %{|S:X} like %{S:X}, but if no S switch, substitute `-'. 35518334Speter %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'. 35618334Speter %{.S:X} substitutes X, but only if processing a file with suffix S. 35718334Speter %{!.S:X} substitutes X, but only if NOT processing a file with suffix S. 35850599Sobrien %{S|P:X} substitutes X if either -S or -P was given to CC. This may be 35950599Sobrien combined with ! and . as above binding stronger than the OR. 36018334Speter %(Spec) processes a specification defined in a specs file as *Spec: 36118334Speter %[Spec] as above, but put __ around -D arguments 36218334Speter 36318334SpeterThe conditional text X in a %{S:X} or %{!S:X} construct may contain 36418334Speterother nested % constructs or spaces, or even newlines. They are 36518334Speterprocessed as usual, as described above. 36618334Speter 36718334SpeterThe -O, -f, -m, and -W switches are handled specifically in these 36818334Speterconstructs. If another value of -O or the negated form of a -f, -m, or 36918334Speter-W switch is found later in the command line, the earlier switch 37018334Spetervalue is ignored, except with {S*} where S is just one letter; this 37118334Speterpasses all matching options. 37218334Speter 37350599SobrienThe character | at the beginning of the predicate text is used to indicate 37450599Sobrienthat a command should be piped to the following command, but only if -pipe 37550599Sobrienis specified. 37618334Speter 37718334SpeterNote that it is built into CC which switches take arguments and which 37818334Speterdo not. You might think it would be useful to generalize this to 37918334Speterallow each compiler's spec to say which switches take arguments. But 38018334Speterthis cannot be done in a consistent fashion. CC cannot even decide 38118334Speterwhich input files have been specified without knowing which switches 38218334Spetertake arguments, and it must know which input files to compile in order 38318334Speterto tell which compilers to run. 38418334Speter 38518334SpeterCC also knows implicitly that arguments starting in `-l' are to be 38618334Spetertreated as compiler output files, and passed to the linker in their 38718334Speterproper position among the other output files. */ 38818334Speter 38918334Speter/* Define the macros used for specs %a, %l, %L, %S, %c, %C, %1. */ 39018334Speter 39118334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler 39218334Speter or extra switch-translations. */ 39318334Speter#ifndef ASM_SPEC 39418334Speter#define ASM_SPEC "" 39518334Speter#endif 39618334Speter 39718334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after 39818334Speter the assembler has run. */ 39918334Speter#ifndef ASM_FINAL_SPEC 40018334Speter#define ASM_FINAL_SPEC "" 40118334Speter#endif 40218334Speter 40318334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor 40418334Speter or extra switch-translations. */ 40518334Speter#ifndef CPP_SPEC 40618334Speter#define CPP_SPEC "" 40718334Speter#endif 40818334Speter 40918334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus 41018334Speter or extra switch-translations. */ 41118334Speter#ifndef CC1_SPEC 41218334Speter#define CC1_SPEC "" 41318334Speter#endif 41418334Speter 41518334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus 41618334Speter or extra switch-translations. */ 41718334Speter#ifndef CC1PLUS_SPEC 41818334Speter#define CC1PLUS_SPEC "" 41918334Speter#endif 42018334Speter 42118334Speter/* config.h can define LINK_SPEC to provide extra args to the linker 42218334Speter or extra switch-translations. */ 42318334Speter#ifndef LINK_SPEC 42418334Speter#define LINK_SPEC "" 42518334Speter#endif 42618334Speter 42718334Speter/* config.h can define LIB_SPEC to override the default libraries. */ 42818334Speter#ifndef LIB_SPEC 42918334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}" 43018334Speter#endif 43118334Speter 43218334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is 43318334Speter included. */ 43418334Speter#ifndef LIBGCC_SPEC 43518334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1) 43618334Speter/* Have gcc do the search for libgcc.a. */ 43750599Sobrien#define LIBGCC_SPEC "libgcc.a%s" 43818334Speter#else 43950599Sobrien#define LIBGCC_SPEC "-lgcc" 44018334Speter#endif 44118334Speter#endif 44218334Speter 44318334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files. */ 44418334Speter#ifndef STARTFILE_SPEC 44518334Speter#define STARTFILE_SPEC \ 44618334Speter "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}" 44718334Speter#endif 44818334Speter 44950599Sobrien/* config.h can define SWITCHES_NEED_SPACES to control which options 45050599Sobrien require spaces between the option and the argument. */ 45118334Speter#ifndef SWITCHES_NEED_SPACES 45218334Speter#define SWITCHES_NEED_SPACES "" 45318334Speter#endif 45418334Speter 45518334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files. */ 45618334Speter#ifndef ENDFILE_SPEC 45718334Speter#define ENDFILE_SPEC "" 45818334Speter#endif 45918334Speter 46018334Speter/* This spec is used for telling cpp whether char is signed or not. */ 46118334Speter#ifndef SIGNED_CHAR_SPEC 46218334Speter/* Use #if rather than ?: 46318334Speter because MIPS C compiler rejects like ?: in initializers. */ 46418334Speter#if DEFAULT_SIGNED_CHAR 46518334Speter#define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}" 46618334Speter#else 46718334Speter#define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}" 46818334Speter#endif 46918334Speter#endif 47018334Speter 47150599Sobrien#ifndef LINKER_NAME 47250599Sobrien#define LINKER_NAME "collect2" 47318334Speter#endif 47418334Speter 47518334Speterstatic char *cpp_spec = CPP_SPEC; 47618334Speterstatic char *cpp_predefines = CPP_PREDEFINES; 47718334Speterstatic char *cc1_spec = CC1_SPEC; 47818334Speterstatic char *cc1plus_spec = CC1PLUS_SPEC; 47918334Speterstatic char *signed_char_spec = SIGNED_CHAR_SPEC; 48018334Speterstatic char *asm_spec = ASM_SPEC; 48118334Speterstatic char *asm_final_spec = ASM_FINAL_SPEC; 48218334Speterstatic char *link_spec = LINK_SPEC; 48318334Speterstatic char *lib_spec = LIB_SPEC; 48418334Speterstatic char *libgcc_spec = LIBGCC_SPEC; 48518334Speterstatic char *endfile_spec = ENDFILE_SPEC; 48618334Speterstatic char *startfile_spec = STARTFILE_SPEC; 48718334Speterstatic char *switches_need_spaces = SWITCHES_NEED_SPACES; 48850599Sobrienstatic char *linker_name_spec = LINKER_NAME; 48918334Speter 49050599Sobrien/* Some compilers have limits on line lengths, and the multilib_select 49150599Sobrien and/or multilib_matches strings can be very long, so we build them at 49250599Sobrien run time. */ 49350599Sobrienstatic struct obstack multilib_obstack; 49450599Sobrienstatic char *multilib_select; 49550599Sobrienstatic char *multilib_matches; 49650599Sobrienstatic char *multilib_defaults; 49750599Sobrien#include "multilib.h" 49850599Sobrien 49950599Sobrien/* Check whether a particular argument is a default argument. */ 50050599Sobrien 50150599Sobrien#ifndef MULTILIB_DEFAULTS 50250599Sobrien#define MULTILIB_DEFAULTS { "" } 50350599Sobrien#endif 50450599Sobrien 50550599Sobrienstatic char *multilib_defaults_raw[] = MULTILIB_DEFAULTS; 50650599Sobrien 50750599Sobrienstruct user_specs { 50850599Sobrien struct user_specs *next; 50952520Sobrien const char *filename; 51050599Sobrien}; 51150599Sobrien 51250599Sobrienstatic struct user_specs *user_specs_head, *user_specs_tail; 51350599Sobrien 51418334Speter/* This defines which switch letters take arguments. */ 51518334Speter 51650599Sobrien#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \ 51718334Speter ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \ 51818334Speter || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \ 51918334Speter || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \ 52050599Sobrien || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \ 52150599Sobrien || (CHAR) == 'B' || (CHAR) == 'b') 52250599Sobrien 52350599Sobrien#ifndef SWITCH_TAKES_ARG 52450599Sobrien#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR) 52518334Speter#endif 52618334Speter 52718334Speter/* This defines which multi-letter switches take arguments. */ 52818334Speter 52918334Speter#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \ 53018334Speter (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ 53118334Speter || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \ 53218334Speter || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \ 53318334Speter || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \ 53418334Speter || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \ 53550599Sobrien || !strcmp (STR, "isystem") || !strcmp (STR, "specs")) 53618334Speter 53718334Speter#ifndef WORD_SWITCH_TAKES_ARG 53818334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR) 53918334Speter#endif 54018334Speter 54150599Sobrien 54250599Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 54350599Sobrien/* This defines which switches stop a full compilation. */ 54450599Sobrien#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \ 54550599Sobrien ((CHAR) == 'c' || (CHAR) == 'S') 54650599Sobrien 54750599Sobrien#ifndef SWITCH_CURTAILS_COMPILATION 54850599Sobrien#define SWITCH_CURTAILS_COMPILATION(CHAR) \ 54950599Sobrien DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) 55050599Sobrien#endif 55150599Sobrien#endif 55250599Sobrien 55318334Speter/* Record the mapping from file suffixes for compilation specs. */ 55418334Speter 55518334Speterstruct compiler 55618334Speter{ 55752520Sobrien const char *suffix; /* Use this compiler for input files 55818334Speter whose names end in this suffix. */ 55918334Speter 56052520Sobrien const char *spec[4]; /* To use this compiler, concatenate these 56118334Speter specs and pass to do_spec. */ 56218334Speter}; 56318334Speter 56418334Speter/* Pointer to a vector of `struct compiler' that gives the spec for 56518334Speter compiling a file, based on its suffix. 56618334Speter A file that does not end in any of these suffixes will be passed 56718334Speter unchanged to the loader and nothing else will be done to it. 56818334Speter 56918334Speter An entry containing two 0s is used to terminate the vector. 57018334Speter 57118334Speter If multiple entries match a file, the last matching one is used. */ 57218334Speter 57318334Speterstatic struct compiler *compilers; 57418334Speter 57518334Speter/* Number of entries in `compilers', not counting the null terminator. */ 57618334Speter 57718334Speterstatic int n_compilers; 57818334Speter 57918334Speter/* The default list of file name suffixes and their compilation specs. */ 58018334Speter 58118334Speterstatic struct compiler default_compilers[] = 58218334Speter{ 58350599Sobrien /* Add lists of suffixes of known languages here. If those languages 58450599Sobrien were not present when we built the driver, we will hit these copies 58550599Sobrien and be given a more meaningful error than "file not used since 58650599Sobrien linking is not done". */ 58752520Sobrien {".m", {"#Objective-C"}}, 58852520Sobrien {".cc", {"#C++"}}, {".cxx", {"#C++"}}, {".cpp", {"#C++"}}, 58952520Sobrien {".c++", {"#C++"}}, {".C", {"#C++"}}, 59052520Sobrien {".ads", {"#Ada"}}, {".adb", {"#Ada"}}, {".ada", {"#Ada"}}, 59150599Sobrien {".f", {"#Fortran"}}, {".for", {"#Fortran"}}, {".F", {"#Fortran"}}, 59250599Sobrien {".fpp", {"#Fortran"}}, 59350599Sobrien {".p", {"#Pascal"}}, {".pas", {"#Pascal"}}, 59450599Sobrien /* Next come the entries for C. */ 59550599Sobrien {".c", {"@c"}}, 59618334Speter {"@c", 59750599Sobrien { 59850599Sobrien#if USE_CPPLIB 59952520Sobrien "%{E|M|MM:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\ 60052520Sobrien %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ 60118334Speter %{C:%{!E:%eGNU C does not support -C without using -E}}\ 60218334Speter %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ 60352520Sobrien %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\ 60452520Sobrien %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\ 60552520Sobrien %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\ 60650599Sobrien %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\ 60752520Sobrien %{ffast-math:-D__FAST_MATH__}\ 60850599Sobrien %{traditional} %{ftraditional:-traditional}\ 60918334Speter %{traditional-cpp:-traditional}\ 61052520Sobrien %{fleading-underscore} %{fno-leading-underscore}\ 61118334Speter %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\ 61250599Sobrien %i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}\ 61350599Sobrien %{!E:%{!M:%{!MM:cc1 %i %1 \ 61452520Sobrien %{std*} %{nostdinc*} %{A*} %{I*} %I\ 61550599Sobrien %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\ 61650599Sobrien %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ 61752520Sobrien %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\ 61852520Sobrien %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\ 61952520Sobrien %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\ 62050599Sobrien %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\ 62152520Sobrien %{ffast-math:-D__FAST_MATH__}\ 62250599Sobrien %{H} %C %{D*} %{U*} %{i*} %Z\ 62350599Sobrien %{ftraditional:-traditional}\ 62450599Sobrien %{traditional-cpp:-traditional}\ 62550599Sobrien %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\ 62652520Sobrien %{aux-info*} %{Qn:-fno-ident}\ 62752520Sobrien %{--help:--help}\ 62852520Sobrien %{g*} %{O*} %{W*} %{w} %{pedantic*}\ 62950599Sobrien %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 63050599Sobrien %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ 63150599Sobrien %{!S:as %a %Y\ 63250599Sobrien %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ 63350599Sobrien %{!pipe:%g.s} %A\n }}}}" 63450599Sobrien#else /* ! USE_CPPLIB */ 63552520Sobrien "cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\ 63652520Sobrien %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ 63750599Sobrien %{C:%{!E:%eGNU C does not support -C without using -E}}\ 63850599Sobrien %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ 63952520Sobrien %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\ 64052520Sobrien %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\ 64152520Sobrien %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\ 64250599Sobrien %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\ 64352520Sobrien %{ffast-math:-D__FAST_MATH__}\ 64450599Sobrien %{traditional} %{ftraditional:-traditional}\ 64550599Sobrien %{traditional-cpp:-traditional}\ 64652520Sobrien %{fleading-underscore} %{fno-leading-underscore}\ 64750599Sobrien %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\ 64818334Speter %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n", 64918334Speter "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \ 65050599Sobrien %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\ 65152520Sobrien %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\ 65218334Speter %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\ 65352520Sobrien %{aux-info*} %{Qn:-fno-ident}\ 65450599Sobrien %{--help:--help} \ 65518334Speter %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 65618334Speter %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ 65718334Speter %{!S:as %a %Y\ 65818334Speter %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ 65950599Sobrien %{!pipe:%g.s} %A\n }}}}" 66052520Sobrien#endif /* ! USE_CPPLIB */ 66150599Sobrien }}, 66218334Speter {"-", 66352520Sobrien {"%{E:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\ 66452520Sobrien %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ 66518334Speter %{C:%{!E:%eGNU C does not support -C without using -E}}\ 66618334Speter %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ 66752520Sobrien %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\ 66852520Sobrien %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\ 66952520Sobrien %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\ 67050599Sobrien %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\ 67152520Sobrien %{ffast-math:-D__FAST_MATH__}\ 67250599Sobrien %{traditional} %{ftraditional:-traditional}\ 67318334Speter %{traditional-cpp:-traditional}\ 67452520Sobrien %{fleading-underscore} %{fno-leading-underscore}\ 67518334Speter %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\ 67618334Speter %i %W{o*}}\ 67750599Sobrien %{!E:%e-E required when input is from standard input}"}}, 67850599Sobrien {".h", {"@c-header"}}, 67918334Speter {"@c-header", 68050599Sobrien {"%{!E:%eCompilation of header file requested} \ 68152520Sobrien cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ 68218334Speter %{C:%{!E:%eGNU C does not support -C without using -E}}\ 68352520Sobrien %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ 68452520Sobrien %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\ 68552520Sobrien %{std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\ 68652520Sobrien %{!undef:%{!std=*:%p}%{std=gnu*:%p} %P} %{trigraphs}\ 68750599Sobrien %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\ 68852520Sobrien %{ffast-math:-D__FAST_MATH__}\ 68950599Sobrien %{traditional} %{ftraditional:-traditional}\ 69018334Speter %{traditional-cpp:-traditional}\ 69152520Sobrien %{fleading-underscore} %{fno-leading-underscore}\ 69218334Speter %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\ 69350599Sobrien %i %W{o*}"}}, 69450599Sobrien {".i", {"@cpp-output"}}, 69518334Speter {"@cpp-output", 69650599Sobrien {"%{!M:%{!MM:%{!E:cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a*}\ 69752520Sobrien %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\ 69818334Speter %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\ 69952520Sobrien %{aux-info*} %{Qn:-fno-ident}\ 70018334Speter %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 70118334Speter %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ 70218334Speter %{!S:as %a %Y\ 70318334Speter %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ 70450599Sobrien %{!pipe:%g.s} %A\n }}}}"}}, 70550599Sobrien {".s", {"@assembler"}}, 70618334Speter {"@assembler", 70750599Sobrien {"%{!M:%{!MM:%{!E:%{!S:as %a %Y\ 70818334Speter %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ 70950599Sobrien %i %A\n }}}}"}}, 71050599Sobrien {".S", {"@assembler-with-cpp"}}, 71118334Speter {"@assembler-with-cpp", 71252520Sobrien {"cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ 71318334Speter %{C:%{!E:%eGNU C does not support -C without using -E}}\ 71418334Speter %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} %{trigraphs}\ 71552520Sobrien -$ %{!undef:%p %P} -D__ASSEMBLER__ \ 71650599Sobrien %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\ 71752520Sobrien %{ffast-math:-D__FAST_MATH__}\ 71850599Sobrien %{traditional} %{ftraditional:-traditional}\ 71918334Speter %{traditional-cpp:-traditional}\ 72052520Sobrien %{fleading-underscore} %{fno-leading-underscore}\ 72118334Speter %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\ 72218334Speter %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n", 72350599Sobrien "%{!M:%{!MM:%{!E:%{!S:as %a %Y\ 72418334Speter %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ 72550599Sobrien %{!pipe:%g.s} %A\n }}}}"}}, 72618334Speter#include "specs.h" 72718334Speter /* Mark end of table */ 72850599Sobrien {0, {0}} 72918334Speter}; 73018334Speter 73118334Speter/* Number of elements in default_compilers, not counting the terminator. */ 73218334Speter 73318334Speterstatic int n_default_compilers 73418334Speter = (sizeof default_compilers / sizeof (struct compiler)) - 1; 73518334Speter 73618334Speter/* Here is the spec for running the linker, after compiling all files. */ 73718334Speter 73818334Speter/* -u* was put back because both BSD and SysV seem to support it. */ 73918334Speter/* %{static:} simply prevents an error message if the target machine 74018334Speter doesn't handle -static. */ 74118334Speter/* We want %{T*} after %{L*} and %D so that it can be used to specify linker 74218334Speter scripts which exist in user specified directories, or in standard 74318334Speter directories. */ 74450599Sobrien#ifdef LINK_COMMAND_SPEC 74550599Sobrien/* Provide option to override link_command_spec from machine specific 74650599Sobrien configuration files. */ 74752520Sobrienstatic const char *link_command_spec = 74850599Sobrien LINK_COMMAND_SPEC; 74950599Sobrien#else 75018334Speter#ifdef LINK_LIBGCC_SPECIAL 75118334Speter/* Don't generate -L options. */ 75252520Sobrienstatic const char *link_command_spec = "\ 75318334Speter%{!fsyntax-only: \ 75450599Sobrien %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \ 75518334Speter %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\ 75618334Speter %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ 75750599Sobrien %{static:} %{L*} %o\ 75818334Speter %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\ 75950599Sobrien %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\ 76050599Sobrien %{T*}\ 76150599Sobrien \n }}}}}}"; 76218334Speter#else 76318334Speter/* Use -L. */ 76452520Sobrienstatic const char *link_command_spec = "\ 76518334Speter%{!fsyntax-only: \ 76650599Sobrien %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \ 76718334Speter %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\ 76818334Speter %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ 76950599Sobrien %{static:} %{L*} %D %o\ 77018334Speter %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\ 77150599Sobrien %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\ 77250599Sobrien %{T*}\ 77350599Sobrien \n }}}}}}"; 77418334Speter#endif 77550599Sobrien#endif 77618334Speter 77718334Speter/* A vector of options to give to the linker. 77818334Speter These options are accumulated by %x, 77918334Speter and substituted into the linker command with %X. */ 78018334Speterstatic int n_linker_options; 78118334Speterstatic char **linker_options; 78218334Speter 78318334Speter/* A vector of options to give to the assembler. 78418334Speter These options are accumulated by -Wa, 78518334Speter and substituted into the assembler command with %Y. */ 78618334Speterstatic int n_assembler_options; 78718334Speterstatic char **assembler_options; 78818334Speter 78918334Speter/* A vector of options to give to the preprocessor. 79018334Speter These options are accumulated by -Wp, 79118334Speter and substituted into the preprocessor command with %Z. */ 79218334Speterstatic int n_preprocessor_options; 79318334Speterstatic char **preprocessor_options; 79418334Speter 79518334Speter/* Define how to map long options into short ones. */ 79618334Speter 79718334Speter/* This structure describes one mapping. */ 79818334Speterstruct option_map 79918334Speter{ 80018334Speter /* The long option's name. */ 80152520Sobrien const char *name; 80218334Speter /* The equivalent short option. */ 80352520Sobrien const char *equivalent; 80418334Speter /* Argument info. A string of flag chars; NULL equals no options. 80518334Speter a => argument required. 80618334Speter o => argument optional. 80718334Speter j => join argument to equivalent, making one word. 80818334Speter * => require other text after NAME as an argument. */ 80952520Sobrien const char *arg_info; 81018334Speter}; 81118334Speter 81218334Speter/* This is the table of mappings. Mappings are tried sequentially 81318334Speter for each option encountered; the first one that matches, wins. */ 81418334Speter 81518334Speterstruct option_map option_map[] = 81618334Speter { 81718334Speter {"--all-warnings", "-Wall", 0}, 81818334Speter {"--ansi", "-ansi", 0}, 81918334Speter {"--assemble", "-S", 0}, 82018334Speter {"--assert", "-A", "a"}, 82152520Sobrien {"--classpath", "-fclasspath=", "aj"}, 82252520Sobrien {"--CLASSPATH", "-fCLASSPATH=", "aj"}, 82318334Speter {"--comments", "-C", 0}, 82418334Speter {"--compile", "-c", 0}, 82518334Speter {"--debug", "-g", "oj"}, 82650599Sobrien {"--define-macro", "-D", "aj"}, 82718334Speter {"--dependencies", "-M", 0}, 82818334Speter {"--dump", "-d", "a"}, 82918334Speter {"--dumpbase", "-dumpbase", "a"}, 83018334Speter {"--entry", "-e", 0}, 83118334Speter {"--extra-warnings", "-W", 0}, 83218334Speter {"--for-assembler", "-Wa", "a"}, 83318334Speter {"--for-linker", "-Xlinker", "a"}, 83418334Speter {"--force-link", "-u", "a"}, 83518334Speter {"--imacros", "-imacros", "a"}, 83618334Speter {"--include", "-include", "a"}, 83718334Speter {"--include-barrier", "-I-", 0}, 83850599Sobrien {"--include-directory", "-I", "aj"}, 83918334Speter {"--include-directory-after", "-idirafter", "a"}, 84018334Speter {"--include-prefix", "-iprefix", "a"}, 84118334Speter {"--include-with-prefix", "-iwithprefix", "a"}, 84218334Speter {"--include-with-prefix-before", "-iwithprefixbefore", "a"}, 84318334Speter {"--include-with-prefix-after", "-iwithprefix", "a"}, 84418334Speter {"--language", "-x", "a"}, 84518334Speter {"--library-directory", "-L", "a"}, 84618334Speter {"--machine", "-m", "aj"}, 84718334Speter {"--machine-", "-m", "*j"}, 84818334Speter {"--no-line-commands", "-P", 0}, 84918334Speter {"--no-precompiled-includes", "-noprecomp", 0}, 85018334Speter {"--no-standard-includes", "-nostdinc", 0}, 85118334Speter {"--no-standard-libraries", "-nostdlib", 0}, 85218334Speter {"--no-warnings", "-w", 0}, 85318334Speter {"--optimize", "-O", "oj"}, 85418334Speter {"--output", "-o", "a"}, 85552520Sobrien {"--output-class-directory", "-foutput-class-dir=", "ja"}, 85618334Speter {"--pedantic", "-pedantic", 0}, 85718334Speter {"--pedantic-errors", "-pedantic-errors", 0}, 85818334Speter {"--pipe", "-pipe", 0}, 85918334Speter {"--prefix", "-B", "a"}, 86018334Speter {"--preprocess", "-E", 0}, 86118334Speter {"--print-search-dirs", "-print-search-dirs", 0}, 86218334Speter {"--print-file-name", "-print-file-name=", "aj"}, 86318334Speter {"--print-libgcc-file-name", "-print-libgcc-file-name", 0}, 86418334Speter {"--print-missing-file-dependencies", "-MG", 0}, 86518334Speter {"--print-multi-lib", "-print-multi-lib", 0}, 86618334Speter {"--print-multi-directory", "-print-multi-directory", 0}, 86718334Speter {"--print-prog-name", "-print-prog-name=", "aj"}, 86818334Speter {"--profile", "-p", 0}, 86918334Speter {"--profile-blocks", "-a", 0}, 87018334Speter {"--quiet", "-q", 0}, 87118334Speter {"--save-temps", "-save-temps", 0}, 87218334Speter {"--shared", "-shared", 0}, 87318334Speter {"--silent", "-q", 0}, 87450599Sobrien {"--specs", "-specs=", "aj"}, 87518334Speter {"--static", "-static", 0}, 87652520Sobrien {"--std", "-std=", "aj"}, 87718334Speter {"--symbolic", "-symbolic", 0}, 87818334Speter {"--target", "-b", "a"}, 87918334Speter {"--trace-includes", "-H", 0}, 88018334Speter {"--traditional", "-traditional", 0}, 88118334Speter {"--traditional-cpp", "-traditional-cpp", 0}, 88218334Speter {"--trigraphs", "-trigraphs", 0}, 88350599Sobrien {"--undefine-macro", "-U", "aj"}, 88418334Speter {"--use-version", "-V", "a"}, 88518334Speter {"--user-dependencies", "-MM", 0}, 88618334Speter {"--verbose", "-v", 0}, 88718334Speter {"--version", "-dumpversion", 0}, 88818334Speter {"--warn-", "-W", "*j"}, 88918334Speter {"--write-dependencies", "-MD", 0}, 89018334Speter {"--write-user-dependencies", "-MMD", 0}, 89118334Speter {"--", "-f", "*j"} 89218334Speter }; 89318334Speter 89418334Speter/* Translate the options described by *ARGCP and *ARGVP. 89518334Speter Make a new vector and store it back in *ARGVP, 89618334Speter and store its length in *ARGVC. */ 89718334Speter 89818334Speterstatic void 89918334Spetertranslate_options (argcp, argvp) 90018334Speter int *argcp; 90152520Sobrien const char ***argvp; 90218334Speter{ 90352520Sobrien int i; 90418334Speter int argc = *argcp; 90552520Sobrien const char **argv = *argvp; 90652520Sobrien const char **newv = 90752520Sobrien (const char **) xmalloc ((argc + 2) * 2 * sizeof (const char *)); 90818334Speter int newindex = 0; 90918334Speter 91018334Speter i = 0; 91118334Speter newv[newindex++] = argv[i++]; 91218334Speter 91318334Speter while (i < argc) 91418334Speter { 91518334Speter /* Translate -- options. */ 91618334Speter if (argv[i][0] == '-' && argv[i][1] == '-') 91718334Speter { 91852520Sobrien size_t j; 91918334Speter /* Find a mapping that applies to this option. */ 92018334Speter for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++) 92118334Speter { 92250599Sobrien size_t optlen = strlen (option_map[j].name); 92350599Sobrien size_t arglen = strlen (argv[i]); 92450599Sobrien size_t complen = arglen > optlen ? optlen : arglen; 92552520Sobrien const char *arginfo = option_map[j].arg_info; 92618334Speter 92718334Speter if (arginfo == 0) 92818334Speter arginfo = ""; 92918334Speter 93018334Speter if (!strncmp (argv[i], option_map[j].name, complen)) 93118334Speter { 93252520Sobrien const char *arg = 0; 93318334Speter 93418334Speter if (arglen < optlen) 93518334Speter { 93652520Sobrien size_t k; 93718334Speter for (k = j + 1; 93818334Speter k < sizeof (option_map) / sizeof (option_map[0]); 93918334Speter k++) 94018334Speter if (strlen (option_map[k].name) >= arglen 94118334Speter && !strncmp (argv[i], option_map[k].name, arglen)) 94218334Speter { 94318334Speter error ("Ambiguous abbreviation %s", argv[i]); 94418334Speter break; 94518334Speter } 94618334Speter 94718334Speter if (k != sizeof (option_map) / sizeof (option_map[0])) 94818334Speter break; 94918334Speter } 95018334Speter 95118334Speter if (arglen > optlen) 95218334Speter { 95318334Speter /* If the option has an argument, accept that. */ 95418334Speter if (argv[i][optlen] == '=') 95518334Speter arg = argv[i] + optlen + 1; 95618334Speter 95718334Speter /* If this mapping requires extra text at end of name, 95818334Speter accept that as "argument". */ 95918334Speter else if (index (arginfo, '*') != 0) 96018334Speter arg = argv[i] + optlen; 96118334Speter 96218334Speter /* Otherwise, extra text at end means mismatch. 96318334Speter Try other mappings. */ 96418334Speter else 96518334Speter continue; 96618334Speter } 96718334Speter 96818334Speter else if (index (arginfo, '*') != 0) 96918334Speter { 97018334Speter error ("Incomplete `%s' option", option_map[j].name); 97118334Speter break; 97218334Speter } 97318334Speter 97418334Speter /* Handle arguments. */ 97518334Speter if (index (arginfo, 'a') != 0) 97618334Speter { 97718334Speter if (arg == 0) 97818334Speter { 97918334Speter if (i + 1 == argc) 98018334Speter { 98118334Speter error ("Missing argument to `%s' option", 98218334Speter option_map[j].name); 98318334Speter break; 98418334Speter } 98518334Speter 98618334Speter arg = argv[++i]; 98718334Speter } 98818334Speter } 98918334Speter else if (index (arginfo, '*') != 0) 99018334Speter ; 99118334Speter else if (index (arginfo, 'o') == 0) 99218334Speter { 99318334Speter if (arg != 0) 99418334Speter error ("Extraneous argument to `%s' option", 99518334Speter option_map[j].name); 99618334Speter arg = 0; 99718334Speter } 99818334Speter 99918334Speter /* Store the translation as one argv elt or as two. */ 100018334Speter if (arg != 0 && index (arginfo, 'j') != 0) 100150599Sobrien newv[newindex++] = concat (option_map[j].equivalent, arg, 100250599Sobrien NULL_PTR); 100318334Speter else if (arg != 0) 100418334Speter { 100518334Speter newv[newindex++] = option_map[j].equivalent; 100618334Speter newv[newindex++] = arg; 100718334Speter } 100818334Speter else 100918334Speter newv[newindex++] = option_map[j].equivalent; 101018334Speter 101118334Speter break; 101218334Speter } 101318334Speter } 101418334Speter i++; 101518334Speter } 101618334Speter 101718334Speter /* Handle old-fashioned options--just copy them through, 101818334Speter with their arguments. */ 101918334Speter else if (argv[i][0] == '-') 102018334Speter { 102152520Sobrien const char *p = argv[i] + 1; 102218334Speter int c = *p; 102318334Speter int nskip = 1; 102418334Speter 102518334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 102618334Speter nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0); 102718334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 102818334Speter nskip += WORD_SWITCH_TAKES_ARG (p); 102918334Speter else if ((c == 'B' || c == 'b' || c == 'V' || c == 'x') 103018334Speter && p[1] == 0) 103118334Speter nskip += 1; 103218334Speter else if (! strcmp (p, "Xlinker")) 103318334Speter nskip += 1; 103418334Speter 103518334Speter /* Watch out for an option at the end of the command line that 103618334Speter is missing arguments, and avoid skipping past the end of the 103718334Speter command line. */ 103818334Speter if (nskip + i > argc) 103918334Speter nskip = argc - i; 104018334Speter 104118334Speter while (nskip > 0) 104218334Speter { 104318334Speter newv[newindex++] = argv[i++]; 104418334Speter nskip--; 104518334Speter } 104618334Speter } 104718334Speter else 104818334Speter /* Ordinary operands, or +e options. */ 104918334Speter newv[newindex++] = argv[i++]; 105018334Speter } 105118334Speter 105218334Speter newv[newindex] = 0; 105318334Speter 105418334Speter *argvp = newv; 105518334Speter *argcp = newindex; 105618334Speter} 105718334Speter 105818334Speterchar * 105952520Sobrienxstrerror(e) 106018334Speter int e; 106118334Speter{ 106250599Sobrien#ifdef HAVE_STRERROR 106318334Speter 106418334Speter return strerror(e); 106518334Speter 106618334Speter#else 106718334Speter 106818334Speter if (!e) 106952520Sobrien return "errno = 0"; 107018334Speter 107118334Speter if (e > 0 && e < sys_nerr) 107218334Speter return sys_errlist[e]; 107318334Speter 107452520Sobrien return "errno = ?"; 107518334Speter#endif 107618334Speter} 107718334Speter 107818334Speterstatic char * 107918334Speterskip_whitespace (p) 108018334Speter char *p; 108118334Speter{ 108218334Speter while (1) 108318334Speter { 108418334Speter /* A fully-blank line is a delimiter in the SPEC file and shouldn't 108518334Speter be considered whitespace. */ 108618334Speter if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n') 108718334Speter return p + 1; 108818334Speter else if (*p == '\n' || *p == ' ' || *p == '\t') 108918334Speter p++; 109018334Speter else if (*p == '#') 109118334Speter { 109218334Speter while (*p != '\n') p++; 109318334Speter p++; 109418334Speter } 109518334Speter else 109618334Speter break; 109718334Speter } 109818334Speter 109918334Speter return p; 110018334Speter} 110118334Speter 110250599Sobrien/* Structure to keep track of the specs that have been defined so far. 110350599Sobrien These are accessed using %(specname) or %[specname] in a compiler 110450599Sobrien or link spec. */ 110518334Speter 110618334Speterstruct spec_list 110718334Speter{ 110850599Sobrien /* The following 2 fields must be first */ 110950599Sobrien /* to allow EXTRA_SPECS to be initialized */ 111050599Sobrien char *name; /* name of the spec. */ 111150599Sobrien char *ptr; /* available ptr if no static pointer */ 111250599Sobrien 111350599Sobrien /* The following fields are not initialized */ 111450599Sobrien /* by EXTRA_SPECS */ 111550599Sobrien char **ptr_spec; /* pointer to the spec itself. */ 111650599Sobrien struct spec_list *next; /* Next spec in linked list. */ 111750599Sobrien int name_len; /* length of the name */ 111850599Sobrien int alloc_p; /* whether string was allocated */ 111918334Speter}; 112018334Speter 112150599Sobrien#define INIT_STATIC_SPEC(NAME,PTR) \ 112250599Sobrien{ NAME, NULL_PTR, PTR, (struct spec_list *)0, sizeof (NAME)-1, 0 } 112318334Speter 112450599Sobrien/* List of statically defined specs */ 112550599Sobrienstatic struct spec_list static_specs[] = { 112650599Sobrien INIT_STATIC_SPEC ("asm", &asm_spec), 112750599Sobrien INIT_STATIC_SPEC ("asm_final", &asm_final_spec), 112850599Sobrien INIT_STATIC_SPEC ("cpp", &cpp_spec), 112950599Sobrien INIT_STATIC_SPEC ("cc1", &cc1_spec), 113050599Sobrien INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec), 113150599Sobrien INIT_STATIC_SPEC ("endfile", &endfile_spec), 113250599Sobrien INIT_STATIC_SPEC ("link", &link_spec), 113350599Sobrien INIT_STATIC_SPEC ("lib", &lib_spec), 113450599Sobrien INIT_STATIC_SPEC ("libgcc", &libgcc_spec), 113550599Sobrien INIT_STATIC_SPEC ("startfile", &startfile_spec), 113650599Sobrien INIT_STATIC_SPEC ("switches_need_spaces", &switches_need_spaces), 113750599Sobrien INIT_STATIC_SPEC ("signed_char", &signed_char_spec), 113850599Sobrien INIT_STATIC_SPEC ("predefines", &cpp_predefines), 113950599Sobrien INIT_STATIC_SPEC ("cross_compile", &cross_compile), 114050599Sobrien INIT_STATIC_SPEC ("version", &compiler_version), 114150599Sobrien INIT_STATIC_SPEC ("multilib", &multilib_select), 114250599Sobrien INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults), 114350599Sobrien INIT_STATIC_SPEC ("multilib_extra", &multilib_extra), 114450599Sobrien INIT_STATIC_SPEC ("multilib_matches", &multilib_matches), 114550599Sobrien INIT_STATIC_SPEC ("linker", &linker_name_spec), 114650599Sobrien}; 114750599Sobrien 114850599Sobrien#ifdef EXTRA_SPECS /* additional specs needed */ 114952520Sobrien/* Structure to keep track of just the first two args of a spec_list. 115052520Sobrien That is all that the EXTRA_SPECS macro gives us. */ 115152520Sobrienstruct spec_list_1 115252520Sobrien{ 115352520Sobrien char *name; 115452520Sobrien char *ptr; 115552520Sobrien}; 115652520Sobrien 115752520Sobrienstatic struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS }; 115852520Sobrienstatic struct spec_list * extra_specs = (struct spec_list *)0; 115950599Sobrien#endif 116050599Sobrien 116150599Sobrien/* List of dynamically allocates specs that have been defined so far. */ 116250599Sobrien 116350599Sobrienstatic struct spec_list *specs = (struct spec_list *)0; 116450599Sobrien 116518334Speter 116650599Sobrien/* Initialize the specs lookup routines. */ 116750599Sobrien 116850599Sobrienstatic void 116950599Sobrieninit_spec () 117050599Sobrien{ 117150599Sobrien struct spec_list *next = (struct spec_list *)0; 117250599Sobrien struct spec_list *sl = (struct spec_list *)0; 117350599Sobrien int i; 117450599Sobrien 117550599Sobrien if (specs) 117650599Sobrien return; /* already initialized */ 117750599Sobrien 117850599Sobrien if (verbose_flag) 117952520Sobrien notice ("Using builtin specs.\n"); 118050599Sobrien 118150599Sobrien#ifdef EXTRA_SPECS 118252520Sobrien extra_specs = (struct spec_list *) 118352520Sobrien xmalloc (sizeof(struct spec_list) * 118452520Sobrien (sizeof(extra_specs_1)/sizeof(extra_specs_1[0]))); 118552520Sobrien bzero ((PTR) extra_specs, sizeof(struct spec_list) * 118652520Sobrien (sizeof(extra_specs_1)/sizeof(extra_specs_1[0]))); 118752520Sobrien 118852520Sobrien for (i = (sizeof(extra_specs_1) / sizeof(extra_specs_1[0])) - 1; i >= 0; i--) 118950599Sobrien { 119050599Sobrien sl = &extra_specs[i]; 119152520Sobrien sl->name = extra_specs_1[i].name; 119252520Sobrien sl->ptr = extra_specs_1[i].ptr; 119350599Sobrien sl->next = next; 119450599Sobrien sl->name_len = strlen (sl->name); 119550599Sobrien sl->ptr_spec = &sl->ptr; 119650599Sobrien next = sl; 119750599Sobrien } 119850599Sobrien#endif 119950599Sobrien 120050599Sobrien for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1; i >= 0; i--) 120150599Sobrien { 120250599Sobrien sl = &static_specs[i]; 120350599Sobrien sl->next = next; 120450599Sobrien next = sl; 120550599Sobrien } 120650599Sobrien 120750599Sobrien specs = sl; 120850599Sobrien} 120950599Sobrien 121050599Sobrien 121118334Speter/* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is 121218334Speter removed; If the spec starts with a + then SPEC is added to the end of the 121350599Sobrien current spec. */ 121418334Speter 121518334Speterstatic void 121618334Speterset_spec (name, spec) 121752520Sobrien const char *name; 121852520Sobrien const char *spec; 121918334Speter{ 122018334Speter struct spec_list *sl; 122118334Speter char *old_spec; 122250599Sobrien int name_len = strlen (name); 122350599Sobrien int i; 122418334Speter 122550599Sobrien /* If this is the first call, initialize the statically allocated specs */ 122650599Sobrien if (!specs) 122750599Sobrien { 122850599Sobrien struct spec_list *next = (struct spec_list *)0; 122950599Sobrien for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1; 123050599Sobrien i >= 0; i--) 123150599Sobrien { 123250599Sobrien sl = &static_specs[i]; 123350599Sobrien sl->next = next; 123450599Sobrien next = sl; 123550599Sobrien } 123650599Sobrien specs = sl; 123750599Sobrien } 123850599Sobrien 123918334Speter /* See if the spec already exists */ 124018334Speter for (sl = specs; sl; sl = sl->next) 124150599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, name)) 124218334Speter break; 124318334Speter 124418334Speter if (!sl) 124518334Speter { 124618334Speter /* Not found - make it */ 124718334Speter sl = (struct spec_list *) xmalloc (sizeof (struct spec_list)); 124818334Speter sl->name = save_string (name, strlen (name)); 124950599Sobrien sl->name_len = name_len; 125050599Sobrien sl->ptr_spec = &sl->ptr; 125150599Sobrien sl->alloc_p = 0; 125250599Sobrien *(sl->ptr_spec) = ""; 125318334Speter sl->next = specs; 125418334Speter specs = sl; 125518334Speter } 125618334Speter 125750599Sobrien old_spec = *(sl->ptr_spec); 125852520Sobrien *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1])) 125950599Sobrien ? concat (old_spec, spec + 1, NULL_PTR) 126050599Sobrien : save_string (spec, strlen (spec))); 126118334Speter 126250599Sobrien#ifdef DEBUG_SPECS 126350599Sobrien if (verbose_flag) 126452520Sobrien notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec)); 126550599Sobrien#endif 126650599Sobrien 126718334Speter /* Free the old spec */ 126850599Sobrien if (old_spec && sl->alloc_p) 126918334Speter free (old_spec); 127050599Sobrien 127150599Sobrien sl->alloc_p = 1; 127218334Speter} 127318334Speter 127418334Speter/* Accumulate a command (program name and args), and run it. */ 127518334Speter 127618334Speter/* Vector of pointers to arguments in the current line of specifications. */ 127718334Speter 127818334Speterstatic char **argbuf; 127918334Speter 128018334Speter/* Number of elements allocated in argbuf. */ 128118334Speter 128218334Speterstatic int argbuf_length; 128318334Speter 128418334Speter/* Number of elements in argbuf currently in use (containing args). */ 128518334Speter 128618334Speterstatic int argbuf_index; 128718334Speter 128850599Sobrien/* We want this on by default all the time now. */ 128950599Sobrien#define MKTEMP_EACH_FILE 129050599Sobrien 129150599Sobrien#ifdef MKTEMP_EACH_FILE 129250599Sobrien 129352520Sobrienextern char *make_temp_file PROTO((const char *)); 129450599Sobrien 129518334Speter/* This is the list of suffixes and codes (%g/%u/%U) and the associated 129650599Sobrien temp file. */ 129718334Speter 129818334Speterstatic struct temp_name { 129952520Sobrien const char *suffix; /* suffix associated with the code. */ 130018334Speter int length; /* strlen (suffix). */ 130118334Speter int unique; /* Indicates whether %g or %u/%U was used. */ 130252520Sobrien const char *filename; /* associated filename. */ 130318334Speter int filename_length; /* strlen (filename). */ 130418334Speter struct temp_name *next; 130518334Speter} *temp_names; 130650599Sobrien#endif 130718334Speter 130850599Sobrien 130918334Speter/* Number of commands executed so far. */ 131018334Speter 131118334Speterstatic int execution_count; 131218334Speter 131318334Speter/* Number of commands that exited with a signal. */ 131418334Speter 131518334Speterstatic int signal_count; 131618334Speter 131718334Speter/* Name with which this program was invoked. */ 131818334Speter 131952520Sobrienstatic const char *programname; 132018334Speter 132150599Sobrien/* Structures to keep track of prefixes to try when looking for files. */ 132218334Speter 132318334Speterstruct prefix_list 132418334Speter{ 132550599Sobrien char *prefix; /* String to prepend to the path. */ 132650599Sobrien struct prefix_list *next; /* Next in linked list. */ 132718334Speter int require_machine_suffix; /* Don't use without machine_suffix. */ 132818334Speter /* 2 means try both machine_suffix and just_machine_suffix. */ 132918334Speter int *used_flag_ptr; /* 1 if a file was found with this prefix. */ 133018334Speter}; 133118334Speter 133218334Speterstruct path_prefix 133318334Speter{ 133418334Speter struct prefix_list *plist; /* List of prefixes to try */ 133518334Speter int max_len; /* Max length of a prefix in PLIST */ 133652520Sobrien const char *name; /* Name of this list (used in config stuff) */ 133718334Speter}; 133818334Speter 133950599Sobrien/* List of prefixes to try when looking for executables. */ 134018334Speter 134118334Speterstatic struct path_prefix exec_prefixes = { 0, 0, "exec" }; 134218334Speter 134350599Sobrien/* List of prefixes to try when looking for startup (crt0) files. */ 134418334Speter 134518334Speterstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" }; 134618334Speter 134718334Speter/* List of prefixes to try when looking for include files. */ 134818334Speter 134918334Speterstatic struct path_prefix include_prefixes = { 0, 0, "include" }; 135018334Speter 135118334Speter/* Suffix to attach to directories searched for commands. 135218334Speter This looks like `MACHINE/VERSION/'. */ 135318334Speter 135452520Sobrienstatic const char *machine_suffix = 0; 135518334Speter 135618334Speter/* Suffix to attach to directories searched for commands. 135718334Speter This is just `MACHINE/'. */ 135818334Speter 135952520Sobrienstatic const char *just_machine_suffix = 0; 136018334Speter 136118334Speter/* Adjusted value of GCC_EXEC_PREFIX envvar. */ 136218334Speter 136352520Sobrienstatic const char *gcc_exec_prefix; 136418334Speter 136518334Speter/* Default prefixes to attach to command names. */ 136618334Speter 136718334Speter#ifdef CROSS_COMPILE /* Don't use these prefixes for a cross compiler. */ 136818334Speter#undef MD_EXEC_PREFIX 136918334Speter#undef MD_STARTFILE_PREFIX 137018334Speter#undef MD_STARTFILE_PREFIX_1 137118334Speter#endif 137218334Speter 137318334Speter#ifndef STANDARD_EXEC_PREFIX 137418334Speter#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/" 137518334Speter#endif /* !defined STANDARD_EXEC_PREFIX */ 137618334Speter 137752520Sobrienstatic const char *standard_exec_prefix = STANDARD_EXEC_PREFIX; 137852520Sobrienstatic const char *standard_exec_prefix_1 = "/usr/lib/gcc/"; 137918334Speter#ifdef MD_EXEC_PREFIX 138052520Sobrienstatic const char *md_exec_prefix = MD_EXEC_PREFIX; 138118334Speter#endif 138218334Speter 138318334Speter#ifndef STANDARD_STARTFILE_PREFIX 138418334Speter#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/" 138518334Speter#endif /* !defined STANDARD_STARTFILE_PREFIX */ 138618334Speter 138718334Speter#ifdef MD_STARTFILE_PREFIX 138852520Sobrienstatic const char *md_startfile_prefix = MD_STARTFILE_PREFIX; 138918334Speter#endif 139018334Speter#ifdef MD_STARTFILE_PREFIX_1 139152520Sobrienstatic const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1; 139218334Speter#endif 139352520Sobrienstatic const char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; 139452520Sobrienstatic const char *standard_startfile_prefix_1 = "/lib/"; 139552520Sobrienstatic const char *standard_startfile_prefix_2 = "/usr/lib/"; 139618334Speter 139718334Speter#ifndef TOOLDIR_BASE_PREFIX 139818334Speter#define TOOLDIR_BASE_PREFIX "/usr/local/" 139918334Speter#endif 140052520Sobrienstatic const char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX; 140152520Sobrienstatic const char *tooldir_prefix; 140218334Speter 140318334Speter/* Subdirectory to use for locating libraries. Set by 140418334Speter set_multilib_dir based on the compilation options. */ 140518334Speter 140652520Sobrienstatic const char *multilib_dir; 140718334Speter 140818334Speter/* Clear out the vector of arguments (after a command is executed). */ 140918334Speter 141018334Speterstatic void 141118334Speterclear_args () 141218334Speter{ 141318334Speter argbuf_index = 0; 141418334Speter} 141518334Speter 141618334Speter/* Add one argument to the vector at the end. 141718334Speter This is done when a space is seen or at the end of the line. 141818334Speter If DELETE_ALWAYS is nonzero, the arg is a filename 141918334Speter and the file should be deleted eventually. 142018334Speter If DELETE_FAILURE is nonzero, the arg is a filename 142118334Speter and the file should be deleted if this compilation fails. */ 142218334Speter 142318334Speterstatic void 142418334Speterstore_arg (arg, delete_always, delete_failure) 142518334Speter char *arg; 142618334Speter int delete_always, delete_failure; 142718334Speter{ 142818334Speter if (argbuf_index + 1 == argbuf_length) 142950599Sobrien argbuf 143050599Sobrien = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *)); 143118334Speter 143218334Speter argbuf[argbuf_index++] = arg; 143318334Speter argbuf[argbuf_index] = 0; 143418334Speter 143518334Speter if (delete_always || delete_failure) 143618334Speter record_temp_file (arg, delete_always, delete_failure); 143718334Speter} 143818334Speter 143950599Sobrien/* Read compilation specs from a file named FILENAME, 144050599Sobrien replacing the default ones. 144150599Sobrien 144250599Sobrien A suffix which starts with `*' is a definition for 144350599Sobrien one of the machine-specific sub-specs. The "suffix" should be 144450599Sobrien *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc. 144550599Sobrien The corresponding spec is stored in asm_spec, etc., 144650599Sobrien rather than in the `compilers' vector. 144750599Sobrien 144850599Sobrien Anything invalid in the file is a fatal error. */ 144950599Sobrien 145050599Sobrienstatic void 145150599Sobrienread_specs (filename, main_p) 145252520Sobrien const char *filename; 145350599Sobrien int main_p; 145450599Sobrien{ 145550599Sobrien int desc; 145650599Sobrien int readlen; 145750599Sobrien struct stat statbuf; 145850599Sobrien char *buffer; 145950599Sobrien register char *p; 146050599Sobrien 146150599Sobrien if (verbose_flag) 146252520Sobrien notice ("Reading specs from %s\n", filename); 146350599Sobrien 146450599Sobrien /* Open and stat the file. */ 146550599Sobrien desc = open (filename, O_RDONLY, 0); 146650599Sobrien if (desc < 0) 146750599Sobrien pfatal_with_name (filename); 146850599Sobrien if (stat (filename, &statbuf) < 0) 146950599Sobrien pfatal_with_name (filename); 147050599Sobrien 147150599Sobrien /* Read contents of file into BUFFER. */ 147250599Sobrien buffer = xmalloc ((unsigned) statbuf.st_size + 1); 147350599Sobrien readlen = read (desc, buffer, (unsigned) statbuf.st_size); 147450599Sobrien if (readlen < 0) 147550599Sobrien pfatal_with_name (filename); 147650599Sobrien buffer[readlen] = 0; 147750599Sobrien close (desc); 147850599Sobrien 147950599Sobrien /* Scan BUFFER for specs, putting them in the vector. */ 148050599Sobrien p = buffer; 148150599Sobrien while (1) 148250599Sobrien { 148350599Sobrien char *suffix; 148450599Sobrien char *spec; 148550599Sobrien char *in, *out, *p1, *p2, *p3; 148650599Sobrien 148750599Sobrien /* Advance P in BUFFER to the next nonblank nocomment line. */ 148850599Sobrien p = skip_whitespace (p); 148950599Sobrien if (*p == 0) 149050599Sobrien break; 149150599Sobrien 149250599Sobrien /* Is this a special command that starts with '%'? */ 149350599Sobrien /* Don't allow this for the main specs file, since it would 149450599Sobrien encourage people to overwrite it. */ 149550599Sobrien if (*p == '%' && !main_p) 149650599Sobrien { 149750599Sobrien p1 = p; 149850599Sobrien while (*p && *p != '\n') 149950599Sobrien p++; 150050599Sobrien 150150599Sobrien p++; /* Skip '\n' */ 150250599Sobrien 150350599Sobrien if (!strncmp (p1, "%include", sizeof ("%include")-1) 150450599Sobrien && (p1[sizeof "%include" - 1] == ' ' 150550599Sobrien || p1[sizeof "%include" - 1] == '\t')) 150650599Sobrien { 150750599Sobrien char *new_filename; 150850599Sobrien 150950599Sobrien p1 += sizeof ("%include"); 151050599Sobrien while (*p1 == ' ' || *p1 == '\t') 151150599Sobrien p1++; 151250599Sobrien 151350599Sobrien if (*p1++ != '<' || p[-2] != '>') 151452520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 151552520Sobrien (long) (p1 - buffer + 1)); 151650599Sobrien 151750599Sobrien p[-2] = '\0'; 151850599Sobrien new_filename = find_a_file (&startfile_prefixes, p1, R_OK); 151950599Sobrien read_specs (new_filename ? new_filename : p1, FALSE); 152050599Sobrien continue; 152150599Sobrien } 152250599Sobrien else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1) 152350599Sobrien && (p1[sizeof "%include_noerr" - 1] == ' ' 152450599Sobrien || p1[sizeof "%include_noerr" - 1] == '\t')) 152550599Sobrien { 152650599Sobrien char *new_filename; 152750599Sobrien 152850599Sobrien p1 += sizeof "%include_noerr"; 152950599Sobrien while (*p1 == ' ' || *p1 == '\t') p1++; 153050599Sobrien 153150599Sobrien if (*p1++ != '<' || p[-2] != '>') 153252520Sobrien fatal ("specs %%include syntax malformed after %ld characters", 153352520Sobrien (long) (p1 - buffer + 1)); 153450599Sobrien 153550599Sobrien p[-2] = '\0'; 153650599Sobrien new_filename = find_a_file (&startfile_prefixes, p1, R_OK); 153750599Sobrien if (new_filename) 153850599Sobrien read_specs (new_filename, FALSE); 153950599Sobrien else if (verbose_flag) 154052520Sobrien notice ("Could not find specs file %s\n", p1); 154150599Sobrien continue; 154250599Sobrien } 154350599Sobrien else if (!strncmp (p1, "%rename", sizeof "%rename" - 1) 154450599Sobrien && (p1[sizeof "%rename" - 1] == ' ' 154550599Sobrien || p1[sizeof "%rename" - 1] == '\t')) 154650599Sobrien { 154750599Sobrien int name_len; 154850599Sobrien struct spec_list *sl; 154950599Sobrien 155050599Sobrien /* Get original name */ 155150599Sobrien p1 += sizeof "%rename"; 155250599Sobrien while (*p1 == ' ' || *p1 == '\t') 155350599Sobrien p1++; 155450599Sobrien 155552520Sobrien if (! ISALPHA ((unsigned char)*p1)) 155652520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 155752520Sobrien (long) (p1 - buffer)); 155850599Sobrien 155950599Sobrien p2 = p1; 156052520Sobrien while (*p2 && !ISSPACE ((unsigned char)*p2)) 156150599Sobrien p2++; 156250599Sobrien 156350599Sobrien if (*p2 != ' ' && *p2 != '\t') 156452520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 156552520Sobrien (long) (p2 - buffer)); 156650599Sobrien 156750599Sobrien name_len = p2 - p1; 156850599Sobrien *p2++ = '\0'; 156950599Sobrien while (*p2 == ' ' || *p2 == '\t') 157050599Sobrien p2++; 157150599Sobrien 157252520Sobrien if (! ISALPHA ((unsigned char)*p2)) 157352520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 157452520Sobrien (long) (p2 - buffer)); 157550599Sobrien 157650599Sobrien /* Get new spec name */ 157750599Sobrien p3 = p2; 157852520Sobrien while (*p3 && !ISSPACE ((unsigned char)*p3)) 157950599Sobrien p3++; 158050599Sobrien 158150599Sobrien if (p3 != p-1) 158252520Sobrien fatal ("specs %%rename syntax malformed after %ld characters", 158352520Sobrien (long) (p3 - buffer)); 158450599Sobrien *p3 = '\0'; 158550599Sobrien 158650599Sobrien for (sl = specs; sl; sl = sl->next) 158750599Sobrien if (name_len == sl->name_len && !strcmp (sl->name, p1)) 158850599Sobrien break; 158950599Sobrien 159050599Sobrien if (!sl) 159150599Sobrien fatal ("specs %s spec was not found to be renamed", p1); 159250599Sobrien 159350599Sobrien if (strcmp (p1, p2) == 0) 159450599Sobrien continue; 159550599Sobrien 159650599Sobrien if (verbose_flag) 159750599Sobrien { 159852520Sobrien notice ("rename spec %s to %s\n", p1, p2); 159950599Sobrien#ifdef DEBUG_SPECS 160052520Sobrien notice ("spec is '%s'\n\n", *(sl->ptr_spec)); 160150599Sobrien#endif 160250599Sobrien } 160350599Sobrien 160450599Sobrien set_spec (p2, *(sl->ptr_spec)); 160550599Sobrien if (sl->alloc_p) 160650599Sobrien free (*(sl->ptr_spec)); 160750599Sobrien 160850599Sobrien *(sl->ptr_spec) = ""; 160950599Sobrien sl->alloc_p = 0; 161050599Sobrien continue; 161150599Sobrien } 161250599Sobrien else 161352520Sobrien fatal ("specs unknown %% command after %ld characters", 161452520Sobrien (long) (p1 - buffer)); 161550599Sobrien } 161650599Sobrien 161750599Sobrien /* Find the colon that should end the suffix. */ 161850599Sobrien p1 = p; 161950599Sobrien while (*p1 && *p1 != ':' && *p1 != '\n') 162050599Sobrien p1++; 162150599Sobrien 162250599Sobrien /* The colon shouldn't be missing. */ 162350599Sobrien if (*p1 != ':') 162452520Sobrien fatal ("specs file malformed after %ld characters", 162552520Sobrien (long) (p1 - buffer)); 162650599Sobrien 162750599Sobrien /* Skip back over trailing whitespace. */ 162850599Sobrien p2 = p1; 162950599Sobrien while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) 163050599Sobrien p2--; 163150599Sobrien 163250599Sobrien /* Copy the suffix to a string. */ 163350599Sobrien suffix = save_string (p, p2 - p); 163450599Sobrien /* Find the next line. */ 163550599Sobrien p = skip_whitespace (p1 + 1); 163650599Sobrien if (p[1] == 0) 163752520Sobrien fatal ("specs file malformed after %ld characters", 163852520Sobrien (long) (p - buffer)); 163950599Sobrien 164050599Sobrien p1 = p; 164150599Sobrien /* Find next blank line or end of string. */ 164250599Sobrien while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0'))) 164350599Sobrien p1++; 164450599Sobrien 164550599Sobrien /* Specs end at the blank line and do not include the newline. */ 164650599Sobrien spec = save_string (p, p1 - p); 164750599Sobrien p = p1; 164850599Sobrien 164950599Sobrien /* Delete backslash-newline sequences from the spec. */ 165050599Sobrien in = spec; 165150599Sobrien out = spec; 165250599Sobrien while (*in != 0) 165350599Sobrien { 165450599Sobrien if (in[0] == '\\' && in[1] == '\n') 165550599Sobrien in += 2; 165650599Sobrien else if (in[0] == '#') 165750599Sobrien while (*in && *in != '\n') 165850599Sobrien in++; 165950599Sobrien 166050599Sobrien else 166150599Sobrien *out++ = *in++; 166250599Sobrien } 166350599Sobrien *out = 0; 166450599Sobrien 166550599Sobrien if (suffix[0] == '*') 166650599Sobrien { 166750599Sobrien if (! strcmp (suffix, "*link_command")) 166850599Sobrien link_command_spec = spec; 166950599Sobrien else 167050599Sobrien set_spec (suffix + 1, spec); 167150599Sobrien } 167250599Sobrien else 167350599Sobrien { 167450599Sobrien /* Add this pair to the vector. */ 167550599Sobrien compilers 167650599Sobrien = ((struct compiler *) 167750599Sobrien xrealloc (compilers, 167850599Sobrien (n_compilers + 2) * sizeof (struct compiler))); 167950599Sobrien 168050599Sobrien compilers[n_compilers].suffix = suffix; 168150599Sobrien bzero ((char *) compilers[n_compilers].spec, 168250599Sobrien sizeof compilers[n_compilers].spec); 168350599Sobrien compilers[n_compilers].spec[0] = spec; 168450599Sobrien n_compilers++; 168550599Sobrien bzero ((char *) &compilers[n_compilers], 168650599Sobrien sizeof compilers[n_compilers]); 168750599Sobrien } 168850599Sobrien 168950599Sobrien if (*suffix == 0) 169050599Sobrien link_command_spec = spec; 169150599Sobrien } 169250599Sobrien 169350599Sobrien if (link_command_spec == 0) 169450599Sobrien fatal ("spec file has no spec for linking"); 169550599Sobrien} 169650599Sobrien 169718334Speter/* Record the names of temporary files we tell compilers to write, 169818334Speter and delete them at the end of the run. */ 169918334Speter 170018334Speter/* This is the common prefix we use to make temp file names. 170118334Speter It is chosen once for each run of this program. 170218334Speter It is substituted into a spec by %g. 170318334Speter Thus, all temp file names contain this prefix. 170418334Speter In practice, all temp file names start with this prefix. 170518334Speter 170618334Speter This prefix comes from the envvar TMPDIR if it is defined; 170718334Speter otherwise, from the P_tmpdir macro if that is defined; 170850599Sobrien otherwise, in /usr/tmp or /tmp; 170950599Sobrien or finally the current directory if all else fails. */ 171018334Speter 171152520Sobrienstatic const char *temp_filename; 171218334Speter 171318334Speter/* Length of the prefix. */ 171418334Speter 171518334Speterstatic int temp_filename_length; 171618334Speter 171718334Speter/* Define the list of temporary files to delete. */ 171818334Speter 171918334Speterstruct temp_file 172018334Speter{ 172152520Sobrien const char *name; 172218334Speter struct temp_file *next; 172318334Speter}; 172418334Speter 172518334Speter/* Queue of files to delete on success or failure of compilation. */ 172618334Speterstatic struct temp_file *always_delete_queue; 172718334Speter/* Queue of files to delete on failure of compilation. */ 172818334Speterstatic struct temp_file *failure_delete_queue; 172918334Speter 173018334Speter/* Record FILENAME as a file to be deleted automatically. 173118334Speter ALWAYS_DELETE nonzero means delete it if all compilation succeeds; 173218334Speter otherwise delete it in any case. 173318334Speter FAIL_DELETE nonzero means delete it if a compilation step fails; 173418334Speter otherwise delete it in any case. */ 173518334Speter 173618334Speterstatic void 173718334Speterrecord_temp_file (filename, always_delete, fail_delete) 173852520Sobrien const char *filename; 173918334Speter int always_delete; 174018334Speter int fail_delete; 174118334Speter{ 174218334Speter register char *name; 174318334Speter name = xmalloc (strlen (filename) + 1); 174418334Speter strcpy (name, filename); 174518334Speter 174618334Speter if (always_delete) 174718334Speter { 174818334Speter register struct temp_file *temp; 174918334Speter for (temp = always_delete_queue; temp; temp = temp->next) 175018334Speter if (! strcmp (name, temp->name)) 175118334Speter goto already1; 175250599Sobrien 175318334Speter temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); 175418334Speter temp->next = always_delete_queue; 175518334Speter temp->name = name; 175618334Speter always_delete_queue = temp; 175750599Sobrien 175818334Speter already1:; 175918334Speter } 176018334Speter 176118334Speter if (fail_delete) 176218334Speter { 176318334Speter register struct temp_file *temp; 176418334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 176518334Speter if (! strcmp (name, temp->name)) 176618334Speter goto already2; 176750599Sobrien 176818334Speter temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); 176918334Speter temp->next = failure_delete_queue; 177018334Speter temp->name = name; 177118334Speter failure_delete_queue = temp; 177250599Sobrien 177318334Speter already2:; 177418334Speter } 177518334Speter} 177618334Speter 177718334Speter/* Delete all the temporary files whose names we previously recorded. */ 177818334Speter 177918334Speterstatic void 178018334Speterdelete_if_ordinary (name) 178152520Sobrien const char *name; 178218334Speter{ 178318334Speter struct stat st; 178418334Speter#ifdef DEBUG 178518334Speter int i, c; 178618334Speter 178718334Speter printf ("Delete %s? (y or n) ", name); 178818334Speter fflush (stdout); 178918334Speter i = getchar (); 179018334Speter if (i != '\n') 179150599Sobrien while ((c = getchar ()) != '\n' && c != EOF) 179250599Sobrien ; 179350599Sobrien 179418334Speter if (i == 'y' || i == 'Y') 179518334Speter#endif /* DEBUG */ 179618334Speter if (stat (name, &st) >= 0 && S_ISREG (st.st_mode)) 179718334Speter if (unlink (name) < 0) 179818334Speter if (verbose_flag) 179918334Speter perror_with_name (name); 180018334Speter} 180118334Speter 180218334Speterstatic void 180318334Speterdelete_temp_files () 180418334Speter{ 180518334Speter register struct temp_file *temp; 180618334Speter 180718334Speter for (temp = always_delete_queue; temp; temp = temp->next) 180818334Speter delete_if_ordinary (temp->name); 180918334Speter always_delete_queue = 0; 181018334Speter} 181118334Speter 181218334Speter/* Delete all the files to be deleted on error. */ 181318334Speter 181418334Speterstatic void 181518334Speterdelete_failure_queue () 181618334Speter{ 181718334Speter register struct temp_file *temp; 181818334Speter 181918334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 182018334Speter delete_if_ordinary (temp->name); 182118334Speter} 182218334Speter 182318334Speterstatic void 182418334Speterclear_failure_queue () 182518334Speter{ 182618334Speter failure_delete_queue = 0; 182718334Speter} 182818334Speter 182918334Speter/* Routine to add variables to the environment. We do this to pass 183018334Speter the pathname of the gcc driver, and the directories search to the 183118334Speter collect2 program, which is being run as ld. This way, we can be 183218334Speter sure of executing the right compiler when collect2 wants to build 183318334Speter constructors and destructors. Since the environment variables we 183418334Speter use come from an obstack, we don't have to worry about allocating 183518334Speter space for them. */ 183618334Speter 183718334Speter#ifndef HAVE_PUTENV 183818334Speter 183918334Spetervoid 184018334Speterputenv (str) 184118334Speter char *str; 184218334Speter{ 184318334Speter#ifndef VMS /* nor about VMS */ 184418334Speter 184518334Speter extern char **environ; 184618334Speter char **old_environ = environ; 184718334Speter char **envp; 184818334Speter int num_envs = 0; 184918334Speter int name_len = 1; 185050599Sobrien int str_len = strlen (str); 185118334Speter char *p = str; 185218334Speter int ch; 185318334Speter 185418334Speter while ((ch = *p++) != '\0' && ch != '=') 185518334Speter name_len++; 185618334Speter 185718334Speter if (!ch) 185818334Speter abort (); 185918334Speter 186018334Speter /* Search for replacing an existing environment variable, and 186118334Speter count the number of total environment variables. */ 186218334Speter for (envp = old_environ; *envp; envp++) 186318334Speter { 186418334Speter num_envs++; 186518334Speter if (!strncmp (str, *envp, name_len)) 186618334Speter { 186718334Speter *envp = str; 186818334Speter return; 186918334Speter } 187018334Speter } 187118334Speter 187218334Speter /* Add a new environment variable */ 187318334Speter environ = (char **) xmalloc (sizeof (char *) * (num_envs+2)); 187418334Speter *environ = str; 187552520Sobrien memcpy ((char *) (environ + 1), (char *) old_environ, 187618334Speter sizeof (char *) * (num_envs+1)); 187718334Speter 187818334Speter#endif /* VMS */ 187918334Speter} 188018334Speter 188118334Speter#endif /* HAVE_PUTENV */ 188218334Speter 188318334Speter 188418334Speter/* Build a list of search directories from PATHS. 188518334Speter PREFIX is a string to prepend to the list. 188618334Speter If CHECK_DIR_P is non-zero we ensure the directory exists. 188718334Speter This is used mostly by putenv_from_prefixes so we use `collect_obstack'. 188818334Speter It is also used by the --print-search-dirs flag. */ 188918334Speter 189018334Speterstatic char * 189118334Speterbuild_search_list (paths, prefix, check_dir_p) 189218334Speter struct path_prefix *paths; 189352520Sobrien const char *prefix; 189418334Speter int check_dir_p; 189518334Speter{ 189618334Speter int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0; 189718334Speter int just_suffix_len 189818334Speter = (just_machine_suffix) ? strlen (just_machine_suffix) : 0; 189918334Speter int first_time = TRUE; 190018334Speter struct prefix_list *pprefix; 190118334Speter 190218334Speter obstack_grow (&collect_obstack, prefix, strlen (prefix)); 190318334Speter 190418334Speter for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next) 190518334Speter { 190618334Speter int len = strlen (pprefix->prefix); 190718334Speter 190818334Speter if (machine_suffix 190950599Sobrien && (! check_dir_p 191018334Speter || is_directory (pprefix->prefix, machine_suffix, 0))) 191118334Speter { 191218334Speter if (!first_time) 191318334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 191418334Speter 191518334Speter first_time = FALSE; 191618334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 191718334Speter obstack_grow (&collect_obstack, machine_suffix, suffix_len); 191818334Speter } 191918334Speter 192018334Speter if (just_machine_suffix 192118334Speter && pprefix->require_machine_suffix == 2 192250599Sobrien && (! check_dir_p 192318334Speter || is_directory (pprefix->prefix, just_machine_suffix, 0))) 192418334Speter { 192550599Sobrien if (! first_time) 192618334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 192718334Speter 192818334Speter first_time = FALSE; 192918334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 193018334Speter obstack_grow (&collect_obstack, just_machine_suffix, 193118334Speter just_suffix_len); 193218334Speter } 193318334Speter 193450599Sobrien if (! pprefix->require_machine_suffix) 193518334Speter { 193650599Sobrien if (! first_time) 193718334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 193818334Speter 193918334Speter first_time = FALSE; 194018334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 194118334Speter } 194218334Speter } 194350599Sobrien 194418334Speter obstack_1grow (&collect_obstack, '\0'); 194518334Speter return obstack_finish (&collect_obstack); 194618334Speter} 194718334Speter 194850599Sobrien/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 194950599Sobrien for collect. */ 195018334Speter 195118334Speterstatic void 195218334Speterputenv_from_prefixes (paths, env_var) 195318334Speter struct path_prefix *paths; 195452520Sobrien const char *env_var; 195518334Speter{ 195618334Speter putenv (build_search_list (paths, env_var, 1)); 195718334Speter} 195818334Speter 195918334Speter/* Search for NAME using the prefix list PREFIXES. MODE is passed to 196018334Speter access to check permissions. 196150599Sobrien Return 0 if not found, otherwise return its name, allocated with malloc. */ 196218334Speter 196318334Speterstatic char * 196418334Speterfind_a_file (pprefix, name, mode) 196518334Speter struct path_prefix *pprefix; 196652520Sobrien const char *name; 196718334Speter int mode; 196818334Speter{ 196918334Speter char *temp; 197052520Sobrien const char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : ""); 197118334Speter struct prefix_list *pl; 197218334Speter int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1; 197318334Speter 197452520Sobrien#ifdef DEFAULT_ASSEMBLER 197552520Sobrien if (! strcmp(name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) { 197652520Sobrien name = DEFAULT_ASSEMBLER; 197752520Sobrien len = strlen(name)+1; 197852520Sobrien temp = xmalloc (len); 197952520Sobrien strcpy (temp, name); 198052520Sobrien return temp; 198152520Sobrien } 198252520Sobrien#endif 198352520Sobrien 198452520Sobrien#ifdef DEFAULT_LINKER 198552520Sobrien if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) { 198652520Sobrien name = DEFAULT_LINKER; 198752520Sobrien len = strlen(name)+1; 198852520Sobrien temp = xmalloc (len); 198952520Sobrien strcpy (temp, name); 199052520Sobrien return temp; 199152520Sobrien } 199252520Sobrien#endif 199352520Sobrien 199418334Speter if (machine_suffix) 199518334Speter len += strlen (machine_suffix); 199618334Speter 199718334Speter temp = xmalloc (len); 199818334Speter 199918334Speter /* Determine the filename to execute (special case for absolute paths). */ 200018334Speter 200152520Sobrien if (IS_DIR_SEPARATOR (*name) 200252520Sobrien#ifdef HAVE_DOS_BASED_FILESYSTEM 200350599Sobrien /* Check for disk name on MS-DOS-based systems. */ 200452520Sobrien || (name[0] && name[1] == ':' && IS_DIR_SEPARATOR (name[2])) 200552520Sobrien#endif 200652520Sobrien ) 200718334Speter { 200852520Sobrien if (access (name, mode) == 0) 200918334Speter { 201018334Speter strcpy (temp, name); 201118334Speter return temp; 201218334Speter } 201318334Speter } 201418334Speter else 201518334Speter for (pl = pprefix->plist; pl; pl = pl->next) 201618334Speter { 201718334Speter if (machine_suffix) 201818334Speter { 201918334Speter /* Some systems have a suffix for executable files. 202018334Speter So try appending that first. */ 202118334Speter if (file_suffix[0] != 0) 202218334Speter { 202318334Speter strcpy (temp, pl->prefix); 202418334Speter strcat (temp, machine_suffix); 202518334Speter strcat (temp, name); 202618334Speter strcat (temp, file_suffix); 202718334Speter if (access (temp, mode) == 0) 202818334Speter { 202918334Speter if (pl->used_flag_ptr != 0) 203018334Speter *pl->used_flag_ptr = 1; 203118334Speter return temp; 203218334Speter } 203318334Speter } 203418334Speter 203518334Speter /* Now try just the name. */ 203618334Speter strcpy (temp, pl->prefix); 203718334Speter strcat (temp, machine_suffix); 203818334Speter strcat (temp, name); 203918334Speter if (access (temp, mode) == 0) 204018334Speter { 204118334Speter if (pl->used_flag_ptr != 0) 204218334Speter *pl->used_flag_ptr = 1; 204318334Speter return temp; 204418334Speter } 204518334Speter } 204618334Speter 204718334Speter /* Certain prefixes are tried with just the machine type, 204818334Speter not the version. This is used for finding as, ld, etc. */ 204918334Speter if (just_machine_suffix && pl->require_machine_suffix == 2) 205018334Speter { 205118334Speter /* Some systems have a suffix for executable files. 205218334Speter So try appending that first. */ 205318334Speter if (file_suffix[0] != 0) 205418334Speter { 205518334Speter strcpy (temp, pl->prefix); 205618334Speter strcat (temp, just_machine_suffix); 205718334Speter strcat (temp, name); 205818334Speter strcat (temp, file_suffix); 205918334Speter if (access (temp, mode) == 0) 206018334Speter { 206118334Speter if (pl->used_flag_ptr != 0) 206218334Speter *pl->used_flag_ptr = 1; 206318334Speter return temp; 206418334Speter } 206518334Speter } 206618334Speter 206718334Speter strcpy (temp, pl->prefix); 206818334Speter strcat (temp, just_machine_suffix); 206918334Speter strcat (temp, name); 207018334Speter if (access (temp, mode) == 0) 207118334Speter { 207218334Speter if (pl->used_flag_ptr != 0) 207318334Speter *pl->used_flag_ptr = 1; 207418334Speter return temp; 207518334Speter } 207618334Speter } 207718334Speter 207818334Speter /* Certain prefixes can't be used without the machine suffix 207918334Speter when the machine or version is explicitly specified. */ 208050599Sobrien if (! pl->require_machine_suffix) 208118334Speter { 208218334Speter /* Some systems have a suffix for executable files. 208318334Speter So try appending that first. */ 208418334Speter if (file_suffix[0] != 0) 208518334Speter { 208618334Speter strcpy (temp, pl->prefix); 208718334Speter strcat (temp, name); 208818334Speter strcat (temp, file_suffix); 208918334Speter if (access (temp, mode) == 0) 209018334Speter { 209118334Speter if (pl->used_flag_ptr != 0) 209218334Speter *pl->used_flag_ptr = 1; 209318334Speter return temp; 209418334Speter } 209518334Speter } 209618334Speter 209718334Speter strcpy (temp, pl->prefix); 209818334Speter strcat (temp, name); 209918334Speter if (access (temp, mode) == 0) 210018334Speter { 210118334Speter if (pl->used_flag_ptr != 0) 210218334Speter *pl->used_flag_ptr = 1; 210318334Speter return temp; 210418334Speter } 210518334Speter } 210618334Speter } 210718334Speter 210818334Speter free (temp); 210918334Speter return 0; 211018334Speter} 211118334Speter 211218334Speter/* Add an entry for PREFIX in PLIST. If FIRST is set, it goes 211318334Speter at the start of the list, otherwise it goes at the end. 211418334Speter 211518334Speter If WARN is nonzero, we will warn if no file is found 211618334Speter through this prefix. WARN should point to an int 211718334Speter which will be set to 1 if this entry is used. 211818334Speter 211950599Sobrien COMPONENT is the value to be passed to update_path. 212050599Sobrien 212118334Speter REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without 212218334Speter the complete value of machine_suffix. 212318334Speter 2 means try both machine_suffix and just_machine_suffix. */ 212418334Speter 212518334Speterstatic void 212650599Sobrienadd_prefix (pprefix, prefix, component, first, require_machine_suffix, warn) 212718334Speter struct path_prefix *pprefix; 212852520Sobrien const char *prefix; 212952520Sobrien const char *component; 213018334Speter int first; 213118334Speter int require_machine_suffix; 213218334Speter int *warn; 213318334Speter{ 213418334Speter struct prefix_list *pl, **prev; 213518334Speter int len; 213618334Speter 213750599Sobrien if (! first && pprefix->plist) 213818334Speter { 213918334Speter for (pl = pprefix->plist; pl->next; pl = pl->next) 214018334Speter ; 214118334Speter prev = &pl->next; 214218334Speter } 214318334Speter else 214418334Speter prev = &pprefix->plist; 214518334Speter 214618334Speter /* Keep track of the longest prefix */ 214718334Speter 214850599Sobrien prefix = update_path (prefix, component); 214918334Speter len = strlen (prefix); 215018334Speter if (len > pprefix->max_len) 215118334Speter pprefix->max_len = len; 215218334Speter 215318334Speter pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list)); 215418334Speter pl->prefix = save_string (prefix, len); 215518334Speter pl->require_machine_suffix = require_machine_suffix; 215618334Speter pl->used_flag_ptr = warn; 215718334Speter if (warn) 215818334Speter *warn = 0; 215918334Speter 216018334Speter if (*prev) 216118334Speter pl->next = *prev; 216218334Speter else 216318334Speter pl->next = (struct prefix_list *) 0; 216418334Speter *prev = pl; 216518334Speter} 216618334Speter 216718334Speter/* Print warnings for any prefixes in the list PPREFIX that were not used. */ 216818334Speter 216918334Speterstatic void 217018334Speterunused_prefix_warnings (pprefix) 217118334Speter struct path_prefix *pprefix; 217218334Speter{ 217318334Speter struct prefix_list *pl = pprefix->plist; 217418334Speter 217518334Speter while (pl) 217618334Speter { 217718334Speter if (pl->used_flag_ptr != 0 && !*pl->used_flag_ptr) 217818334Speter { 217950599Sobrien if (pl->require_machine_suffix && machine_suffix) 218050599Sobrien error ("file path prefix `%s%s' never used", pl->prefix, 218150599Sobrien machine_suffix); 218250599Sobrien else 218350599Sobrien error ("file path prefix `%s' never used", pl->prefix); 218450599Sobrien 218518334Speter /* Prevent duplicate warnings. */ 218618334Speter *pl->used_flag_ptr = 1; 218718334Speter } 218818334Speter 218918334Speter pl = pl->next; 219018334Speter } 219118334Speter} 219218334Speter 219318334Speter 219418334Speter/* Execute the command specified by the arguments on the current line of spec. 219518334Speter When using pipes, this includes several piped-together commands 219618334Speter with `|' between them. 219718334Speter 219818334Speter Return 0 if successful, -1 if failed. */ 219918334Speter 220018334Speterstatic int 220118334Speterexecute () 220218334Speter{ 220318334Speter int i; 220418334Speter int n_commands; /* # of command. */ 220518334Speter char *string; 220618334Speter struct command 220718334Speter { 220852520Sobrien const char *prog; /* program name. */ 220952520Sobrien char **argv; /* vector of args. */ 221018334Speter int pid; /* pid of process for this command. */ 221118334Speter }; 221218334Speter 221318334Speter struct command *commands; /* each command buffer with above info. */ 221418334Speter 221518334Speter /* Count # of piped commands. */ 221618334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 221718334Speter if (strcmp (argbuf[i], "|") == 0) 221818334Speter n_commands++; 221918334Speter 222018334Speter /* Get storage for each command. */ 222118334Speter commands 222218334Speter = (struct command *) alloca (n_commands * sizeof (struct command)); 222318334Speter 222418334Speter /* Split argbuf into its separate piped processes, 222518334Speter and record info about each one. 222618334Speter Also search for the programs that are to be run. */ 222718334Speter 222818334Speter commands[0].prog = argbuf[0]; /* first command. */ 222918334Speter commands[0].argv = &argbuf[0]; 223018334Speter string = find_a_file (&exec_prefixes, commands[0].prog, X_OK); 223150599Sobrien 223218334Speter if (string) 223318334Speter commands[0].argv[0] = string; 223418334Speter 223518334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 223618334Speter if (strcmp (argbuf[i], "|") == 0) 223718334Speter { /* each command. */ 223852520Sobrien#if defined (__MSDOS__) || defined (OS2) || defined (VMS) 223950599Sobrien fatal ("-pipe not supported"); 224018334Speter#endif 224118334Speter argbuf[i] = 0; /* termination of command args. */ 224218334Speter commands[n_commands].prog = argbuf[i + 1]; 224318334Speter commands[n_commands].argv = &argbuf[i + 1]; 224418334Speter string = find_a_file (&exec_prefixes, commands[n_commands].prog, X_OK); 224518334Speter if (string) 224618334Speter commands[n_commands].argv[0] = string; 224718334Speter n_commands++; 224818334Speter } 224918334Speter 225018334Speter argbuf[argbuf_index] = 0; 225118334Speter 225218334Speter /* If -v, print what we are about to do, and maybe query. */ 225318334Speter 225418334Speter if (verbose_flag) 225518334Speter { 225650599Sobrien /* For help listings, put a blank line between sub-processes. */ 225750599Sobrien if (print_help_list) 225850599Sobrien fputc ('\n', stderr); 225950599Sobrien 226018334Speter /* Print each piped command as a separate line. */ 226118334Speter for (i = 0; i < n_commands ; i++) 226218334Speter { 226318334Speter char **j; 226418334Speter 226518334Speter for (j = commands[i].argv; *j; j++) 226618334Speter fprintf (stderr, " %s", *j); 226718334Speter 226818334Speter /* Print a pipe symbol after all but the last command. */ 226918334Speter if (i + 1 != n_commands) 227018334Speter fprintf (stderr, " |"); 227118334Speter fprintf (stderr, "\n"); 227218334Speter } 227318334Speter fflush (stderr); 227418334Speter#ifdef DEBUG 227552520Sobrien notice ("\nGo ahead? (y or n) "); 227618334Speter fflush (stderr); 227718334Speter i = getchar (); 227818334Speter if (i != '\n') 227950599Sobrien while (getchar () != '\n') 228050599Sobrien ; 228150599Sobrien 228218334Speter if (i != 'y' && i != 'Y') 228318334Speter return 0; 228418334Speter#endif /* DEBUG */ 228518334Speter } 228618334Speter 228718334Speter /* Run each piped subprocess. */ 228818334Speter 228918334Speter for (i = 0; i < n_commands; i++) 229018334Speter { 229150599Sobrien char *errmsg_fmt, *errmsg_arg; 229218334Speter char *string = commands[i].argv[0]; 229318334Speter 229450599Sobrien commands[i].pid = pexecute (string, commands[i].argv, 229550599Sobrien programname, temp_filename, 229650599Sobrien &errmsg_fmt, &errmsg_arg, 229750599Sobrien ((i == 0 ? PEXECUTE_FIRST : 0) 229850599Sobrien | (i + 1 == n_commands ? PEXECUTE_LAST : 0) 229950599Sobrien | (string == commands[i].prog 230050599Sobrien ? PEXECUTE_SEARCH : 0) 230150599Sobrien | (verbose_flag ? PEXECUTE_VERBOSE : 0))); 230218334Speter 230350599Sobrien if (commands[i].pid == -1) 230450599Sobrien pfatal_pexecute (errmsg_fmt, errmsg_arg); 230550599Sobrien 230618334Speter if (string != commands[i].prog) 230718334Speter free (string); 230818334Speter } 230918334Speter 231018334Speter execution_count++; 231118334Speter 231218334Speter /* Wait for all the subprocesses to finish. 231318334Speter We don't care what order they finish in; 231418334Speter we know that N_COMMANDS waits will get them all. 231518334Speter Ignore subprocesses that we don't know about, 231618334Speter since they can be spawned by the process that exec'ed us. */ 231718334Speter 231818334Speter { 231918334Speter int ret_code = 0; 232018334Speter 232118334Speter for (i = 0; i < n_commands; ) 232218334Speter { 232318334Speter int j; 232418334Speter int status; 232518334Speter int pid; 232618334Speter 232750599Sobrien pid = pwait (commands[i].pid, &status, 0); 232818334Speter if (pid < 0) 232918334Speter abort (); 233018334Speter 233118334Speter for (j = 0; j < n_commands; j++) 233218334Speter if (commands[j].pid == pid) 233318334Speter { 233418334Speter i++; 233518334Speter if (status != 0) 233618334Speter { 233718334Speter if (WIFSIGNALED (status)) 233818334Speter { 233918334Speter fatal ("Internal compiler error: program %s got fatal signal %d", 234018334Speter commands[j].prog, WTERMSIG (status)); 234118334Speter signal_count++; 234218334Speter ret_code = -1; 234318334Speter } 234418334Speter else if (WIFEXITED (status) 234518334Speter && WEXITSTATUS (status) >= MIN_FATAL_STATUS) 234618334Speter ret_code = -1; 234718334Speter } 234818334Speter break; 234918334Speter } 235018334Speter } 235118334Speter return ret_code; 235218334Speter } 235318334Speter} 235418334Speter 235518334Speter/* Find all the switches given to us 235618334Speter and make a vector describing them. 235718334Speter The elements of the vector are strings, one per switch given. 235818334Speter If a switch uses following arguments, then the `part1' field 235918334Speter is the switch itself and the `args' field 236018334Speter is a null-terminated vector containing the following arguments. 236118334Speter The `live_cond' field is 1 if the switch is true in a conditional spec, 236218334Speter -1 if false (overridden by a later switch), and is initialized to zero. 236352520Sobrien The `validated' field is nonzero if any spec has looked at this switch; 236418334Speter if it remains zero at the end of the run, it must be meaningless. */ 236518334Speter 236618334Speterstruct switchstr 236718334Speter{ 236852520Sobrien const char *part1; 236918334Speter char **args; 237018334Speter int live_cond; 237152520Sobrien int validated; 237218334Speter}; 237318334Speter 237418334Speterstatic struct switchstr *switches; 237518334Speter 237618334Speterstatic int n_switches; 237718334Speter 237818334Speterstruct infile 237918334Speter{ 238052520Sobrien const char *name; 238152520Sobrien const char *language; 238218334Speter}; 238318334Speter 238418334Speter/* Also a vector of input files specified. */ 238518334Speter 238618334Speterstatic struct infile *infiles; 238718334Speter 238818334Speterstatic int n_infiles; 238918334Speter 239052520Sobrien/* This counts the number of libraries added by lang_specific_driver, so that 239150599Sobrien we can tell if there were any user supplied any files or libraries. */ 239250599Sobrien 239350599Sobrienstatic int added_libraries; 239450599Sobrien 239518334Speter/* And a vector of corresponding output files is made up later. */ 239618334Speter 239752520Sobrienstatic const char **outfiles; 239818334Speter 239950599Sobrien/* Used to track if none of the -B paths are used. */ 240050599Sobrienstatic int warn_B; 240150599Sobrien 240250599Sobrien/* Used to track if standard path isn't used and -b or -V is specified. */ 240350599Sobrienstatic int warn_std; 240450599Sobrien 240550599Sobrien/* Gives value to pass as "warn" to add_prefix for standard prefixes. */ 240650599Sobrienstatic int *warn_std_ptr = 0; 240750599Sobrien 240853878Sobrien#if defined(FREEBSD_NATIVE) 240953878Sobrien#include <objformat.h> 241053878Sobrien 241153878Sobrientypedef enum { OBJFMT_UNKNOWN, OBJFMT_AOUT, OBJFMT_ELF } objf_t; 241253878Sobrien 241353878Sobrienstatic objf_t objformat = OBJFMT_UNKNOWN; 241450599Sobrien#endif 241550599Sobrien 241650599Sobrien#if defined(HAVE_OBJECT_SUFFIX) || defined(HAVE_EXECUTABLE_SUFFIX) 241750599Sobrien 241850599Sobrien/* Convert NAME to a new name if it is the standard suffix. DO_EXE 241950599Sobrien is true if we should look for an executable suffix as well. */ 242050599Sobrien 242150599Sobrienstatic char * 242250599Sobrienconvert_filename (name, do_exe) 242350599Sobrien char *name; 242450599Sobrien int do_exe; 242550599Sobrien{ 242650599Sobrien int i; 242752520Sobrien int len; 242850599Sobrien 242952520Sobrien if (name == NULL) 243052520Sobrien return NULL; 243152520Sobrien 243252520Sobrien len = strlen (name); 243352520Sobrien 243450599Sobrien#ifdef HAVE_OBJECT_SUFFIX 243550599Sobrien /* Convert x.o to x.obj if OBJECT_SUFFIX is ".obj". */ 243650599Sobrien if (len > 2 243750599Sobrien && name[len - 2] == '.' 243850599Sobrien && name[len - 1] == 'o') 243950599Sobrien { 244050599Sobrien obstack_grow (&obstack, name, len - 2); 244150599Sobrien obstack_grow0 (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX)); 244250599Sobrien name = obstack_finish (&obstack); 244350599Sobrien } 244450599Sobrien#endif 244550599Sobrien 244650599Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 244750599Sobrien /* If there is no filetype, make it the executable suffix (which includes 244850599Sobrien the "."). But don't get confused if we have just "-o". */ 244950599Sobrien if (! do_exe || EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-')) 245050599Sobrien return name; 245150599Sobrien 245250599Sobrien for (i = len - 1; i >= 0; i--) 245352520Sobrien if (IS_DIR_SEPARATOR (name[i])) 245450599Sobrien break; 245550599Sobrien 245650599Sobrien for (i++; i < len; i++) 245750599Sobrien if (name[i] == '.') 245850599Sobrien return name; 245950599Sobrien 246050599Sobrien obstack_grow (&obstack, name, len); 246150599Sobrien obstack_grow0 (&obstack, EXECUTABLE_SUFFIX, strlen (EXECUTABLE_SUFFIX)); 246250599Sobrien name = obstack_finish (&obstack); 246350599Sobrien#endif 246450599Sobrien 246550599Sobrien return name; 246650599Sobrien} 246750599Sobrien#endif 246850599Sobrien 246950599Sobrien/* Display the command line switches accepted by gcc. */ 247050599Sobrienstatic void 247150599Sobriendisplay_help () 247250599Sobrien{ 247350599Sobrien printf ("Usage: %s [options] file...\n", programname); 247450599Sobrien printf ("Options:\n"); 247550599Sobrien 247650599Sobrien printf (" --help Display this information\n"); 247750599Sobrien if (! verbose_flag) 247850599Sobrien printf (" (Use '-v --help' to display command line options of sub-processes)\n"); 247950599Sobrien printf (" -dumpspecs Display all of the built in spec strings\n"); 248050599Sobrien printf (" -dumpversion Display the version of the compiler\n"); 248150599Sobrien printf (" -dumpmachine Display the compiler's target processor\n"); 248250599Sobrien printf (" -print-search-dirs Display the directories in the compiler's search path\n"); 248350599Sobrien printf (" -print-libgcc-file-name Display the name of the compiler's companion library\n"); 248450599Sobrien printf (" -print-file-name=<lib> Display the full path to library <lib>\n"); 248550599Sobrien printf (" -print-prog-name=<prog> Display the full path to compiler component <prog>\n"); 248650599Sobrien printf (" -print-multi-directory Display the root directory for versions of libgcc\n"); 248750599Sobrien printf (" -print-multi-lib Display the mapping between command line options and\n"); 248850599Sobrien printf (" multiple library search directories\n"); 248950599Sobrien printf (" -Wa,<options> Pass comma-separated <options> on to the assembler\n"); 249050599Sobrien printf (" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"); 249150599Sobrien printf (" -Wl,<options> Pass comma-separated <options> on to the linker\n"); 249250599Sobrien printf (" -Xlinker <arg> Pass <arg> on to the linker\n"); 249350599Sobrien printf (" -save-temps Do not delete intermediate files\n"); 249450599Sobrien printf (" -pipe Use pipes rather than intermediate files\n"); 249550599Sobrien printf (" -specs=<file> Override builtin specs with the contents of <file>\n"); 249652520Sobrien printf (" -std=<standard> Assume that the input sources are for <standard>\n"); 249750599Sobrien printf (" -B <directory> Add <directory> to the compiler's search paths\n"); 249850599Sobrien printf (" -b <machine> Run gcc for target <machine>, if installed\n"); 249950599Sobrien printf (" -V <version> Run gcc version number <version>, if installed\n"); 250050599Sobrien printf (" -v Display the programs invoked by the compiler\n"); 250150599Sobrien printf (" -E Preprocess only; do not compile, assemble or link\n"); 250250599Sobrien printf (" -S Compile only; do not assemble or link\n"); 250350599Sobrien printf (" -c Compile and assemble, but do not link\n"); 250450599Sobrien printf (" -o <file> Place the output into <file>\n"); 250550599Sobrien printf (" -x <language> Specify the language of the following input files\n"); 250650599Sobrien printf (" Permissable languages include: c c++ assembler none\n"); 250750599Sobrien printf (" 'none' means revert to the default behaviour of\n"); 250850599Sobrien printf (" guessing the language based on the file's extension\n"); 250950599Sobrien 251050599Sobrien printf ("\nOptions starting with -g, -f, -m, -O or -W are automatically passed on to\n"); 251150599Sobrien printf ("the various sub-processes invoked by %s. In order to pass other options\n", 251250599Sobrien programname); 251350599Sobrien printf ("on to these processes the -W<letter> options must be used.\n"); 251450599Sobrien 251550599Sobrien /* The rest of the options are displayed by invocations of the various 251650599Sobrien sub-processes. */ 251750599Sobrien} 251850599Sobrien 251950599Sobrienstatic void 252050599Sobrienadd_preprocessor_option (option, len) 252152520Sobrien const char * option; 252252520Sobrien int len; 252350599Sobrien{ 252452520Sobrien n_preprocessor_options++; 252550599Sobrien 252652520Sobrien if (! preprocessor_options) 252752520Sobrien preprocessor_options 252852520Sobrien = (char **) xmalloc (n_preprocessor_options * sizeof (char *)); 252952520Sobrien else 253052520Sobrien preprocessor_options 253152520Sobrien = (char **) xrealloc (preprocessor_options, 253252520Sobrien n_preprocessor_options * sizeof (char *)); 253350599Sobrien 253452520Sobrien preprocessor_options [n_preprocessor_options - 1] = 253552520Sobrien save_string (option, len); 253650599Sobrien} 253750599Sobrien 253850599Sobrienstatic void 253950599Sobrienadd_assembler_option (option, len) 254052520Sobrien const char * option; 254152520Sobrien int len; 254252520Sobrien{ 254352520Sobrien n_assembler_options++; 254452520Sobrien 254552520Sobrien if (! assembler_options) 254652520Sobrien assembler_options 254752520Sobrien = (char **) xmalloc (n_assembler_options * sizeof (char *)); 254852520Sobrien else 254952520Sobrien assembler_options 255052520Sobrien = (char **) xrealloc (assembler_options, 255152520Sobrien n_assembler_options * sizeof (char *)); 255252520Sobrien 255352520Sobrien assembler_options [n_assembler_options - 1] = save_string (option, len); 255450599Sobrien} 255550599Sobrien 255650599Sobrienstatic void 255750599Sobrienadd_linker_option (option, len) 255852520Sobrien const char * option; 255952520Sobrien int len; 256052520Sobrien{ 256152520Sobrien n_linker_options++; 256252520Sobrien 256352520Sobrien if (! linker_options) 256452520Sobrien linker_options 256552520Sobrien = (char **) xmalloc (n_linker_options * sizeof (char *)); 256652520Sobrien else 256752520Sobrien linker_options 256852520Sobrien = (char **) xrealloc (linker_options, 256952520Sobrien n_linker_options * sizeof (char *)); 257052520Sobrien 257152520Sobrien linker_options [n_linker_options - 1] = save_string (option, len); 257250599Sobrien} 257350599Sobrien 257418334Speter/* Create the vector `switches' and its contents. 257518334Speter Store its length in `n_switches'. */ 257618334Speter 257718334Speterstatic void 257818334Speterprocess_command (argc, argv) 257918334Speter int argc; 258018334Speter char **argv; 258118334Speter{ 258218334Speter register int i; 258352520Sobrien const char *temp; 258452520Sobrien char *temp1; 258518334Speter char *spec_lang = 0; 258618334Speter int last_language_n_infiles; 258750599Sobrien int have_c = 0; 258850599Sobrien int have_o = 0; 258950599Sobrien int lang_n_infiles = 0; 259018334Speter 259152520Sobrien GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX"); 259218334Speter 259318334Speter n_switches = 0; 259418334Speter n_infiles = 0; 259550599Sobrien added_libraries = 0; 259618334Speter 259718334Speter /* Figure compiler version from version string. */ 259818334Speter 259952520Sobrien compiler_version = temp1 = 260052520Sobrien save_string (version_string, strlen (version_string)); 260152520Sobrien for (; *temp1; ++temp1) 260218334Speter { 260352520Sobrien if (*temp1 == ' ') 260418334Speter { 260552520Sobrien *temp1 = '\0'; 260618334Speter break; 260718334Speter } 260818334Speter } 260918334Speter 261018334Speter /* Set up the default search paths. */ 261118334Speter 261218334Speter if (gcc_exec_prefix) 261318334Speter { 261450599Sobrien int len = strlen (gcc_exec_prefix); 261552520Sobrien if (len > (int) sizeof ("/lib/gcc-lib/")-1 261652520Sobrien && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1]))) 261750599Sobrien { 261850599Sobrien temp = gcc_exec_prefix + len - sizeof ("/lib/gcc-lib/") + 1; 261952520Sobrien if (IS_DIR_SEPARATOR (*temp) 262050599Sobrien && strncmp (temp+1, "lib", 3) == 0 262152520Sobrien && IS_DIR_SEPARATOR (temp[4]) 262250599Sobrien && strncmp (temp+5, "gcc-lib", 7) == 0) 262350599Sobrien len -= sizeof ("/lib/gcc-lib/") - 1; 262450599Sobrien } 262550599Sobrien 262650599Sobrien set_std_prefix (gcc_exec_prefix, len); 262750599Sobrien add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR); 262850599Sobrien add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR); 262918334Speter } 263018334Speter 263118334Speter /* COMPILER_PATH and LIBRARY_PATH have values 263218334Speter that are lists of directory names with colons. */ 263318334Speter 263452520Sobrien GET_ENV_PATH_LIST (temp, "COMPILER_PATH"); 263518334Speter if (temp) 263618334Speter { 263752520Sobrien const char *startp, *endp; 263818334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 263918334Speter 264018334Speter startp = endp = temp; 264118334Speter while (1) 264218334Speter { 264318334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 264418334Speter { 264518334Speter strncpy (nstore, startp, endp-startp); 264618334Speter if (endp == startp) 264750599Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL_PTR)); 264852520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 264918334Speter { 265018334Speter nstore[endp-startp] = DIR_SEPARATOR; 265118334Speter nstore[endp-startp+1] = 0; 265218334Speter } 265318334Speter else 265418334Speter nstore[endp-startp] = 0; 265550599Sobrien add_prefix (&exec_prefixes, nstore, 0, 0, 0, NULL_PTR); 265650599Sobrien add_prefix (&include_prefixes, 265750599Sobrien concat (nstore, "include", NULL_PTR), 265850599Sobrien 0, 0, 0, NULL_PTR); 265918334Speter if (*endp == 0) 266018334Speter break; 266118334Speter endp = startp = endp + 1; 266218334Speter } 266318334Speter else 266418334Speter endp++; 266518334Speter } 266618334Speter } 266718334Speter 266852520Sobrien GET_ENV_PATH_LIST (temp, "LIBRARY_PATH"); 266955220Sobrien if (temp) 267018334Speter { 267152520Sobrien const char *startp, *endp; 267218334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 267318334Speter 267418334Speter startp = endp = temp; 267518334Speter while (1) 267618334Speter { 267718334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 267818334Speter { 267918334Speter strncpy (nstore, startp, endp-startp); 268018334Speter if (endp == startp) 268150599Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL_PTR)); 268252520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 268318334Speter { 268418334Speter nstore[endp-startp] = DIR_SEPARATOR; 268518334Speter nstore[endp-startp+1] = 0; 268618334Speter } 268718334Speter else 268818334Speter nstore[endp-startp] = 0; 268950599Sobrien add_prefix (&startfile_prefixes, nstore, NULL_PTR, 269050599Sobrien 0, 0, NULL_PTR); 269118334Speter if (*endp == 0) 269218334Speter break; 269318334Speter endp = startp = endp + 1; 269418334Speter } 269518334Speter else 269618334Speter endp++; 269718334Speter } 269818334Speter } 269918334Speter 270018334Speter /* Use LPATH like LIBRARY_PATH (for the CMU build program). */ 270152520Sobrien GET_ENV_PATH_LIST (temp, "LPATH"); 270250599Sobrien if (temp && *cross_compile == '0') 270318334Speter { 270452520Sobrien const char *startp, *endp; 270518334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 270618334Speter 270718334Speter startp = endp = temp; 270818334Speter while (1) 270918334Speter { 271018334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 271118334Speter { 271218334Speter strncpy (nstore, startp, endp-startp); 271318334Speter if (endp == startp) 271450599Sobrien strcpy (nstore, concat (".", dir_separator_str, NULL_PTR)); 271552520Sobrien else if (!IS_DIR_SEPARATOR (endp[-1])) 271618334Speter { 271718334Speter nstore[endp-startp] = DIR_SEPARATOR; 271818334Speter nstore[endp-startp+1] = 0; 271918334Speter } 272018334Speter else 272118334Speter nstore[endp-startp] = 0; 272250599Sobrien add_prefix (&startfile_prefixes, nstore, NULL_PTR, 272350599Sobrien 0, 0, NULL_PTR); 272418334Speter if (*endp == 0) 272518334Speter break; 272618334Speter endp = startp = endp + 1; 272718334Speter } 272818334Speter else 272918334Speter endp++; 273018334Speter } 273118334Speter } 273218334Speter 273353878Sobrien#if defined(FREEBSD_NATIVE) 273434229Speter { 273553878Sobrien char buf[64]; 273653878Sobrien if (getobjformat (buf, sizeof buf, &argc, argv)) 273753878Sobrien if (strcmp (buf, "aout") == 0) 273853878Sobrien objformat = OBJFMT_AOUT; 273953878Sobrien else if (strcmp (buf, "elf") == 0) 274053878Sobrien objformat = OBJFMT_ELF; 274134229Speter else 274253878Sobrien fprintf(stderr, "Unrecognized object format: %s\n", buf); 274334229Speter } 274434229Speter#endif 274550599Sobrien 274618334Speter /* Convert new-style -- options to old-style. */ 274718334Speter translate_options (&argc, &argv); 274818334Speter 274950599Sobrien /* Do language-specific adjustment/addition of flags. */ 275050599Sobrien lang_specific_driver (fatal, &argc, &argv, &added_libraries); 275150599Sobrien 275218334Speter /* Scan argv twice. Here, the first time, just count how many switches 275318334Speter there will be in their vector, and how many input files in theirs. 275418334Speter Here we also parse the switches that cc itself uses (e.g. -v). */ 275518334Speter 275618334Speter for (i = 1; i < argc; i++) 275718334Speter { 275818334Speter if (! strcmp (argv[i], "-dumpspecs")) 275918334Speter { 276050599Sobrien struct spec_list *sl; 276150599Sobrien init_spec (); 276250599Sobrien for (sl = specs; sl; sl = sl->next) 276350599Sobrien printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec)); 276452520Sobrien if (link_command_spec) 276552520Sobrien printf ("*link_command:\n%s\n\n", link_command_spec); 276618334Speter exit (0); 276718334Speter } 276818334Speter else if (! strcmp (argv[i], "-dumpversion")) 276918334Speter { 277050599Sobrien printf ("%s\n", spec_version); 277118334Speter exit (0); 277218334Speter } 277318334Speter else if (! strcmp (argv[i], "-dumpmachine")) 277418334Speter { 277518334Speter printf ("%s\n", spec_machine); 277618334Speter exit (0); 277718334Speter } 277850599Sobrien else if (strcmp (argv[i], "-fhelp") == 0) 277950599Sobrien { 278050599Sobrien /* translate_options () has turned --help into -fhelp. */ 278150599Sobrien print_help_list = 1; 278250599Sobrien 278350599Sobrien /* We will be passing a dummy file on to the sub-processes. */ 278450599Sobrien n_infiles++; 278550599Sobrien n_switches++; 278650599Sobrien 278750599Sobrien add_preprocessor_option ("--help", 6); 278850599Sobrien add_assembler_option ("--help", 6); 278950599Sobrien add_linker_option ("--help", 6); 279050599Sobrien } 279118334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 279218334Speter print_search_dirs = 1; 279318334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 279418334Speter print_file_name = "libgcc.a"; 279518334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 279618334Speter print_file_name = argv[i] + 17; 279718334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 279818334Speter print_prog_name = argv[i] + 17; 279918334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 280018334Speter print_multi_lib = 1; 280118334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 280218334Speter print_multi_directory = 1; 280318334Speter else if (! strncmp (argv[i], "-Wa,", 4)) 280418334Speter { 280518334Speter int prev, j; 280618334Speter /* Pass the rest of this option to the assembler. */ 280718334Speter 280818334Speter /* Split the argument at commas. */ 280918334Speter prev = 4; 281018334Speter for (j = 4; argv[i][j]; j++) 281118334Speter if (argv[i][j] == ',') 281218334Speter { 281350599Sobrien add_assembler_option (argv[i] + prev, j - prev); 281418334Speter prev = j + 1; 281518334Speter } 281650599Sobrien 281718334Speter /* Record the part after the last comma. */ 281850599Sobrien add_assembler_option (argv[i] + prev, j - prev); 281918334Speter } 282018334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 282118334Speter { 282218334Speter int prev, j; 282318334Speter /* Pass the rest of this option to the preprocessor. */ 282418334Speter 282518334Speter /* Split the argument at commas. */ 282618334Speter prev = 4; 282718334Speter for (j = 4; argv[i][j]; j++) 282818334Speter if (argv[i][j] == ',') 282918334Speter { 283050599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 283118334Speter prev = j + 1; 283218334Speter } 283350599Sobrien 283418334Speter /* Record the part after the last comma. */ 283550599Sobrien add_preprocessor_option (argv[i] + prev, j - prev); 283618334Speter } 283718334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 283818334Speter /* The +e options to the C++ front-end. */ 283918334Speter n_switches++; 284018334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 284118334Speter { 284218334Speter int j; 284318334Speter /* Split the argument at commas. */ 284418334Speter for (j = 3; argv[i][j]; j++) 284518334Speter n_infiles += (argv[i][j] == ','); 284618334Speter } 284718334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 284818334Speter { 284918334Speter if (i + 1 == argc) 285018334Speter fatal ("argument to `-Xlinker' is missing"); 285118334Speter 285218334Speter n_infiles++; 285318334Speter i++; 285418334Speter } 285518334Speter else if (strncmp (argv[i], "-l", 2) == 0) 285618334Speter n_infiles++; 285750599Sobrien else if (strcmp (argv[i], "-save-temps") == 0) 285850599Sobrien { 285950599Sobrien save_temps_flag = 1; 286050599Sobrien n_switches++; 286150599Sobrien } 286250599Sobrien else if (strcmp (argv[i], "-specs") == 0) 286350599Sobrien { 286450599Sobrien struct user_specs *user = (struct user_specs *) 286550599Sobrien xmalloc (sizeof (struct user_specs)); 286650599Sobrien if (++i >= argc) 286750599Sobrien fatal ("argument to `-specs' is missing"); 286850599Sobrien 286950599Sobrien user->next = (struct user_specs *)0; 287050599Sobrien user->filename = argv[i]; 287150599Sobrien if (user_specs_tail) 287250599Sobrien user_specs_tail->next = user; 287350599Sobrien else 287450599Sobrien user_specs_head = user; 287550599Sobrien user_specs_tail = user; 287650599Sobrien } 287750599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 287850599Sobrien { 287950599Sobrien struct user_specs *user = (struct user_specs *) 288050599Sobrien xmalloc (sizeof (struct user_specs)); 288150599Sobrien if (strlen (argv[i]) == 7) 288250599Sobrien fatal ("argument to `-specs=' is missing"); 288350599Sobrien 288450599Sobrien user->next = (struct user_specs *)0; 288550599Sobrien user->filename = argv[i]+7; 288650599Sobrien if (user_specs_tail) 288750599Sobrien user_specs_tail->next = user; 288850599Sobrien else 288950599Sobrien user_specs_head = user; 289050599Sobrien user_specs_tail = user; 289150599Sobrien } 289218334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 289318334Speter { 289418334Speter register char *p = &argv[i][1]; 289518334Speter register int c = *p; 289618334Speter 289718334Speter switch (c) 289818334Speter { 289918334Speter case 'b': 290050599Sobrien n_switches++; 290118334Speter if (p[1] == 0 && i + 1 == argc) 290218334Speter fatal ("argument to `-b' is missing"); 290318334Speter if (p[1] == 0) 290418334Speter spec_machine = argv[++i]; 290518334Speter else 290618334Speter spec_machine = p + 1; 290750599Sobrien 290850599Sobrien warn_std_ptr = &warn_std; 290918334Speter break; 291018334Speter 291118334Speter case 'B': 291218334Speter { 291318334Speter char *value; 291418334Speter if (p[1] == 0 && i + 1 == argc) 291518334Speter fatal ("argument to `-B' is missing"); 291618334Speter if (p[1] == 0) 291718334Speter value = argv[++i]; 291818334Speter else 291918334Speter value = p + 1; 292050599Sobrien add_prefix (&exec_prefixes, value, NULL_PTR, 1, 0, &warn_B); 292150599Sobrien add_prefix (&startfile_prefixes, value, NULL_PTR, 292250599Sobrien 1, 0, &warn_B); 292350599Sobrien add_prefix (&include_prefixes, concat (value, "include", 292450599Sobrien NULL_PTR), 292550599Sobrien NULL_PTR, 1, 0, NULL_PTR); 292618334Speter 292718334Speter /* As a kludge, if the arg is "[foo/]stageN/", just add 292818334Speter "[foo/]include" to the include prefix. */ 292918334Speter { 293018334Speter int len = strlen (value); 293118334Speter if ((len == 7 293218334Speter || (len > 7 293352520Sobrien && (IS_DIR_SEPARATOR (value[len - 8])))) 293418334Speter && strncmp (value + len - 7, "stage", 5) == 0 293550599Sobrien && ISDIGIT (value[len - 2]) 293652520Sobrien && (IS_DIR_SEPARATOR (value[len - 1]))) 293718334Speter { 293818334Speter if (len == 7) 293950599Sobrien add_prefix (&include_prefixes, "include", NULL_PTR, 294050599Sobrien 1, 0, NULL_PTR); 294118334Speter else 294218334Speter { 294318334Speter char *string = xmalloc (len + 1); 294418334Speter strncpy (string, value, len-7); 294550599Sobrien strcpy (string+len-7, "include"); 294650599Sobrien add_prefix (&include_prefixes, string, NULL_PTR, 294750599Sobrien 1, 0, NULL_PTR); 294818334Speter } 294918334Speter } 295018334Speter } 295150599Sobrien n_switches++; 295218334Speter } 295318334Speter break; 295418334Speter 295518334Speter case 'v': /* Print our subcommands and print versions. */ 295618334Speter n_switches++; 295718334Speter /* If they do anything other than exactly `-v', don't set 295818334Speter verbose_flag; rather, continue on to give the error. */ 295918334Speter if (p[1] != 0) 296018334Speter break; 296118334Speter verbose_flag++; 296218334Speter break; 296318334Speter 296418334Speter case 'V': 296550599Sobrien n_switches++; 296618334Speter if (p[1] == 0 && i + 1 == argc) 296718334Speter fatal ("argument to `-V' is missing"); 296818334Speter if (p[1] == 0) 296918334Speter spec_version = argv[++i]; 297018334Speter else 297118334Speter spec_version = p + 1; 297218334Speter compiler_version = spec_version; 297350599Sobrien warn_std_ptr = &warn_std; 297450599Sobrien 297550599Sobrien /* Validate the version number. Use the same checks 297650599Sobrien done when inserting it into a spec. 297750599Sobrien 297850599Sobrien The format of the version string is 297950599Sobrien ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */ 298050599Sobrien { 298152520Sobrien const char *v = compiler_version; 298250599Sobrien 298350599Sobrien /* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */ 298450599Sobrien while (! ISDIGIT (*v)) 298550599Sobrien v++; 298650599Sobrien 298750599Sobrien if (v > compiler_version && v[-1] != '-') 298850599Sobrien fatal ("invalid version number format"); 298950599Sobrien 299050599Sobrien /* Set V after the first period. */ 299150599Sobrien while (ISDIGIT (*v)) 299250599Sobrien v++; 299350599Sobrien 299450599Sobrien if (*v != '.') 299550599Sobrien fatal ("invalid version number format"); 299650599Sobrien 299750599Sobrien v++; 299850599Sobrien while (ISDIGIT (*v)) 299950599Sobrien v++; 300050599Sobrien 300150599Sobrien if (*v != 0 && *v != ' ' && *v != '.' && *v != '-') 300250599Sobrien fatal ("invalid version number format"); 300350599Sobrien } 300418334Speter break; 300518334Speter 300650599Sobrien case 'S': 300750599Sobrien case 'c': 300850599Sobrien if (p[1] == 0) 300918334Speter { 301050599Sobrien have_c = 1; 301118334Speter n_switches++; 301218334Speter break; 301318334Speter } 301450599Sobrien goto normal_switch; 301550599Sobrien 301650599Sobrien case 'o': 301750599Sobrien have_o = 1; 301850599Sobrien#if defined(HAVE_EXECUTABLE_SUFFIX) 301950599Sobrien if (! have_c) 302050599Sobrien { 302150599Sobrien int skip; 302250599Sobrien 302350599Sobrien /* Forward scan, just in case -S or -c is specified 302450599Sobrien after -o. */ 302550599Sobrien int j = i + 1; 302650599Sobrien if (p[1] == 0) 302750599Sobrien ++j; 302850599Sobrien while (j < argc) 302950599Sobrien { 303050599Sobrien if (argv[j][0] == '-') 303150599Sobrien { 303250599Sobrien if (SWITCH_CURTAILS_COMPILATION (argv[j][1]) 303350599Sobrien && argv[j][2] == 0) 303450599Sobrien { 303550599Sobrien have_c = 1; 303650599Sobrien break; 303750599Sobrien } 303850599Sobrien else if (skip = SWITCH_TAKES_ARG (argv[j][1])) 303950599Sobrien j += skip - (argv[j][2] != 0); 304050599Sobrien else if (skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1)) 304150599Sobrien j += skip; 304250599Sobrien } 304350599Sobrien j++; 304450599Sobrien } 304550599Sobrien } 304650599Sobrien#endif 304750599Sobrien#if defined(HAVE_EXECUTABLE_SUFFIX) || defined(HAVE_OBJECT_SUFFIX) 304850599Sobrien if (p[1] == 0) 304950599Sobrien argv[i+1] = convert_filename (argv[i+1], ! have_c); 305050599Sobrien else 305150599Sobrien argv[i] = convert_filename (argv[i], ! have_c); 305250599Sobrien#endif 305350599Sobrien goto normal_switch; 305450599Sobrien 305518334Speter default: 305650599Sobrien normal_switch: 305718334Speter n_switches++; 305818334Speter 305918334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 306018334Speter i += SWITCH_TAKES_ARG (c) - (p[1] != 0); 306118334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 306218334Speter i += WORD_SWITCH_TAKES_ARG (p); 306318334Speter } 306418334Speter } 306518334Speter else 306650599Sobrien { 306750599Sobrien n_infiles++; 306850599Sobrien lang_n_infiles++; 306950599Sobrien } 307018334Speter } 307118334Speter 307250599Sobrien if (have_c && have_o && lang_n_infiles > 1) 307350599Sobrien fatal ("cannot specify -o with -c or -S and multiple compilations"); 307450599Sobrien 307518334Speter /* Set up the search paths before we go looking for config files. */ 307618334Speter 307718334Speter /* These come before the md prefixes so that we will find gcc's subcommands 307818334Speter (such as cpp) rather than those of the host system. */ 307918334Speter /* Use 2 as fourth arg meaning try just the machine as a suffix, 308018334Speter as well as trying the machine and the version. */ 308118346Speter#ifdef FREEBSD_NATIVE 308253878Sobrien switch (objformat) 308353878Sobrien { 308453878Sobrien case OBJFMT_AOUT: 308553878Sobrien n_switches++; /* add implied -maout */ 308655220Sobrien add_prefix (&exec_prefixes, PREFIX"/libexec/aout/", "BINUTILS", 308753878Sobrien 0, 0, NULL_PTR); 308853878Sobrien break; 308953878Sobrien case OBJFMT_ELF: 309055220Sobrien add_prefix (&exec_prefixes, PREFIX"/libexec/elf/", "BINUTILS", 309153878Sobrien 0, 0, NULL_PTR); 309253878Sobrien break; 309354778Sobrien case OBJFMT_UNKNOWN: 309454778Sobrien fatal ("object format unknown"); 309553878Sobrien } 309618346Speter#else /* not FREEBSD_NATIVE */ 309718334Speter#ifndef OS2 309850599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", 309950599Sobrien 0, 2, warn_std_ptr); 310050599Sobrien add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS", 310150599Sobrien 0, 2, warn_std_ptr); 310218334Speter#endif 310318334Speter 310450599Sobrien add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", 310550599Sobrien 0, 1, warn_std_ptr); 310650599Sobrien add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS", 310750599Sobrien 0, 1, warn_std_ptr); 310818346Speter#endif /* FREEBSD_NATIVE */ 310918334Speter 311050599Sobrien tooldir_prefix = concat (tooldir_base_prefix, spec_machine, 311150599Sobrien dir_separator_str, NULL_PTR); 311218334Speter 311318334Speter /* If tooldir is relative, base it on exec_prefixes. A relative 311418334Speter tooldir lets us move the installed tree as a unit. 311518334Speter 311618334Speter If GCC_EXEC_PREFIX is defined, then we want to add two relative 311718334Speter directories, so that we can search both the user specified directory 311818334Speter and the standard place. */ 311918334Speter 312052520Sobrien if (!IS_DIR_SEPARATOR (*tooldir_prefix)) 312118334Speter { 312218334Speter if (gcc_exec_prefix) 312318334Speter { 312418334Speter char *gcc_exec_tooldir_prefix 312550599Sobrien = concat (gcc_exec_prefix, spec_machine, dir_separator_str, 312650599Sobrien spec_version, dir_separator_str, tooldir_prefix, NULL_PTR); 312718334Speter 312818334Speter add_prefix (&exec_prefixes, 312950599Sobrien concat (gcc_exec_tooldir_prefix, "bin", 313050599Sobrien dir_separator_str, NULL_PTR), 313150599Sobrien NULL_PTR, 0, 0, NULL_PTR); 313218334Speter add_prefix (&startfile_prefixes, 313350599Sobrien concat (gcc_exec_tooldir_prefix, "lib", 313450599Sobrien dir_separator_str, NULL_PTR), 313550599Sobrien NULL_PTR, 0, 0, NULL_PTR); 313618334Speter } 313718334Speter 313850599Sobrien tooldir_prefix = concat (standard_exec_prefix, spec_machine, 313950599Sobrien dir_separator_str, spec_version, 314050599Sobrien dir_separator_str, tooldir_prefix, NULL_PTR); 314118334Speter } 314218334Speter 314318346Speter#ifndef FREEBSD_NATIVE 314418334Speter add_prefix (&exec_prefixes, 314550599Sobrien concat (tooldir_prefix, "bin", dir_separator_str, NULL_PTR), 314650599Sobrien "BINUTILS", 0, 0, NULL_PTR); 314718334Speter add_prefix (&startfile_prefixes, 314850599Sobrien concat (tooldir_prefix, "lib", dir_separator_str, NULL_PTR), 314950599Sobrien "BINUTILS", 0, 0, NULL_PTR); 315018346Speter#endif /* FREEBSD_NATIVE */ 315118334Speter 315218334Speter /* More prefixes are enabled in main, after we read the specs file 315318334Speter and determine whether this is cross-compilation or not. */ 315418334Speter 315518334Speter 315618334Speter /* Then create the space for the vectors and scan again. */ 315718334Speter 315818334Speter switches = ((struct switchstr *) 315918334Speter xmalloc ((n_switches + 1) * sizeof (struct switchstr))); 316018334Speter infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile)); 316118334Speter n_switches = 0; 316218334Speter n_infiles = 0; 316318334Speter last_language_n_infiles = -1; 316418334Speter 316518334Speter /* This, time, copy the text of each switch and store a pointer 316618334Speter to the copy in the vector of switches. 316718334Speter Store all the infiles in their vector. */ 316818334Speter 316953878Sobrien#if defined(FREEBSD_NATIVE) 317053878Sobrien switch (objformat) 317153878Sobrien { 317253878Sobrien case OBJFMT_AOUT: 317353878Sobrien switches[n_switches].part1 = "maout"; 317453878Sobrien switches[n_switches].args = 0; 317553878Sobrien switches[n_switches].live_cond = 0; 317653878Sobrien switches[n_switches].validated = 0; 317753878Sobrien n_switches++; 317853878Sobrien putenv("OBJFORMAT=aout"); 317953878Sobrien break; 318053878Sobrien case OBJFMT_ELF: 318153878Sobrien putenv("OBJFORMAT=elf"); 318253878Sobrien break; 318354778Sobrien case OBJFMT_UNKNOWN: 318454778Sobrien fatal ("object format unknown"); 318553878Sobrien } 318634229Speter#endif 318734229Speter 318818334Speter for (i = 1; i < argc; i++) 318918334Speter { 319018334Speter /* Just skip the switches that were handled by the preceding loop. */ 319118334Speter if (! strncmp (argv[i], "-Wa,", 4)) 319218334Speter ; 319318334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 319418334Speter ; 319518334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 319618334Speter ; 319718334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 319818334Speter ; 319918334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 320018334Speter ; 320118334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 320218334Speter ; 320318334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 320418334Speter ; 320518334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 320618334Speter ; 320750599Sobrien else if (strcmp (argv[i], "-fhelp") == 0) 320850599Sobrien { 320950599Sobrien if (verbose_flag) 321050599Sobrien { 321150599Sobrien /* Create a dummy input file, so that we can pass --help on to 321250599Sobrien the various sub-processes. */ 321350599Sobrien infiles[n_infiles].language = "c"; 321450599Sobrien infiles[n_infiles++].name = "help-dummy"; 321550599Sobrien 321650599Sobrien /* Preserve the --help switch so that it can be caught by the 321750599Sobrien cc1 spec string. */ 321850599Sobrien switches[n_switches].part1 = "--help"; 321950599Sobrien switches[n_switches].args = 0; 322050599Sobrien switches[n_switches].live_cond = 0; 322152520Sobrien switches[n_switches].validated = 0; 322250599Sobrien 322350599Sobrien n_switches++; 322450599Sobrien } 322550599Sobrien } 322618334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 322718334Speter { 322818334Speter /* Compensate for the +e options to the C++ front-end; 322918334Speter they're there simply for cfront call-compatibility. We do 323018334Speter some magic in default_compilers to pass them down properly. 323118334Speter Note we deliberately start at the `+' here, to avoid passing 323218334Speter -e0 or -e1 down into the linker. */ 323318334Speter switches[n_switches].part1 = &argv[i][0]; 323418334Speter switches[n_switches].args = 0; 323518334Speter switches[n_switches].live_cond = 0; 323652520Sobrien switches[n_switches].validated = 0; 323718334Speter n_switches++; 323818334Speter } 323918334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 324018334Speter { 324118334Speter int prev, j; 324218334Speter /* Split the argument at commas. */ 324318334Speter prev = 4; 324418334Speter for (j = 4; argv[i][j]; j++) 324518334Speter if (argv[i][j] == ',') 324618334Speter { 324750599Sobrien infiles[n_infiles].language = "*"; 324818334Speter infiles[n_infiles++].name 324918334Speter = save_string (argv[i] + prev, j - prev); 325018334Speter prev = j + 1; 325118334Speter } 325218334Speter /* Record the part after the last comma. */ 325350599Sobrien infiles[n_infiles].language = "*"; 325418334Speter infiles[n_infiles++].name = argv[i] + prev; 325518334Speter } 325618334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 325718334Speter { 325850599Sobrien infiles[n_infiles].language = "*"; 325918334Speter infiles[n_infiles++].name = argv[++i]; 326018334Speter } 326118334Speter else if (strncmp (argv[i], "-l", 2) == 0) 326218334Speter { 326350599Sobrien infiles[n_infiles].language = "*"; 326418334Speter infiles[n_infiles++].name = argv[i]; 326518334Speter } 326650599Sobrien else if (strcmp (argv[i], "-specs") == 0) 326750599Sobrien i++; 326850599Sobrien else if (strncmp (argv[i], "-specs=", 7) == 0) 326950599Sobrien ; 327050599Sobrien /* -save-temps overrides -pipe, so that temp files are produced */ 327150599Sobrien else if (save_temps_flag && strcmp (argv[i], "-pipe") == 0) 327250599Sobrien error ("Warning: -pipe ignored since -save-temps specified"); 327318334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 327418334Speter { 327518334Speter register char *p = &argv[i][1]; 327618334Speter register int c = *p; 327718334Speter 327818334Speter if (c == 'x') 327918334Speter { 328018334Speter if (p[1] == 0 && i + 1 == argc) 328118334Speter fatal ("argument to `-x' is missing"); 328218334Speter if (p[1] == 0) 328318334Speter spec_lang = argv[++i]; 328418334Speter else 328518334Speter spec_lang = p + 1; 328618334Speter if (! strcmp (spec_lang, "none")) 328718334Speter /* Suppress the warning if -xnone comes after the last input 328818334Speter file, because alternate command interfaces like g++ might 328918334Speter find it useful to place -xnone after each input file. */ 329018334Speter spec_lang = 0; 329118334Speter else 329218334Speter last_language_n_infiles = n_infiles; 329318334Speter continue; 329418334Speter } 329518334Speter switches[n_switches].part1 = p; 329618334Speter /* Deal with option arguments in separate argv elements. */ 329718334Speter if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) 329818334Speter || WORD_SWITCH_TAKES_ARG (p)) 329918334Speter { 330018334Speter int j = 0; 330118334Speter int n_args = WORD_SWITCH_TAKES_ARG (p); 330218334Speter 330318334Speter if (n_args == 0) 330418334Speter { 330518334Speter /* Count only the option arguments in separate argv elements. */ 330618334Speter n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); 330718334Speter } 330818334Speter if (i + n_args >= argc) 330918334Speter fatal ("argument to `-%s' is missing", p); 331018334Speter switches[n_switches].args 331118334Speter = (char **) xmalloc ((n_args + 1) * sizeof (char *)); 331218334Speter while (j < n_args) 331318334Speter switches[n_switches].args[j++] = argv[++i]; 331418334Speter /* Null-terminate the vector. */ 331518334Speter switches[n_switches].args[j] = 0; 331618334Speter } 331750599Sobrien else if (index (switches_need_spaces, c)) 331818334Speter { 331950599Sobrien /* On some systems, ld cannot handle some options without 332050599Sobrien a space. So split the option from its argument. */ 332150599Sobrien char *part1 = (char *) xmalloc (2); 332250599Sobrien part1[0] = c; 332350599Sobrien part1[1] = '\0'; 332450599Sobrien 332550599Sobrien switches[n_switches].part1 = part1; 332618334Speter switches[n_switches].args = (char **) xmalloc (2 * sizeof (char *)); 332718334Speter switches[n_switches].args[0] = xmalloc (strlen (p)); 332818334Speter strcpy (switches[n_switches].args[0], &p[1]); 332918334Speter switches[n_switches].args[1] = 0; 333018334Speter } 333118334Speter else 333218334Speter switches[n_switches].args = 0; 333318334Speter 333418334Speter switches[n_switches].live_cond = 0; 333552520Sobrien switches[n_switches].validated = 0; 333618334Speter /* This is always valid, since gcc.c itself understands it. */ 333718334Speter if (!strcmp (p, "save-temps")) 333852520Sobrien switches[n_switches].validated = 1; 333950599Sobrien else 334050599Sobrien { 334150599Sobrien char ch = switches[n_switches].part1[0]; 334250599Sobrien if (ch == 'V' || ch == 'b' || ch == 'B') 334352520Sobrien switches[n_switches].validated = 1; 334450599Sobrien } 334518334Speter n_switches++; 334618334Speter } 334718334Speter else 334818334Speter { 334918334Speter#ifdef HAVE_OBJECT_SUFFIX 335050599Sobrien argv[i] = convert_filename (argv[i], 0); 335118334Speter#endif 335218334Speter 335318334Speter if (strcmp (argv[i], "-") != 0 && access (argv[i], R_OK) < 0) 335418334Speter { 335518334Speter perror_with_name (argv[i]); 335618334Speter error_count++; 335718334Speter } 335818334Speter else 335918334Speter { 336018334Speter infiles[n_infiles].language = spec_lang; 336118334Speter infiles[n_infiles++].name = argv[i]; 336218334Speter } 336318334Speter } 336418334Speter } 336518334Speter 336618334Speter if (n_infiles == last_language_n_infiles && spec_lang != 0) 336718334Speter error ("Warning: `-x %s' after last input file has no effect", spec_lang); 336818334Speter 336918334Speter switches[n_switches].part1 = 0; 337018334Speter infiles[n_infiles].name = 0; 337118334Speter} 337218334Speter 337318334Speter/* Process a spec string, accumulating and running commands. */ 337418334Speter 337518334Speter/* These variables describe the input file name. 337618334Speter input_file_number is the index on outfiles of this file, 337718334Speter so that the output file name can be stored for later use by %o. 337818334Speter input_basename is the start of the part of the input file 337918334Speter sans all directory names, and basename_length is the number 338018334Speter of characters starting there excluding the suffix .c or whatever. */ 338118334Speter 338252520Sobrienconst char *input_filename; 338318334Speterstatic int input_file_number; 338450599Sobriensize_t input_filename_length; 338518334Speterstatic int basename_length; 338652520Sobrienstatic const char *input_basename; 338752520Sobrienstatic const char *input_suffix; 338818334Speter 338918334Speter/* These are variables used within do_spec and do_spec_1. */ 339018334Speter 339118334Speter/* Nonzero if an arg has been started and not yet terminated 339218334Speter (with space, tab or newline). */ 339318334Speterstatic int arg_going; 339418334Speter 339518334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated 339618334Speter is a temporary file name. */ 339718334Speterstatic int delete_this_arg; 339818334Speter 339918334Speter/* Nonzero means %w has been seen; the next arg to be terminated 340018334Speter is the output file name of this compilation. */ 340118334Speterstatic int this_is_output_file; 340218334Speter 340318334Speter/* Nonzero means %s has been seen; the next arg to be terminated 340418334Speter is the name of a library file and we should try the standard 340518334Speter search dirs for it. */ 340618334Speterstatic int this_is_library_file; 340718334Speter 340818334Speter/* Nonzero means that the input of this command is coming from a pipe. */ 340918334Speterstatic int input_from_pipe; 341018334Speter 341118334Speter/* Process the spec SPEC and run the commands specified therein. 341218334Speter Returns 0 if the spec is successfully processed; -1 if failed. */ 341318334Speter 341450599Sobrienint 341518334Speterdo_spec (spec) 341652520Sobrien const char *spec; 341718334Speter{ 341818334Speter int value; 341918334Speter 342018334Speter clear_args (); 342118334Speter arg_going = 0; 342218334Speter delete_this_arg = 0; 342318334Speter this_is_output_file = 0; 342418334Speter this_is_library_file = 0; 342518334Speter input_from_pipe = 0; 342618334Speter 342718334Speter value = do_spec_1 (spec, 0, NULL_PTR); 342818334Speter 342918334Speter /* Force out any unfinished command. 343018334Speter If -pipe, this forces out the last command if it ended in `|'. */ 343118334Speter if (value == 0) 343218334Speter { 343318334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 343418334Speter argbuf_index--; 343518334Speter 343618334Speter if (argbuf_index > 0) 343718334Speter value = execute (); 343818334Speter } 343918334Speter 344018334Speter return value; 344118334Speter} 344218334Speter 344318334Speter/* Process the sub-spec SPEC as a portion of a larger spec. 344418334Speter This is like processing a whole spec except that we do 344518334Speter not initialize at the beginning and we do not supply a 344618334Speter newline by default at the end. 344718334Speter INSWITCH nonzero means don't process %-sequences in SPEC; 344818334Speter in this case, % is treated as an ordinary character. 344918334Speter This is used while substituting switches. 345018334Speter INSWITCH nonzero also causes SPC not to terminate an argument. 345118334Speter 345218334Speter Value is zero unless a line was finished 345318334Speter and the command on that line reported an error. */ 345418334Speter 345518334Speterstatic int 345618334Speterdo_spec_1 (spec, inswitch, soft_matched_part) 345752520Sobrien const char *spec; 345818334Speter int inswitch; 345952520Sobrien const char *soft_matched_part; 346018334Speter{ 346152520Sobrien register const char *p = spec; 346218334Speter register int c; 346318334Speter int i; 346452520Sobrien const char *string; 346518334Speter int value; 346618334Speter 346750599Sobrien while ((c = *p++)) 346818334Speter /* If substituting a switch, treat all chars like letters. 346918334Speter Otherwise, NL, SPC, TAB and % are special. */ 347018334Speter switch (inswitch ? 'a' : c) 347118334Speter { 347218334Speter case '\n': 347318334Speter /* End of line: finish any pending argument, 347418334Speter then run the pending command if one has been started. */ 347518334Speter if (arg_going) 347618334Speter { 347718334Speter obstack_1grow (&obstack, 0); 347818334Speter string = obstack_finish (&obstack); 347918334Speter if (this_is_library_file) 348018334Speter string = find_file (string); 348118334Speter store_arg (string, delete_this_arg, this_is_output_file); 348218334Speter if (this_is_output_file) 348318334Speter outfiles[input_file_number] = string; 348418334Speter } 348518334Speter arg_going = 0; 348618334Speter 348718334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 348818334Speter { 348918334Speter for (i = 0; i < n_switches; i++) 349018334Speter if (!strcmp (switches[i].part1, "pipe")) 349118334Speter break; 349218334Speter 349318334Speter /* A `|' before the newline means use a pipe here, 349418334Speter but only if -pipe was specified. 349518334Speter Otherwise, execute now and don't pass the `|' as an arg. */ 349618334Speter if (i < n_switches) 349718334Speter { 349818334Speter input_from_pipe = 1; 349952520Sobrien switches[i].validated = 1; 350018334Speter break; 350118334Speter } 350218334Speter else 350318334Speter argbuf_index--; 350418334Speter } 350518334Speter 350618334Speter if (argbuf_index > 0) 350718334Speter { 350818334Speter value = execute (); 350918334Speter if (value) 351018334Speter return value; 351118334Speter } 351218334Speter /* Reinitialize for a new command, and for a new argument. */ 351318334Speter clear_args (); 351418334Speter arg_going = 0; 351518334Speter delete_this_arg = 0; 351618334Speter this_is_output_file = 0; 351718334Speter this_is_library_file = 0; 351818334Speter input_from_pipe = 0; 351918334Speter break; 352018334Speter 352118334Speter case '|': 352218334Speter /* End any pending argument. */ 352318334Speter if (arg_going) 352418334Speter { 352518334Speter obstack_1grow (&obstack, 0); 352618334Speter string = obstack_finish (&obstack); 352718334Speter if (this_is_library_file) 352818334Speter string = find_file (string); 352918334Speter store_arg (string, delete_this_arg, this_is_output_file); 353018334Speter if (this_is_output_file) 353118334Speter outfiles[input_file_number] = string; 353218334Speter } 353318334Speter 353418334Speter /* Use pipe */ 353518334Speter obstack_1grow (&obstack, c); 353618334Speter arg_going = 1; 353718334Speter break; 353818334Speter 353918334Speter case '\t': 354018334Speter case ' ': 354118334Speter /* Space or tab ends an argument if one is pending. */ 354218334Speter if (arg_going) 354318334Speter { 354418334Speter obstack_1grow (&obstack, 0); 354518334Speter string = obstack_finish (&obstack); 354618334Speter if (this_is_library_file) 354718334Speter string = find_file (string); 354818334Speter store_arg (string, delete_this_arg, this_is_output_file); 354918334Speter if (this_is_output_file) 355018334Speter outfiles[input_file_number] = string; 355118334Speter } 355218334Speter /* Reinitialize for a new argument. */ 355318334Speter arg_going = 0; 355418334Speter delete_this_arg = 0; 355518334Speter this_is_output_file = 0; 355618334Speter this_is_library_file = 0; 355718334Speter break; 355818334Speter 355918334Speter case '%': 356018334Speter switch (c = *p++) 356118334Speter { 356218334Speter case 0: 356318334Speter fatal ("Invalid specification! Bug in cc."); 356418334Speter 356518334Speter case 'b': 356618334Speter obstack_grow (&obstack, input_basename, basename_length); 356718334Speter arg_going = 1; 356818334Speter break; 356918334Speter 357018334Speter case 'd': 357118334Speter delete_this_arg = 2; 357218334Speter break; 357318334Speter 357418334Speter /* Dump out the directories specified with LIBRARY_PATH, 357518334Speter followed by the absolute directories 357618334Speter that we search for startfiles. */ 357718334Speter case 'D': 357818334Speter { 357918334Speter struct prefix_list *pl = startfile_prefixes.plist; 358050599Sobrien size_t bufsize = 100; 358118334Speter char *buffer = (char *) xmalloc (bufsize); 358218334Speter int idx; 358318334Speter 358418334Speter for (; pl; pl = pl->next) 358518334Speter { 358618334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR 358718334Speter /* Used on systems which record the specified -L dirs 358818334Speter and use them to search for dynamic linking. */ 358918334Speter /* Relative directories always come from -B, 359018334Speter and it is better not to use them for searching 359118334Speter at run time. In particular, stage1 loses */ 359252520Sobrien if (!IS_DIR_SEPARATOR (pl->prefix[0])) 359318334Speter continue; 359418334Speter#endif 359518334Speter /* Try subdirectory if there is one. */ 359618334Speter if (multilib_dir != NULL) 359718334Speter { 359818334Speter if (machine_suffix) 359918334Speter { 360018334Speter if (strlen (pl->prefix) + strlen (machine_suffix) 360118334Speter >= bufsize) 360218334Speter bufsize = (strlen (pl->prefix) 360318334Speter + strlen (machine_suffix)) * 2 + 1; 360418334Speter buffer = (char *) xrealloc (buffer, bufsize); 360518334Speter strcpy (buffer, pl->prefix); 360618334Speter strcat (buffer, machine_suffix); 360718334Speter if (is_directory (buffer, multilib_dir, 1)) 360818334Speter { 360918334Speter do_spec_1 ("-L", 0, NULL_PTR); 361018334Speter#ifdef SPACE_AFTER_L_OPTION 361118334Speter do_spec_1 (" ", 0, NULL_PTR); 361218334Speter#endif 361318334Speter do_spec_1 (buffer, 1, NULL_PTR); 361418334Speter do_spec_1 (multilib_dir, 1, NULL_PTR); 361518334Speter /* Make this a separate argument. */ 361618334Speter do_spec_1 (" ", 0, NULL_PTR); 361718334Speter } 361818334Speter } 361918334Speter if (!pl->require_machine_suffix) 362018334Speter { 362118334Speter if (is_directory (pl->prefix, multilib_dir, 1)) 362218334Speter { 362318334Speter do_spec_1 ("-L", 0, NULL_PTR); 362418334Speter#ifdef SPACE_AFTER_L_OPTION 362518334Speter do_spec_1 (" ", 0, NULL_PTR); 362618334Speter#endif 362718334Speter do_spec_1 (pl->prefix, 1, NULL_PTR); 362818334Speter do_spec_1 (multilib_dir, 1, NULL_PTR); 362918334Speter /* Make this a separate argument. */ 363018334Speter do_spec_1 (" ", 0, NULL_PTR); 363118334Speter } 363218334Speter } 363318334Speter } 363418334Speter if (machine_suffix) 363518334Speter { 363618334Speter if (is_directory (pl->prefix, machine_suffix, 1)) 363718334Speter { 363818334Speter do_spec_1 ("-L", 0, NULL_PTR); 363918334Speter#ifdef SPACE_AFTER_L_OPTION 364018334Speter do_spec_1 (" ", 0, NULL_PTR); 364118334Speter#endif 364218334Speter do_spec_1 (pl->prefix, 1, NULL_PTR); 364318334Speter /* Remove slash from machine_suffix. */ 364418334Speter if (strlen (machine_suffix) >= bufsize) 364518334Speter bufsize = strlen (machine_suffix) * 2 + 1; 364618334Speter buffer = (char *) xrealloc (buffer, bufsize); 364718334Speter strcpy (buffer, machine_suffix); 364818334Speter idx = strlen (buffer); 364952520Sobrien if (IS_DIR_SEPARATOR (buffer[idx - 1])) 365018334Speter buffer[idx - 1] = 0; 365118334Speter do_spec_1 (buffer, 1, NULL_PTR); 365218334Speter /* Make this a separate argument. */ 365318334Speter do_spec_1 (" ", 0, NULL_PTR); 365418334Speter } 365518334Speter } 365618334Speter if (!pl->require_machine_suffix) 365718334Speter { 365818334Speter if (is_directory (pl->prefix, "", 1)) 365918334Speter { 366018334Speter do_spec_1 ("-L", 0, NULL_PTR); 366118334Speter#ifdef SPACE_AFTER_L_OPTION 366218334Speter do_spec_1 (" ", 0, NULL_PTR); 366318334Speter#endif 366418334Speter /* Remove slash from pl->prefix. */ 366518334Speter if (strlen (pl->prefix) >= bufsize) 366618334Speter bufsize = strlen (pl->prefix) * 2 + 1; 366718334Speter buffer = (char *) xrealloc (buffer, bufsize); 366818334Speter strcpy (buffer, pl->prefix); 366918334Speter idx = strlen (buffer); 367052520Sobrien if (IS_DIR_SEPARATOR (buffer[idx - 1])) 367118334Speter buffer[idx - 1] = 0; 367218334Speter do_spec_1 (buffer, 1, NULL_PTR); 367318334Speter /* Make this a separate argument. */ 367418334Speter do_spec_1 (" ", 0, NULL_PTR); 367518334Speter } 367618334Speter } 367718334Speter } 367818334Speter free (buffer); 367918334Speter } 368018334Speter break; 368118334Speter 368218334Speter case 'e': 368352520Sobrien /* %efoo means report an error with `foo' as error message 368418334Speter and don't execute any more commands for this file. */ 368518334Speter { 368652520Sobrien const char *q = p; 368718334Speter char *buf; 368818334Speter while (*p != 0 && *p != '\n') p++; 368918334Speter buf = (char *) alloca (p - q + 1); 369018334Speter strncpy (buf, q, p - q); 369118334Speter buf[p - q] = 0; 369252520Sobrien error (buf); 369318334Speter return -1; 369418334Speter } 369518334Speter break; 369618334Speter 369718334Speter case 'g': 369818334Speter case 'u': 369918334Speter case 'U': 370018334Speter if (save_temps_flag) 370118334Speter { 370218334Speter obstack_grow (&obstack, input_basename, basename_length); 370318334Speter delete_this_arg = 0; 370418334Speter } 370518334Speter else 370618334Speter { 370718334Speter#ifdef MKTEMP_EACH_FILE 370818334Speter /* ??? This has a problem: the total number of 370918334Speter values mktemp can return is limited. 371018334Speter That matters for the names of object files. 371118334Speter In 2.4, do something about that. */ 371218334Speter struct temp_name *t; 371350599Sobrien int suffix_length; 371452520Sobrien const char *suffix = p; 371518334Speter 371650599Sobrien if (p[0] == '%' && p[1] == 'O') 371750599Sobrien { 371850599Sobrien p += 2; 371950599Sobrien /* We don't support extra suffix characters after %O. */ 372052520Sobrien if (*p == '.' || ISALPHA ((unsigned char)*p)) 372150599Sobrien abort (); 372250599Sobrien suffix = OBJECT_SUFFIX; 372350599Sobrien suffix_length = strlen (OBJECT_SUFFIX); 372450599Sobrien } 372550599Sobrien else 372650599Sobrien { 372752520Sobrien while (*p == '.' || ISALPHA ((unsigned char)*p)) 372850599Sobrien p++; 372950599Sobrien suffix_length = p - suffix; 373050599Sobrien } 373150599Sobrien 373218334Speter /* See if we already have an association of %g/%u/%U and 373318334Speter suffix. */ 373418334Speter for (t = temp_names; t; t = t->next) 373550599Sobrien if (t->length == suffix_length 373650599Sobrien && strncmp (t->suffix, suffix, suffix_length) == 0 373718334Speter && t->unique == (c != 'g')) 373818334Speter break; 373918334Speter 374018334Speter /* Make a new association if needed. %u requires one. */ 374118334Speter if (t == 0 || c == 'u') 374218334Speter { 374318334Speter if (t == 0) 374418334Speter { 374518334Speter t = (struct temp_name *) xmalloc (sizeof (struct temp_name)); 374618334Speter t->next = temp_names; 374718334Speter temp_names = t; 374818334Speter } 374950599Sobrien t->length = suffix_length; 375050599Sobrien t->suffix = save_string (suffix, suffix_length); 375118334Speter t->unique = (c != 'g'); 375250599Sobrien temp_filename = make_temp_file (t->suffix); 375350599Sobrien temp_filename_length = strlen (temp_filename); 375418334Speter t->filename = temp_filename; 375518334Speter t->filename_length = temp_filename_length; 375618334Speter } 375718334Speter 375818334Speter obstack_grow (&obstack, t->filename, t->filename_length); 375918334Speter delete_this_arg = 1; 376018334Speter#else 376118334Speter obstack_grow (&obstack, temp_filename, temp_filename_length); 376218334Speter if (c == 'u' || c == 'U') 376318334Speter { 376418334Speter static int unique; 376518334Speter char buff[9]; 376618334Speter if (c == 'u') 376718334Speter unique++; 376818334Speter sprintf (buff, "%d", unique); 376918334Speter obstack_grow (&obstack, buff, strlen (buff)); 377018334Speter } 377118334Speter#endif 377218334Speter delete_this_arg = 1; 377318334Speter } 377418334Speter arg_going = 1; 377518334Speter break; 377618334Speter 377718334Speter case 'i': 377818334Speter obstack_grow (&obstack, input_filename, input_filename_length); 377918334Speter arg_going = 1; 378018334Speter break; 378118334Speter 378218334Speter case 'I': 378318334Speter { 378418334Speter struct prefix_list *pl = include_prefixes.plist; 378518334Speter 378618334Speter if (gcc_exec_prefix) 378718334Speter { 378818334Speter do_spec_1 ("-iprefix", 1, NULL_PTR); 378918334Speter /* Make this a separate argument. */ 379018334Speter do_spec_1 (" ", 0, NULL_PTR); 379118334Speter do_spec_1 (gcc_exec_prefix, 1, NULL_PTR); 379218334Speter do_spec_1 (" ", 0, NULL_PTR); 379318334Speter } 379418334Speter 379518334Speter for (; pl; pl = pl->next) 379618334Speter { 379718334Speter do_spec_1 ("-isystem", 1, NULL_PTR); 379818334Speter /* Make this a separate argument. */ 379918334Speter do_spec_1 (" ", 0, NULL_PTR); 380018334Speter do_spec_1 (pl->prefix, 1, NULL_PTR); 380118334Speter do_spec_1 (" ", 0, NULL_PTR); 380218334Speter } 380318334Speter } 380418334Speter break; 380518334Speter 380618334Speter case 'o': 380752520Sobrien { 380852520Sobrien int max = n_infiles; 380952520Sobrien max += lang_specific_extra_outfiles; 381018334Speter 381152520Sobrien for (i = 0; i < max; i++) 381252520Sobrien if (outfiles[i]) 381352520Sobrien store_arg (outfiles[i], 0, 0); 381452520Sobrien break; 381552520Sobrien } 381652520Sobrien 381718334Speter case 'O': 381818334Speter obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX)); 381918334Speter arg_going = 1; 382018334Speter break; 382118334Speter 382218334Speter case 's': 382318334Speter this_is_library_file = 1; 382418334Speter break; 382518334Speter 382618334Speter case 'w': 382718334Speter this_is_output_file = 1; 382818334Speter break; 382918334Speter 383018334Speter case 'W': 383118334Speter { 383250599Sobrien int cur_index = argbuf_index; 383318334Speter /* Handle the {...} following the %W. */ 383418334Speter if (*p != '{') 383518334Speter abort (); 383618334Speter p = handle_braces (p + 1); 383718334Speter if (p == 0) 383818334Speter return -1; 383918334Speter /* If any args were output, mark the last one for deletion 384018334Speter on failure. */ 384150599Sobrien if (argbuf_index != cur_index) 384218334Speter record_temp_file (argbuf[argbuf_index - 1], 0, 1); 384318334Speter break; 384418334Speter } 384518334Speter 384618334Speter /* %x{OPTION} records OPTION for %X to output. */ 384718334Speter case 'x': 384818334Speter { 384952520Sobrien const char *p1 = p; 385018334Speter char *string; 385118334Speter 385218334Speter /* Skip past the option value and make a copy. */ 385318334Speter if (*p != '{') 385418334Speter abort (); 385518334Speter while (*p++ != '}') 385618334Speter ; 385718334Speter string = save_string (p1 + 1, p - p1 - 2); 385818334Speter 385918334Speter /* See if we already recorded this option. */ 386018334Speter for (i = 0; i < n_linker_options; i++) 386118334Speter if (! strcmp (string, linker_options[i])) 386218334Speter { 386318334Speter free (string); 386418334Speter return 0; 386518334Speter } 386618334Speter 386718334Speter /* This option is new; add it. */ 386850599Sobrien add_linker_option (string, strlen (string)); 386918334Speter } 387018334Speter break; 387118334Speter 387218334Speter /* Dump out the options accumulated previously using %x. */ 387318334Speter case 'X': 387418334Speter for (i = 0; i < n_linker_options; i++) 387518334Speter { 387618334Speter do_spec_1 (linker_options[i], 1, NULL_PTR); 387718334Speter /* Make each accumulated option a separate argument. */ 387818334Speter do_spec_1 (" ", 0, NULL_PTR); 387918334Speter } 388018334Speter break; 388118334Speter 388218334Speter /* Dump out the options accumulated previously using -Wa,. */ 388318334Speter case 'Y': 388418334Speter for (i = 0; i < n_assembler_options; i++) 388518334Speter { 388618334Speter do_spec_1 (assembler_options[i], 1, NULL_PTR); 388718334Speter /* Make each accumulated option a separate argument. */ 388818334Speter do_spec_1 (" ", 0, NULL_PTR); 388918334Speter } 389018334Speter break; 389118334Speter 389218334Speter /* Dump out the options accumulated previously using -Wp,. */ 389318334Speter case 'Z': 389418334Speter for (i = 0; i < n_preprocessor_options; i++) 389518334Speter { 389618334Speter do_spec_1 (preprocessor_options[i], 1, NULL_PTR); 389718334Speter /* Make each accumulated option a separate argument. */ 389818334Speter do_spec_1 (" ", 0, NULL_PTR); 389918334Speter } 390018334Speter break; 390118334Speter 390218334Speter /* Here are digits and numbers that just process 390318334Speter a certain constant string as a spec. */ 390418334Speter 390518334Speter case '1': 390618334Speter value = do_spec_1 (cc1_spec, 0, NULL_PTR); 390718334Speter if (value != 0) 390818334Speter return value; 390918334Speter break; 391018334Speter 391118334Speter case '2': 391218334Speter value = do_spec_1 (cc1plus_spec, 0, NULL_PTR); 391318334Speter if (value != 0) 391418334Speter return value; 391518334Speter break; 391618334Speter 391718334Speter case 'a': 391818334Speter value = do_spec_1 (asm_spec, 0, NULL_PTR); 391918334Speter if (value != 0) 392018334Speter return value; 392118334Speter break; 392218334Speter 392318334Speter case 'A': 392418334Speter value = do_spec_1 (asm_final_spec, 0, NULL_PTR); 392518334Speter if (value != 0) 392618334Speter return value; 392718334Speter break; 392818334Speter 392918334Speter case 'c': 393018334Speter value = do_spec_1 (signed_char_spec, 0, NULL_PTR); 393118334Speter if (value != 0) 393218334Speter return value; 393318334Speter break; 393418334Speter 393518334Speter case 'C': 393618334Speter value = do_spec_1 (cpp_spec, 0, NULL_PTR); 393718334Speter if (value != 0) 393818334Speter return value; 393918334Speter break; 394018334Speter 394118334Speter case 'E': 394218334Speter value = do_spec_1 (endfile_spec, 0, NULL_PTR); 394318334Speter if (value != 0) 394418334Speter return value; 394518334Speter break; 394618334Speter 394718334Speter case 'l': 394818334Speter value = do_spec_1 (link_spec, 0, NULL_PTR); 394918334Speter if (value != 0) 395018334Speter return value; 395118334Speter break; 395218334Speter 395318334Speter case 'L': 395418334Speter value = do_spec_1 (lib_spec, 0, NULL_PTR); 395518334Speter if (value != 0) 395618334Speter return value; 395718334Speter break; 395818334Speter 395918334Speter case 'G': 396018334Speter value = do_spec_1 (libgcc_spec, 0, NULL_PTR); 396118334Speter if (value != 0) 396218334Speter return value; 396318334Speter break; 396418334Speter 396518334Speter case 'p': 396618334Speter { 396718334Speter char *x = (char *) alloca (strlen (cpp_predefines) + 1); 396818334Speter char *buf = x; 396918334Speter char *y; 397018334Speter 397118334Speter /* Copy all of the -D options in CPP_PREDEFINES into BUF. */ 397218334Speter y = cpp_predefines; 397318334Speter while (*y != 0) 397418334Speter { 397518334Speter if (! strncmp (y, "-D", 2)) 397618334Speter /* Copy the whole option. */ 397718334Speter while (*y && *y != ' ' && *y != '\t') 397818334Speter *x++ = *y++; 397918334Speter else if (*y == ' ' || *y == '\t') 398018334Speter /* Copy whitespace to the result. */ 398118334Speter *x++ = *y++; 398218334Speter /* Don't copy other options. */ 398318334Speter else 398418334Speter y++; 398518334Speter } 398618334Speter 398718334Speter *x = 0; 398818334Speter 398918334Speter value = do_spec_1 (buf, 0, NULL_PTR); 399018334Speter if (value != 0) 399118334Speter return value; 399218334Speter } 399318334Speter break; 399418334Speter 399518334Speter case 'P': 399618334Speter { 399718334Speter char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1); 399818334Speter char *buf = x; 399918334Speter char *y; 400018334Speter 400118334Speter /* Copy all of CPP_PREDEFINES into BUF, 400218334Speter but put __ after every -D and at the end of each arg. */ 400318334Speter y = cpp_predefines; 400418334Speter while (*y != 0) 400518334Speter { 400618334Speter if (! strncmp (y, "-D", 2)) 400718334Speter { 400818334Speter int flag = 0; 400918334Speter 401018334Speter *x++ = *y++; 401118334Speter *x++ = *y++; 401218334Speter 401318334Speter if (*y != '_' 401452520Sobrien || (*(y+1) != '_' 401552520Sobrien && ! ISUPPER ((unsigned char)*(y+1)))) 401618334Speter { 401718334Speter /* Stick __ at front of macro name. */ 401818334Speter *x++ = '_'; 401918334Speter *x++ = '_'; 402018334Speter /* Arrange to stick __ at the end as well. */ 402118334Speter flag = 1; 402218334Speter } 402318334Speter 402418334Speter /* Copy the macro name. */ 402518334Speter while (*y && *y != '=' && *y != ' ' && *y != '\t') 402618334Speter *x++ = *y++; 402718334Speter 402818334Speter if (flag) 402918334Speter { 403018334Speter *x++ = '_'; 403118334Speter *x++ = '_'; 403218334Speter } 403318334Speter 403418334Speter /* Copy the value given, if any. */ 403518334Speter while (*y && *y != ' ' && *y != '\t') 403618334Speter *x++ = *y++; 403718334Speter } 403818334Speter else if (*y == ' ' || *y == '\t') 403918334Speter /* Copy whitespace to the result. */ 404018334Speter *x++ = *y++; 404118334Speter /* Don't copy -A options */ 404218334Speter else 404318334Speter y++; 404418334Speter } 404518334Speter *x++ = ' '; 404618334Speter 404718334Speter /* Copy all of CPP_PREDEFINES into BUF, 404818334Speter but put __ after every -D. */ 404918334Speter y = cpp_predefines; 405018334Speter while (*y != 0) 405118334Speter { 405218334Speter if (! strncmp (y, "-D", 2)) 405318334Speter { 405418334Speter y += 2; 405518334Speter 405618334Speter if (*y != '_' 405752520Sobrien || (*(y+1) != '_' 405852520Sobrien && ! ISUPPER ((unsigned char)*(y+1)))) 405918334Speter { 406018334Speter /* Stick -D__ at front of macro name. */ 406118334Speter *x++ = '-'; 406218334Speter *x++ = 'D'; 406318334Speter *x++ = '_'; 406418334Speter *x++ = '_'; 406518334Speter 406618334Speter /* Copy the macro name. */ 406718334Speter while (*y && *y != '=' && *y != ' ' && *y != '\t') 406818334Speter *x++ = *y++; 406918334Speter 407018334Speter /* Copy the value given, if any. */ 407118334Speter while (*y && *y != ' ' && *y != '\t') 407218334Speter *x++ = *y++; 407318334Speter } 407418334Speter else 407518334Speter { 407618334Speter /* Do not copy this macro - we have just done it before */ 407718334Speter while (*y && *y != ' ' && *y != '\t') 407818334Speter y++; 407918334Speter } 408018334Speter } 408118334Speter else if (*y == ' ' || *y == '\t') 408218334Speter /* Copy whitespace to the result. */ 408318334Speter *x++ = *y++; 408418334Speter /* Don't copy -A options */ 408518334Speter else 408618334Speter y++; 408718334Speter } 408818334Speter *x++ = ' '; 408918334Speter 409018334Speter /* Copy all of the -A options in CPP_PREDEFINES into BUF. */ 409118334Speter y = cpp_predefines; 409218334Speter while (*y != 0) 409318334Speter { 409418334Speter if (! strncmp (y, "-A", 2)) 409518334Speter /* Copy the whole option. */ 409618334Speter while (*y && *y != ' ' && *y != '\t') 409718334Speter *x++ = *y++; 409818334Speter else if (*y == ' ' || *y == '\t') 409918334Speter /* Copy whitespace to the result. */ 410018334Speter *x++ = *y++; 410118334Speter /* Don't copy other options. */ 410218334Speter else 410318334Speter y++; 410418334Speter } 410518334Speter 410618334Speter *x = 0; 410718334Speter 410818334Speter value = do_spec_1 (buf, 0, NULL_PTR); 410918334Speter if (value != 0) 411018334Speter return value; 411118334Speter } 411218334Speter break; 411318334Speter 411418334Speter case 'S': 411518334Speter value = do_spec_1 (startfile_spec, 0, NULL_PTR); 411618334Speter if (value != 0) 411718334Speter return value; 411818334Speter break; 411918334Speter 412018334Speter /* Here we define characters other than letters and digits. */ 412118334Speter 412218334Speter case '{': 412318334Speter p = handle_braces (p); 412418334Speter if (p == 0) 412518334Speter return -1; 412618334Speter break; 412718334Speter 412818334Speter case '%': 412918334Speter obstack_1grow (&obstack, '%'); 413018334Speter break; 413118334Speter 413218334Speter case '*': 413318334Speter do_spec_1 (soft_matched_part, 1, NULL_PTR); 413418334Speter do_spec_1 (" ", 0, NULL_PTR); 413518334Speter break; 413618334Speter 413718334Speter /* Process a string found as the value of a spec given by name. 413818334Speter This feature allows individual machine descriptions 413918334Speter to add and use their own specs. 414018334Speter %[...] modifies -D options the way %P does; 414118334Speter %(...) uses the spec unmodified. */ 414250599Sobrien case '[': 414350599Sobrien error ("Warning: use of obsolete %%[ operator in specs"); 414418334Speter case '(': 414518334Speter { 414652520Sobrien const char *name = p; 414718334Speter struct spec_list *sl; 414818334Speter int len; 414918334Speter 415018334Speter /* The string after the S/P is the name of a spec that is to be 415150599Sobrien processed. */ 415218334Speter while (*p && *p != ')' && *p != ']') 415318334Speter p++; 415418334Speter 415518334Speter /* See if it's in the list */ 415618334Speter for (len = p - name, sl = specs; sl; sl = sl->next) 415750599Sobrien if (sl->name_len == len && !strncmp (sl->name, name, len)) 415818334Speter { 415950599Sobrien name = *(sl->ptr_spec); 416050599Sobrien#ifdef DEBUG_SPECS 416152520Sobrien notice ("Processing spec %c%s%c, which is '%s'\n", 416252520Sobrien c, sl->name, (c == '(') ? ')' : ']', name); 416350599Sobrien#endif 416418334Speter break; 416518334Speter } 416618334Speter 416718334Speter if (sl) 416818334Speter { 416918334Speter if (c == '(') 417018334Speter { 417118334Speter value = do_spec_1 (name, 0, NULL_PTR); 417218334Speter if (value != 0) 417318334Speter return value; 417418334Speter } 417518334Speter else 417618334Speter { 417718334Speter char *x = (char *) alloca (strlen (name) * 2 + 1); 417818334Speter char *buf = x; 417952520Sobrien const char *y = name; 418050599Sobrien int flag = 0; 418118334Speter 418218334Speter /* Copy all of NAME into BUF, but put __ after 418318334Speter every -D and at the end of each arg, */ 418418334Speter while (1) 418518334Speter { 418618334Speter if (! strncmp (y, "-D", 2)) 418718334Speter { 418818334Speter *x++ = '-'; 418918334Speter *x++ = 'D'; 419018334Speter *x++ = '_'; 419118334Speter *x++ = '_'; 419218334Speter y += 2; 419350599Sobrien flag = 1; 419450599Sobrien continue; 419518334Speter } 419650599Sobrien else if (flag && (*y == ' ' || *y == '\t' || *y == '=' 419750599Sobrien || *y == '}' || *y == 0)) 419818334Speter { 419918334Speter *x++ = '_'; 420018334Speter *x++ = '_'; 420150599Sobrien flag = 0; 420218334Speter } 420350599Sobrien if (*y == 0) 420450599Sobrien break; 420518334Speter else 420618334Speter *x++ = *y++; 420718334Speter } 420818334Speter *x = 0; 420918334Speter 421018334Speter value = do_spec_1 (buf, 0, NULL_PTR); 421118334Speter if (value != 0) 421218334Speter return value; 421318334Speter } 421418334Speter } 421518334Speter 421618334Speter /* Discard the closing paren or bracket. */ 421718334Speter if (*p) 421818334Speter p++; 421918334Speter } 422018334Speter break; 422118334Speter 422218334Speter case 'v': 422318334Speter { 422418334Speter int c1 = *p++; /* Select first or second version number. */ 422518334Speter char *v = compiler_version; 422618346Speter char *q; 422750599Sobrien 422850599Sobrien /* The format of the version string is 422950599Sobrien ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */ 423050599Sobrien 423150599Sobrien /* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */ 423250599Sobrien while (! ISDIGIT (*v)) 423350599Sobrien v++; 423450599Sobrien if (v > compiler_version && v[-1] != '-') 423550599Sobrien abort (); 423650599Sobrien 423718334Speter /* If desired, advance to second version number. */ 423818334Speter if (c1 == '2') 423918334Speter { 424050599Sobrien /* Set V after the first period. */ 424150599Sobrien while (ISDIGIT (*v)) 424218334Speter v++; 424350599Sobrien if (*v != '.') 424450599Sobrien abort (); 424550599Sobrien v++; 424618334Speter } 424750599Sobrien 424818334Speter /* Set Q at the next period or at the end. */ 424918334Speter q = v; 425050599Sobrien while (ISDIGIT (*q)) 425118334Speter q++; 425250599Sobrien if (*q != 0 && *q != ' ' && *q != '.' && *q != '-') 425350599Sobrien abort (); 425450599Sobrien 425518334Speter /* Put that part into the command. */ 425618334Speter obstack_grow (&obstack, v, q - v); 425718334Speter arg_going = 1; 425818334Speter } 425918334Speter break; 426018334Speter 426118334Speter case '|': 426218334Speter if (input_from_pipe) 426318334Speter do_spec_1 ("-", 0, NULL_PTR); 426418334Speter break; 426518334Speter 426618334Speter default: 426718334Speter abort (); 426818334Speter } 426918334Speter break; 427018334Speter 427118334Speter case '\\': 427218334Speter /* Backslash: treat next character as ordinary. */ 427318334Speter c = *p++; 427418334Speter 427518334Speter /* fall through */ 427618334Speter default: 427718334Speter /* Ordinary character: put it into the current argument. */ 427818334Speter obstack_1grow (&obstack, c); 427918334Speter arg_going = 1; 428018334Speter } 428118334Speter 428218334Speter return 0; /* End of string */ 428318334Speter} 428418334Speter 428518334Speter/* Return 0 if we call do_spec_1 and that returns -1. */ 428618334Speter 428752520Sobrienstatic const char * 428818334Speterhandle_braces (p) 428952520Sobrien register const char *p; 429018334Speter{ 429152520Sobrien const char *filter, *body = NULL, *endbody = NULL; 429250599Sobrien int pipe_p = 0; 429350599Sobrien int negate; 429450599Sobrien int suffix; 429550599Sobrien int include_blanks = 1; 429618334Speter 429750599Sobrien if (*p == '^') 429850599Sobrien /* A '^' after the open-brace means to not give blanks before args. */ 429950599Sobrien include_blanks = 0, ++p; 430050599Sobrien 430118334Speter if (*p == '|') 430218334Speter /* A `|' after the open-brace means, 430318334Speter if the test fails, output a single minus sign rather than nothing. 430418334Speter This is used in %{|!pipe:...}. */ 430550599Sobrien pipe_p = 1, ++p; 430618334Speter 430750599Sobriennext_member: 430850599Sobrien negate = suffix = 0; 430950599Sobrien 431018334Speter if (*p == '!') 431118334Speter /* A `!' after the open-brace negates the condition: 431218334Speter succeed if the specified switch is not present. */ 431318334Speter negate = 1, ++p; 431418334Speter 431518334Speter if (*p == '.') 431618334Speter /* A `.' after the open-brace means test against the current suffix. */ 431718334Speter { 431850599Sobrien if (pipe_p) 431918334Speter abort (); 432018334Speter 432118334Speter suffix = 1; 432218334Speter ++p; 432318334Speter } 432418334Speter 432518334Speter filter = p; 432650599Sobrien while (*p != ':' && *p != '}' && *p != '|') p++; 432750599Sobrien 432850599Sobrien if (*p == '|' && pipe_p) 432950599Sobrien abort (); 433050599Sobrien 433150599Sobrien if (!body) 433218334Speter { 433350599Sobrien if (*p != '}') 433450599Sobrien { 433550599Sobrien register int count = 1; 433652520Sobrien register const char *q = p; 433750599Sobrien 433850599Sobrien while (*q++ != ':') continue; 433950599Sobrien body = q; 434050599Sobrien 434150599Sobrien while (count > 0) 434250599Sobrien { 434350599Sobrien if (*q == '{') 434450599Sobrien count++; 434550599Sobrien else if (*q == '}') 434650599Sobrien count--; 434750599Sobrien else if (*q == 0) 434850599Sobrien abort (); 434950599Sobrien q++; 435050599Sobrien } 435150599Sobrien endbody = q; 435218334Speter } 435350599Sobrien else 435450599Sobrien body = p, endbody = p+1; 435518334Speter } 435618334Speter 435718334Speter if (suffix) 435818334Speter { 435918334Speter int found = (input_suffix != 0 436052520Sobrien && (long) strlen (input_suffix) == (long)(p - filter) 436118334Speter && strncmp (input_suffix, filter, p - filter) == 0); 436218334Speter 436350599Sobrien if (body[0] == '}') 436418334Speter abort (); 436518334Speter 436618334Speter if (negate != found 436750599Sobrien && do_spec_1 (save_string (body, endbody-body-1), 0, NULL_PTR) < 0) 436818334Speter return 0; 436918334Speter } 437018334Speter else if (p[-1] == '*' && p[0] == '}') 437118334Speter { 437218334Speter /* Substitute all matching switches as separate args. */ 437318334Speter register int i; 437418334Speter --p; 437518334Speter for (i = 0; i < n_switches; i++) 437618334Speter if (!strncmp (switches[i].part1, filter, p - filter) 437718334Speter && check_live_switch (i, p - filter)) 437850599Sobrien give_switch (i, 0, include_blanks); 437918334Speter } 438018334Speter else 438118334Speter { 438218334Speter /* Test for presence of the specified switch. */ 438318334Speter register int i; 438418334Speter int present = 0; 438518334Speter 438618334Speter /* If name specified ends in *, as in {x*:...}, 438718334Speter check for %* and handle that case. */ 438818334Speter if (p[-1] == '*' && !negate) 438918334Speter { 439018334Speter int substitution; 439152520Sobrien const char *r = body; 439218334Speter 439318334Speter /* First see whether we have %*. */ 439418334Speter substitution = 0; 439550599Sobrien while (r < endbody) 439618334Speter { 439718334Speter if (*r == '%' && r[1] == '*') 439818334Speter substitution = 1; 439918334Speter r++; 440018334Speter } 440118334Speter /* If we do, handle that case. */ 440218334Speter if (substitution) 440318334Speter { 440418334Speter /* Substitute all matching switches as separate args. 440518334Speter But do this by substituting for %* 440618334Speter in the text that follows the colon. */ 440718334Speter 440818334Speter unsigned hard_match_len = p - filter - 1; 440950599Sobrien char *string = save_string (body, endbody - body - 1); 441018334Speter 441118334Speter for (i = 0; i < n_switches; i++) 441218334Speter if (!strncmp (switches[i].part1, filter, hard_match_len) 441318334Speter && check_live_switch (i, -1)) 441418334Speter { 441518334Speter do_spec_1 (string, 0, &switches[i].part1[hard_match_len]); 441618334Speter /* Pass any arguments this switch has. */ 441750599Sobrien give_switch (i, 1, 1); 441818334Speter } 441918334Speter 442050599Sobrien /* We didn't match. Try again. */ 442150599Sobrien if (*p++ == '|') 442250599Sobrien goto next_member; 442350599Sobrien return endbody; 442418334Speter } 442518334Speter } 442618334Speter 442718334Speter /* If name specified ends in *, as in {x*:...}, 442818334Speter check for presence of any switch name starting with x. */ 442918334Speter if (p[-1] == '*') 443018334Speter { 443118334Speter for (i = 0; i < n_switches; i++) 443218334Speter { 443318334Speter unsigned hard_match_len = p - filter - 1; 443418334Speter 443518334Speter if (!strncmp (switches[i].part1, filter, hard_match_len) 443618334Speter && check_live_switch (i, hard_match_len)) 443718334Speter { 443818334Speter present = 1; 443918334Speter } 444018334Speter } 444118334Speter } 444218334Speter /* Otherwise, check for presence of exact name specified. */ 444318334Speter else 444418334Speter { 444518334Speter for (i = 0; i < n_switches; i++) 444618334Speter { 444718334Speter if (!strncmp (switches[i].part1, filter, p - filter) 444818334Speter && switches[i].part1[p - filter] == 0 444918334Speter && check_live_switch (i, -1)) 445018334Speter { 445118334Speter present = 1; 445218334Speter break; 445318334Speter } 445418334Speter } 445518334Speter } 445618334Speter 445750599Sobrien /* If it is as desired (present for %{s...}, absent for %{!s...}) 445818334Speter then substitute either the switch or the specified 445918334Speter conditional text. */ 446018334Speter if (present != negate) 446118334Speter { 446218334Speter if (*p == '}') 446318334Speter { 446450599Sobrien give_switch (i, 0, include_blanks); 446518334Speter } 446618334Speter else 446718334Speter { 446850599Sobrien if (do_spec_1 (save_string (body, endbody - body - 1), 446950599Sobrien 0, NULL_PTR) < 0) 447018334Speter return 0; 447118334Speter } 447218334Speter } 447350599Sobrien else if (pipe_p) 447418334Speter { 447518334Speter /* Here if a %{|...} conditional fails: output a minus sign, 447618334Speter which means "standard output" or "standard input". */ 447718334Speter do_spec_1 ("-", 0, NULL_PTR); 447850599Sobrien return endbody; 447918334Speter } 448018334Speter } 448118334Speter 448250599Sobrien /* We didn't match; try again. */ 448350599Sobrien if (*p++ == '|') 448450599Sobrien goto next_member; 448550599Sobrien 448650599Sobrien return endbody; 448718334Speter} 448818334Speter 448918334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch 449018334Speter on the command line. PREFIX_LENGTH is the length of XXX in an {XXX*} 449118334Speter spec, or -1 if either exact match or %* is used. 449218334Speter 449318334Speter A -O switch is obsoleted by a later -O switch. A -f, -m, or -W switch 449418334Speter whose value does not begin with "no-" is obsoleted by the same value 449518334Speter with the "no-", similarly for a switch with the "no-" prefix. */ 449618334Speter 449718334Speterstatic int 449818334Spetercheck_live_switch (switchnum, prefix_length) 449918334Speter int switchnum; 450018334Speter int prefix_length; 450118334Speter{ 450252520Sobrien const char *name = switches[switchnum].part1; 450318334Speter int i; 450418334Speter 450518334Speter /* In the common case of {<at-most-one-letter>*}, a negating 450618334Speter switch would always match, so ignore that case. We will just 450718334Speter send the conflicting switches to the compiler phase. */ 450818334Speter if (prefix_length >= 0 && prefix_length <= 1) 450918334Speter return 1; 451018334Speter 451118334Speter /* If we already processed this switch and determined if it was 451218334Speter live or not, return our past determination. */ 451318334Speter if (switches[switchnum].live_cond != 0) 451418334Speter return switches[switchnum].live_cond > 0; 451518334Speter 451618334Speter /* Now search for duplicate in a manner that depends on the name. */ 451718334Speter switch (*name) 451818334Speter { 451918334Speter case 'O': 452018334Speter for (i = switchnum + 1; i < n_switches; i++) 452118334Speter if (switches[i].part1[0] == 'O') 452218334Speter { 452352520Sobrien switches[switchnum].validated = 1; 452418334Speter switches[switchnum].live_cond = -1; 452518334Speter return 0; 452618334Speter } 452718334Speter break; 452818334Speter 452918334Speter case 'W': case 'f': case 'm': 453018334Speter if (! strncmp (name + 1, "no-", 3)) 453118334Speter { 453250599Sobrien /* We have Xno-YYY, search for XYYY. */ 453318334Speter for (i = switchnum + 1; i < n_switches; i++) 453418334Speter if (switches[i].part1[0] == name[0] 453518334Speter && ! strcmp (&switches[i].part1[1], &name[4])) 453618334Speter { 453752520Sobrien switches[switchnum].validated = 1; 453818334Speter switches[switchnum].live_cond = -1; 453918334Speter return 0; 454018334Speter } 454118334Speter } 454218334Speter else 454318334Speter { 454418334Speter /* We have XYYY, search for Xno-YYY. */ 454518334Speter for (i = switchnum + 1; i < n_switches; i++) 454618334Speter if (switches[i].part1[0] == name[0] 454718334Speter && switches[i].part1[1] == 'n' 454818334Speter && switches[i].part1[2] == 'o' 454918334Speter && switches[i].part1[3] == '-' 455018334Speter && !strcmp (&switches[i].part1[4], &name[1])) 455118334Speter { 455252520Sobrien switches[switchnum].validated = 1; 455318334Speter switches[switchnum].live_cond = -1; 455418334Speter return 0; 455518334Speter } 455618334Speter } 455718334Speter break; 455818334Speter } 455918334Speter 456018334Speter /* Otherwise the switch is live. */ 456118334Speter switches[switchnum].live_cond = 1; 456218334Speter return 1; 456318334Speter} 456418334Speter 456518334Speter/* Pass a switch to the current accumulating command 456618334Speter in the same form that we received it. 456718334Speter SWITCHNUM identifies the switch; it is an index into 456818334Speter the vector of switches gcc received, which is `switches'. 456918334Speter This cannot fail since it never finishes a command line. 457018334Speter 457150599Sobrien If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. 457218334Speter 457350599Sobrien If INCLUDE_BLANKS is nonzero, then we include blanks before each argument 457450599Sobrien of the switch. */ 457550599Sobrien 457618334Speterstatic void 457750599Sobriengive_switch (switchnum, omit_first_word, include_blanks) 457818334Speter int switchnum; 457918334Speter int omit_first_word; 458050599Sobrien int include_blanks; 458118334Speter{ 458218334Speter if (!omit_first_word) 458318334Speter { 458418334Speter do_spec_1 ("-", 0, NULL_PTR); 458518334Speter do_spec_1 (switches[switchnum].part1, 1, NULL_PTR); 458618334Speter } 458750599Sobrien 458818334Speter if (switches[switchnum].args != 0) 458918334Speter { 459018334Speter char **p; 459118334Speter for (p = switches[switchnum].args; *p; p++) 459218334Speter { 459350599Sobrien if (include_blanks) 459450599Sobrien do_spec_1 (" ", 0, NULL_PTR); 459518334Speter do_spec_1 (*p, 1, NULL_PTR); 459618334Speter } 459718334Speter } 459850599Sobrien 459950599Sobrien do_spec_1 (" ", 0, NULL_PTR); 460052520Sobrien switches[switchnum].validated = 1; 460118334Speter} 460218334Speter 460318334Speter/* Search for a file named NAME trying various prefixes including the 460418334Speter user's -B prefix and some standard ones. 460518334Speter Return the absolute file name found. If nothing is found, return NAME. */ 460618334Speter 460752520Sobrienstatic const char * 460818334Speterfind_file (name) 460952520Sobrien const char *name; 461018334Speter{ 461118334Speter char *newname; 461218334Speter 461318334Speter /* Try multilib_dir if it is defined. */ 461418334Speter if (multilib_dir != NULL) 461518334Speter { 461618334Speter char *try; 461718334Speter 461818334Speter try = (char *) alloca (strlen (multilib_dir) + strlen (name) + 2); 461918334Speter strcpy (try, multilib_dir); 462018334Speter strcat (try, dir_separator_str); 462118334Speter strcat (try, name); 462218334Speter 462318334Speter newname = find_a_file (&startfile_prefixes, try, R_OK); 462418334Speter 462518334Speter /* If we don't find it in the multi library dir, then fall 462618334Speter through and look for it in the normal places. */ 462718334Speter if (newname != NULL) 462818334Speter return newname; 462918334Speter } 463018334Speter 463118334Speter newname = find_a_file (&startfile_prefixes, name, R_OK); 463218334Speter return newname ? newname : name; 463318334Speter} 463418334Speter 463518334Speter/* Determine whether a directory exists. If LINKER, return 0 for 463618334Speter certain fixed names not needed by the linker. If not LINKER, it is 463718334Speter only important to return 0 if the host machine has a small ARG_MAX 463818334Speter limit. */ 463918334Speter 464018334Speterstatic int 464118334Speteris_directory (path1, path2, linker) 464252520Sobrien const char *path1; 464352520Sobrien const char *path2; 464418334Speter int linker; 464518334Speter{ 464618334Speter int len1 = strlen (path1); 464718334Speter int len2 = strlen (path2); 464818334Speter char *path = (char *) alloca (3 + len1 + len2); 464918334Speter char *cp; 465018334Speter struct stat st; 465118334Speter 465218334Speter#ifndef SMALL_ARG_MAX 465318334Speter if (! linker) 465418334Speter return 1; 465518334Speter#endif 465618334Speter 465718334Speter /* Construct the path from the two parts. Ensure the string ends with "/.". 465818334Speter The resulting path will be a directory even if the given path is a 465918334Speter symbolic link. */ 466052520Sobrien memcpy (path, path1, len1); 466152520Sobrien memcpy (path + len1, path2, len2); 466218334Speter cp = path + len1 + len2; 466352520Sobrien if (!IS_DIR_SEPARATOR (cp[-1])) 466418334Speter *cp++ = DIR_SEPARATOR; 466518334Speter *cp++ = '.'; 466618334Speter *cp = '\0'; 466718334Speter 466851232Sbde#ifndef FREEBSD_NATIVE 466918334Speter /* Exclude directories that the linker is known to search. */ 467018334Speter if (linker 467118334Speter && ((cp - path == 6 467250599Sobrien && strcmp (path, concat (dir_separator_str, "lib", 467350599Sobrien dir_separator_str, ".", NULL_PTR)) == 0) 467418334Speter || (cp - path == 10 467550599Sobrien && strcmp (path, concat (dir_separator_str, "usr", 467650599Sobrien dir_separator_str, "lib", 467750599Sobrien dir_separator_str, ".", NULL_PTR)) == 0))) 467818334Speter return 0; 467951232Sbde#endif /* FREEBSD_NATIVE */ 468018334Speter 468118334Speter return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode)); 468218334Speter} 468318334Speter 468418334Speter/* On fatal signals, delete all the temporary files. */ 468518334Speter 468618334Speterstatic void 468718334Speterfatal_error (signum) 468818334Speter int signum; 468918334Speter{ 469018334Speter signal (signum, SIG_DFL); 469118334Speter delete_failure_queue (); 469218334Speter delete_temp_files (); 469318334Speter /* Get the same signal again, this time not handled, 469418334Speter so its normal effect occurs. */ 469518334Speter kill (getpid (), signum); 469618334Speter} 469718334Speter 469818334Speterint 469918334Spetermain (argc, argv) 470018334Speter int argc; 470118334Speter char **argv; 470218334Speter{ 470350599Sobrien register size_t i; 470450599Sobrien size_t j; 470518334Speter int value; 470618334Speter int linker_was_run = 0; 470718334Speter char *explicit_link_files; 470818334Speter char *specs_file; 470952520Sobrien const char *p; 471050599Sobrien struct user_specs *uptr; 471118334Speter 471218334Speter p = argv[0] + strlen (argv[0]); 471352520Sobrien while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) 471452520Sobrien --p; 471518334Speter programname = p; 471618334Speter 471752520Sobrien#ifdef HAVE_LC_MESSAGES 471852520Sobrien setlocale (LC_MESSAGES, ""); 471952520Sobrien#endif 472052520Sobrien (void) bindtextdomain (PACKAGE, localedir); 472152520Sobrien (void) textdomain (PACKAGE); 472252520Sobrien 472318334Speter if (signal (SIGINT, SIG_IGN) != SIG_IGN) 472418334Speter signal (SIGINT, fatal_error); 472518334Speter#ifdef SIGHUP 472618334Speter if (signal (SIGHUP, SIG_IGN) != SIG_IGN) 472718334Speter signal (SIGHUP, fatal_error); 472818334Speter#endif 472918334Speter if (signal (SIGTERM, SIG_IGN) != SIG_IGN) 473018334Speter signal (SIGTERM, fatal_error); 473118334Speter#ifdef SIGPIPE 473218334Speter if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) 473318334Speter signal (SIGPIPE, fatal_error); 473418334Speter#endif 473518334Speter 473618334Speter argbuf_length = 10; 473718334Speter argbuf = (char **) xmalloc (argbuf_length * sizeof (char *)); 473818334Speter 473918334Speter obstack_init (&obstack); 474018334Speter 474150599Sobrien /* Build multilib_select, et. al from the separate lines that make up each 474250599Sobrien multilib selection. */ 474350599Sobrien { 474450599Sobrien char **q = multilib_raw; 474550599Sobrien int need_space; 474650599Sobrien 474750599Sobrien obstack_init (&multilib_obstack); 474850599Sobrien while ((p = *q++) != (char *) 0) 474950599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 475050599Sobrien 475150599Sobrien obstack_1grow (&multilib_obstack, 0); 475250599Sobrien multilib_select = obstack_finish (&multilib_obstack); 475350599Sobrien 475450599Sobrien q = multilib_matches_raw; 475550599Sobrien while ((p = *q++) != (char *) 0) 475650599Sobrien obstack_grow (&multilib_obstack, p, strlen (p)); 475750599Sobrien 475850599Sobrien obstack_1grow (&multilib_obstack, 0); 475950599Sobrien multilib_matches = obstack_finish (&multilib_obstack); 476050599Sobrien 476150599Sobrien need_space = FALSE; 476250599Sobrien for (i = 0; 476350599Sobrien i < sizeof (multilib_defaults_raw) / sizeof (multilib_defaults_raw[0]); 476450599Sobrien i++) 476550599Sobrien { 476650599Sobrien if (need_space) 476750599Sobrien obstack_1grow (&multilib_obstack, ' '); 476850599Sobrien obstack_grow (&multilib_obstack, 476950599Sobrien multilib_defaults_raw[i], 477050599Sobrien strlen (multilib_defaults_raw[i])); 477150599Sobrien need_space = TRUE; 477250599Sobrien } 477350599Sobrien 477450599Sobrien obstack_1grow (&multilib_obstack, 0); 477550599Sobrien multilib_defaults = obstack_finish (&multilib_obstack); 477650599Sobrien } 477750599Sobrien 477818334Speter /* Set up to remember the pathname of gcc and any options 477918334Speter needed for collect. We use argv[0] instead of programname because 478018334Speter we need the complete pathname. */ 478118334Speter obstack_init (&collect_obstack); 478218334Speter obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=")-1); 478318334Speter obstack_grow (&collect_obstack, argv[0], strlen (argv[0])+1); 478418334Speter putenv (obstack_finish (&collect_obstack)); 478518334Speter 478618334Speter#ifdef INIT_ENVIRONMENT 478718334Speter /* Set up any other necessary machine specific environment variables. */ 478818334Speter putenv (INIT_ENVIRONMENT); 478918334Speter#endif 479018334Speter 479118334Speter /* Choose directory for temp files. */ 479218334Speter 479350599Sobrien#ifndef MKTEMP_EACH_FILE 479450599Sobrien temp_filename = choose_temp_base (); 479550599Sobrien temp_filename_length = strlen (temp_filename); 479650599Sobrien#endif 479718334Speter 479818334Speter /* Make a table of what switches there are (switches, n_switches). 479918334Speter Make a table of specified input files (infiles, n_infiles). 480018334Speter Decode switches that are handled locally. */ 480118334Speter 480218334Speter process_command (argc, argv); 480318334Speter 480450599Sobrien { 480550599Sobrien int first_time; 480650599Sobrien 480750599Sobrien /* Build COLLECT_GCC_OPTIONS to have all of the options specified to 480850599Sobrien the compiler. */ 480950599Sobrien obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=", 481050599Sobrien sizeof ("COLLECT_GCC_OPTIONS=")-1); 481150599Sobrien 481250599Sobrien first_time = TRUE; 481352520Sobrien for (i = 0; (int)i < n_switches; i++) 481450599Sobrien { 481550599Sobrien char **args; 481652520Sobrien const char *p, *q; 481750599Sobrien if (!first_time) 481850599Sobrien obstack_grow (&collect_obstack, " ", 1); 481950599Sobrien 482050599Sobrien first_time = FALSE; 482150599Sobrien obstack_grow (&collect_obstack, "'-", 2); 482250599Sobrien q = switches[i].part1; 482350599Sobrien while ((p = index (q,'\''))) 482450599Sobrien { 482550599Sobrien obstack_grow (&collect_obstack, q, p-q); 482650599Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 482750599Sobrien q = ++p; 482850599Sobrien } 482950599Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 483050599Sobrien obstack_grow (&collect_obstack, "'", 1); 483150599Sobrien 483250599Sobrien for (args = switches[i].args; args && *args; args++) 483350599Sobrien { 483450599Sobrien obstack_grow (&collect_obstack, " '", 2); 483550599Sobrien q = *args; 483650599Sobrien while ((p = index (q,'\''))) 483750599Sobrien { 483850599Sobrien obstack_grow (&collect_obstack, q, p-q); 483950599Sobrien obstack_grow (&collect_obstack, "'\\''", 4); 484050599Sobrien q = ++p; 484150599Sobrien } 484250599Sobrien obstack_grow (&collect_obstack, q, strlen (q)); 484350599Sobrien obstack_grow (&collect_obstack, "'", 1); 484450599Sobrien } 484550599Sobrien } 484650599Sobrien obstack_grow (&collect_obstack, "\0", 1); 484750599Sobrien putenv (obstack_finish (&collect_obstack)); 484850599Sobrien } 484950599Sobrien 485018334Speter /* Initialize the vector of specs to just the default. 485118334Speter This means one element containing 0s, as a terminator. */ 485218334Speter 485318334Speter compilers = (struct compiler *) xmalloc (sizeof default_compilers); 485418334Speter bcopy ((char *) default_compilers, (char *) compilers, 485518334Speter sizeof default_compilers); 485618334Speter n_compilers = n_default_compilers; 485718334Speter 485818334Speter /* Read specs from a file if there is one. */ 485918334Speter 486018346Speter#ifndef FREEBSD_NATIVE 486150599Sobrien machine_suffix = concat (spec_machine, dir_separator_str, 486250599Sobrien spec_version, dir_separator_str, NULL_PTR); 486350599Sobrien just_machine_suffix = concat (spec_machine, dir_separator_str, NULL_PTR); 486450599Sobrien#else /* FREEBSD_NATIVE */ 486550599Sobrien just_machine_suffix = ""; 486650599Sobrien#endif /* FREEBSD_NATIVE */ 486718334Speter 486818334Speter specs_file = find_a_file (&startfile_prefixes, "specs", R_OK); 486918334Speter /* Read the specs file unless it is a default one. */ 487018334Speter if (specs_file != 0 && strcmp (specs_file, "specs")) 487150599Sobrien read_specs (specs_file, TRUE); 487250599Sobrien else 487350599Sobrien init_spec (); 487418334Speter 487550599Sobrien /* We need to check standard_exec_prefix/just_machine_suffix/specs 487650599Sobrien for any override of as, ld and libraries. */ 487750599Sobrien specs_file = (char *) alloca (strlen (standard_exec_prefix) 487850599Sobrien + strlen (just_machine_suffix) 487950599Sobrien + sizeof ("specs")); 488050599Sobrien 488150599Sobrien strcpy (specs_file, standard_exec_prefix); 488250599Sobrien strcat (specs_file, just_machine_suffix); 488350599Sobrien strcat (specs_file, "specs"); 488450599Sobrien if (access (specs_file, R_OK) == 0) 488550599Sobrien read_specs (specs_file, TRUE); 488650599Sobrien 488718334Speter /* If not cross-compiling, look for startfiles in the standard places. */ 488850599Sobrien if (*cross_compile == '0') 488918334Speter { 489018334Speter#ifdef MD_EXEC_PREFIX 489150599Sobrien add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR); 489250599Sobrien add_prefix (&startfile_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR); 489318334Speter#endif 489418334Speter 489518334Speter#ifdef MD_STARTFILE_PREFIX 489650599Sobrien add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC", 489750599Sobrien 0, 0, NULL_PTR); 489818334Speter#endif 489918334Speter 490018334Speter#ifdef MD_STARTFILE_PREFIX_1 490150599Sobrien add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC", 490250599Sobrien 0, 0, NULL_PTR); 490318334Speter#endif 490418334Speter 490518334Speter /* If standard_startfile_prefix is relative, base it on 490618334Speter standard_exec_prefix. This lets us move the installed tree 490718334Speter as a unit. If GCC_EXEC_PREFIX is defined, base 490818334Speter standard_startfile_prefix on that as well. */ 490952520Sobrien if (IS_DIR_SEPARATOR (*standard_startfile_prefix) 491052520Sobrien || *standard_startfile_prefix == '$' 491152520Sobrien#ifdef HAVE_DOS_BASED_FILESYSTEM 491252520Sobrien /* Check for disk name on MS-DOS-based systems. */ 491350599Sobrien || (standard_startfile_prefix[1] == ':' 491452520Sobrien && (IS_DIR_SEPARATOR (standard_startfile_prefix[2]))) 491550599Sobrien#endif 491650599Sobrien ) 491750599Sobrien add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS", 491850599Sobrien 0, 0, NULL_PTR); 491918334Speter else 492018334Speter { 492118334Speter if (gcc_exec_prefix) 492218334Speter add_prefix (&startfile_prefixes, 492350599Sobrien concat (gcc_exec_prefix, machine_suffix, 492450599Sobrien standard_startfile_prefix, NULL_PTR), 492550599Sobrien NULL_PTR, 0, 0, NULL_PTR); 492618334Speter add_prefix (&startfile_prefixes, 492750599Sobrien concat (standard_exec_prefix, 492850599Sobrien machine_suffix, 492950599Sobrien standard_startfile_prefix, NULL_PTR), 493050599Sobrien NULL_PTR, 0, 0, NULL_PTR); 493118334Speter } 493218334Speter 493318346Speter#ifndef FREEBSD_NATIVE 493450599Sobrien add_prefix (&startfile_prefixes, standard_startfile_prefix_1, 493550599Sobrien "BINUTILS", 0, 0, NULL_PTR); 493650599Sobrien add_prefix (&startfile_prefixes, standard_startfile_prefix_2, 493750599Sobrien "BINUTILS", 0, 0, NULL_PTR); 493818334Speter#if 0 /* Can cause surprises, and one can use -B./ instead. */ 493950599Sobrien add_prefix (&startfile_prefixes, "./", NULL_PTR, 0, 1, NULL_PTR); 494018334Speter#endif 494118346Speter#endif /* FREEBSD_NATIVE */ 494218334Speter } 494318334Speter else 494418334Speter { 494552520Sobrien if (!IS_DIR_SEPARATOR (*standard_startfile_prefix) && gcc_exec_prefix) 494618334Speter add_prefix (&startfile_prefixes, 494750599Sobrien concat (gcc_exec_prefix, machine_suffix, 494850599Sobrien standard_startfile_prefix, NULL_PTR), 494950599Sobrien "BINUTILS", 0, 0, NULL_PTR); 495018334Speter } 495118334Speter 495252520Sobrien /* Process any user specified specs in the order given on the command 495352520Sobrien line. */ 495452520Sobrien for (uptr = user_specs_head; uptr; uptr = uptr->next) 495552520Sobrien { 495652520Sobrien char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK); 495752520Sobrien read_specs (filename ? filename : uptr->filename, FALSE); 495852520Sobrien } 495952520Sobrien 496018334Speter /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */ 496118334Speter if (gcc_exec_prefix) 496218334Speter { 496318334Speter char * temp = (char *) xmalloc (strlen (gcc_exec_prefix) 496418334Speter + strlen (spec_version) 496518334Speter + strlen (spec_machine) + 3); 496618334Speter strcpy (temp, gcc_exec_prefix); 496718334Speter strcat (temp, spec_machine); 496818334Speter strcat (temp, dir_separator_str); 496918334Speter strcat (temp, spec_version); 497018334Speter strcat (temp, dir_separator_str); 497118334Speter gcc_exec_prefix = temp; 497218334Speter } 497318334Speter 497418334Speter /* Now we have the specs. 497518334Speter Set the `valid' bits for switches that match anything in any spec. */ 497618334Speter 497718334Speter validate_all_switches (); 497818334Speter 497918334Speter /* Now that we have the switches and the specs, set 498018334Speter the subdirectory based on the options. */ 498118334Speter set_multilib_dir (); 498218334Speter 498318334Speter /* Warn about any switches that no pass was interested in. */ 498418334Speter 498552520Sobrien for (i = 0; (int)i < n_switches; i++) 498652520Sobrien if (! switches[i].validated) 498718334Speter error ("unrecognized option `-%s'", switches[i].part1); 498818334Speter 498918334Speter /* Obey some of the options. */ 499018334Speter 499118334Speter if (print_search_dirs) 499218334Speter { 499318334Speter printf ("install: %s%s\n", standard_exec_prefix, machine_suffix); 499418334Speter printf ("programs: %s\n", build_search_list (&exec_prefixes, "", 0)); 499518334Speter printf ("libraries: %s\n", build_search_list (&startfile_prefixes, "", 0)); 499618334Speter exit (0); 499718334Speter } 499818334Speter 499918334Speter if (print_file_name) 500018334Speter { 500118334Speter printf ("%s\n", find_file (print_file_name)); 500218334Speter exit (0); 500318334Speter } 500418334Speter 500518334Speter if (print_prog_name) 500618334Speter { 500718334Speter char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK); 500818334Speter printf ("%s\n", (newname ? newname : print_prog_name)); 500918334Speter exit (0); 501018334Speter } 501118334Speter 501218334Speter if (print_multi_lib) 501318334Speter { 501418334Speter print_multilib_info (); 501518334Speter exit (0); 501618334Speter } 501718334Speter 501818334Speter if (print_multi_directory) 501918334Speter { 502018334Speter if (multilib_dir == NULL) 502118334Speter printf (".\n"); 502218334Speter else 502318334Speter printf ("%s\n", multilib_dir); 502418334Speter exit (0); 502518334Speter } 502618334Speter 502750599Sobrien if (print_help_list) 502850599Sobrien { 502950599Sobrien display_help (); 503050599Sobrien 503150599Sobrien if (! verbose_flag) 503250599Sobrien { 503352520Sobrien printf ("\nFor bug reporting instructions, please see:\n"); 503457849Sobrien printf ("%s.\n", GCCBUGURL); 503550599Sobrien 503650599Sobrien exit (0); 503750599Sobrien } 503850599Sobrien 503950599Sobrien /* We do not exit here. Instead we have created a fake input file 504050599Sobrien called 'help-dummy' which needs to be compiled, and we pass this 504150599Sobrien on the the various sub-processes, along with the --help switch. */ 504250599Sobrien } 504350599Sobrien 504418334Speter if (verbose_flag) 504518334Speter { 504650599Sobrien int n; 504750599Sobrien 504850599Sobrien /* compiler_version is truncated at the first space when initialized 504950599Sobrien from version string, so truncate version_string at the first space 505050599Sobrien before comparing. */ 505150599Sobrien for (n = 0; version_string[n]; n++) 505250599Sobrien if (version_string[n] == ' ') 505350599Sobrien break; 505450599Sobrien 505550599Sobrien if (! strncmp (version_string, compiler_version, n) 505650599Sobrien && compiler_version[n] == 0) 505752520Sobrien notice ("gcc version %s\n", version_string); 505818334Speter else 505952520Sobrien notice ("gcc driver version %s executing gcc version %s\n", 506052520Sobrien version_string, compiler_version); 506118334Speter 506218334Speter if (n_infiles == 0) 506318334Speter exit (0); 506418334Speter } 506518334Speter 506650599Sobrien if (n_infiles == added_libraries) 506718346Speter fatal ("No input files specified"); 506818334Speter 506918334Speter /* Make a place to record the compiler output file names 507018334Speter that correspond to the input files. */ 507118334Speter 507250599Sobrien i = n_infiles; 507350599Sobrien i += lang_specific_extra_outfiles; 507452520Sobrien outfiles = (const char **) xmalloc (i * sizeof (char *)); 507552520Sobrien bzero ((char *) outfiles, i * sizeof (char *)); 507618334Speter 507718334Speter /* Record which files were specified explicitly as link input. */ 507818334Speter 507918334Speter explicit_link_files = xmalloc (n_infiles); 508018334Speter bzero (explicit_link_files, n_infiles); 508118334Speter 508252520Sobrien for (i = 0; (int)i < n_infiles; i++) 508318334Speter { 508418334Speter register struct compiler *cp = 0; 508518334Speter int this_file_error = 0; 508618334Speter 508718334Speter /* Tell do_spec what to substitute for %i. */ 508818334Speter 508918334Speter input_filename = infiles[i].name; 509018334Speter input_filename_length = strlen (input_filename); 509118334Speter input_file_number = i; 509218334Speter 509318334Speter /* Use the same thing in %o, unless cp->spec says otherwise. */ 509418334Speter 509518334Speter outfiles[i] = input_filename; 509618334Speter 509718334Speter /* Figure out which compiler from the file's suffix. */ 509818334Speter 509918334Speter cp = lookup_compiler (infiles[i].name, input_filename_length, 510018334Speter infiles[i].language); 510118334Speter 510218334Speter if (cp) 510318334Speter { 510418334Speter /* Ok, we found an applicable compiler. Run its spec. */ 510518334Speter /* First say how much of input_filename to substitute for %b */ 510652520Sobrien register const char *p; 510718334Speter int len; 510818334Speter 510950599Sobrien if (cp->spec[0][0] == '#') 511050599Sobrien error ("%s: %s compiler not installed on this system", 511150599Sobrien input_filename, &cp->spec[0][1]); 511250599Sobrien 511318334Speter input_basename = input_filename; 511418334Speter for (p = input_filename; *p; p++) 511552520Sobrien if (IS_DIR_SEPARATOR (*p)) 511618334Speter input_basename = p + 1; 511718334Speter 511818334Speter /* Find a suffix starting with the last period, 511918334Speter and set basename_length to exclude that suffix. */ 512018334Speter basename_length = strlen (input_basename); 512118334Speter p = input_basename + basename_length; 512218334Speter while (p != input_basename && *p != '.') --p; 512318334Speter if (*p == '.' && p != input_basename) 512418334Speter { 512518334Speter basename_length = p - input_basename; 512618334Speter input_suffix = p + 1; 512718334Speter } 512818334Speter else 512918334Speter input_suffix = ""; 513018334Speter 513118334Speter len = 0; 513218334Speter for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++) 513318334Speter if (cp->spec[j]) 513418334Speter len += strlen (cp->spec[j]); 513518334Speter 513652520Sobrien { 513752520Sobrien char *p1 = (char *) xmalloc (len + 1); 513852520Sobrien 513952520Sobrien len = 0; 514052520Sobrien for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++) 514152520Sobrien if (cp->spec[j]) 514252520Sobrien { 514352520Sobrien strcpy (p1 + len, cp->spec[j]); 514452520Sobrien len += strlen (cp->spec[j]); 514552520Sobrien } 514652520Sobrien 514752520Sobrien value = do_spec (p1); 514852520Sobrien free (p1); 514952520Sobrien } 515018334Speter if (value < 0) 515118334Speter this_file_error = 1; 515218334Speter } 515318334Speter 515418334Speter /* If this file's name does not contain a recognized suffix, 515518334Speter record it as explicit linker input. */ 515618334Speter 515718334Speter else 515818334Speter explicit_link_files[i] = 1; 515918334Speter 516018334Speter /* Clear the delete-on-failure queue, deleting the files in it 516118334Speter if this compilation failed. */ 516218334Speter 516318334Speter if (this_file_error) 516418334Speter { 516518334Speter delete_failure_queue (); 516618334Speter error_count++; 516718334Speter } 516818334Speter /* If this compilation succeeded, don't delete those files later. */ 516918334Speter clear_failure_queue (); 517018334Speter } 517118334Speter 517252520Sobrien if (error_count == 0) 517352520Sobrien { 517452520Sobrien /* Make sure INPUT_FILE_NUMBER points to first available open 517552520Sobrien slot. */ 517652520Sobrien input_file_number = n_infiles; 517752520Sobrien if (lang_specific_pre_link ()) 517852520Sobrien error_count++; 517952520Sobrien } 518050599Sobrien 518118334Speter /* Run ld to link all the compiler output files. */ 518218334Speter 518318334Speter if (error_count == 0) 518418334Speter { 518518334Speter int tmp = execution_count; 518618334Speter 518750599Sobrien /* We'll use ld if we can't find collect2. */ 518850599Sobrien if (! strcmp (linker_name_spec, "collect2")) 518950599Sobrien { 519050599Sobrien char *s = find_a_file (&exec_prefixes, "collect2", X_OK); 519150599Sobrien if (s == NULL) 519250599Sobrien linker_name_spec = "ld"; 519350599Sobrien } 519418334Speter /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 519518334Speter for collect. */ 519618334Speter putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH="); 519718334Speter putenv_from_prefixes (&startfile_prefixes, "LIBRARY_PATH="); 519818334Speter 519918334Speter value = do_spec (link_command_spec); 520018334Speter if (value < 0) 520118334Speter error_count = 1; 520218334Speter linker_was_run = (tmp != execution_count); 520318334Speter } 520418334Speter 520518334Speter /* Warn if a -B option was specified but the prefix was never used. */ 520618334Speter unused_prefix_warnings (&exec_prefixes); 520718334Speter unused_prefix_warnings (&startfile_prefixes); 520818334Speter 520918334Speter /* If options said don't run linker, 521018334Speter complain about input files to be given to the linker. */ 521118334Speter 521218334Speter if (! linker_was_run && error_count == 0) 521352520Sobrien for (i = 0; (int)i < n_infiles; i++) 521418334Speter if (explicit_link_files[i]) 521518334Speter error ("%s: linker input file unused since linking not done", 521618334Speter outfiles[i]); 521718334Speter 521818334Speter /* Delete some or all of the temporary files we made. */ 521918334Speter 522018334Speter if (error_count) 522118334Speter delete_failure_queue (); 522218334Speter delete_temp_files (); 522318334Speter 522450599Sobrien if (print_help_list) 522550599Sobrien { 522652520Sobrien printf ("\nFor bug reporting instructions, please see:\n"); 522757849Sobrien printf ("%s\n", GCCBUGURL); 522850599Sobrien } 522950599Sobrien 523018334Speter exit (error_count > 0 ? (signal_count ? 2 : 1) : 0); 523118334Speter /* NOTREACHED */ 523218334Speter return 0; 523318334Speter} 523418334Speter 523518334Speter/* Find the proper compilation spec for the file name NAME, 523618334Speter whose length is LENGTH. LANGUAGE is the specified language, 523750599Sobrien or 0 if this file is to be passed to the linker. */ 523818334Speter 523918334Speterstatic struct compiler * 524018334Speterlookup_compiler (name, length, language) 524152520Sobrien const char *name; 524250599Sobrien size_t length; 524352520Sobrien const char *language; 524418334Speter{ 524518334Speter struct compiler *cp; 524618334Speter 524750599Sobrien /* If this was specified by the user to be a linker input, indicate that. */ 524850599Sobrien if (language != 0 && language[0] == '*') 524950599Sobrien return 0; 525050599Sobrien 525150599Sobrien /* Otherwise, look for the language, if one is spec'd. */ 525218334Speter if (language != 0) 525318334Speter { 525418334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 525550599Sobrien if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language)) 525650599Sobrien return cp; 525750599Sobrien 525818334Speter error ("language %s not recognized", language); 525950599Sobrien return 0; 526018334Speter } 526118334Speter 526218334Speter /* Look for a suffix. */ 526318334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 526418334Speter { 526518334Speter if (/* The suffix `-' matches only the file name `-'. */ 526618334Speter (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 526750599Sobrien || (strlen (cp->suffix) < length 526850599Sobrien /* See if the suffix matches the end of NAME. */ 526918334Speter#ifdef OS2 527050599Sobrien && ((!strcmp (cp->suffix, 527150599Sobrien name + length - strlen (cp->suffix)) 527250599Sobrien || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) 527350599Sobrien && !strcasecmp (cp->suffix, 527450599Sobrien name + length - strlen (cp->suffix))) 527518334Speter#else 527650599Sobrien && !strcmp (cp->suffix, 527750599Sobrien name + length - strlen (cp->suffix)) 527818334Speter#endif 527950599Sobrien )) 528018334Speter { 528118334Speter if (cp->spec[0][0] == '@') 528218334Speter { 528318334Speter struct compiler *new; 528450599Sobrien 528518334Speter /* An alias entry maps a suffix to a language. 528618334Speter Search for the language; pass 0 for NAME and LENGTH 528718334Speter to avoid infinite recursion if language not found. 528818334Speter Construct the new compiler spec. */ 528918334Speter language = cp->spec[0] + 1; 529018334Speter new = (struct compiler *) xmalloc (sizeof (struct compiler)); 529118334Speter new->suffix = cp->suffix; 529218334Speter bcopy ((char *) lookup_compiler (NULL_PTR, 0, language)->spec, 529318334Speter (char *) new->spec, sizeof new->spec); 529418334Speter return new; 529518334Speter } 529650599Sobrien 529718334Speter /* A non-alias entry: return it. */ 529818334Speter return cp; 529918334Speter } 530018334Speter } 530118334Speter 530218334Speter return 0; 530318334Speter} 530418334Speter 530552520SobrienPTR 530618334Speterxmalloc (size) 530752520Sobrien size_t size; 530818334Speter{ 530952520Sobrien register PTR value = (PTR) malloc (size); 531018334Speter if (value == 0) 531118334Speter fatal ("virtual memory exhausted"); 531218334Speter return value; 531318334Speter} 531418334Speter 531552520SobrienPTR 531652520Sobrienxrealloc (old, size) 531752520Sobrien PTR old; 531852520Sobrien size_t size; 531918334Speter{ 532052520Sobrien register PTR ptr; 532152520Sobrien if (old) 532252520Sobrien ptr = (PTR) realloc (old, size); 532352520Sobrien else 532452520Sobrien ptr = (PTR) malloc (size); 532552520Sobrien if (ptr == 0) 532618334Speter fatal ("virtual memory exhausted"); 532752520Sobrien return ptr; 532818334Speter} 532918334Speter 533018334Speterstatic char * 533118334Spetersave_string (s, len) 533252520Sobrien const char *s; 533352520Sobrien int len; 533418334Speter{ 533518334Speter register char *result = xmalloc (len + 1); 533618334Speter 533718334Speter bcopy (s, result, len); 533818334Speter result[len] = 0; 533918334Speter return result; 534018334Speter} 534118334Speter 534218334Speterstatic void 534318334Speterpfatal_with_name (name) 534452520Sobrien const char *name; 534518334Speter{ 534652520Sobrien perror_with_name (name); 534752520Sobrien delete_temp_files (); 534852520Sobrien exit (1); 534918334Speter} 535018334Speter 535118334Speterstatic void 535218334Speterperror_with_name (name) 535352520Sobrien const char *name; 535418334Speter{ 535552520Sobrien error ("%s: %s", name, xstrerror (errno)); 535618334Speter} 535718334Speter 535818334Speterstatic void 535950599Sobrienpfatal_pexecute (errmsg_fmt, errmsg_arg) 536052520Sobrien const char *errmsg_fmt; 536152520Sobrien const char *errmsg_arg; 536218334Speter{ 536350599Sobrien if (errmsg_arg) 536450599Sobrien { 536552520Sobrien int save_errno = errno; 536652520Sobrien 536750599Sobrien /* Space for trailing '\0' is in %s. */ 536850599Sobrien char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg)); 536950599Sobrien sprintf (msg, errmsg_fmt, errmsg_arg); 537050599Sobrien errmsg_fmt = msg; 537152520Sobrien 537252520Sobrien errno = save_errno; 537350599Sobrien } 537450599Sobrien 537552520Sobrien pfatal_with_name (errmsg_fmt); 537618334Speter} 537718334Speter 537818334Speter/* More 'friendly' abort that prints the line and file. 537918334Speter config.h can #define abort fancy_abort if you like that sort of thing. */ 538018334Speter 538118334Spetervoid 538218334Speterfancy_abort () 538318334Speter{ 538418334Speter fatal ("Internal gcc abort."); 538518334Speter} 538618334Speter 538718334Speter/* Output an error message and exit */ 538818334Speter 538952520Sobrienvoid 539052520Sobrienfatal VPROTO((const char *msgid, ...)) 539118334Speter{ 539252520Sobrien#ifndef ANSI_PROTOTYPES 539352520Sobrien const char *msgid; 539418334Speter#endif 539518334Speter va_list ap; 539618334Speter 539752520Sobrien VA_START (ap, msgid); 539818334Speter 539952520Sobrien#ifndef ANSI_PROTOTYPES 540052520Sobrien msgid = va_arg (ap, const char *); 540118334Speter#endif 540218334Speter 540318334Speter fprintf (stderr, "%s: ", programname); 540452520Sobrien vfprintf (stderr, _(msgid), ap); 540518334Speter va_end (ap); 540618334Speter fprintf (stderr, "\n"); 540718334Speter delete_temp_files (); 540818334Speter exit (1); 540918334Speter} 541018334Speter 541118334Speterstatic void 541252520Sobrienerror VPROTO((const char *msgid, ...)) 541318334Speter{ 541452520Sobrien#ifndef ANSI_PROTOTYPES 541552520Sobrien const char *msgid; 541618334Speter#endif 541718334Speter va_list ap; 541818334Speter 541952520Sobrien VA_START (ap, msgid); 542018334Speter 542152520Sobrien#ifndef ANSI_PROTOTYPES 542252520Sobrien msgid = va_arg (ap, const char *); 542318334Speter#endif 542418334Speter 542518334Speter fprintf (stderr, "%s: ", programname); 542652520Sobrien vfprintf (stderr, _(msgid), ap); 542718334Speter va_end (ap); 542818334Speter 542918334Speter fprintf (stderr, "\n"); 543018334Speter} 543152520Sobrien 543252520Sobrienstatic void 543352520Sobriennotice VPROTO((const char *msgid, ...)) 543452520Sobrien{ 543552520Sobrien#ifndef ANSI_PROTOTYPES 543652520Sobrien const char *msgid; 543752520Sobrien#endif 543852520Sobrien va_list ap; 543952520Sobrien 544052520Sobrien VA_START (ap, msgid); 544152520Sobrien 544252520Sobrien#ifndef ANSI_PROTOTYPES 544352520Sobrien msgid = va_arg (ap, const char *); 544452520Sobrien#endif 544552520Sobrien 544652520Sobrien vfprintf (stderr, _(msgid), ap); 544752520Sobrien va_end (ap); 544852520Sobrien} 544952520Sobrien 545018334Speter 545118334Speterstatic void 545218334Spetervalidate_all_switches () 545318334Speter{ 545418334Speter struct compiler *comp; 545552520Sobrien register const char *p; 545618334Speter register char c; 545718334Speter struct spec_list *spec; 545818334Speter 545918334Speter for (comp = compilers; comp->spec[0]; comp++) 546018334Speter { 546150599Sobrien size_t i; 546218334Speter for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++) 546318334Speter { 546418334Speter p = comp->spec[i]; 546550599Sobrien while ((c = *p++)) 546618334Speter if (c == '%' && *p == '{') 546718334Speter /* We have a switch spec. */ 546818334Speter validate_switches (p + 1); 546918334Speter } 547018334Speter } 547118334Speter 547250599Sobrien /* look through the linked list of specs read from the specs file */ 547318334Speter for (spec = specs; spec ; spec = spec->next) 547418334Speter { 547550599Sobrien p = *(spec->ptr_spec); 547650599Sobrien while ((c = *p++)) 547718334Speter if (c == '%' && *p == '{') 547818334Speter /* We have a switch spec. */ 547918334Speter validate_switches (p + 1); 548018334Speter } 548118334Speter 548218334Speter p = link_command_spec; 548350599Sobrien while ((c = *p++)) 548418334Speter if (c == '%' && *p == '{') 548518334Speter /* We have a switch spec. */ 548618334Speter validate_switches (p + 1); 548718334Speter} 548818334Speter 548918334Speter/* Look at the switch-name that comes after START 549018334Speter and mark as valid all supplied switches that match it. */ 549118334Speter 549218334Speterstatic void 549318334Spetervalidate_switches (start) 549452520Sobrien const char *start; 549518334Speter{ 549652520Sobrien register const char *p = start; 549752520Sobrien const char *filter; 549818334Speter register int i; 549918334Speter int suffix = 0; 550018334Speter 550118334Speter if (*p == '|') 550218334Speter ++p; 550318334Speter 550418334Speter if (*p == '!') 550518334Speter ++p; 550618334Speter 550718334Speter if (*p == '.') 550818334Speter suffix = 1, ++p; 550918334Speter 551018334Speter filter = p; 551118334Speter while (*p != ':' && *p != '}') p++; 551218334Speter 551318334Speter if (suffix) 551418334Speter ; 551518334Speter else if (p[-1] == '*') 551618334Speter { 551718334Speter /* Mark all matching switches as valid. */ 551818334Speter --p; 551918334Speter for (i = 0; i < n_switches; i++) 552018334Speter if (!strncmp (switches[i].part1, filter, p - filter)) 552152520Sobrien switches[i].validated = 1; 552218334Speter } 552318334Speter else 552418334Speter { 552518334Speter /* Mark an exact matching switch as valid. */ 552618334Speter for (i = 0; i < n_switches; i++) 552718334Speter { 552818334Speter if (!strncmp (switches[i].part1, filter, p - filter) 552918334Speter && switches[i].part1[p - filter] == 0) 553052520Sobrien switches[i].validated = 1; 553118334Speter } 553218334Speter } 553318334Speter} 553418334Speter 553550599Sobrien/* Check whether a particular argument was used. The first time we 553650599Sobrien canonicalize the switches to keep only the ones we care about. */ 553718334Speter 553818334Speterstatic int 553918334Speterused_arg (p, len) 554052520Sobrien const char *p; 554118334Speter int len; 554218334Speter{ 554350599Sobrien struct mswitchstr { 554450599Sobrien char *str; 554550599Sobrien char *replace; 554650599Sobrien int len; 554750599Sobrien int rep_len; 554850599Sobrien }; 554918334Speter 555050599Sobrien static struct mswitchstr *mswitches; 555150599Sobrien static int n_mswitches; 555250599Sobrien int i, j; 555350599Sobrien 555450599Sobrien if (!mswitches) 555550599Sobrien { 555650599Sobrien struct mswitchstr *matches; 555750599Sobrien char *q; 555850599Sobrien int cnt = 0; 555950599Sobrien 556050599Sobrien /* Break multilib_matches into the component strings of string and replacement 556150599Sobrien string */ 556250599Sobrien for (q = multilib_matches; *q != '\0'; q++) 556350599Sobrien if (*q == ';') 556450599Sobrien cnt++; 556550599Sobrien 556650599Sobrien matches = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt); 556750599Sobrien i = 0; 556850599Sobrien q = multilib_matches; 556950599Sobrien while (*q != '\0') 557050599Sobrien { 557150599Sobrien matches[i].str = q; 557250599Sobrien while (*q != ' ') 557350599Sobrien { 557450599Sobrien if (*q == '\0') 557550599Sobrien abort (); 557650599Sobrien q++; 557750599Sobrien } 557850599Sobrien *q = '\0'; 557950599Sobrien matches[i].len = q - matches[i].str; 558050599Sobrien 558150599Sobrien matches[i].replace = ++q; 558250599Sobrien while (*q != ';' && *q != '\0') 558350599Sobrien { 558450599Sobrien if (*q == ' ') 558550599Sobrien abort (); 558650599Sobrien q++; 558750599Sobrien } 558850599Sobrien matches[i].rep_len = q - matches[i].replace; 558950599Sobrien i++; 559050599Sobrien if (*q == ';') 559150599Sobrien *q++ = '\0'; 559250599Sobrien else 559350599Sobrien break; 559450599Sobrien } 559550599Sobrien 559650599Sobrien /* Now build a list of the replacement string for switches that we care 559750599Sobrien about. Make sure we allocate at least one entry. This prevents 559850599Sobrien xmalloc from calling fatal, and prevents us from re-executing this 559950599Sobrien block of code. */ 560050599Sobrien mswitches 560150599Sobrien = (struct mswitchstr *) xmalloc ((sizeof (struct mswitchstr)) 560250599Sobrien * (n_switches ? n_switches : 1)); 560350599Sobrien for (i = 0; i < n_switches; i++) 560450599Sobrien { 560550599Sobrien int xlen = strlen (switches[i].part1); 560650599Sobrien for (j = 0; j < cnt; j++) 560750599Sobrien if (xlen == matches[j].len && ! strcmp (switches[i].part1, matches[j].str)) 560850599Sobrien { 560950599Sobrien mswitches[n_mswitches].str = matches[j].replace; 561050599Sobrien mswitches[n_mswitches].len = matches[j].rep_len; 561150599Sobrien mswitches[n_mswitches].replace = (char *)0; 561250599Sobrien mswitches[n_mswitches].rep_len = 0; 561350599Sobrien n_mswitches++; 561450599Sobrien break; 561550599Sobrien } 561650599Sobrien } 561750599Sobrien } 561850599Sobrien 561950599Sobrien for (i = 0; i < n_mswitches; i++) 562050599Sobrien if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len)) 562118334Speter return 1; 562250599Sobrien 562318334Speter return 0; 562418334Speter} 562518334Speter 562618334Speterstatic int 562718334Speterdefault_arg (p, len) 562852520Sobrien const char *p; 562918334Speter int len; 563018334Speter{ 563150599Sobrien char *start, *end; 563218334Speter 563350599Sobrien for (start = multilib_defaults; *start != '\0'; start = end+1) 563450599Sobrien { 563550599Sobrien while (*start == ' ' || *start == '\t') 563650599Sobrien start++; 563718334Speter 563850599Sobrien if (*start == '\0') 563950599Sobrien break; 564050599Sobrien 564150599Sobrien for (end = start+1; *end != ' ' && *end != '\t' && *end != '\0'; end++) 564250599Sobrien ; 564350599Sobrien 564450599Sobrien if ((end - start) == len && strncmp (p, start, len) == 0) 564550599Sobrien return 1; 564650599Sobrien 564750599Sobrien if (*end == '\0') 564850599Sobrien break; 564950599Sobrien } 565050599Sobrien 565118334Speter return 0; 565218334Speter} 565318334Speter 565418334Speter/* Work out the subdirectory to use based on the 565518334Speter options. The format of multilib_select is a list of elements. 565618334Speter Each element is a subdirectory name followed by a list of options 565718334Speter followed by a semicolon. gcc will consider each line in turn. If 565818334Speter none of the options beginning with an exclamation point are 565918334Speter present, and all of the other options are present, that 566018334Speter subdirectory will be used. */ 566118334Speter 566218334Speterstatic void 566318334Speterset_multilib_dir () 566418334Speter{ 566518334Speter char *p = multilib_select; 566618334Speter int this_path_len; 566718334Speter char *this_path, *this_arg; 566818334Speter int not_arg; 566918334Speter int ok; 567018334Speter 567118334Speter while (*p != '\0') 567218334Speter { 567318334Speter /* Ignore newlines. */ 567418334Speter if (*p == '\n') 567518334Speter { 567618334Speter ++p; 567718334Speter continue; 567818334Speter } 567918334Speter 568018334Speter /* Get the initial path. */ 568118334Speter this_path = p; 568218334Speter while (*p != ' ') 568318334Speter { 568418334Speter if (*p == '\0') 568518334Speter abort (); 568618334Speter ++p; 568718334Speter } 568818334Speter this_path_len = p - this_path; 568918334Speter 569018334Speter /* Check the arguments. */ 569118334Speter ok = 1; 569218334Speter ++p; 569318334Speter while (*p != ';') 569418334Speter { 569518334Speter if (*p == '\0') 569618334Speter abort (); 569718334Speter 569818334Speter if (! ok) 569918334Speter { 570018334Speter ++p; 570118334Speter continue; 570218334Speter } 570318334Speter 570418334Speter this_arg = p; 570518334Speter while (*p != ' ' && *p != ';') 570618334Speter { 570718334Speter if (*p == '\0') 570818334Speter abort (); 570918334Speter ++p; 571018334Speter } 571118334Speter 571218334Speter if (*this_arg != '!') 571318334Speter not_arg = 0; 571418334Speter else 571518334Speter { 571618334Speter not_arg = 1; 571718334Speter ++this_arg; 571818334Speter } 571918334Speter 572018334Speter /* If this is a default argument, we can just ignore it. 572118334Speter This is true even if this_arg begins with '!'. Beginning 572218334Speter with '!' does not mean that this argument is necessarily 572318334Speter inappropriate for this library: it merely means that 572418334Speter there is a more specific library which uses this 572518334Speter argument. If this argument is a default, we need not 572618334Speter consider that more specific library. */ 572718334Speter if (! default_arg (this_arg, p - this_arg)) 572818334Speter { 572918334Speter ok = used_arg (this_arg, p - this_arg); 573018334Speter if (not_arg) 573118334Speter ok = ! ok; 573218334Speter } 573318334Speter 573418334Speter if (*p == ' ') 573518334Speter ++p; 573618334Speter } 573718334Speter 573818334Speter if (ok) 573918334Speter { 574018334Speter if (this_path_len != 1 574118334Speter || this_path[0] != '.') 574218334Speter { 574352520Sobrien char * new_multilib_dir = xmalloc (this_path_len + 1); 574452520Sobrien strncpy (new_multilib_dir, this_path, this_path_len); 574552520Sobrien new_multilib_dir[this_path_len] = '\0'; 574652520Sobrien multilib_dir = new_multilib_dir; 574718334Speter } 574818334Speter break; 574918334Speter } 575018334Speter 575118334Speter ++p; 575218334Speter } 575318334Speter} 575418334Speter 575518334Speter/* Print out the multiple library subdirectory selection 575618334Speter information. This prints out a series of lines. Each line looks 575718334Speter like SUBDIRECTORY;@OPTION@OPTION, with as many options as is 575818334Speter required. Only the desired options are printed out, the negative 575918334Speter matches. The options are print without a leading dash. There are 576018334Speter no spaces to make it easy to use the information in the shell. 576118334Speter Each subdirectory is printed only once. This assumes the ordering 576218334Speter generated by the genmultilib script. */ 576318334Speter 576418334Speterstatic void 576518334Speterprint_multilib_info () 576618334Speter{ 576718334Speter char *p = multilib_select; 576818334Speter char *last_path = 0, *this_path; 576918334Speter int skip; 577018334Speter int last_path_len = 0; 577118334Speter 577218334Speter while (*p != '\0') 577318334Speter { 577418334Speter /* Ignore newlines. */ 577518334Speter if (*p == '\n') 577618334Speter { 577718334Speter ++p; 577818334Speter continue; 577918334Speter } 578018334Speter 578118334Speter /* Get the initial path. */ 578218334Speter this_path = p; 578318334Speter while (*p != ' ') 578418334Speter { 578518334Speter if (*p == '\0') 578618334Speter abort (); 578718334Speter ++p; 578818334Speter } 578918334Speter 579018334Speter /* If this is a duplicate, skip it. */ 579118334Speter skip = (last_path != 0 && p - this_path == last_path_len 579218334Speter && ! strncmp (last_path, this_path, last_path_len)); 579318334Speter 579418334Speter last_path = this_path; 579518334Speter last_path_len = p - this_path; 579618334Speter 579718334Speter /* If this directory requires any default arguments, we can skip 579818334Speter it. We will already have printed a directory identical to 579918334Speter this one which does not require that default argument. */ 580018334Speter if (! skip) 580118334Speter { 580218334Speter char *q; 580318334Speter 580418334Speter q = p + 1; 580518334Speter while (*q != ';') 580618334Speter { 580718334Speter char *arg; 580818334Speter 580918334Speter if (*q == '\0') 581018334Speter abort (); 581118334Speter 581218334Speter if (*q == '!') 581318334Speter arg = NULL; 581418334Speter else 581518334Speter arg = q; 581618334Speter 581718334Speter while (*q != ' ' && *q != ';') 581818334Speter { 581918334Speter if (*q == '\0') 582018334Speter abort (); 582118334Speter ++q; 582218334Speter } 582318334Speter 582418334Speter if (arg != NULL 582518334Speter && default_arg (arg, q - arg)) 582618334Speter { 582718334Speter skip = 1; 582818334Speter break; 582918334Speter } 583018334Speter 583118334Speter if (*q == ' ') 583218334Speter ++q; 583318334Speter } 583418334Speter } 583518334Speter 583618334Speter if (! skip) 583718334Speter { 583818334Speter char *p1; 583918334Speter 584018334Speter for (p1 = last_path; p1 < p; p1++) 584118334Speter putchar (*p1); 584218334Speter putchar (';'); 584318334Speter } 584418334Speter 584518334Speter ++p; 584618334Speter while (*p != ';') 584718334Speter { 584818334Speter int use_arg; 584918334Speter 585018334Speter if (*p == '\0') 585118334Speter abort (); 585218334Speter 585318334Speter if (skip) 585418334Speter { 585518334Speter ++p; 585618334Speter continue; 585718334Speter } 585818334Speter 585918334Speter use_arg = *p != '!'; 586018334Speter 586118334Speter if (use_arg) 586218334Speter putchar ('@'); 586318334Speter 586418334Speter while (*p != ' ' && *p != ';') 586518334Speter { 586618334Speter if (*p == '\0') 586718334Speter abort (); 586818334Speter if (use_arg) 586918334Speter putchar (*p); 587018334Speter ++p; 587118334Speter } 587218334Speter 587318334Speter if (*p == ' ') 587418334Speter ++p; 587518334Speter } 587618334Speter 587718334Speter if (! skip) 587850599Sobrien { 587950599Sobrien /* If there are extra options, print them now */ 588050599Sobrien if (multilib_extra && *multilib_extra) 588150599Sobrien { 588250599Sobrien int print_at = TRUE; 588350599Sobrien char *q; 588418334Speter 588550599Sobrien for (q = multilib_extra; *q != '\0'; q++) 588650599Sobrien { 588750599Sobrien if (*q == ' ') 588850599Sobrien print_at = TRUE; 588950599Sobrien else 589050599Sobrien { 589150599Sobrien if (print_at) 589250599Sobrien putchar ('@'); 589350599Sobrien putchar (*q); 589450599Sobrien print_at = FALSE; 589550599Sobrien } 589650599Sobrien } 589750599Sobrien } 589850599Sobrien putchar ('\n'); 589950599Sobrien } 590050599Sobrien 590118334Speter ++p; 590218334Speter } 590318334Speter} 5904