gcc.c revision 18346
118334Speter/* Compiler driver program that can handle many languages. 218334Speter Copyright (C) 1987, 89, 92, 93, 94, 1995 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 2418334Speter/* This program is the user interface to the C compiler and possibly to 2518334Speterother compilers. It is used because compilation is a complicated procedure 2618334Speterwhich involves running several programs and passing temporary files between 2718334Speterthem, forwarding the users switches to those programs selectively, 2818334Speterand deleting the temporary files at the end. 2918334Speter 3018334SpeterCC recognizes how to compile each input file by suffixes in the file names. 3118334SpeterOnce it knows which kind of compilation to perform, the procedure for 3218334Spetercompilation is specified by a string called a "spec". */ 3318334Speter 3418334Speter#include <sys/types.h> 3518346Speter#include <sys/wait.h> 3618334Speter#include <ctype.h> 3718334Speter#include <signal.h> 3818334Speter#include <sys/stat.h> 3918334Speter#include <errno.h> 4018334Speter 4118334Speter#ifndef _WIN32 4218334Speter#include <sys/file.h> /* May get R_OK, etc. on some systems. */ 4318334Speter#else 4418334Speter#include <process.h> 4518334Speterint __spawnv (); 4618334Speterint __spawnvp (); 4718334Speter#endif 4818334Speter 4918334Speter#include "config.h" 5018334Speter#include "obstack.h" 5118334Speter#ifdef __STDC__ 5218334Speter#include <stdarg.h> 5318334Speter#else 5418334Speter#include <varargs.h> 5518334Speter#endif 5618334Speter#include <stdio.h> 5718346Speter#include <stdlib.h> 5818346Speter#include <unistd.h> 5918346Speter#include <string.h> 6018334Speter 6118334Speter/* Include multi-lib information. */ 6218334Speter#include "multilib.h" 6318334Speter 6418334Speter#ifndef R_OK 6518334Speter#define R_OK 4 6618334Speter#define W_OK 2 6718334Speter#define X_OK 1 6818334Speter#endif 6918334Speter 7018334Speter#ifndef WIFSIGNALED 7118334Speter#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f) 7218334Speter#endif 7318334Speter#ifndef WTERMSIG 7418334Speter#define WTERMSIG(S) ((S) & 0x7f) 7518334Speter#endif 7618334Speter#ifndef WIFEXITED 7718334Speter#define WIFEXITED(S) (((S) & 0xff) == 0) 7818334Speter#endif 7918334Speter#ifndef WEXITSTATUS 8018334Speter#define WEXITSTATUS(S) (((S) & 0xff00) >> 8) 8118334Speter#endif 8218334Speter 8318334Speter/* Add prototype support. */ 8418334Speter#ifndef PROTO 8518334Speter#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) 8618334Speter#define PROTO(ARGS) ARGS 8718334Speter#else 8818334Speter#define PROTO(ARGS) () 8918334Speter#endif 9018334Speter#endif 9118334Speter 9218334Speter#ifndef VPROTO 9318334Speter#ifdef __STDC__ 9418334Speter#define PVPROTO(ARGS) ARGS 9518334Speter#define VPROTO(ARGS) ARGS 9618334Speter#define VA_START(va_list,var) va_start(va_list,var) 9718334Speter#else 9818334Speter#define PVPROTO(ARGS) () 9918334Speter#define VPROTO(ARGS) (va_alist) va_dcl 10018334Speter#define VA_START(va_list,var) va_start(va_list) 10118334Speter#endif 10218334Speter#endif 10318334Speter 10418334Speter/* Define a generic NULL if one hasn't already been defined. */ 10518334Speter 10618334Speter#ifndef NULL 10718334Speter#define NULL 0 10818334Speter#endif 10918334Speter 11018334Speter/* Define O_RDONLY if the system hasn't defined it for us. */ 11118334Speter#ifndef O_RDONLY 11218334Speter#define O_RDONLY 0 11318334Speter#endif 11418334Speter 11518334Speter#ifndef GENERIC_PTR 11618334Speter#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) 11718334Speter#define GENERIC_PTR void * 11818334Speter#else 11918334Speter#define GENERIC_PTR char * 12018334Speter#endif 12118334Speter#endif 12218334Speter 12318334Speter#ifndef NULL_PTR 12418334Speter#define NULL_PTR ((GENERIC_PTR)0) 12518334Speter#endif 12618334Speter 12718334Speter#ifdef USG 12818334Speter#define vfork fork 12918334Speter#endif /* USG */ 13018334Speter 13118334Speter/* On MSDOS, write temp files in current dir 13218334Speter because there's no place else we can expect to use. */ 13318334Speter#ifdef __MSDOS__ 13418334Speter#ifndef P_tmpdir 13518334Speter#define P_tmpdir "." 13618334Speter#endif 13718334Speter#endif 13818334Speter 13918334Speter/* Test if something is a normal file. */ 14018334Speter#ifndef S_ISREG 14118334Speter#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 14218334Speter#endif 14318334Speter 14418334Speter/* Test if something is a directory. */ 14518334Speter#ifndef S_ISDIR 14618334Speter#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 14718334Speter#endif 14818334Speter 14918334Speter/* By default there is no special suffix for executables. */ 15018334Speter#ifndef EXECUTABLE_SUFFIX 15118334Speter#define EXECUTABLE_SUFFIX "" 15218334Speter#endif 15318334Speter 15418334Speter/* By default, the suffix for object files is ".o". */ 15518334Speter#ifdef OBJECT_SUFFIX 15618334Speter#define HAVE_OBJECT_SUFFIX 15718334Speter#else 15818334Speter#define OBJECT_SUFFIX ".o" 15918334Speter#endif 16018334Speter 16118334Speter/* By default, colon separates directories in a path. */ 16218334Speter#ifndef PATH_SEPARATOR 16318334Speter#define PATH_SEPARATOR ':' 16418334Speter#endif 16518334Speter 16618334Speter#ifndef DIR_SEPARATOR 16718334Speter#define DIR_SEPARATOR '/' 16818334Speter#endif 16918334Speter 17018334Speterstatic char dir_separator_str[] = {DIR_SEPARATOR, 0}; 17118334Speter 17218334Speter#define obstack_chunk_alloc xmalloc 17318334Speter#define obstack_chunk_free free 17418334Speter 17518334Speterextern void free (); 17618334Speterextern char *getenv (); 17718334Speter 17818334Speter#ifndef errno 17918334Speterextern int errno; 18018334Speter#endif 18118334Speter 18218334Speterextern int sys_nerr; 18318334Speter#ifndef HAVE_STRERROR 18418334Speter#if defined(bsd4_4) 18518334Speterextern const char *const sys_errlist[]; 18618334Speter#else 18718334Speterextern char *sys_errlist[]; 18818334Speter#endif 18918334Speter#else 19018334Speterextern char *strerror(); 19118334Speter#endif 19218334Speter 19318334Speterextern int execv (), execvp (); 19418334Speter 19518334Speter/* If a stage of compilation returns an exit status >= 1, 19618334Speter compilation of that file ceases. */ 19718334Speter 19818334Speter#define MIN_FATAL_STATUS 1 19918334Speter 20018334Speter/* Flag saying to print the directories gcc will search through looking for 20118334Speter programs, libraries, etc. */ 20218334Speter 20318334Speterstatic int print_search_dirs; 20418334Speter 20518334Speter/* Flag saying to print the full filename of this file 20618334Speter as found through our usual search mechanism. */ 20718334Speter 20818334Speterstatic char *print_file_name = NULL; 20918334Speter 21018334Speter/* As print_file_name, but search for executable file. */ 21118334Speter 21218334Speterstatic char *print_prog_name = NULL; 21318334Speter 21418334Speter/* Flag saying to print the relative path we'd use to 21518334Speter find libgcc.a given the current compiler flags. */ 21618334Speter 21718334Speterstatic int print_multi_directory; 21818334Speter 21918334Speter/* Flag saying to print the list of subdirectories and 22018334Speter compiler flags used to select them in a standard form. */ 22118334Speter 22218334Speterstatic int print_multi_lib; 22318334Speter 22418334Speter/* Flag indicating whether we should print the command and arguments */ 22518334Speter 22618334Speterstatic int verbose_flag; 22718334Speter 22818334Speter/* Nonzero means write "temp" files in source directory 22918334Speter and use the source file's name in them, and don't delete them. */ 23018334Speter 23118334Speterstatic int save_temps_flag; 23218334Speter 23318334Speter/* The compiler version. */ 23418334Speter 23518334Speterstatic char *compiler_version; 23618334Speter 23718334Speter/* The target version specified with -V */ 23818334Speter 23918334Speterstatic char *spec_version = DEFAULT_TARGET_VERSION; 24018334Speter 24118334Speter/* The target machine specified with -b. */ 24218334Speter 24318334Speterstatic char *spec_machine = DEFAULT_TARGET_MACHINE; 24418334Speter 24518334Speter/* Nonzero if cross-compiling. 24618334Speter When -b is used, the value comes from the `specs' file. */ 24718334Speter 24818334Speter#ifdef CROSS_COMPILE 24918334Speterstatic int cross_compile = 1; 25018334Speter#else 25118334Speterstatic int cross_compile = 0; 25218334Speter#endif 25318334Speter 25418334Speter/* The number of errors that have occurred; the link phase will not be 25518334Speter run if this is non-zero. */ 25618334Speterstatic int error_count = 0; 25718334Speter 25818334Speter/* This is the obstack which we use to allocate many strings. */ 25918334Speter 26018334Speterstatic struct obstack obstack; 26118334Speter 26218334Speter/* This is the obstack to build an environment variable to pass to 26318334Speter collect2 that describes all of the relevant switches of what to 26418334Speter pass the compiler in building the list of pointers to constructors 26518334Speter and destructors. */ 26618334Speter 26718334Speterstatic struct obstack collect_obstack; 26818334Speter 26918334Speterextern char *version_string; 27018334Speter 27118334Speter/* Forward declaration for prototypes. */ 27218334Speterstruct path_prefix; 27318334Speter 27418334Speterstatic void set_spec PROTO((char *, char *)); 27518334Speterstatic struct compiler *lookup_compiler PROTO((char *, int, char *)); 27618334Speterstatic char *build_search_list PROTO((struct path_prefix *, char *, int)); 27718334Speterstatic void putenv_from_prefixes PROTO((struct path_prefix *, char *)); 27818334Speterstatic char *find_a_file PROTO((struct path_prefix *, char *, int)); 27918334Speterstatic void add_prefix PROTO((struct path_prefix *, char *, int, int, int *)); 28018334Speterstatic char *skip_whitespace PROTO((char *)); 28118334Speterstatic void record_temp_file PROTO((char *, int, int)); 28218334Speterstatic void delete_if_ordinary PROTO((char *)); 28318334Speterstatic void delete_temp_files PROTO((void)); 28418334Speterstatic void delete_failure_queue PROTO((void)); 28518334Speterstatic void clear_failure_queue PROTO((void)); 28618334Speterstatic char *choose_temp_base_try PROTO((char *, char *)); 28718334Speterstatic void choose_temp_base PROTO((void)); 28818334Speterstatic int check_live_switch PROTO((int, int)); 28918334Speterstatic char *handle_braces PROTO((char *)); 29018334Speterstatic char *save_string PROTO((char *, int)); 29118334Speterstatic char *concat PROTO((char *, char *)); 29218334Speterstatic char *concat3 PROTO((char *, char *, char *)); 29318334Speterstatic char *concat4 PROTO((char *, char *, char *, char *)); 29418334Speterstatic char *concat6 PROTO((char *, char *, char *, char *, char *, \ 29518334Speter char *)); 29618334Speterstatic int do_spec PROTO((char *)); 29718334Speterstatic int do_spec_1 PROTO((char *, int, char *)); 29818334Speterstatic char *find_file PROTO((char *)); 29918334Speterstatic int is_directory PROTO((char *, char *, int)); 30018334Speterstatic void validate_switches PROTO((char *)); 30118334Speterstatic void validate_all_switches PROTO((void)); 30218334Speterstatic void give_switch PROTO((int, int)); 30318334Speterstatic int used_arg PROTO((char *, int)); 30418334Speterstatic int default_arg PROTO((char *, int)); 30518334Speterstatic void set_multilib_dir PROTO((void)); 30618334Speterstatic void print_multilib_info PROTO((void)); 30718334Speterstatic void pfatal_with_name PROTO((char *)); 30818334Speterstatic void perror_with_name PROTO((char *)); 30918334Speterstatic void perror_exec PROTO((char *)); 31018334Speter#ifdef HAVE_VPRINTF 31118334Speterstatic void fatal PVPROTO((char *, ...)); 31218334Speterstatic void error PVPROTO((char *, ...)); 31318334Speter#else 31418334Speter/* We must not provide any prototype here, even if ANSI C. */ 31518334Speterstatic void fatal PROTO(()); 31618334Speterstatic void error PROTO(()); 31718334Speter#endif 31818334Speter 31918334Spetervoid fancy_abort (); 32018334Speterchar *xmalloc (); 32118334Speterchar *xrealloc (); 32218334Speter 32318334Speter/* Specs are strings containing lines, each of which (if not blank) 32418334Speteris made up of a program name, and arguments separated by spaces. 32518334SpeterThe program name must be exact and start from root, since no path 32618334Speteris searched and it is unreliable to depend on the current working directory. 32718334SpeterRedirection of input or output is not supported; the subprograms must 32818334Speteraccept filenames saying what files to read and write. 32918334Speter 33018334SpeterIn addition, the specs can contain %-sequences to substitute variable text 33118334Speteror for conditional text. Here is a table of all defined %-sequences. 33218334SpeterNote that spaces are not generated automatically around the results of 33318334Speterexpanding these sequences; therefore, you can concatenate them together 33418334Speteror with constant text in a single argument. 33518334Speter 33618334Speter %% substitute one % into the program name or argument. 33718334Speter %i substitute the name of the input file being processed. 33818334Speter %b substitute the basename of the input file being processed. 33918334Speter This is the substring up to (and not including) the last period 34018334Speter and not including the directory. 34118334Speter %g substitute the temporary-file-name-base. This is a string chosen 34218334Speter once per compilation. Different temporary file names are made by 34318334Speter concatenation of constant strings on the end, as in `%g.s'. 34418334Speter %g also has the same effect of %d. 34518334Speter %u like %g, but make the temporary file name unique. 34618334Speter %U returns the last file name generated with %u. 34718334Speter %d marks the argument containing or following the %d as a 34818334Speter temporary file name, so that that file will be deleted if CC exits 34918334Speter successfully. Unlike %g, this contributes no text to the argument. 35018334Speter %w marks the argument containing or following the %w as the 35118334Speter "output file" of this compilation. This puts the argument 35218334Speter into the sequence of arguments that %o will substitute later. 35318334Speter %W{...} 35418334Speter like %{...} but mark last argument supplied within 35518334Speter as a file to be deleted on failure. 35618334Speter %o substitutes the names of all the output files, with spaces 35718334Speter automatically placed around them. You should write spaces 35818334Speter around the %o as well or the results are undefined. 35918334Speter %o is for use in the specs for running the linker. 36018334Speter Input files whose names have no recognized suffix are not compiled 36118334Speter at all, but they are included among the output files, so they will 36218334Speter be linked. 36318334Speter %O substitutes the suffix for object files. 36418334Speter %p substitutes the standard macro predefinitions for the 36518334Speter current target machine. Use this when running cpp. 36618334Speter %P like %p, but puts `__' before and after the name of each macro. 36718334Speter (Except macros that already have __.) 36818334Speter This is for ANSI C. 36918334Speter %I Substitute a -iprefix option made from GCC_EXEC_PREFIX. 37018334Speter %s current argument is the name of a library or startup file of some sort. 37118334Speter Search for that file in a standard list of directories 37218334Speter and substitute the full name found. 37318334Speter %eSTR Print STR as an error message. STR is terminated by a newline. 37418334Speter Use this when inconsistent options are detected. 37518334Speter %x{OPTION} Accumulate an option for %X. 37618334Speter %X Output the accumulated linker options specified by compilations. 37718334Speter %Y Output the accumulated assembler options specified by compilations. 37818334Speter %Z Output the accumulated preprocessor options specified by compilations. 37918334Speter %v1 Substitute the major version number of GCC. 38018334Speter (For version 2.5.n, this is 2.) 38118334Speter %v2 Substitute the minor version number of GCC. 38218334Speter (For version 2.5.n, this is 5.) 38318334Speter %a process ASM_SPEC as a spec. 38418334Speter This allows config.h to specify part of the spec for running as. 38518334Speter %A process ASM_FINAL_SPEC as a spec. A capital A is actually 38618334Speter used here. This can be used to run a post-processor after the 38718334Speter assembler has done it's job. 38818334Speter %D Dump out a -L option for each directory in startfile_prefixes. 38918334Speter If multilib_dir is set, extra entries are generated with it affixed. 39018334Speter %l process LINK_SPEC as a spec. 39118334Speter %L process LIB_SPEC as a spec. 39218334Speter %G process LIBGCC_SPEC as a spec. 39318334Speter %S process STARTFILE_SPEC as a spec. A capital S is actually used here. 39418334Speter %E process ENDFILE_SPEC as a spec. A capital E is actually used here. 39518334Speter %c process SIGNED_CHAR_SPEC as a spec. 39618334Speter %C process CPP_SPEC as a spec. A capital C is actually used here. 39718334Speter %1 process CC1_SPEC as a spec. 39818334Speter %2 process CC1PLUS_SPEC as a spec. 39918334Speter %| output "-" if the input for the current command is coming from a pipe. 40018334Speter %* substitute the variable part of a matched option. (See below.) 40118334Speter Note that each comma in the substituted string is replaced by 40218334Speter a single space. 40318334Speter %{S} substitutes the -S switch, if that switch was given to CC. 40418334Speter If that switch was not specified, this substitutes nothing. 40518334Speter Here S is a metasyntactic variable. 40618334Speter %{S*} substitutes all the switches specified to CC whose names start 40718334Speter with -S. This is used for -o, -D, -I, etc; switches that take 40818334Speter arguments. CC considers `-o foo' as being one switch whose 40918334Speter name starts with `o'. %{o*} would substitute this text, 41018334Speter including the space; thus, two arguments would be generated. 41118334Speter %{S*:X} substitutes X if one or more switches whose names start with -S are 41218334Speter specified to CC. Note that the tail part of the -S option 41318334Speter (i.e. the part matched by the `*') will be substituted for each 41418334Speter occurrence of %* within X. 41518334Speter %{S:X} substitutes X, but only if the -S switch was given to CC. 41618334Speter %{!S:X} substitutes X, but only if the -S switch was NOT given to CC. 41718334Speter %{|S:X} like %{S:X}, but if no S switch, substitute `-'. 41818334Speter %{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'. 41918334Speter %{.S:X} substitutes X, but only if processing a file with suffix S. 42018334Speter %{!.S:X} substitutes X, but only if NOT processing a file with suffix S. 42118334Speter %(Spec) processes a specification defined in a specs file as *Spec: 42218334Speter %[Spec] as above, but put __ around -D arguments 42318334Speter 42418334SpeterThe conditional text X in a %{S:X} or %{!S:X} construct may contain 42518334Speterother nested % constructs or spaces, or even newlines. They are 42618334Speterprocessed as usual, as described above. 42718334Speter 42818334SpeterThe -O, -f, -m, and -W switches are handled specifically in these 42918334Speterconstructs. If another value of -O or the negated form of a -f, -m, or 43018334Speter-W switch is found later in the command line, the earlier switch 43118334Spetervalue is ignored, except with {S*} where S is just one letter; this 43218334Speterpasses all matching options. 43318334Speter 43418334SpeterThe character | is used to indicate that a command should be piped to 43518334Speterthe following command, but only if -pipe is specified. 43618334Speter 43718334SpeterNote that it is built into CC which switches take arguments and which 43818334Speterdo not. You might think it would be useful to generalize this to 43918334Speterallow each compiler's spec to say which switches take arguments. But 44018334Speterthis cannot be done in a consistent fashion. CC cannot even decide 44118334Speterwhich input files have been specified without knowing which switches 44218334Spetertake arguments, and it must know which input files to compile in order 44318334Speterto tell which compilers to run. 44418334Speter 44518334SpeterCC also knows implicitly that arguments starting in `-l' are to be 44618334Spetertreated as compiler output files, and passed to the linker in their 44718334Speterproper position among the other output files. */ 44818334Speter 44918334Speter/* Define the macros used for specs %a, %l, %L, %S, %c, %C, %1. */ 45018334Speter 45118334Speter/* config.h can define ASM_SPEC to provide extra args to the assembler 45218334Speter or extra switch-translations. */ 45318334Speter#ifndef ASM_SPEC 45418334Speter#define ASM_SPEC "" 45518334Speter#endif 45618334Speter 45718334Speter/* config.h can define ASM_FINAL_SPEC to run a post processor after 45818334Speter the assembler has run. */ 45918334Speter#ifndef ASM_FINAL_SPEC 46018334Speter#define ASM_FINAL_SPEC "" 46118334Speter#endif 46218334Speter 46318334Speter/* config.h can define CPP_SPEC to provide extra args to the C preprocessor 46418334Speter or extra switch-translations. */ 46518334Speter#ifndef CPP_SPEC 46618334Speter#define CPP_SPEC "" 46718334Speter#endif 46818334Speter 46918334Speter/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus 47018334Speter or extra switch-translations. */ 47118334Speter#ifndef CC1_SPEC 47218334Speter#define CC1_SPEC "" 47318334Speter#endif 47418334Speter 47518334Speter/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus 47618334Speter or extra switch-translations. */ 47718334Speter#ifndef CC1PLUS_SPEC 47818334Speter#define CC1PLUS_SPEC "" 47918334Speter#endif 48018334Speter 48118334Speter/* config.h can define LINK_SPEC to provide extra args to the linker 48218334Speter or extra switch-translations. */ 48318334Speter#ifndef LINK_SPEC 48418334Speter#define LINK_SPEC "" 48518334Speter#endif 48618334Speter 48718334Speter/* config.h can define LIB_SPEC to override the default libraries. */ 48818334Speter#ifndef LIB_SPEC 48918334Speter#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}" 49018334Speter#endif 49118334Speter 49218334Speter/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is 49318334Speter included. */ 49418334Speter#ifndef LIBGCC_SPEC 49518334Speter#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1) 49618334Speter/* Have gcc do the search for libgcc.a. */ 49718334Speter#define LIBGCC_SPEC "%{!shared:libgcc.a%s}" 49818334Speter#else 49918334Speter#define LIBGCC_SPEC "%{!shared:-lgcc}" 50018334Speter#endif 50118334Speter#endif 50218334Speter 50318334Speter/* config.h can define STARTFILE_SPEC to override the default crt0 files. */ 50418334Speter#ifndef STARTFILE_SPEC 50518334Speter#define STARTFILE_SPEC \ 50618334Speter "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}" 50718334Speter#endif 50818334Speter 50918334Speter/* config.h can define SWITCHES_NEED_SPACES to control passing -o and -L. 51018334Speter Make the string nonempty to require spaces there. */ 51118334Speter#ifndef SWITCHES_NEED_SPACES 51218334Speter#define SWITCHES_NEED_SPACES "" 51318334Speter#endif 51418334Speter 51518334Speter/* config.h can define ENDFILE_SPEC to override the default crtn files. */ 51618334Speter#ifndef ENDFILE_SPEC 51718334Speter#define ENDFILE_SPEC "" 51818334Speter#endif 51918334Speter 52018334Speter/* This spec is used for telling cpp whether char is signed or not. */ 52118334Speter#ifndef SIGNED_CHAR_SPEC 52218334Speter/* Use #if rather than ?: 52318334Speter because MIPS C compiler rejects like ?: in initializers. */ 52418334Speter#if DEFAULT_SIGNED_CHAR 52518334Speter#define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}" 52618334Speter#else 52718334Speter#define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}" 52818334Speter#endif 52918334Speter#endif 53018334Speter 53118334Speter/* MULTILIB_SELECT comes from multilib.h. It gives a 53218334Speter string interpreted by set_multilib_dir to select a library 53318334Speter subdirectory based on the compiler options. */ 53418334Speter#ifndef MULTILIB_SELECT 53518334Speter#define MULTILIB_SELECT ". ;" 53618334Speter#endif 53718334Speter 53818334Speterstatic char *cpp_spec = CPP_SPEC; 53918334Speterstatic char *cpp_predefines = CPP_PREDEFINES; 54018334Speterstatic char *cc1_spec = CC1_SPEC; 54118334Speterstatic char *cc1plus_spec = CC1PLUS_SPEC; 54218334Speterstatic char *signed_char_spec = SIGNED_CHAR_SPEC; 54318334Speterstatic char *asm_spec = ASM_SPEC; 54418334Speterstatic char *asm_final_spec = ASM_FINAL_SPEC; 54518334Speterstatic char *link_spec = LINK_SPEC; 54618334Speterstatic char *lib_spec = LIB_SPEC; 54718334Speterstatic char *libgcc_spec = LIBGCC_SPEC; 54818334Speterstatic char *endfile_spec = ENDFILE_SPEC; 54918334Speterstatic char *startfile_spec = STARTFILE_SPEC; 55018334Speterstatic char *switches_need_spaces = SWITCHES_NEED_SPACES; 55118334Speterstatic char *multilib_select = MULTILIB_SELECT; 55218334Speter 55318334Speter/* This defines which switch letters take arguments. */ 55418334Speter 55518334Speter#ifndef SWITCH_TAKES_ARG 55618334Speter#define SWITCH_TAKES_ARG(CHAR) \ 55718334Speter ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \ 55818334Speter || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \ 55918334Speter || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \ 56018334Speter || (CHAR) == 'L' || (CHAR) == 'A') 56118334Speter#endif 56218334Speter 56318334Speter/* This defines which multi-letter switches take arguments. */ 56418334Speter 56518334Speter#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \ 56618334Speter (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ 56718334Speter || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \ 56818334Speter || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \ 56918334Speter || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \ 57018334Speter || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \ 57118334Speter || !strcmp (STR, "isystem")) 57218334Speter 57318334Speter#ifndef WORD_SWITCH_TAKES_ARG 57418334Speter#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR) 57518334Speter#endif 57618334Speter 57718334Speter/* Record the mapping from file suffixes for compilation specs. */ 57818334Speter 57918334Speterstruct compiler 58018334Speter{ 58118334Speter char *suffix; /* Use this compiler for input files 58218334Speter whose names end in this suffix. */ 58318334Speter 58418334Speter char *spec[4]; /* To use this compiler, concatenate these 58518334Speter specs and pass to do_spec. */ 58618334Speter}; 58718334Speter 58818334Speter/* Pointer to a vector of `struct compiler' that gives the spec for 58918334Speter compiling a file, based on its suffix. 59018334Speter A file that does not end in any of these suffixes will be passed 59118334Speter unchanged to the loader and nothing else will be done to it. 59218334Speter 59318334Speter An entry containing two 0s is used to terminate the vector. 59418334Speter 59518334Speter If multiple entries match a file, the last matching one is used. */ 59618334Speter 59718334Speterstatic struct compiler *compilers; 59818334Speter 59918334Speter/* Number of entries in `compilers', not counting the null terminator. */ 60018334Speter 60118334Speterstatic int n_compilers; 60218334Speter 60318334Speter/* The default list of file name suffixes and their compilation specs. */ 60418334Speter 60518334Speterstatic struct compiler default_compilers[] = 60618334Speter{ 60718334Speter {".c", "@c"}, 60818334Speter {"@c", 60918334Speter "cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\ 61018334Speter %{C:%{!E:%eGNU C does not support -C without using -E}}\ 61118334Speter %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ 61218334Speter -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\ 61318334Speter %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\ 61418334Speter %{!undef:%{!ansi:%p} %P} %{trigraphs} \ 61518334Speter %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\ 61618334Speter %{traditional-cpp:-traditional}\ 61718334Speter %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\ 61818334Speter %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n", 61918334Speter "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \ 62018334Speter %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a}\ 62118334Speter %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \ 62218334Speter %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\ 62318334Speter %{aux-info*}\ 62418334Speter %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 62518334Speter %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ 62618334Speter %{!S:as %a %Y\ 62718334Speter %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ 62818334Speter %{!pipe:%g.s} %A\n }}}}"}, 62918334Speter {"-", 63018334Speter "%{E:cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\ 63118334Speter %{C:%{!E:%eGNU C does not support -C without using -E}}\ 63218334Speter %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ 63318334Speter -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\ 63418334Speter %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\ 63518334Speter %{!undef:%{!ansi:%p} %P} %{trigraphs}\ 63618334Speter %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\ 63718334Speter %{traditional-cpp:-traditional}\ 63818334Speter %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\ 63918334Speter %i %W{o*}}\ 64018334Speter %{!E:%e-E required when input is from standard input}"}, 64118334Speter {".m", "@objective-c"}, 64218334Speter {"@objective-c", 64318334Speter "cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\ 64418334Speter %{C:%{!E:%eGNU C does not support -C without using -E}}\ 64518334Speter %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ 64618334Speter -undef -D__OBJC__ -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\ 64718334Speter %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\ 64818334Speter %{!undef:%{!ansi:%p} %P} %{trigraphs}\ 64918334Speter %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\ 65018334Speter %{traditional-cpp:-traditional}\ 65118334Speter %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\ 65218334Speter %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n", 65318334Speter "%{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \ 65418334Speter %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a}\ 65518334Speter %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \ 65618334Speter %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \ 65718334Speter -lang-objc %{gen-decls} \ 65818334Speter %{aux-info*}\ 65918334Speter %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 66018334Speter %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ 66118334Speter %{!S:as %a %Y\ 66218334Speter %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ 66318334Speter %{!pipe:%g.s} %A\n }}}}"}, 66418334Speter {".h", "@c-header"}, 66518334Speter {"@c-header", 66618334Speter "%{!E:%eCompilation of header file requested} \ 66718334Speter cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\ 66818334Speter %{C:%{!E:%eGNU C does not support -C without using -E}}\ 66918334Speter %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ 67018334Speter -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\ 67118334Speter %{ansi:-trigraphs -$ -D__STRICT_ANSI__}\ 67218334Speter %{!undef:%{!ansi:%p} %P} %{trigraphs}\ 67318334Speter %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\ 67418334Speter %{traditional-cpp:-traditional}\ 67518334Speter %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\ 67618334Speter %i %W{o*}"}, 67718334Speter {".i", "@cpp-output"}, 67818334Speter {"@cpp-output", 67918334Speter "%{!M:%{!MM:%{!E:cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a}\ 68018334Speter %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\ 68118334Speter %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\ 68218334Speter %{aux-info*}\ 68318334Speter %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ 68418334Speter %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ 68518334Speter %{!S:as %a %Y\ 68618334Speter %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ 68718334Speter %{!pipe:%g.s} %A\n }}}}"}, 68818334Speter {".s", "@assembler"}, 68918334Speter {"@assembler", 69018334Speter "%{!M:%{!MM:%{!E:%{!S:as %a %Y\ 69118334Speter %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ 69218334Speter %i %A\n }}}}"}, 69318334Speter {".S", "@assembler-with-cpp"}, 69418334Speter {"@assembler-with-cpp", 69518334Speter "cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\ 69618334Speter %{C:%{!E:%eGNU C does not support -C without using -E}}\ 69718334Speter %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} %{trigraphs}\ 69818334Speter -undef -$ %{!undef:%p %P} -D__ASSEMBLER__ \ 69918334Speter %c %{O*:%{!O0:-D__OPTIMIZE__}} %{traditional} %{ftraditional:-traditional}\ 70018334Speter %{traditional-cpp:-traditional}\ 70118334Speter %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\ 70218334Speter %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n", 70318334Speter "%{!M:%{!MM:%{!E:%{!S:as %a %Y\ 70418334Speter %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ 70518334Speter %{!pipe:%g.s} %A\n }}}}"}, 70618334Speter#include "specs.h" 70718334Speter /* Mark end of table */ 70818334Speter {0, 0} 70918334Speter}; 71018334Speter 71118334Speter/* Number of elements in default_compilers, not counting the terminator. */ 71218334Speter 71318334Speterstatic int n_default_compilers 71418334Speter = (sizeof default_compilers / sizeof (struct compiler)) - 1; 71518334Speter 71618334Speter/* Here is the spec for running the linker, after compiling all files. */ 71718334Speter 71818334Speter/* -u* was put back because both BSD and SysV seem to support it. */ 71918334Speter/* %{static:} simply prevents an error message if the target machine 72018334Speter doesn't handle -static. */ 72118334Speter/* We want %{T*} after %{L*} and %D so that it can be used to specify linker 72218334Speter scripts which exist in user specified directories, or in standard 72318334Speter directories. */ 72418334Speter#ifdef LINK_LIBGCC_SPECIAL 72518334Speter/* Don't generate -L options. */ 72618334Speterstatic char *link_command_spec = "\ 72718334Speter%{!fsyntax-only: \ 72818334Speter %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \ 72918334Speter %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\ 73018334Speter %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ 73118334Speter %{static:} %{L*} %{T*} %o\ 73218334Speter %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\ 73318334Speter %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\n }}}}}}"; 73418334Speter#else 73518334Speter/* Use -L. */ 73618334Speterstatic char *link_command_spec = "\ 73718334Speter%{!fsyntax-only: \ 73818334Speter %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \ 73918334Speter %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\ 74018334Speter %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\ 74118334Speter %{static:} %{L*} %D %{T*} %o\ 74218334Speter %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\ 74318334Speter %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\n }}}}}}"; 74418334Speter#endif 74518334Speter 74618334Speter/* A vector of options to give to the linker. 74718334Speter These options are accumulated by %x, 74818334Speter and substituted into the linker command with %X. */ 74918334Speterstatic int n_linker_options; 75018334Speterstatic char **linker_options; 75118334Speter 75218334Speter/* A vector of options to give to the assembler. 75318334Speter These options are accumulated by -Wa, 75418334Speter and substituted into the assembler command with %Y. */ 75518334Speterstatic int n_assembler_options; 75618334Speterstatic char **assembler_options; 75718334Speter 75818334Speter/* A vector of options to give to the preprocessor. 75918334Speter These options are accumulated by -Wp, 76018334Speter and substituted into the preprocessor command with %Z. */ 76118334Speterstatic int n_preprocessor_options; 76218334Speterstatic char **preprocessor_options; 76318334Speter 76418334Speter/* Define how to map long options into short ones. */ 76518334Speter 76618334Speter/* This structure describes one mapping. */ 76718334Speterstruct option_map 76818334Speter{ 76918334Speter /* The long option's name. */ 77018334Speter char *name; 77118334Speter /* The equivalent short option. */ 77218334Speter char *equivalent; 77318334Speter /* Argument info. A string of flag chars; NULL equals no options. 77418334Speter a => argument required. 77518334Speter o => argument optional. 77618334Speter j => join argument to equivalent, making one word. 77718334Speter * => require other text after NAME as an argument. */ 77818334Speter char *arg_info; 77918334Speter}; 78018334Speter 78118334Speter/* This is the table of mappings. Mappings are tried sequentially 78218334Speter for each option encountered; the first one that matches, wins. */ 78318334Speter 78418334Speterstruct option_map option_map[] = 78518334Speter { 78618334Speter {"--all-warnings", "-Wall", 0}, 78718334Speter {"--ansi", "-ansi", 0}, 78818334Speter {"--assemble", "-S", 0}, 78918334Speter {"--assert", "-A", "a"}, 79018334Speter {"--comments", "-C", 0}, 79118334Speter {"--compile", "-c", 0}, 79218334Speter {"--debug", "-g", "oj"}, 79318334Speter {"--define-macro", "-D", "a"}, 79418334Speter {"--dependencies", "-M", 0}, 79518334Speter {"--dump", "-d", "a"}, 79618334Speter {"--dumpbase", "-dumpbase", "a"}, 79718334Speter {"--entry", "-e", 0}, 79818334Speter {"--extra-warnings", "-W", 0}, 79918334Speter {"--for-assembler", "-Wa", "a"}, 80018334Speter {"--for-linker", "-Xlinker", "a"}, 80118334Speter {"--force-link", "-u", "a"}, 80218334Speter {"--imacros", "-imacros", "a"}, 80318334Speter {"--include", "-include", "a"}, 80418334Speter {"--include-barrier", "-I-", 0}, 80518334Speter {"--include-directory", "-I", "a"}, 80618334Speter {"--include-directory-after", "-idirafter", "a"}, 80718334Speter {"--include-prefix", "-iprefix", "a"}, 80818334Speter {"--include-with-prefix", "-iwithprefix", "a"}, 80918334Speter {"--include-with-prefix-before", "-iwithprefixbefore", "a"}, 81018334Speter {"--include-with-prefix-after", "-iwithprefix", "a"}, 81118334Speter {"--language", "-x", "a"}, 81218334Speter {"--library-directory", "-L", "a"}, 81318334Speter {"--machine", "-m", "aj"}, 81418334Speter {"--machine-", "-m", "*j"}, 81518334Speter {"--no-line-commands", "-P", 0}, 81618334Speter {"--no-precompiled-includes", "-noprecomp", 0}, 81718334Speter {"--no-standard-includes", "-nostdinc", 0}, 81818334Speter {"--no-standard-libraries", "-nostdlib", 0}, 81918334Speter {"--no-warnings", "-w", 0}, 82018334Speter {"--optimize", "-O", "oj"}, 82118334Speter {"--output", "-o", "a"}, 82218334Speter {"--pedantic", "-pedantic", 0}, 82318334Speter {"--pedantic-errors", "-pedantic-errors", 0}, 82418334Speter {"--pipe", "-pipe", 0}, 82518334Speter {"--prefix", "-B", "a"}, 82618334Speter {"--preprocess", "-E", 0}, 82718334Speter {"--print-search-dirs", "-print-search-dirs", 0}, 82818334Speter {"--print-file-name", "-print-file-name=", "aj"}, 82918334Speter {"--print-libgcc-file-name", "-print-libgcc-file-name", 0}, 83018334Speter {"--print-missing-file-dependencies", "-MG", 0}, 83118334Speter {"--print-multi-lib", "-print-multi-lib", 0}, 83218334Speter {"--print-multi-directory", "-print-multi-directory", 0}, 83318334Speter {"--print-prog-name", "-print-prog-name=", "aj"}, 83418334Speter {"--profile", "-p", 0}, 83518334Speter {"--profile-blocks", "-a", 0}, 83618334Speter {"--quiet", "-q", 0}, 83718334Speter {"--save-temps", "-save-temps", 0}, 83818334Speter {"--shared", "-shared", 0}, 83918334Speter {"--silent", "-q", 0}, 84018334Speter {"--static", "-static", 0}, 84118334Speter {"--symbolic", "-symbolic", 0}, 84218334Speter {"--target", "-b", "a"}, 84318334Speter {"--trace-includes", "-H", 0}, 84418334Speter {"--traditional", "-traditional", 0}, 84518334Speter {"--traditional-cpp", "-traditional-cpp", 0}, 84618334Speter {"--trigraphs", "-trigraphs", 0}, 84718334Speter {"--undefine-macro", "-U", "a"}, 84818334Speter {"--use-version", "-V", "a"}, 84918334Speter {"--user-dependencies", "-MM", 0}, 85018334Speter {"--verbose", "-v", 0}, 85118334Speter {"--version", "-dumpversion", 0}, 85218334Speter {"--warn-", "-W", "*j"}, 85318334Speter {"--write-dependencies", "-MD", 0}, 85418334Speter {"--write-user-dependencies", "-MMD", 0}, 85518334Speter {"--", "-f", "*j"} 85618334Speter }; 85718334Speter 85818334Speter/* Translate the options described by *ARGCP and *ARGVP. 85918334Speter Make a new vector and store it back in *ARGVP, 86018334Speter and store its length in *ARGVC. */ 86118334Speter 86218334Speterstatic void 86318334Spetertranslate_options (argcp, argvp) 86418334Speter int *argcp; 86518334Speter char ***argvp; 86618334Speter{ 86718334Speter int i, j, k; 86818334Speter int argc = *argcp; 86918334Speter char **argv = *argvp; 87018334Speter char **newv = (char **) xmalloc ((argc + 2) * 2 * sizeof (char *)); 87118334Speter int newindex = 0; 87218334Speter 87318334Speter i = 0; 87418334Speter newv[newindex++] = argv[i++]; 87518334Speter 87618334Speter while (i < argc) 87718334Speter { 87818334Speter /* Translate -- options. */ 87918334Speter if (argv[i][0] == '-' && argv[i][1] == '-') 88018334Speter { 88118334Speter /* Find a mapping that applies to this option. */ 88218334Speter for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++) 88318334Speter { 88418334Speter int optlen = strlen (option_map[j].name); 88518334Speter int arglen = strlen (argv[i]); 88618334Speter int complen = arglen > optlen ? optlen : arglen; 88718334Speter char *arginfo = option_map[j].arg_info; 88818334Speter 88918334Speter if (arginfo == 0) 89018334Speter arginfo = ""; 89118334Speter 89218334Speter if (!strncmp (argv[i], option_map[j].name, complen)) 89318334Speter { 89418334Speter char *arg = 0; 89518334Speter 89618334Speter if (arglen < optlen) 89718334Speter { 89818334Speter for (k = j + 1; 89918334Speter k < sizeof (option_map) / sizeof (option_map[0]); 90018334Speter k++) 90118334Speter if (strlen (option_map[k].name) >= arglen 90218334Speter && !strncmp (argv[i], option_map[k].name, arglen)) 90318334Speter { 90418334Speter error ("Ambiguous abbreviation %s", argv[i]); 90518334Speter break; 90618334Speter } 90718334Speter 90818334Speter if (k != sizeof (option_map) / sizeof (option_map[0])) 90918334Speter break; 91018334Speter } 91118334Speter 91218334Speter if (arglen > optlen) 91318334Speter { 91418334Speter /* If the option has an argument, accept that. */ 91518334Speter if (argv[i][optlen] == '=') 91618334Speter arg = argv[i] + optlen + 1; 91718334Speter 91818334Speter /* If this mapping requires extra text at end of name, 91918334Speter accept that as "argument". */ 92018334Speter else if (index (arginfo, '*') != 0) 92118334Speter arg = argv[i] + optlen; 92218334Speter 92318334Speter /* Otherwise, extra text at end means mismatch. 92418334Speter Try other mappings. */ 92518334Speter else 92618334Speter continue; 92718334Speter } 92818334Speter 92918334Speter else if (index (arginfo, '*') != 0) 93018334Speter { 93118334Speter error ("Incomplete `%s' option", option_map[j].name); 93218334Speter break; 93318334Speter } 93418334Speter 93518334Speter /* Handle arguments. */ 93618334Speter if (index (arginfo, 'a') != 0) 93718334Speter { 93818334Speter if (arg == 0) 93918334Speter { 94018334Speter if (i + 1 == argc) 94118334Speter { 94218334Speter error ("Missing argument to `%s' option", 94318334Speter option_map[j].name); 94418334Speter break; 94518334Speter } 94618334Speter 94718334Speter arg = argv[++i]; 94818334Speter } 94918334Speter } 95018334Speter else if (index (arginfo, '*') != 0) 95118334Speter ; 95218334Speter else if (index (arginfo, 'o') == 0) 95318334Speter { 95418334Speter if (arg != 0) 95518334Speter error ("Extraneous argument to `%s' option", 95618334Speter option_map[j].name); 95718334Speter arg = 0; 95818334Speter } 95918334Speter 96018334Speter /* Store the translation as one argv elt or as two. */ 96118334Speter if (arg != 0 && index (arginfo, 'j') != 0) 96218334Speter newv[newindex++] = concat (option_map[j].equivalent, arg); 96318334Speter else if (arg != 0) 96418334Speter { 96518334Speter newv[newindex++] = option_map[j].equivalent; 96618334Speter newv[newindex++] = arg; 96718334Speter } 96818334Speter else 96918334Speter newv[newindex++] = option_map[j].equivalent; 97018334Speter 97118334Speter break; 97218334Speter } 97318334Speter } 97418334Speter i++; 97518334Speter } 97618334Speter 97718334Speter /* Handle old-fashioned options--just copy them through, 97818334Speter with their arguments. */ 97918334Speter else if (argv[i][0] == '-') 98018334Speter { 98118334Speter char *p = argv[i] + 1; 98218334Speter int c = *p; 98318334Speter int nskip = 1; 98418334Speter 98518334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 98618334Speter nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0); 98718334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 98818334Speter nskip += WORD_SWITCH_TAKES_ARG (p); 98918334Speter else if ((c == 'B' || c == 'b' || c == 'V' || c == 'x') 99018334Speter && p[1] == 0) 99118334Speter nskip += 1; 99218334Speter else if (! strcmp (p, "Xlinker")) 99318334Speter nskip += 1; 99418334Speter 99518334Speter /* Watch out for an option at the end of the command line that 99618334Speter is missing arguments, and avoid skipping past the end of the 99718334Speter command line. */ 99818334Speter if (nskip + i > argc) 99918334Speter nskip = argc - i; 100018334Speter 100118334Speter while (nskip > 0) 100218334Speter { 100318334Speter newv[newindex++] = argv[i++]; 100418334Speter nskip--; 100518334Speter } 100618334Speter } 100718334Speter else 100818334Speter /* Ordinary operands, or +e options. */ 100918334Speter newv[newindex++] = argv[i++]; 101018334Speter } 101118334Speter 101218334Speter newv[newindex] = 0; 101318334Speter 101418334Speter *argvp = newv; 101518334Speter *argcp = newindex; 101618334Speter} 101718334Speter 101818334Speterchar * 101918334Spetermy_strerror(e) 102018334Speter int e; 102118334Speter{ 102218334Speter 102318334Speter#ifdef HAVE_STRERROR 102418334Speter return strerror(e); 102518334Speter 102618334Speter#else 102718334Speter 102818334Speter static char buffer[30]; 102918334Speter if (!e) 103018334Speter return ""; 103118334Speter 103218334Speter if (e > 0 && e < sys_nerr) 103318334Speter return sys_errlist[e]; 103418334Speter 103518334Speter sprintf (buffer, "Unknown error %d", e); 103618334Speter return buffer; 103718334Speter#endif 103818334Speter} 103918334Speter 104018334Speter/* Read compilation specs from a file named FILENAME, 104118334Speter replacing the default ones. 104218334Speter 104318334Speter A suffix which starts with `*' is a definition for 104418334Speter one of the machine-specific sub-specs. The "suffix" should be 104518334Speter *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc. 104618334Speter The corresponding spec is stored in asm_spec, etc., 104718334Speter rather than in the `compilers' vector. 104818334Speter 104918334Speter Anything invalid in the file is a fatal error. */ 105018334Speter 105118334Speterstatic void 105218334Speterread_specs (filename) 105318334Speter char *filename; 105418334Speter{ 105518334Speter int desc; 105618334Speter int readlen; 105718334Speter struct stat statbuf; 105818334Speter char *buffer; 105918334Speter register char *p; 106018334Speter 106118334Speter if (verbose_flag) 106218334Speter fprintf (stderr, "Reading specs from %s\n", filename); 106318334Speter 106418334Speter /* Open and stat the file. */ 106518334Speter desc = open (filename, O_RDONLY, 0); 106618334Speter if (desc < 0) 106718334Speter pfatal_with_name (filename); 106818334Speter if (stat (filename, &statbuf) < 0) 106918334Speter pfatal_with_name (filename); 107018334Speter 107118334Speter /* Read contents of file into BUFFER. */ 107218334Speter buffer = xmalloc ((unsigned) statbuf.st_size + 1); 107318334Speter readlen = read (desc, buffer, (unsigned) statbuf.st_size); 107418334Speter if (readlen < 0) 107518334Speter pfatal_with_name (filename); 107618334Speter buffer[readlen] = 0; 107718334Speter close (desc); 107818334Speter 107918334Speter /* Scan BUFFER for specs, putting them in the vector. */ 108018334Speter p = buffer; 108118334Speter while (1) 108218334Speter { 108318334Speter char *suffix; 108418334Speter char *spec; 108518334Speter char *in, *out, *p1, *p2; 108618334Speter 108718334Speter /* Advance P in BUFFER to the next nonblank nocomment line. */ 108818334Speter p = skip_whitespace (p); 108918334Speter if (*p == 0) 109018334Speter break; 109118334Speter 109218334Speter /* Find the colon that should end the suffix. */ 109318334Speter p1 = p; 109418334Speter while (*p1 && *p1 != ':' && *p1 != '\n') p1++; 109518334Speter /* The colon shouldn't be missing. */ 109618334Speter if (*p1 != ':') 109718334Speter fatal ("specs file malformed after %d characters", p1 - buffer); 109818334Speter /* Skip back over trailing whitespace. */ 109918334Speter p2 = p1; 110018334Speter while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) p2--; 110118334Speter /* Copy the suffix to a string. */ 110218334Speter suffix = save_string (p, p2 - p); 110318334Speter /* Find the next line. */ 110418334Speter p = skip_whitespace (p1 + 1); 110518334Speter if (p[1] == 0) 110618334Speter fatal ("specs file malformed after %d characters", p - buffer); 110718334Speter p1 = p; 110818334Speter /* Find next blank line. */ 110918334Speter while (*p1 && !(*p1 == '\n' && p1[1] == '\n')) p1++; 111018334Speter /* Specs end at the blank line and do not include the newline. */ 111118334Speter spec = save_string (p, p1 - p); 111218334Speter p = p1; 111318334Speter 111418334Speter /* Delete backslash-newline sequences from the spec. */ 111518334Speter in = spec; 111618334Speter out = spec; 111718334Speter while (*in != 0) 111818334Speter { 111918334Speter if (in[0] == '\\' && in[1] == '\n') 112018334Speter in += 2; 112118334Speter else if (in[0] == '#') 112218334Speter { 112318334Speter while (*in && *in != '\n') in++; 112418334Speter } 112518334Speter else 112618334Speter *out++ = *in++; 112718334Speter } 112818334Speter *out = 0; 112918334Speter 113018334Speter if (suffix[0] == '*') 113118334Speter { 113218334Speter if (! strcmp (suffix, "*link_command")) 113318334Speter link_command_spec = spec; 113418334Speter else 113518334Speter set_spec (suffix + 1, spec); 113618334Speter } 113718334Speter else 113818334Speter { 113918334Speter /* Add this pair to the vector. */ 114018334Speter compilers 114118334Speter = ((struct compiler *) 114218334Speter xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler))); 114318334Speter compilers[n_compilers].suffix = suffix; 114418334Speter bzero ((char *) compilers[n_compilers].spec, 114518334Speter sizeof compilers[n_compilers].spec); 114618334Speter compilers[n_compilers].spec[0] = spec; 114718334Speter n_compilers++; 114818334Speter bzero ((char *) &compilers[n_compilers], 114918334Speter sizeof compilers[n_compilers]); 115018334Speter } 115118334Speter 115218334Speter if (*suffix == 0) 115318334Speter link_command_spec = spec; 115418334Speter } 115518334Speter 115618334Speter if (link_command_spec == 0) 115718334Speter fatal ("spec file has no spec for linking"); 115818334Speter} 115918334Speter 116018334Speterstatic char * 116118334Speterskip_whitespace (p) 116218334Speter char *p; 116318334Speter{ 116418334Speter while (1) 116518334Speter { 116618334Speter /* A fully-blank line is a delimiter in the SPEC file and shouldn't 116718334Speter be considered whitespace. */ 116818334Speter if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n') 116918334Speter return p + 1; 117018334Speter else if (*p == '\n' || *p == ' ' || *p == '\t') 117118334Speter p++; 117218334Speter else if (*p == '#') 117318334Speter { 117418334Speter while (*p != '\n') p++; 117518334Speter p++; 117618334Speter } 117718334Speter else 117818334Speter break; 117918334Speter } 118018334Speter 118118334Speter return p; 118218334Speter} 118318334Speter 118418334Speter/* Structure to keep track of the specs that have been defined so far. These 118518334Speter are accessed using %(specname) or %[specname] in a compiler or link spec. */ 118618334Speter 118718334Speterstruct spec_list 118818334Speter{ 118918334Speter char *name; /* Name of the spec. */ 119018334Speter char *spec; /* The spec itself. */ 119118334Speter struct spec_list *next; /* Next spec in linked list. */ 119218334Speter}; 119318334Speter 119418334Speter/* List of specs that have been defined so far. */ 119518334Speter 119618334Speterstatic struct spec_list *specs = (struct spec_list *) 0; 119718334Speter 119818334Speter/* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is 119918334Speter removed; If the spec starts with a + then SPEC is added to the end of the 120018334Speter current spec. */ 120118334Speter 120218334Speterstatic void 120318334Speterset_spec (name, spec) 120418334Speter char *name; 120518334Speter char *spec; 120618334Speter{ 120718334Speter struct spec_list *sl; 120818334Speter char *old_spec; 120918334Speter 121018334Speter /* See if the spec already exists */ 121118334Speter for (sl = specs; sl; sl = sl->next) 121218334Speter if (strcmp (sl->name, name) == 0) 121318334Speter break; 121418334Speter 121518334Speter if (!sl) 121618334Speter { 121718334Speter /* Not found - make it */ 121818334Speter sl = (struct spec_list *) xmalloc (sizeof (struct spec_list)); 121918334Speter sl->name = save_string (name, strlen (name)); 122018334Speter sl->spec = save_string ("", 0); 122118334Speter sl->next = specs; 122218334Speter specs = sl; 122318334Speter } 122418334Speter 122518334Speter old_spec = sl->spec; 122618334Speter if (name && spec[0] == '+' && isspace (spec[1])) 122718334Speter sl->spec = concat (old_spec, spec + 1); 122818334Speter else 122918334Speter sl->spec = save_string (spec, strlen (spec)); 123018334Speter 123118334Speter if (! strcmp (name, "asm")) 123218334Speter asm_spec = sl->spec; 123318334Speter else if (! strcmp (name, "asm_final")) 123418334Speter asm_final_spec = sl->spec; 123518334Speter else if (! strcmp (name, "cc1")) 123618334Speter cc1_spec = sl->spec; 123718334Speter else if (! strcmp (name, "cc1plus")) 123818334Speter cc1plus_spec = sl->spec; 123918334Speter else if (! strcmp (name, "cpp")) 124018334Speter cpp_spec = sl->spec; 124118334Speter else if (! strcmp (name, "endfile")) 124218334Speter endfile_spec = sl->spec; 124318334Speter else if (! strcmp (name, "lib")) 124418334Speter lib_spec = sl->spec; 124518334Speter else if (! strcmp (name, "libgcc")) 124618334Speter libgcc_spec = sl->spec; 124718334Speter else if (! strcmp (name, "link")) 124818334Speter link_spec = sl->spec; 124918334Speter else if (! strcmp (name, "predefines")) 125018334Speter cpp_predefines = sl->spec; 125118334Speter else if (! strcmp (name, "signed_char")) 125218334Speter signed_char_spec = sl->spec; 125318334Speter else if (! strcmp (name, "startfile")) 125418334Speter startfile_spec = sl->spec; 125518334Speter else if (! strcmp (name, "switches_need_spaces")) 125618334Speter switches_need_spaces = sl->spec; 125718334Speter else if (! strcmp (name, "cross_compile")) 125818334Speter cross_compile = atoi (sl->spec); 125918334Speter else if (! strcmp (name, "multilib")) 126018334Speter multilib_select = sl->spec; 126118334Speter /* Free the old spec */ 126218334Speter if (old_spec) 126318334Speter free (old_spec); 126418334Speter} 126518334Speter 126618334Speter/* Accumulate a command (program name and args), and run it. */ 126718334Speter 126818334Speter/* Vector of pointers to arguments in the current line of specifications. */ 126918334Speter 127018334Speterstatic char **argbuf; 127118334Speter 127218334Speter/* Number of elements allocated in argbuf. */ 127318334Speter 127418334Speterstatic int argbuf_length; 127518334Speter 127618334Speter/* Number of elements in argbuf currently in use (containing args). */ 127718334Speter 127818334Speterstatic int argbuf_index; 127918334Speter 128018334Speter/* This is the list of suffixes and codes (%g/%u/%U) and the associated 128118334Speter temp file. Used only if MKTEMP_EACH_FILE. */ 128218334Speter 128318334Speterstatic struct temp_name { 128418334Speter char *suffix; /* suffix associated with the code. */ 128518334Speter int length; /* strlen (suffix). */ 128618334Speter int unique; /* Indicates whether %g or %u/%U was used. */ 128718334Speter char *filename; /* associated filename. */ 128818334Speter int filename_length; /* strlen (filename). */ 128918334Speter struct temp_name *next; 129018334Speter} *temp_names; 129118334Speter 129218334Speter/* Number of commands executed so far. */ 129318334Speter 129418334Speterstatic int execution_count; 129518334Speter 129618334Speter/* Number of commands that exited with a signal. */ 129718334Speter 129818334Speterstatic int signal_count; 129918334Speter 130018334Speter/* Name with which this program was invoked. */ 130118334Speter 130218334Speterstatic char *programname; 130318334Speter 130418334Speter/* Structures to keep track of prefixes to try when looking for files. */ 130518334Speter 130618334Speterstruct prefix_list 130718334Speter{ 130818334Speter char *prefix; /* String to prepend to the path. */ 130918334Speter struct prefix_list *next; /* Next in linked list. */ 131018334Speter int require_machine_suffix; /* Don't use without machine_suffix. */ 131118334Speter /* 2 means try both machine_suffix and just_machine_suffix. */ 131218334Speter int *used_flag_ptr; /* 1 if a file was found with this prefix. */ 131318334Speter}; 131418334Speter 131518334Speterstruct path_prefix 131618334Speter{ 131718334Speter struct prefix_list *plist; /* List of prefixes to try */ 131818334Speter int max_len; /* Max length of a prefix in PLIST */ 131918334Speter char *name; /* Name of this list (used in config stuff) */ 132018334Speter}; 132118334Speter 132218334Speter/* List of prefixes to try when looking for executables. */ 132318334Speter 132418334Speterstatic struct path_prefix exec_prefixes = { 0, 0, "exec" }; 132518334Speter 132618334Speter/* List of prefixes to try when looking for startup (crt0) files. */ 132718334Speter 132818334Speterstatic struct path_prefix startfile_prefixes = { 0, 0, "startfile" }; 132918334Speter 133018334Speter/* List of prefixes to try when looking for include files. */ 133118334Speter 133218334Speterstatic struct path_prefix include_prefixes = { 0, 0, "include" }; 133318334Speter 133418334Speter/* Suffix to attach to directories searched for commands. 133518334Speter This looks like `MACHINE/VERSION/'. */ 133618334Speter 133718334Speterstatic char *machine_suffix = 0; 133818334Speter 133918334Speter/* Suffix to attach to directories searched for commands. 134018334Speter This is just `MACHINE/'. */ 134118334Speter 134218334Speterstatic char *just_machine_suffix = 0; 134318334Speter 134418334Speter/* Adjusted value of GCC_EXEC_PREFIX envvar. */ 134518334Speter 134618334Speterstatic char *gcc_exec_prefix; 134718334Speter 134818334Speter/* Default prefixes to attach to command names. */ 134918334Speter 135018334Speter#ifdef CROSS_COMPILE /* Don't use these prefixes for a cross compiler. */ 135118334Speter#undef MD_EXEC_PREFIX 135218334Speter#undef MD_STARTFILE_PREFIX 135318334Speter#undef MD_STARTFILE_PREFIX_1 135418334Speter#endif 135518334Speter 135618334Speter#ifndef STANDARD_EXEC_PREFIX 135718334Speter#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/" 135818334Speter#endif /* !defined STANDARD_EXEC_PREFIX */ 135918334Speter 136018334Speterstatic char *standard_exec_prefix = STANDARD_EXEC_PREFIX; 136118334Speterstatic char *standard_exec_prefix_1 = "/usr/lib/gcc/"; 136218334Speter#ifdef MD_EXEC_PREFIX 136318334Speterstatic char *md_exec_prefix = MD_EXEC_PREFIX; 136418334Speter#endif 136518334Speter 136618334Speter#ifndef STANDARD_STARTFILE_PREFIX 136718334Speter#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/" 136818334Speter#endif /* !defined STANDARD_STARTFILE_PREFIX */ 136918334Speter 137018334Speter#ifdef MD_STARTFILE_PREFIX 137118334Speterstatic char *md_startfile_prefix = MD_STARTFILE_PREFIX; 137218334Speter#endif 137318334Speter#ifdef MD_STARTFILE_PREFIX_1 137418334Speterstatic char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1; 137518334Speter#endif 137618334Speterstatic char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; 137718334Speterstatic char *standard_startfile_prefix_1 = "/lib/"; 137818334Speterstatic char *standard_startfile_prefix_2 = "/usr/lib/"; 137918334Speter 138018334Speter#ifndef TOOLDIR_BASE_PREFIX 138118334Speter#define TOOLDIR_BASE_PREFIX "/usr/local/" 138218334Speter#endif 138318334Speterstatic char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX; 138418334Speterstatic char *tooldir_prefix; 138518334Speter 138618334Speter/* Subdirectory to use for locating libraries. Set by 138718334Speter set_multilib_dir based on the compilation options. */ 138818334Speter 138918334Speterstatic char *multilib_dir; 139018334Speter 139118334Speter/* Clear out the vector of arguments (after a command is executed). */ 139218334Speter 139318334Speterstatic void 139418334Speterclear_args () 139518334Speter{ 139618334Speter argbuf_index = 0; 139718334Speter} 139818334Speter 139918334Speter/* Add one argument to the vector at the end. 140018334Speter This is done when a space is seen or at the end of the line. 140118334Speter If DELETE_ALWAYS is nonzero, the arg is a filename 140218334Speter and the file should be deleted eventually. 140318334Speter If DELETE_FAILURE is nonzero, the arg is a filename 140418334Speter and the file should be deleted if this compilation fails. */ 140518334Speter 140618334Speterstatic void 140718334Speterstore_arg (arg, delete_always, delete_failure) 140818334Speter char *arg; 140918334Speter int delete_always, delete_failure; 141018334Speter{ 141118334Speter if (argbuf_index + 1 == argbuf_length) 141218334Speter { 141318334Speter argbuf = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *)); 141418334Speter } 141518334Speter 141618334Speter argbuf[argbuf_index++] = arg; 141718334Speter argbuf[argbuf_index] = 0; 141818334Speter 141918334Speter if (delete_always || delete_failure) 142018334Speter record_temp_file (arg, delete_always, delete_failure); 142118334Speter} 142218334Speter 142318334Speter/* Record the names of temporary files we tell compilers to write, 142418334Speter and delete them at the end of the run. */ 142518334Speter 142618334Speter/* This is the common prefix we use to make temp file names. 142718334Speter It is chosen once for each run of this program. 142818334Speter It is substituted into a spec by %g. 142918334Speter Thus, all temp file names contain this prefix. 143018334Speter In practice, all temp file names start with this prefix. 143118334Speter 143218334Speter This prefix comes from the envvar TMPDIR if it is defined; 143318334Speter otherwise, from the P_tmpdir macro if that is defined; 143418334Speter otherwise, in /usr/tmp or /tmp. */ 143518334Speter 143618334Speterstatic char *temp_filename; 143718334Speter 143818334Speter/* Length of the prefix. */ 143918334Speter 144018334Speterstatic int temp_filename_length; 144118334Speter 144218334Speter/* Define the list of temporary files to delete. */ 144318334Speter 144418334Speterstruct temp_file 144518334Speter{ 144618334Speter char *name; 144718334Speter struct temp_file *next; 144818334Speter}; 144918334Speter 145018334Speter/* Queue of files to delete on success or failure of compilation. */ 145118334Speterstatic struct temp_file *always_delete_queue; 145218334Speter/* Queue of files to delete on failure of compilation. */ 145318334Speterstatic struct temp_file *failure_delete_queue; 145418334Speter 145518334Speter/* Record FILENAME as a file to be deleted automatically. 145618334Speter ALWAYS_DELETE nonzero means delete it if all compilation succeeds; 145718334Speter otherwise delete it in any case. 145818334Speter FAIL_DELETE nonzero means delete it if a compilation step fails; 145918334Speter otherwise delete it in any case. */ 146018334Speter 146118334Speterstatic void 146218334Speterrecord_temp_file (filename, always_delete, fail_delete) 146318334Speter char *filename; 146418334Speter int always_delete; 146518334Speter int fail_delete; 146618334Speter{ 146718334Speter register char *name; 146818334Speter name = xmalloc (strlen (filename) + 1); 146918334Speter strcpy (name, filename); 147018334Speter 147118334Speter if (always_delete) 147218334Speter { 147318334Speter register struct temp_file *temp; 147418334Speter for (temp = always_delete_queue; temp; temp = temp->next) 147518334Speter if (! strcmp (name, temp->name)) 147618334Speter goto already1; 147718334Speter temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); 147818334Speter temp->next = always_delete_queue; 147918334Speter temp->name = name; 148018334Speter always_delete_queue = temp; 148118334Speter already1:; 148218334Speter } 148318334Speter 148418334Speter if (fail_delete) 148518334Speter { 148618334Speter register struct temp_file *temp; 148718334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 148818334Speter if (! strcmp (name, temp->name)) 148918334Speter goto already2; 149018334Speter temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); 149118334Speter temp->next = failure_delete_queue; 149218334Speter temp->name = name; 149318334Speter failure_delete_queue = temp; 149418334Speter already2:; 149518334Speter } 149618334Speter} 149718334Speter 149818334Speter/* Delete all the temporary files whose names we previously recorded. */ 149918334Speter 150018334Speterstatic void 150118334Speterdelete_if_ordinary (name) 150218334Speter char *name; 150318334Speter{ 150418334Speter struct stat st; 150518334Speter#ifdef DEBUG 150618334Speter int i, c; 150718334Speter 150818334Speter printf ("Delete %s? (y or n) ", name); 150918334Speter fflush (stdout); 151018334Speter i = getchar (); 151118334Speter if (i != '\n') 151218334Speter while ((c = getchar ()) != '\n' && c != EOF) ; 151318334Speter if (i == 'y' || i == 'Y') 151418334Speter#endif /* DEBUG */ 151518334Speter if (stat (name, &st) >= 0 && S_ISREG (st.st_mode)) 151618334Speter if (unlink (name) < 0) 151718334Speter if (verbose_flag) 151818334Speter perror_with_name (name); 151918334Speter} 152018334Speter 152118334Speterstatic void 152218334Speterdelete_temp_files () 152318334Speter{ 152418334Speter register struct temp_file *temp; 152518334Speter 152618334Speter for (temp = always_delete_queue; temp; temp = temp->next) 152718334Speter delete_if_ordinary (temp->name); 152818334Speter always_delete_queue = 0; 152918334Speter} 153018334Speter 153118334Speter/* Delete all the files to be deleted on error. */ 153218334Speter 153318334Speterstatic void 153418334Speterdelete_failure_queue () 153518334Speter{ 153618334Speter register struct temp_file *temp; 153718334Speter 153818334Speter for (temp = failure_delete_queue; temp; temp = temp->next) 153918334Speter delete_if_ordinary (temp->name); 154018334Speter} 154118334Speter 154218334Speterstatic void 154318334Speterclear_failure_queue () 154418334Speter{ 154518334Speter failure_delete_queue = 0; 154618334Speter} 154718334Speter 154818334Speter/* Compute a string to use as the base of all temporary file names. 154918334Speter It is substituted for %g. */ 155018334Speter 155118334Speterstatic char * 155218334Speterchoose_temp_base_try (try, base) 155318334Speter char *try; 155418334Speter char *base; 155518334Speter{ 155618334Speter char *rv; 155718334Speter if (base) 155818334Speter rv = base; 155918334Speter else if (try == (char *)0) 156018334Speter rv = 0; 156118334Speter else if (access (try, R_OK | W_OK) != 0) 156218334Speter rv = 0; 156318334Speter else 156418334Speter rv = try; 156518334Speter return rv; 156618334Speter} 156718334Speter 156818334Speterstatic void 156918334Speterchoose_temp_base () 157018334Speter{ 157118334Speter char *base = 0; 157218334Speter int len; 157318334Speter 157418334Speter base = choose_temp_base_try (getenv ("TMPDIR"), base); 157518334Speter base = choose_temp_base_try (getenv ("TMP"), base); 157618334Speter base = choose_temp_base_try (getenv ("TEMP"), base); 157718334Speter 157818334Speter#ifdef P_tmpdir 157918334Speter base = choose_temp_base_try (P_tmpdir, base); 158018334Speter#endif 158118334Speter 158218334Speter base = choose_temp_base_try (concat4 (dir_separator_str, "usr", 158318334Speter dir_separator_str, "tmp"), 158418334Speter base); 158518334Speter base = choose_temp_base_try (concat (dir_separator_str, "tmp"), base); 158618334Speter 158718334Speter /* If all else fails, use the current directory! */ 158818334Speter if (base == (char *)0) base = concat(".", dir_separator_str); 158918334Speter 159018334Speter len = strlen (base); 159118334Speter temp_filename = xmalloc (len + strlen (concat (dir_separator_str, 159218334Speter "ccXXXXXX")) + 1); 159318334Speter strcpy (temp_filename, base); 159418334Speter if (len > 0 && temp_filename[len-1] != '/' 159518334Speter && temp_filename[len-1] != DIR_SEPARATOR) 159618334Speter temp_filename[len++] = DIR_SEPARATOR; 159718334Speter strcpy (temp_filename + len, "ccXXXXXX"); 159818334Speter 159918334Speter mktemp (temp_filename); 160018334Speter temp_filename_length = strlen (temp_filename); 160118334Speter if (temp_filename_length == 0) 160218334Speter abort (); 160318334Speter} 160418334Speter 160518334Speter 160618334Speter/* Routine to add variables to the environment. We do this to pass 160718334Speter the pathname of the gcc driver, and the directories search to the 160818334Speter collect2 program, which is being run as ld. This way, we can be 160918334Speter sure of executing the right compiler when collect2 wants to build 161018334Speter constructors and destructors. Since the environment variables we 161118334Speter use come from an obstack, we don't have to worry about allocating 161218334Speter space for them. */ 161318334Speter 161418334Speter#ifndef HAVE_PUTENV 161518334Speter 161618334Spetervoid 161718334Speterputenv (str) 161818334Speter char *str; 161918334Speter{ 162018334Speter#ifndef VMS /* nor about VMS */ 162118334Speter 162218334Speter extern char **environ; 162318334Speter char **old_environ = environ; 162418334Speter char **envp; 162518334Speter int num_envs = 0; 162618334Speter int name_len = 1; 162718334Speter char *p = str; 162818334Speter int ch; 162918334Speter 163018334Speter while ((ch = *p++) != '\0' && ch != '=') 163118334Speter name_len++; 163218334Speter 163318334Speter if (!ch) 163418334Speter abort (); 163518334Speter 163618334Speter /* Search for replacing an existing environment variable, and 163718334Speter count the number of total environment variables. */ 163818334Speter for (envp = old_environ; *envp; envp++) 163918334Speter { 164018334Speter num_envs++; 164118334Speter if (!strncmp (str, *envp, name_len)) 164218334Speter { 164318334Speter *envp = str; 164418334Speter return; 164518334Speter } 164618334Speter } 164718334Speter 164818334Speter /* Add a new environment variable */ 164918334Speter environ = (char **) xmalloc (sizeof (char *) * (num_envs+2)); 165018334Speter *environ = str; 165118334Speter bcopy ((char *) old_environ, (char *) (environ + 1), 165218334Speter sizeof (char *) * (num_envs+1)); 165318334Speter 165418334Speter#endif /* VMS */ 165518334Speter} 165618334Speter 165718334Speter#endif /* HAVE_PUTENV */ 165818334Speter 165918334Speter 166018334Speter/* Build a list of search directories from PATHS. 166118334Speter PREFIX is a string to prepend to the list. 166218334Speter If CHECK_DIR_P is non-zero we ensure the directory exists. 166318334Speter This is used mostly by putenv_from_prefixes so we use `collect_obstack'. 166418334Speter It is also used by the --print-search-dirs flag. */ 166518334Speter 166618334Speterstatic char * 166718334Speterbuild_search_list (paths, prefix, check_dir_p) 166818334Speter struct path_prefix *paths; 166918334Speter char *prefix; 167018334Speter int check_dir_p; 167118334Speter{ 167218334Speter int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0; 167318334Speter int just_suffix_len 167418334Speter = (just_machine_suffix) ? strlen (just_machine_suffix) : 0; 167518334Speter int first_time = TRUE; 167618334Speter struct prefix_list *pprefix; 167718334Speter 167818334Speter obstack_grow (&collect_obstack, prefix, strlen (prefix)); 167918334Speter 168018334Speter for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next) 168118334Speter { 168218334Speter int len = strlen (pprefix->prefix); 168318334Speter 168418334Speter if (machine_suffix 168518334Speter && (!check_dir_p 168618334Speter || is_directory (pprefix->prefix, machine_suffix, 0))) 168718334Speter { 168818334Speter if (!first_time) 168918334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 169018334Speter 169118334Speter first_time = FALSE; 169218334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 169318334Speter obstack_grow (&collect_obstack, machine_suffix, suffix_len); 169418334Speter } 169518334Speter 169618334Speter if (just_machine_suffix 169718334Speter && pprefix->require_machine_suffix == 2 169818334Speter && (!check_dir_p 169918334Speter || is_directory (pprefix->prefix, just_machine_suffix, 0))) 170018334Speter { 170118334Speter if (!first_time) 170218334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 170318334Speter 170418334Speter first_time = FALSE; 170518334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 170618334Speter obstack_grow (&collect_obstack, just_machine_suffix, 170718334Speter just_suffix_len); 170818334Speter } 170918334Speter 171018334Speter if (!pprefix->require_machine_suffix) 171118334Speter { 171218334Speter if (!first_time) 171318334Speter obstack_1grow (&collect_obstack, PATH_SEPARATOR); 171418334Speter 171518334Speter first_time = FALSE; 171618334Speter obstack_grow (&collect_obstack, pprefix->prefix, len); 171718334Speter } 171818334Speter } 171918334Speter obstack_1grow (&collect_obstack, '\0'); 172018334Speter return obstack_finish (&collect_obstack); 172118334Speter} 172218334Speter 172318334Speter/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables for collect. */ 172418334Speter 172518334Speterstatic void 172618334Speterputenv_from_prefixes (paths, env_var) 172718334Speter struct path_prefix *paths; 172818334Speter char *env_var; 172918334Speter{ 173018334Speter putenv (build_search_list (paths, env_var, 1)); 173118334Speter} 173218334Speter 173318334Speter/* Search for NAME using the prefix list PREFIXES. MODE is passed to 173418334Speter access to check permissions. 173518334Speter Return 0 if not found, otherwise return its name, allocated with malloc. */ 173618334Speter 173718334Speterstatic char * 173818334Speterfind_a_file (pprefix, name, mode) 173918334Speter struct path_prefix *pprefix; 174018334Speter char *name; 174118334Speter int mode; 174218334Speter{ 174318334Speter char *temp; 174418334Speter char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : ""); 174518334Speter struct prefix_list *pl; 174618334Speter int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1; 174718334Speter 174818334Speter if (machine_suffix) 174918334Speter len += strlen (machine_suffix); 175018334Speter 175118334Speter temp = xmalloc (len); 175218334Speter 175318334Speter /* Determine the filename to execute (special case for absolute paths). */ 175418334Speter 175518334Speter if (*name == '/' || *name == DIR_SEPARATOR) 175618334Speter { 175718334Speter if (access (name, mode)) 175818334Speter { 175918334Speter strcpy (temp, name); 176018334Speter return temp; 176118334Speter } 176218334Speter } 176318334Speter else 176418334Speter for (pl = pprefix->plist; pl; pl = pl->next) 176518334Speter { 176618334Speter if (machine_suffix) 176718334Speter { 176818334Speter /* Some systems have a suffix for executable files. 176918334Speter So try appending that first. */ 177018334Speter if (file_suffix[0] != 0) 177118334Speter { 177218334Speter strcpy (temp, pl->prefix); 177318334Speter strcat (temp, machine_suffix); 177418334Speter strcat (temp, name); 177518334Speter strcat (temp, file_suffix); 177618334Speter if (access (temp, mode) == 0) 177718334Speter { 177818334Speter if (pl->used_flag_ptr != 0) 177918334Speter *pl->used_flag_ptr = 1; 178018334Speter return temp; 178118334Speter } 178218334Speter } 178318334Speter 178418334Speter /* Now try just the name. */ 178518334Speter strcpy (temp, pl->prefix); 178618334Speter strcat (temp, machine_suffix); 178718334Speter strcat (temp, name); 178818334Speter if (access (temp, mode) == 0) 178918334Speter { 179018334Speter if (pl->used_flag_ptr != 0) 179118334Speter *pl->used_flag_ptr = 1; 179218334Speter return temp; 179318334Speter } 179418334Speter } 179518334Speter 179618334Speter /* Certain prefixes are tried with just the machine type, 179718334Speter not the version. This is used for finding as, ld, etc. */ 179818334Speter if (just_machine_suffix && pl->require_machine_suffix == 2) 179918334Speter { 180018334Speter /* Some systems have a suffix for executable files. 180118334Speter So try appending that first. */ 180218334Speter if (file_suffix[0] != 0) 180318334Speter { 180418334Speter strcpy (temp, pl->prefix); 180518334Speter strcat (temp, just_machine_suffix); 180618334Speter strcat (temp, name); 180718334Speter strcat (temp, file_suffix); 180818334Speter if (access (temp, mode) == 0) 180918334Speter { 181018334Speter if (pl->used_flag_ptr != 0) 181118334Speter *pl->used_flag_ptr = 1; 181218334Speter return temp; 181318334Speter } 181418334Speter } 181518334Speter 181618334Speter strcpy (temp, pl->prefix); 181718334Speter strcat (temp, just_machine_suffix); 181818334Speter strcat (temp, name); 181918334Speter if (access (temp, mode) == 0) 182018334Speter { 182118334Speter if (pl->used_flag_ptr != 0) 182218334Speter *pl->used_flag_ptr = 1; 182318334Speter return temp; 182418334Speter } 182518334Speter } 182618334Speter 182718334Speter /* Certain prefixes can't be used without the machine suffix 182818334Speter when the machine or version is explicitly specified. */ 182918334Speter if (!pl->require_machine_suffix) 183018334Speter { 183118334Speter /* Some systems have a suffix for executable files. 183218334Speter So try appending that first. */ 183318334Speter if (file_suffix[0] != 0) 183418334Speter { 183518334Speter strcpy (temp, pl->prefix); 183618334Speter strcat (temp, name); 183718334Speter strcat (temp, file_suffix); 183818334Speter if (access (temp, mode) == 0) 183918334Speter { 184018334Speter if (pl->used_flag_ptr != 0) 184118334Speter *pl->used_flag_ptr = 1; 184218334Speter return temp; 184318334Speter } 184418334Speter } 184518334Speter 184618334Speter strcpy (temp, pl->prefix); 184718334Speter strcat (temp, name); 184818334Speter if (access (temp, mode) == 0) 184918334Speter { 185018334Speter if (pl->used_flag_ptr != 0) 185118334Speter *pl->used_flag_ptr = 1; 185218334Speter return temp; 185318334Speter } 185418334Speter } 185518334Speter } 185618334Speter 185718334Speter free (temp); 185818334Speter return 0; 185918334Speter} 186018334Speter 186118334Speter/* Add an entry for PREFIX in PLIST. If FIRST is set, it goes 186218334Speter at the start of the list, otherwise it goes at the end. 186318334Speter 186418334Speter If WARN is nonzero, we will warn if no file is found 186518334Speter through this prefix. WARN should point to an int 186618334Speter which will be set to 1 if this entry is used. 186718334Speter 186818334Speter REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without 186918334Speter the complete value of machine_suffix. 187018334Speter 2 means try both machine_suffix and just_machine_suffix. */ 187118334Speter 187218334Speterstatic void 187318334Speteradd_prefix (pprefix, prefix, first, require_machine_suffix, warn) 187418334Speter struct path_prefix *pprefix; 187518334Speter char *prefix; 187618334Speter int first; 187718334Speter int require_machine_suffix; 187818334Speter int *warn; 187918334Speter{ 188018334Speter struct prefix_list *pl, **prev; 188118334Speter int len; 188218334Speter 188318334Speter if (!first && pprefix->plist) 188418334Speter { 188518334Speter for (pl = pprefix->plist; pl->next; pl = pl->next) 188618334Speter ; 188718334Speter prev = &pl->next; 188818334Speter } 188918334Speter else 189018334Speter prev = &pprefix->plist; 189118334Speter 189218334Speter /* Keep track of the longest prefix */ 189318334Speter 189418334Speter len = strlen (prefix); 189518334Speter if (len > pprefix->max_len) 189618334Speter pprefix->max_len = len; 189718334Speter 189818334Speter pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list)); 189918334Speter pl->prefix = save_string (prefix, len); 190018334Speter pl->require_machine_suffix = require_machine_suffix; 190118334Speter pl->used_flag_ptr = warn; 190218334Speter if (warn) 190318334Speter *warn = 0; 190418334Speter 190518334Speter if (*prev) 190618334Speter pl->next = *prev; 190718334Speter else 190818334Speter pl->next = (struct prefix_list *) 0; 190918334Speter *prev = pl; 191018334Speter} 191118334Speter 191218334Speter/* Print warnings for any prefixes in the list PPREFIX that were not used. */ 191318334Speter 191418334Speterstatic void 191518334Speterunused_prefix_warnings (pprefix) 191618334Speter struct path_prefix *pprefix; 191718334Speter{ 191818334Speter struct prefix_list *pl = pprefix->plist; 191918334Speter 192018334Speter while (pl) 192118334Speter { 192218334Speter if (pl->used_flag_ptr != 0 && !*pl->used_flag_ptr) 192318334Speter { 192418334Speter error ("file path prefix `%s' never used", 192518334Speter pl->prefix); 192618334Speter /* Prevent duplicate warnings. */ 192718334Speter *pl->used_flag_ptr = 1; 192818334Speter } 192918334Speter pl = pl->next; 193018334Speter } 193118334Speter} 193218334Speter 193318334Speter/* Get rid of all prefixes built up so far in *PLISTP. */ 193418334Speter 193518334Speterstatic void 193618334Speterfree_path_prefix (pprefix) 193718334Speter struct path_prefix *pprefix; 193818334Speter{ 193918334Speter struct prefix_list *pl = pprefix->plist; 194018334Speter struct prefix_list *temp; 194118334Speter 194218334Speter while (pl) 194318334Speter { 194418334Speter temp = pl; 194518334Speter pl = pl->next; 194618334Speter free (temp->prefix); 194718334Speter free ((char *) temp); 194818334Speter } 194918334Speter pprefix->plist = (struct prefix_list *) 0; 195018334Speter} 195118334Speter 195218334Speter/* stdin file number. */ 195318334Speter#define STDIN_FILE_NO 0 195418334Speter 195518334Speter/* stdout file number. */ 195618334Speter#define STDOUT_FILE_NO 1 195718334Speter 195818334Speter/* value of `pipe': port index for reading. */ 195918334Speter#define READ_PORT 0 196018334Speter 196118334Speter/* value of `pipe': port index for writing. */ 196218334Speter#define WRITE_PORT 1 196318334Speter 196418334Speter/* Pipe waiting from last process, to be used as input for the next one. 196518334Speter Value is STDIN_FILE_NO if no pipe is waiting 196618334Speter (i.e. the next command is the first of a group). */ 196718334Speter 196818334Speterstatic int last_pipe_input; 196918334Speter 197018334Speter/* Fork one piped subcommand. FUNC is the system call to use 197118334Speter (either execv or execvp). ARGV is the arg vector to use. 197218334Speter NOT_LAST is nonzero if this is not the last subcommand 197318334Speter (i.e. its output should be piped to the next one.) */ 197418334Speter 197518334Speter#ifdef __MSDOS__ 197618334Speter 197718334Speter#include <process.h> 197818334Speterstatic int 197918334Speterpexecute (search_flag, program, argv, not_last) 198018334Speter int search_flag; 198118334Speter char *program; 198218334Speter char *argv[]; 198318334Speter int not_last; 198418334Speter{ 198518334Speter#ifdef __GO32__ 198618334Speter int i = (search_flag ? spawnv : spawnvp) (1, program, argv); 198718334Speter#else 198818334Speter char *scmd, *rf; 198918334Speter FILE *argfile; 199018334Speter int i, el = search_flag ? 0 : 4; 199118334Speter 199218334Speter scmd = (char *)malloc (strlen (program) + strlen (temp_filename) + 6 + el); 199318334Speter rf = scmd + strlen(program) + 2 + el; 199418334Speter sprintf (scmd, "%s%s @%s.gp", program, 199518334Speter (search_flag ? "" : ".exe"), temp_filename); 199618334Speter argfile = fopen (rf, "w"); 199718334Speter if (argfile == 0) 199818334Speter pfatal_with_name (rf); 199918334Speter 200018334Speter for (i=1; argv[i]; i++) 200118334Speter { 200218334Speter char *cp; 200318334Speter for (cp = argv[i]; *cp; cp++) 200418334Speter { 200518334Speter if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp)) 200618334Speter fputc ('\\', argfile); 200718334Speter fputc (*cp, argfile); 200818334Speter } 200918334Speter fputc ('\n', argfile); 201018334Speter } 201118334Speter fclose (argfile); 201218334Speter 201318334Speter i = system (scmd); 201418334Speter 201518334Speter remove (rf); 201618334Speter#endif 201718334Speter 201818334Speter if (i == -1) 201918334Speter { 202018334Speter perror_exec (program); 202118334Speter return MIN_FATAL_STATUS << 8; 202218334Speter } 202318334Speter return i << 8; 202418334Speter} 202518334Speter 202618334Speter#endif 202718334Speter 202818334Speter#if !defined(__MSDOS__) && !defined(OS2) && !defined(_WIN32) 202918334Speter 203018334Speterstatic int 203118334Speterpexecute (search_flag, program, argv, not_last) 203218334Speter int search_flag; 203318334Speter char *program; 203418334Speter char *argv[]; 203518334Speter int not_last; 203618334Speter{ 203718334Speter int (*func)() = (search_flag ? execv : execvp); 203818334Speter int pid; 203918334Speter int pdes[2]; 204018334Speter int input_desc = last_pipe_input; 204118334Speter int output_desc = STDOUT_FILE_NO; 204218334Speter int retries, sleep_interval; 204318334Speter 204418334Speter /* If this isn't the last process, make a pipe for its output, 204518334Speter and record it as waiting to be the input to the next process. */ 204618334Speter 204718334Speter if (not_last) 204818334Speter { 204918334Speter if (pipe (pdes) < 0) 205018334Speter pfatal_with_name ("pipe"); 205118334Speter output_desc = pdes[WRITE_PORT]; 205218334Speter last_pipe_input = pdes[READ_PORT]; 205318334Speter } 205418334Speter else 205518334Speter last_pipe_input = STDIN_FILE_NO; 205618334Speter 205718334Speter /* Fork a subprocess; wait and retry if it fails. */ 205818334Speter sleep_interval = 1; 205918334Speter for (retries = 0; retries < 4; retries++) 206018334Speter { 206118334Speter pid = vfork (); 206218334Speter if (pid >= 0) 206318334Speter break; 206418334Speter sleep (sleep_interval); 206518334Speter sleep_interval *= 2; 206618334Speter } 206718334Speter 206818334Speter switch (pid) 206918334Speter { 207018334Speter case -1: 207118334Speter#ifdef vfork 207218334Speter pfatal_with_name ("fork"); 207318334Speter#else 207418334Speter pfatal_with_name ("vfork"); 207518334Speter#endif 207618334Speter /* NOTREACHED */ 207718334Speter return 0; 207818334Speter 207918334Speter case 0: /* child */ 208018334Speter /* Move the input and output pipes into place, if nec. */ 208118334Speter if (input_desc != STDIN_FILE_NO) 208218334Speter { 208318334Speter close (STDIN_FILE_NO); 208418334Speter dup (input_desc); 208518334Speter close (input_desc); 208618334Speter } 208718334Speter if (output_desc != STDOUT_FILE_NO) 208818334Speter { 208918334Speter close (STDOUT_FILE_NO); 209018334Speter dup (output_desc); 209118334Speter close (output_desc); 209218334Speter } 209318334Speter 209418334Speter /* Close the parent's descs that aren't wanted here. */ 209518334Speter if (last_pipe_input != STDIN_FILE_NO) 209618334Speter close (last_pipe_input); 209718334Speter 209818334Speter /* Exec the program. */ 209918334Speter (*func) (program, argv); 210018334Speter perror_exec (program); 210118334Speter exit (-1); 210218334Speter /* NOTREACHED */ 210318334Speter return 0; 210418334Speter 210518334Speter default: 210618334Speter /* In the parent, after forking. 210718334Speter Close the descriptors that we made for this child. */ 210818334Speter if (input_desc != STDIN_FILE_NO) 210918334Speter close (input_desc); 211018334Speter if (output_desc != STDOUT_FILE_NO) 211118334Speter close (output_desc); 211218334Speter 211318334Speter /* Return child's process number. */ 211418334Speter return pid; 211518334Speter } 211618334Speter} 211718334Speter 211818334Speter#endif /* not __MSDOS__ and not OS2 and not _WIN32 */ 211918334Speter 212018334Speter#if defined(OS2) 212118334Speter 212218334Speterstatic int 212318334Speterpexecute (search_flag, program, argv, not_last) 212418334Speter int search_flag; 212518334Speter char *program; 212618334Speter char *argv[]; 212718334Speter int not_last; 212818334Speter{ 212918334Speter return (search_flag ? spawnv : spawnvp) (1, program, argv); 213018334Speter} 213118334Speter#endif /* OS2 */ 213218334Speter 213318334Speter#if defined(_WIN32) 213418334Speter 213518334Speterstatic int 213618334Speterpexecute (search_flag, program, argv, not_last) 213718334Speter int search_flag; 213818334Speter char *program; 213918334Speter char *argv[]; 214018334Speter int not_last; 214118334Speter{ 214218334Speter return (search_flag ? __spawnv : __spawnvp) (1, program, argv); 214318334Speter} 214418334Speter#endif /* _WIN32 */ 214518334Speter 214618334Speter 214718334Speter/* Execute the command specified by the arguments on the current line of spec. 214818334Speter When using pipes, this includes several piped-together commands 214918334Speter with `|' between them. 215018334Speter 215118334Speter Return 0 if successful, -1 if failed. */ 215218334Speter 215318334Speterstatic int 215418334Speterexecute () 215518334Speter{ 215618334Speter int i; 215718334Speter int n_commands; /* # of command. */ 215818334Speter char *string; 215918334Speter struct command 216018334Speter { 216118334Speter char *prog; /* program name. */ 216218334Speter char **argv; /* vector of args. */ 216318334Speter int pid; /* pid of process for this command. */ 216418334Speter }; 216518334Speter 216618334Speter struct command *commands; /* each command buffer with above info. */ 216718334Speter 216818334Speter /* Count # of piped commands. */ 216918334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 217018334Speter if (strcmp (argbuf[i], "|") == 0) 217118334Speter n_commands++; 217218334Speter 217318334Speter /* Get storage for each command. */ 217418334Speter commands 217518334Speter = (struct command *) alloca (n_commands * sizeof (struct command)); 217618334Speter 217718334Speter /* Split argbuf into its separate piped processes, 217818334Speter and record info about each one. 217918334Speter Also search for the programs that are to be run. */ 218018334Speter 218118334Speter commands[0].prog = argbuf[0]; /* first command. */ 218218334Speter commands[0].argv = &argbuf[0]; 218318334Speter string = find_a_file (&exec_prefixes, commands[0].prog, X_OK); 218418334Speter if (string) 218518334Speter commands[0].argv[0] = string; 218618334Speter 218718334Speter for (n_commands = 1, i = 0; i < argbuf_index; i++) 218818334Speter if (strcmp (argbuf[i], "|") == 0) 218918334Speter { /* each command. */ 219018334Speter#ifdef __MSDOS__ 219118334Speter fatal ("-pipe not supported under MS-DOS"); 219218334Speter#endif 219318334Speter argbuf[i] = 0; /* termination of command args. */ 219418334Speter commands[n_commands].prog = argbuf[i + 1]; 219518334Speter commands[n_commands].argv = &argbuf[i + 1]; 219618334Speter string = find_a_file (&exec_prefixes, commands[n_commands].prog, X_OK); 219718334Speter if (string) 219818334Speter commands[n_commands].argv[0] = string; 219918334Speter n_commands++; 220018334Speter } 220118334Speter 220218334Speter argbuf[argbuf_index] = 0; 220318334Speter 220418334Speter /* If -v, print what we are about to do, and maybe query. */ 220518334Speter 220618334Speter if (verbose_flag) 220718334Speter { 220818334Speter /* Print each piped command as a separate line. */ 220918334Speter for (i = 0; i < n_commands ; i++) 221018334Speter { 221118334Speter char **j; 221218334Speter 221318334Speter for (j = commands[i].argv; *j; j++) 221418334Speter fprintf (stderr, " %s", *j); 221518334Speter 221618334Speter /* Print a pipe symbol after all but the last command. */ 221718334Speter if (i + 1 != n_commands) 221818334Speter fprintf (stderr, " |"); 221918334Speter fprintf (stderr, "\n"); 222018334Speter } 222118334Speter fflush (stderr); 222218334Speter#ifdef DEBUG 222318334Speter fprintf (stderr, "\nGo ahead? (y or n) "); 222418334Speter fflush (stderr); 222518334Speter i = getchar (); 222618334Speter if (i != '\n') 222718334Speter while (getchar () != '\n') ; 222818334Speter if (i != 'y' && i != 'Y') 222918334Speter return 0; 223018334Speter#endif /* DEBUG */ 223118334Speter } 223218334Speter 223318334Speter /* Run each piped subprocess. */ 223418334Speter 223518334Speter last_pipe_input = STDIN_FILE_NO; 223618334Speter for (i = 0; i < n_commands; i++) 223718334Speter { 223818334Speter char *string = commands[i].argv[0]; 223918334Speter 224018334Speter commands[i].pid = pexecute (string != commands[i].prog, 224118334Speter string, commands[i].argv, 224218334Speter i + 1 < n_commands); 224318334Speter 224418334Speter if (string != commands[i].prog) 224518334Speter free (string); 224618334Speter } 224718334Speter 224818334Speter execution_count++; 224918334Speter 225018334Speter /* Wait for all the subprocesses to finish. 225118334Speter We don't care what order they finish in; 225218334Speter we know that N_COMMANDS waits will get them all. 225318334Speter Ignore subprocesses that we don't know about, 225418334Speter since they can be spawned by the process that exec'ed us. */ 225518334Speter 225618334Speter { 225718334Speter int ret_code = 0; 225818334Speter 225918334Speter for (i = 0; i < n_commands; ) 226018334Speter { 226118334Speter int j; 226218334Speter int status; 226318334Speter int pid; 226418334Speter 226518334Speter#ifdef __MSDOS__ 226618334Speter status = pid = commands[i].pid; 226718334Speter#else 226818334Speter#ifdef _WIN32 226918334Speter pid = cwait (&status, commands[i].pid, WAIT_CHILD); 227018334Speter#else 227118334Speter pid = wait (&status); 227218334Speter#endif 227318334Speter#endif 227418334Speter if (pid < 0) 227518334Speter abort (); 227618334Speter 227718334Speter for (j = 0; j < n_commands; j++) 227818334Speter if (commands[j].pid == pid) 227918334Speter { 228018334Speter i++; 228118334Speter if (status != 0) 228218334Speter { 228318334Speter if (WIFSIGNALED (status)) 228418334Speter { 228518334Speter fatal ("Internal compiler error: program %s got fatal signal %d", 228618334Speter commands[j].prog, WTERMSIG (status)); 228718334Speter signal_count++; 228818334Speter ret_code = -1; 228918334Speter } 229018334Speter else if (WIFEXITED (status) 229118334Speter && WEXITSTATUS (status) >= MIN_FATAL_STATUS) 229218334Speter ret_code = -1; 229318334Speter } 229418334Speter break; 229518334Speter } 229618334Speter } 229718334Speter return ret_code; 229818334Speter } 229918334Speter} 230018334Speter 230118334Speter/* Find all the switches given to us 230218334Speter and make a vector describing them. 230318334Speter The elements of the vector are strings, one per switch given. 230418334Speter If a switch uses following arguments, then the `part1' field 230518334Speter is the switch itself and the `args' field 230618334Speter is a null-terminated vector containing the following arguments. 230718334Speter The `live_cond' field is 1 if the switch is true in a conditional spec, 230818334Speter -1 if false (overridden by a later switch), and is initialized to zero. 230918334Speter The `valid' field is nonzero if any spec has looked at this switch; 231018334Speter if it remains zero at the end of the run, it must be meaningless. */ 231118334Speter 231218334Speterstruct switchstr 231318334Speter{ 231418334Speter char *part1; 231518334Speter char **args; 231618334Speter int live_cond; 231718334Speter int valid; 231818334Speter}; 231918334Speter 232018334Speterstatic struct switchstr *switches; 232118334Speter 232218334Speterstatic int n_switches; 232318334Speter 232418334Speterstruct infile 232518334Speter{ 232618334Speter char *name; 232718334Speter char *language; 232818334Speter}; 232918334Speter 233018334Speter/* Also a vector of input files specified. */ 233118334Speter 233218334Speterstatic struct infile *infiles; 233318334Speter 233418334Speterstatic int n_infiles; 233518334Speter 233618334Speter/* And a vector of corresponding output files is made up later. */ 233718334Speter 233818334Speterstatic char **outfiles; 233918334Speter 234018334Speter/* Create the vector `switches' and its contents. 234118334Speter Store its length in `n_switches'. */ 234218334Speter 234318334Speterstatic void 234418334Speterprocess_command (argc, argv) 234518334Speter int argc; 234618334Speter char **argv; 234718334Speter{ 234818334Speter register int i; 234918334Speter char *temp; 235018334Speter char *spec_lang = 0; 235118334Speter int last_language_n_infiles; 235218334Speter 235318334Speter gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX"); 235418334Speter 235518334Speter n_switches = 0; 235618334Speter n_infiles = 0; 235718334Speter 235818334Speter /* Figure compiler version from version string. */ 235918334Speter 236018334Speter compiler_version = save_string (version_string, strlen (version_string)); 236118334Speter for (temp = compiler_version; *temp; ++temp) 236218334Speter { 236318334Speter if (*temp == ' ') 236418334Speter { 236518334Speter *temp = '\0'; 236618334Speter break; 236718334Speter } 236818334Speter } 236918334Speter 237018334Speter /* Set up the default search paths. */ 237118334Speter 237218334Speter if (gcc_exec_prefix) 237318334Speter { 237418334Speter add_prefix (&exec_prefixes, gcc_exec_prefix, 0, 0, NULL_PTR); 237518334Speter add_prefix (&startfile_prefixes, gcc_exec_prefix, 0, 0, NULL_PTR); 237618334Speter } 237718334Speter 237818334Speter /* COMPILER_PATH and LIBRARY_PATH have values 237918334Speter that are lists of directory names with colons. */ 238018334Speter 238118334Speter temp = getenv ("COMPILER_PATH"); 238218334Speter if (temp) 238318334Speter { 238418334Speter char *startp, *endp; 238518334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 238618334Speter 238718334Speter startp = endp = temp; 238818334Speter while (1) 238918334Speter { 239018334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 239118334Speter { 239218334Speter strncpy (nstore, startp, endp-startp); 239318334Speter if (endp == startp) 239418334Speter strcpy (nstore, concat (".", dir_separator_str)); 239518334Speter else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR) 239618334Speter { 239718334Speter nstore[endp-startp] = DIR_SEPARATOR; 239818334Speter nstore[endp-startp+1] = 0; 239918334Speter } 240018334Speter else 240118334Speter nstore[endp-startp] = 0; 240218334Speter add_prefix (&exec_prefixes, nstore, 0, 0, NULL_PTR); 240318334Speter if (*endp == 0) 240418334Speter break; 240518334Speter endp = startp = endp + 1; 240618334Speter } 240718334Speter else 240818334Speter endp++; 240918334Speter } 241018334Speter } 241118334Speter 241218334Speter temp = getenv ("LIBRARY_PATH"); 241318334Speter if (temp && ! cross_compile) 241418334Speter { 241518334Speter char *startp, *endp; 241618334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 241718334Speter 241818334Speter startp = endp = temp; 241918334Speter while (1) 242018334Speter { 242118334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 242218334Speter { 242318334Speter strncpy (nstore, startp, endp-startp); 242418334Speter if (endp == startp) 242518334Speter strcpy (nstore, concat (".", dir_separator_str)); 242618334Speter else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR) 242718334Speter { 242818334Speter nstore[endp-startp] = DIR_SEPARATOR; 242918334Speter nstore[endp-startp+1] = 0; 243018334Speter } 243118334Speter else 243218334Speter nstore[endp-startp] = 0; 243318334Speter add_prefix (&startfile_prefixes, nstore, 0, 0, NULL_PTR); 243418334Speter if (*endp == 0) 243518334Speter break; 243618334Speter endp = startp = endp + 1; 243718334Speter } 243818334Speter else 243918334Speter endp++; 244018334Speter } 244118334Speter } 244218334Speter 244318334Speter /* Use LPATH like LIBRARY_PATH (for the CMU build program). */ 244418334Speter temp = getenv ("LPATH"); 244518334Speter if (temp && ! cross_compile) 244618334Speter { 244718334Speter char *startp, *endp; 244818334Speter char *nstore = (char *) alloca (strlen (temp) + 3); 244918334Speter 245018334Speter startp = endp = temp; 245118334Speter while (1) 245218334Speter { 245318334Speter if (*endp == PATH_SEPARATOR || *endp == 0) 245418334Speter { 245518334Speter strncpy (nstore, startp, endp-startp); 245618334Speter if (endp == startp) 245718334Speter strcpy (nstore, concat (".", dir_separator_str)); 245818334Speter else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR) 245918334Speter { 246018334Speter nstore[endp-startp] = DIR_SEPARATOR; 246118334Speter nstore[endp-startp+1] = 0; 246218334Speter } 246318334Speter else 246418334Speter nstore[endp-startp] = 0; 246518334Speter add_prefix (&startfile_prefixes, nstore, 0, 0, NULL_PTR); 246618334Speter if (*endp == 0) 246718334Speter break; 246818334Speter endp = startp = endp + 1; 246918334Speter } 247018334Speter else 247118334Speter endp++; 247218334Speter } 247318334Speter } 247418334Speter 247518334Speter /* Convert new-style -- options to old-style. */ 247618334Speter translate_options (&argc, &argv); 247718334Speter 247818334Speter /* Scan argv twice. Here, the first time, just count how many switches 247918334Speter there will be in their vector, and how many input files in theirs. 248018334Speter Here we also parse the switches that cc itself uses (e.g. -v). */ 248118334Speter 248218334Speter for (i = 1; i < argc; i++) 248318334Speter { 248418334Speter if (! strcmp (argv[i], "-dumpspecs")) 248518334Speter { 248618334Speter printf ("*asm:\n%s\n\n", asm_spec); 248718334Speter printf ("*asm_final:\n%s\n\n", asm_final_spec); 248818334Speter printf ("*cpp:\n%s\n\n", cpp_spec); 248918334Speter printf ("*cc1:\n%s\n\n", cc1_spec); 249018334Speter printf ("*cc1plus:\n%s\n\n", cc1plus_spec); 249118334Speter printf ("*endfile:\n%s\n\n", endfile_spec); 249218334Speter printf ("*link:\n%s\n\n", link_spec); 249318334Speter printf ("*lib:\n%s\n\n", lib_spec); 249418334Speter printf ("*libgcc:\n%s\n\n", libgcc_spec); 249518334Speter printf ("*startfile:\n%s\n\n", startfile_spec); 249618334Speter printf ("*switches_need_spaces:\n%s\n\n", switches_need_spaces); 249718334Speter printf ("*signed_char:\n%s\n\n", signed_char_spec); 249818334Speter printf ("*predefines:\n%s\n\n", cpp_predefines); 249918334Speter printf ("*cross_compile:\n%d\n\n", cross_compile); 250018334Speter printf ("*multilib:\n%s\n\n", multilib_select); 250118334Speter 250218334Speter exit (0); 250318334Speter } 250418334Speter else if (! strcmp (argv[i], "-dumpversion")) 250518334Speter { 250618334Speter printf ("%s\n", version_string); 250718334Speter exit (0); 250818334Speter } 250918334Speter else if (! strcmp (argv[i], "-dumpmachine")) 251018334Speter { 251118334Speter printf ("%s\n", spec_machine); 251218334Speter exit (0); 251318334Speter } 251418334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 251518334Speter print_search_dirs = 1; 251618334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 251718334Speter print_file_name = "libgcc.a"; 251818334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 251918334Speter print_file_name = argv[i] + 17; 252018334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 252118334Speter print_prog_name = argv[i] + 17; 252218334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 252318334Speter print_multi_lib = 1; 252418334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 252518334Speter print_multi_directory = 1; 252618334Speter else if (! strncmp (argv[i], "-Wa,", 4)) 252718334Speter { 252818334Speter int prev, j; 252918334Speter /* Pass the rest of this option to the assembler. */ 253018334Speter 253118334Speter n_assembler_options++; 253218334Speter if (!assembler_options) 253318334Speter assembler_options 253418334Speter = (char **) xmalloc (n_assembler_options * sizeof (char **)); 253518334Speter else 253618334Speter assembler_options 253718334Speter = (char **) xrealloc (assembler_options, 253818334Speter n_assembler_options * sizeof (char **)); 253918334Speter 254018334Speter /* Split the argument at commas. */ 254118334Speter prev = 4; 254218334Speter for (j = 4; argv[i][j]; j++) 254318334Speter if (argv[i][j] == ',') 254418334Speter { 254518334Speter assembler_options[n_assembler_options - 1] 254618334Speter = save_string (argv[i] + prev, j - prev); 254718334Speter n_assembler_options++; 254818334Speter assembler_options 254918334Speter = (char **) xrealloc (assembler_options, 255018334Speter n_assembler_options * sizeof (char **)); 255118334Speter prev = j + 1; 255218334Speter } 255318334Speter /* Record the part after the last comma. */ 255418334Speter assembler_options[n_assembler_options - 1] = argv[i] + prev; 255518334Speter } 255618334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 255718334Speter { 255818334Speter int prev, j; 255918334Speter /* Pass the rest of this option to the preprocessor. */ 256018334Speter 256118334Speter n_preprocessor_options++; 256218334Speter if (!preprocessor_options) 256318334Speter preprocessor_options 256418334Speter = (char **) xmalloc (n_preprocessor_options * sizeof (char **)); 256518334Speter else 256618334Speter preprocessor_options 256718334Speter = (char **) xrealloc (preprocessor_options, 256818334Speter n_preprocessor_options * sizeof (char **)); 256918334Speter 257018334Speter /* Split the argument at commas. */ 257118334Speter prev = 4; 257218334Speter for (j = 4; argv[i][j]; j++) 257318334Speter if (argv[i][j] == ',') 257418334Speter { 257518334Speter preprocessor_options[n_preprocessor_options - 1] 257618334Speter = save_string (argv[i] + prev, j - prev); 257718334Speter n_preprocessor_options++; 257818334Speter preprocessor_options 257918334Speter = (char **) xrealloc (preprocessor_options, 258018334Speter n_preprocessor_options * sizeof (char **)); 258118334Speter prev = j + 1; 258218334Speter } 258318334Speter /* Record the part after the last comma. */ 258418334Speter preprocessor_options[n_preprocessor_options - 1] = argv[i] + prev; 258518334Speter } 258618334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 258718334Speter /* The +e options to the C++ front-end. */ 258818334Speter n_switches++; 258918334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 259018334Speter { 259118334Speter int j; 259218334Speter /* Split the argument at commas. */ 259318334Speter for (j = 3; argv[i][j]; j++) 259418334Speter n_infiles += (argv[i][j] == ','); 259518334Speter } 259618334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 259718334Speter { 259818334Speter if (i + 1 == argc) 259918334Speter fatal ("argument to `-Xlinker' is missing"); 260018334Speter 260118334Speter n_infiles++; 260218334Speter i++; 260318334Speter } 260418334Speter else if (strncmp (argv[i], "-l", 2) == 0) 260518334Speter n_infiles++; 260618334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 260718334Speter { 260818334Speter register char *p = &argv[i][1]; 260918334Speter register int c = *p; 261018334Speter 261118334Speter switch (c) 261218334Speter { 261318334Speter case 'b': 261418334Speter if (p[1] == 0 && i + 1 == argc) 261518334Speter fatal ("argument to `-b' is missing"); 261618334Speter if (p[1] == 0) 261718334Speter spec_machine = argv[++i]; 261818334Speter else 261918334Speter spec_machine = p + 1; 262018334Speter break; 262118334Speter 262218334Speter case 'B': 262318334Speter { 262418334Speter int *temp = (int *) xmalloc (sizeof (int)); 262518334Speter char *value; 262618334Speter if (p[1] == 0 && i + 1 == argc) 262718334Speter fatal ("argument to `-B' is missing"); 262818334Speter if (p[1] == 0) 262918334Speter value = argv[++i]; 263018334Speter else 263118334Speter value = p + 1; 263218334Speter add_prefix (&exec_prefixes, value, 1, 0, temp); 263318334Speter add_prefix (&startfile_prefixes, value, 1, 0, temp); 263418334Speter add_prefix (&include_prefixes, concat (value, "include"), 263518334Speter 1, 0, 0); 263618334Speter 263718334Speter /* As a kludge, if the arg is "[foo/]stageN/", just add 263818334Speter "[foo/]include" to the include prefix. */ 263918334Speter { 264018334Speter int len = strlen (value); 264118334Speter if ((len == 7 264218334Speter || (len > 7 264318334Speter && (value[len - 8] == '/' 264418334Speter || value[len - 8] == DIR_SEPARATOR))) 264518334Speter && strncmp (value + len - 7, "stage", 5) == 0 264618334Speter && isdigit (value[len - 2]) 264718334Speter && (value[len - 1] == '/' 264818334Speter || value[len - 1] == DIR_SEPARATOR)) 264918334Speter { 265018334Speter if (len == 7) 265118334Speter add_prefix (&include_prefixes, "include", 1, 0, 0); 265218334Speter else 265318334Speter { 265418334Speter char *string = xmalloc (len + 1); 265518334Speter strncpy (string, value, len-7); 265618334Speter strcat (string, "include"); 265718334Speter add_prefix (&include_prefixes, string, 1, 0, 0); 265818334Speter } 265918334Speter } 266018334Speter } 266118334Speter } 266218334Speter break; 266318334Speter 266418334Speter case 'v': /* Print our subcommands and print versions. */ 266518334Speter n_switches++; 266618334Speter /* If they do anything other than exactly `-v', don't set 266718334Speter verbose_flag; rather, continue on to give the error. */ 266818334Speter if (p[1] != 0) 266918334Speter break; 267018334Speter verbose_flag++; 267118334Speter break; 267218334Speter 267318334Speter case 'V': 267418334Speter if (p[1] == 0 && i + 1 == argc) 267518334Speter fatal ("argument to `-V' is missing"); 267618334Speter if (p[1] == 0) 267718334Speter spec_version = argv[++i]; 267818334Speter else 267918334Speter spec_version = p + 1; 268018334Speter compiler_version = spec_version; 268118334Speter break; 268218334Speter 268318334Speter case 's': 268418334Speter if (!strcmp (p, "save-temps")) 268518334Speter { 268618334Speter save_temps_flag = 1; 268718334Speter n_switches++; 268818334Speter break; 268918334Speter } 269018334Speter default: 269118334Speter n_switches++; 269218334Speter 269318334Speter if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) 269418334Speter i += SWITCH_TAKES_ARG (c) - (p[1] != 0); 269518334Speter else if (WORD_SWITCH_TAKES_ARG (p)) 269618334Speter i += WORD_SWITCH_TAKES_ARG (p); 269718334Speter } 269818334Speter } 269918334Speter else 270018334Speter n_infiles++; 270118334Speter } 270218334Speter 270318334Speter /* Set up the search paths before we go looking for config files. */ 270418334Speter 270518334Speter /* These come before the md prefixes so that we will find gcc's subcommands 270618334Speter (such as cpp) rather than those of the host system. */ 270718334Speter /* Use 2 as fourth arg meaning try just the machine as a suffix, 270818334Speter as well as trying the machine and the version. */ 270918346Speter#ifdef FREEBSD_NATIVE 271018346Speter add_prefix (&exec_prefixes, "/usr/libexec/", 0, 0, NULL_PTR); 271118346Speter add_prefix (&exec_prefixes, "/usr/bin/", 0, 0, NULL_PTR); 271218346Speter#else /* not FREEBSD_NATIVE */ 271318334Speter#ifndef OS2 271418334Speter add_prefix (&exec_prefixes, standard_exec_prefix, 0, 2, NULL_PTR); 271518334Speter add_prefix (&exec_prefixes, standard_exec_prefix_1, 0, 2, NULL_PTR); 271618334Speter#endif 271718334Speter 271818334Speter add_prefix (&startfile_prefixes, standard_exec_prefix, 0, 1, NULL_PTR); 271918334Speter add_prefix (&startfile_prefixes, standard_exec_prefix_1, 0, 1, NULL_PTR); 272018346Speter#endif /* FREEBSD_NATIVE */ 272118334Speter 272218334Speter tooldir_prefix = concat3 (tooldir_base_prefix, spec_machine, 272318334Speter dir_separator_str); 272418334Speter 272518334Speter /* If tooldir is relative, base it on exec_prefixes. A relative 272618334Speter tooldir lets us move the installed tree as a unit. 272718334Speter 272818334Speter If GCC_EXEC_PREFIX is defined, then we want to add two relative 272918334Speter directories, so that we can search both the user specified directory 273018334Speter and the standard place. */ 273118334Speter 273218334Speter if (*tooldir_prefix != '/' && *tooldir_prefix != DIR_SEPARATOR) 273318334Speter { 273418334Speter if (gcc_exec_prefix) 273518334Speter { 273618334Speter char *gcc_exec_tooldir_prefix 273718334Speter = concat6 (gcc_exec_prefix, spec_machine, dir_separator_str, 273818334Speter spec_version, dir_separator_str, tooldir_prefix); 273918334Speter 274018334Speter add_prefix (&exec_prefixes, 274118334Speter concat3 (gcc_exec_tooldir_prefix, "bin", 274218334Speter dir_separator_str), 274318334Speter 0, 0, NULL_PTR); 274418334Speter add_prefix (&startfile_prefixes, 274518334Speter concat3 (gcc_exec_tooldir_prefix, "lib", 274618334Speter dir_separator_str), 274718334Speter 0, 0, NULL_PTR); 274818334Speter } 274918334Speter 275018334Speter tooldir_prefix = concat6 (standard_exec_prefix, spec_machine, 275118334Speter dir_separator_str, spec_version, 275218334Speter dir_separator_str, tooldir_prefix); 275318334Speter } 275418334Speter 275518346Speter#ifndef FREEBSD_NATIVE 275618334Speter add_prefix (&exec_prefixes, 275718334Speter concat3 (tooldir_prefix, "bin", dir_separator_str), 275818334Speter 0, 0, NULL_PTR); 275918334Speter add_prefix (&startfile_prefixes, 276018334Speter concat3 (tooldir_prefix, "lib", dir_separator_str), 276118334Speter 0, 0, NULL_PTR); 276218346Speter#endif /* FREEBSD_NATIVE */ 276318334Speter 276418334Speter /* More prefixes are enabled in main, after we read the specs file 276518334Speter and determine whether this is cross-compilation or not. */ 276618334Speter 276718334Speter 276818334Speter /* Then create the space for the vectors and scan again. */ 276918334Speter 277018334Speter switches = ((struct switchstr *) 277118334Speter xmalloc ((n_switches + 1) * sizeof (struct switchstr))); 277218334Speter infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile)); 277318334Speter n_switches = 0; 277418334Speter n_infiles = 0; 277518334Speter last_language_n_infiles = -1; 277618334Speter 277718334Speter /* This, time, copy the text of each switch and store a pointer 277818334Speter to the copy in the vector of switches. 277918334Speter Store all the infiles in their vector. */ 278018334Speter 278118334Speter for (i = 1; i < argc; i++) 278218334Speter { 278318334Speter /* Just skip the switches that were handled by the preceding loop. */ 278418334Speter if (! strncmp (argv[i], "-Wa,", 4)) 278518334Speter ; 278618334Speter else if (! strncmp (argv[i], "-Wp,", 4)) 278718334Speter ; 278818334Speter else if (! strcmp (argv[i], "-print-search-dirs")) 278918334Speter ; 279018334Speter else if (! strcmp (argv[i], "-print-libgcc-file-name")) 279118334Speter ; 279218334Speter else if (! strncmp (argv[i], "-print-file-name=", 17)) 279318334Speter ; 279418334Speter else if (! strncmp (argv[i], "-print-prog-name=", 17)) 279518334Speter ; 279618334Speter else if (! strcmp (argv[i], "-print-multi-lib")) 279718334Speter ; 279818334Speter else if (! strcmp (argv[i], "-print-multi-directory")) 279918334Speter ; 280018334Speter else if (argv[i][0] == '+' && argv[i][1] == 'e') 280118334Speter { 280218334Speter /* Compensate for the +e options to the C++ front-end; 280318334Speter they're there simply for cfront call-compatibility. We do 280418334Speter some magic in default_compilers to pass them down properly. 280518334Speter Note we deliberately start at the `+' here, to avoid passing 280618334Speter -e0 or -e1 down into the linker. */ 280718334Speter switches[n_switches].part1 = &argv[i][0]; 280818334Speter switches[n_switches].args = 0; 280918334Speter switches[n_switches].live_cond = 0; 281018334Speter switches[n_switches].valid = 0; 281118334Speter n_switches++; 281218334Speter } 281318334Speter else if (strncmp (argv[i], "-Wl,", 4) == 0) 281418334Speter { 281518334Speter int prev, j; 281618334Speter /* Split the argument at commas. */ 281718334Speter prev = 4; 281818334Speter for (j = 4; argv[i][j]; j++) 281918334Speter if (argv[i][j] == ',') 282018334Speter { 282118334Speter infiles[n_infiles].language = 0; 282218334Speter infiles[n_infiles++].name 282318334Speter = save_string (argv[i] + prev, j - prev); 282418334Speter prev = j + 1; 282518334Speter } 282618334Speter /* Record the part after the last comma. */ 282718334Speter infiles[n_infiles].language = 0; 282818334Speter infiles[n_infiles++].name = argv[i] + prev; 282918334Speter } 283018334Speter else if (strcmp (argv[i], "-Xlinker") == 0) 283118334Speter { 283218334Speter infiles[n_infiles].language = 0; 283318334Speter infiles[n_infiles++].name = argv[++i]; 283418334Speter } 283518334Speter else if (strncmp (argv[i], "-l", 2) == 0) 283618334Speter { 283718334Speter infiles[n_infiles].language = 0; 283818334Speter infiles[n_infiles++].name = argv[i]; 283918334Speter } 284018334Speter else if (argv[i][0] == '-' && argv[i][1] != 0) 284118334Speter { 284218334Speter register char *p = &argv[i][1]; 284318334Speter register int c = *p; 284418334Speter 284518334Speter if (c == 'B' || c == 'b' || c == 'V') 284618334Speter { 284718334Speter /* Skip a separate arg, if any. */ 284818334Speter if (p[1] == 0) 284918334Speter i++; 285018334Speter continue; 285118334Speter } 285218334Speter if (c == 'x') 285318334Speter { 285418334Speter if (p[1] == 0 && i + 1 == argc) 285518334Speter fatal ("argument to `-x' is missing"); 285618334Speter if (p[1] == 0) 285718334Speter spec_lang = argv[++i]; 285818334Speter else 285918334Speter spec_lang = p + 1; 286018334Speter if (! strcmp (spec_lang, "none")) 286118334Speter /* Suppress the warning if -xnone comes after the last input 286218334Speter file, because alternate command interfaces like g++ might 286318334Speter find it useful to place -xnone after each input file. */ 286418334Speter spec_lang = 0; 286518334Speter else 286618334Speter last_language_n_infiles = n_infiles; 286718334Speter continue; 286818334Speter } 286918334Speter switches[n_switches].part1 = p; 287018334Speter /* Deal with option arguments in separate argv elements. */ 287118334Speter if ((SWITCH_TAKES_ARG (c) > (p[1] != 0)) 287218334Speter || WORD_SWITCH_TAKES_ARG (p)) 287318334Speter { 287418334Speter int j = 0; 287518334Speter int n_args = WORD_SWITCH_TAKES_ARG (p); 287618334Speter 287718334Speter if (n_args == 0) 287818334Speter { 287918334Speter /* Count only the option arguments in separate argv elements. */ 288018334Speter n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); 288118334Speter } 288218334Speter if (i + n_args >= argc) 288318334Speter fatal ("argument to `-%s' is missing", p); 288418334Speter switches[n_switches].args 288518334Speter = (char **) xmalloc ((n_args + 1) * sizeof (char *)); 288618334Speter while (j < n_args) 288718334Speter switches[n_switches].args[j++] = argv[++i]; 288818334Speter /* Null-terminate the vector. */ 288918334Speter switches[n_switches].args[j] = 0; 289018334Speter } 289118334Speter else if (*switches_need_spaces != 0 && (c == 'o' || c == 'L')) 289218334Speter { 289318334Speter /* On some systems, ld cannot handle -o or -L without space. 289418334Speter So split the -o or -L from its argument. */ 289518334Speter switches[n_switches].part1 = (c == 'o' ? "o" : "L"); 289618334Speter switches[n_switches].args = (char **) xmalloc (2 * sizeof (char *)); 289718334Speter switches[n_switches].args[0] = xmalloc (strlen (p)); 289818334Speter strcpy (switches[n_switches].args[0], &p[1]); 289918334Speter switches[n_switches].args[1] = 0; 290018334Speter } 290118334Speter else 290218334Speter switches[n_switches].args = 0; 290318334Speter 290418334Speter switches[n_switches].live_cond = 0; 290518334Speter switches[n_switches].valid = 0; 290618334Speter /* This is always valid, since gcc.c itself understands it. */ 290718334Speter if (!strcmp (p, "save-temps")) 290818334Speter switches[n_switches].valid = 1; 290918334Speter n_switches++; 291018334Speter } 291118334Speter else 291218334Speter { 291318334Speter#ifdef HAVE_OBJECT_SUFFIX 291418334Speter /* Convert x.o to x.obj if OBJECT_SUFFIX is ".obj". */ 291518334Speter if (strlen (argv[i]) > 2 291618334Speter && argv[i][strlen (argv[i]) - 2] == '.' 291718334Speter && argv[i][strlen (argv[i]) - 1] == 'o') 291818334Speter { 291918334Speter int j; 292018334Speter 292118334Speter for (j = 0; j < strlen (argv[i]) - 2; j++) 292218334Speter obstack_1grow (&obstack, argv[i][j]); 292318334Speter 292418334Speter obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX)); 292518334Speter obstack_1grow (&obstack, 0); 292618334Speter argv[i] = obstack_finish (&obstack); 292718334Speter } 292818334Speter#endif 292918334Speter 293018334Speter if (strcmp (argv[i], "-") != 0 && access (argv[i], R_OK) < 0) 293118334Speter { 293218334Speter perror_with_name (argv[i]); 293318334Speter error_count++; 293418334Speter } 293518334Speter else 293618334Speter { 293718334Speter infiles[n_infiles].language = spec_lang; 293818334Speter infiles[n_infiles++].name = argv[i]; 293918334Speter } 294018334Speter } 294118334Speter } 294218334Speter 294318334Speter if (n_infiles == last_language_n_infiles && spec_lang != 0) 294418334Speter error ("Warning: `-x %s' after last input file has no effect", spec_lang); 294518334Speter 294618334Speter switches[n_switches].part1 = 0; 294718334Speter infiles[n_infiles].name = 0; 294818334Speter} 294918334Speter 295018334Speter/* Process a spec string, accumulating and running commands. */ 295118334Speter 295218334Speter/* These variables describe the input file name. 295318334Speter input_file_number is the index on outfiles of this file, 295418334Speter so that the output file name can be stored for later use by %o. 295518334Speter input_basename is the start of the part of the input file 295618334Speter sans all directory names, and basename_length is the number 295718334Speter of characters starting there excluding the suffix .c or whatever. */ 295818334Speter 295918334Speterstatic char *input_filename; 296018334Speterstatic int input_file_number; 296118334Speterstatic int input_filename_length; 296218334Speterstatic int basename_length; 296318334Speterstatic char *input_basename; 296418334Speterstatic char *input_suffix; 296518334Speter 296618334Speter/* These are variables used within do_spec and do_spec_1. */ 296718334Speter 296818334Speter/* Nonzero if an arg has been started and not yet terminated 296918334Speter (with space, tab or newline). */ 297018334Speterstatic int arg_going; 297118334Speter 297218334Speter/* Nonzero means %d or %g has been seen; the next arg to be terminated 297318334Speter is a temporary file name. */ 297418334Speterstatic int delete_this_arg; 297518334Speter 297618334Speter/* Nonzero means %w has been seen; the next arg to be terminated 297718334Speter is the output file name of this compilation. */ 297818334Speterstatic int this_is_output_file; 297918334Speter 298018334Speter/* Nonzero means %s has been seen; the next arg to be terminated 298118334Speter is the name of a library file and we should try the standard 298218334Speter search dirs for it. */ 298318334Speterstatic int this_is_library_file; 298418334Speter 298518334Speter/* Nonzero means that the input of this command is coming from a pipe. */ 298618334Speterstatic int input_from_pipe; 298718334Speter 298818334Speter/* Process the spec SPEC and run the commands specified therein. 298918334Speter Returns 0 if the spec is successfully processed; -1 if failed. */ 299018334Speter 299118334Speterstatic int 299218334Speterdo_spec (spec) 299318334Speter char *spec; 299418334Speter{ 299518334Speter int value; 299618334Speter 299718334Speter clear_args (); 299818334Speter arg_going = 0; 299918334Speter delete_this_arg = 0; 300018334Speter this_is_output_file = 0; 300118334Speter this_is_library_file = 0; 300218334Speter input_from_pipe = 0; 300318334Speter 300418334Speter value = do_spec_1 (spec, 0, NULL_PTR); 300518334Speter 300618334Speter /* Force out any unfinished command. 300718334Speter If -pipe, this forces out the last command if it ended in `|'. */ 300818334Speter if (value == 0) 300918334Speter { 301018334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 301118334Speter argbuf_index--; 301218334Speter 301318334Speter if (argbuf_index > 0) 301418334Speter value = execute (); 301518334Speter } 301618334Speter 301718334Speter return value; 301818334Speter} 301918334Speter 302018334Speter/* Process the sub-spec SPEC as a portion of a larger spec. 302118334Speter This is like processing a whole spec except that we do 302218334Speter not initialize at the beginning and we do not supply a 302318334Speter newline by default at the end. 302418334Speter INSWITCH nonzero means don't process %-sequences in SPEC; 302518334Speter in this case, % is treated as an ordinary character. 302618334Speter This is used while substituting switches. 302718334Speter INSWITCH nonzero also causes SPC not to terminate an argument. 302818334Speter 302918334Speter Value is zero unless a line was finished 303018334Speter and the command on that line reported an error. */ 303118334Speter 303218334Speterstatic int 303318334Speterdo_spec_1 (spec, inswitch, soft_matched_part) 303418334Speter char *spec; 303518334Speter int inswitch; 303618334Speter char *soft_matched_part; 303718334Speter{ 303818334Speter register char *p = spec; 303918334Speter register int c; 304018334Speter int i; 304118334Speter char *string; 304218334Speter int value; 304318334Speter 304418334Speter while (c = *p++) 304518334Speter /* If substituting a switch, treat all chars like letters. 304618334Speter Otherwise, NL, SPC, TAB and % are special. */ 304718334Speter switch (inswitch ? 'a' : c) 304818334Speter { 304918334Speter case '\n': 305018334Speter /* End of line: finish any pending argument, 305118334Speter then run the pending command if one has been started. */ 305218334Speter if (arg_going) 305318334Speter { 305418334Speter obstack_1grow (&obstack, 0); 305518334Speter string = obstack_finish (&obstack); 305618334Speter if (this_is_library_file) 305718334Speter string = find_file (string); 305818334Speter store_arg (string, delete_this_arg, this_is_output_file); 305918334Speter if (this_is_output_file) 306018334Speter outfiles[input_file_number] = string; 306118334Speter } 306218334Speter arg_going = 0; 306318334Speter 306418334Speter if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) 306518334Speter { 306618334Speter for (i = 0; i < n_switches; i++) 306718334Speter if (!strcmp (switches[i].part1, "pipe")) 306818334Speter break; 306918334Speter 307018334Speter /* A `|' before the newline means use a pipe here, 307118334Speter but only if -pipe was specified. 307218334Speter Otherwise, execute now and don't pass the `|' as an arg. */ 307318334Speter if (i < n_switches) 307418334Speter { 307518334Speter input_from_pipe = 1; 307618334Speter switches[i].valid = 1; 307718334Speter break; 307818334Speter } 307918334Speter else 308018334Speter argbuf_index--; 308118334Speter } 308218334Speter 308318334Speter if (argbuf_index > 0) 308418334Speter { 308518334Speter value = execute (); 308618334Speter if (value) 308718334Speter return value; 308818334Speter } 308918334Speter /* Reinitialize for a new command, and for a new argument. */ 309018334Speter clear_args (); 309118334Speter arg_going = 0; 309218334Speter delete_this_arg = 0; 309318334Speter this_is_output_file = 0; 309418334Speter this_is_library_file = 0; 309518334Speter input_from_pipe = 0; 309618334Speter break; 309718334Speter 309818334Speter case '|': 309918334Speter /* End any pending argument. */ 310018334Speter if (arg_going) 310118334Speter { 310218334Speter obstack_1grow (&obstack, 0); 310318334Speter string = obstack_finish (&obstack); 310418334Speter if (this_is_library_file) 310518334Speter string = find_file (string); 310618334Speter store_arg (string, delete_this_arg, this_is_output_file); 310718334Speter if (this_is_output_file) 310818334Speter outfiles[input_file_number] = string; 310918334Speter } 311018334Speter 311118334Speter /* Use pipe */ 311218334Speter obstack_1grow (&obstack, c); 311318334Speter arg_going = 1; 311418334Speter break; 311518334Speter 311618334Speter case '\t': 311718334Speter case ' ': 311818334Speter /* Space or tab ends an argument if one is pending. */ 311918334Speter if (arg_going) 312018334Speter { 312118334Speter obstack_1grow (&obstack, 0); 312218334Speter string = obstack_finish (&obstack); 312318334Speter if (this_is_library_file) 312418334Speter string = find_file (string); 312518334Speter store_arg (string, delete_this_arg, this_is_output_file); 312618334Speter if (this_is_output_file) 312718334Speter outfiles[input_file_number] = string; 312818334Speter } 312918334Speter /* Reinitialize for a new argument. */ 313018334Speter arg_going = 0; 313118334Speter delete_this_arg = 0; 313218334Speter this_is_output_file = 0; 313318334Speter this_is_library_file = 0; 313418334Speter break; 313518334Speter 313618334Speter case '%': 313718334Speter switch (c = *p++) 313818334Speter { 313918334Speter case 0: 314018334Speter fatal ("Invalid specification! Bug in cc."); 314118334Speter 314218334Speter case 'b': 314318334Speter obstack_grow (&obstack, input_basename, basename_length); 314418334Speter arg_going = 1; 314518334Speter break; 314618334Speter 314718334Speter case 'd': 314818334Speter delete_this_arg = 2; 314918334Speter break; 315018334Speter 315118334Speter /* Dump out the directories specified with LIBRARY_PATH, 315218334Speter followed by the absolute directories 315318334Speter that we search for startfiles. */ 315418334Speter case 'D': 315518334Speter { 315618334Speter struct prefix_list *pl = startfile_prefixes.plist; 315718334Speter int bufsize = 100; 315818334Speter char *buffer = (char *) xmalloc (bufsize); 315918334Speter int idx; 316018334Speter 316118334Speter for (; pl; pl = pl->next) 316218334Speter { 316318334Speter#ifdef RELATIVE_PREFIX_NOT_LINKDIR 316418334Speter /* Used on systems which record the specified -L dirs 316518334Speter and use them to search for dynamic linking. */ 316618334Speter /* Relative directories always come from -B, 316718334Speter and it is better not to use them for searching 316818334Speter at run time. In particular, stage1 loses */ 316918334Speter if (pl->prefix[0] != '/' && pl->prefix[0] != DIR_SEPARATOR) 317018334Speter continue; 317118334Speter#endif 317218334Speter /* Try subdirectory if there is one. */ 317318334Speter if (multilib_dir != NULL) 317418334Speter { 317518334Speter if (machine_suffix) 317618334Speter { 317718334Speter if (strlen (pl->prefix) + strlen (machine_suffix) 317818334Speter >= bufsize) 317918334Speter bufsize = (strlen (pl->prefix) 318018334Speter + strlen (machine_suffix)) * 2 + 1; 318118334Speter buffer = (char *) xrealloc (buffer, bufsize); 318218334Speter strcpy (buffer, pl->prefix); 318318334Speter strcat (buffer, machine_suffix); 318418334Speter if (is_directory (buffer, multilib_dir, 1)) 318518334Speter { 318618334Speter do_spec_1 ("-L", 0, NULL_PTR); 318718334Speter#ifdef SPACE_AFTER_L_OPTION 318818334Speter do_spec_1 (" ", 0, NULL_PTR); 318918334Speter#endif 319018334Speter do_spec_1 (buffer, 1, NULL_PTR); 319118334Speter do_spec_1 (multilib_dir, 1, NULL_PTR); 319218334Speter /* Make this a separate argument. */ 319318334Speter do_spec_1 (" ", 0, NULL_PTR); 319418334Speter } 319518334Speter } 319618334Speter if (!pl->require_machine_suffix) 319718334Speter { 319818334Speter if (is_directory (pl->prefix, multilib_dir, 1)) 319918334Speter { 320018334Speter do_spec_1 ("-L", 0, NULL_PTR); 320118334Speter#ifdef SPACE_AFTER_L_OPTION 320218334Speter do_spec_1 (" ", 0, NULL_PTR); 320318334Speter#endif 320418334Speter do_spec_1 (pl->prefix, 1, NULL_PTR); 320518334Speter do_spec_1 (multilib_dir, 1, NULL_PTR); 320618334Speter /* Make this a separate argument. */ 320718334Speter do_spec_1 (" ", 0, NULL_PTR); 320818334Speter } 320918334Speter } 321018334Speter } 321118334Speter if (machine_suffix) 321218334Speter { 321318334Speter if (is_directory (pl->prefix, machine_suffix, 1)) 321418334Speter { 321518334Speter do_spec_1 ("-L", 0, NULL_PTR); 321618334Speter#ifdef SPACE_AFTER_L_OPTION 321718334Speter do_spec_1 (" ", 0, NULL_PTR); 321818334Speter#endif 321918334Speter do_spec_1 (pl->prefix, 1, NULL_PTR); 322018334Speter /* Remove slash from machine_suffix. */ 322118334Speter if (strlen (machine_suffix) >= bufsize) 322218334Speter bufsize = strlen (machine_suffix) * 2 + 1; 322318334Speter buffer = (char *) xrealloc (buffer, bufsize); 322418334Speter strcpy (buffer, machine_suffix); 322518334Speter idx = strlen (buffer); 322618334Speter if (buffer[idx - 1] == '/' 322718334Speter || buffer[idx - 1] == DIR_SEPARATOR) 322818334Speter buffer[idx - 1] = 0; 322918334Speter do_spec_1 (buffer, 1, NULL_PTR); 323018334Speter /* Make this a separate argument. */ 323118334Speter do_spec_1 (" ", 0, NULL_PTR); 323218334Speter } 323318334Speter } 323418334Speter if (!pl->require_machine_suffix) 323518334Speter { 323618334Speter if (is_directory (pl->prefix, "", 1)) 323718334Speter { 323818334Speter do_spec_1 ("-L", 0, NULL_PTR); 323918334Speter#ifdef SPACE_AFTER_L_OPTION 324018334Speter do_spec_1 (" ", 0, NULL_PTR); 324118334Speter#endif 324218334Speter /* Remove slash from pl->prefix. */ 324318334Speter if (strlen (pl->prefix) >= bufsize) 324418334Speter bufsize = strlen (pl->prefix) * 2 + 1; 324518334Speter buffer = (char *) xrealloc (buffer, bufsize); 324618334Speter strcpy (buffer, pl->prefix); 324718334Speter idx = strlen (buffer); 324818334Speter if (buffer[idx - 1] == '/' 324918334Speter || buffer[idx - 1] == DIR_SEPARATOR) 325018334Speter buffer[idx - 1] = 0; 325118334Speter do_spec_1 (buffer, 1, NULL_PTR); 325218334Speter /* Make this a separate argument. */ 325318334Speter do_spec_1 (" ", 0, NULL_PTR); 325418334Speter } 325518334Speter } 325618334Speter } 325718334Speter free (buffer); 325818334Speter } 325918334Speter break; 326018334Speter 326118334Speter case 'e': 326218334Speter /* {...:%efoo} means report an error with `foo' as error message 326318334Speter and don't execute any more commands for this file. */ 326418334Speter { 326518334Speter char *q = p; 326618334Speter char *buf; 326718334Speter while (*p != 0 && *p != '\n') p++; 326818334Speter buf = (char *) alloca (p - q + 1); 326918334Speter strncpy (buf, q, p - q); 327018334Speter buf[p - q] = 0; 327118334Speter error ("%s", buf); 327218334Speter return -1; 327318334Speter } 327418334Speter break; 327518334Speter 327618334Speter case 'g': 327718334Speter case 'u': 327818334Speter case 'U': 327918334Speter if (save_temps_flag) 328018334Speter { 328118334Speter obstack_grow (&obstack, input_basename, basename_length); 328218334Speter delete_this_arg = 0; 328318334Speter } 328418334Speter else 328518334Speter { 328618334Speter#ifdef MKTEMP_EACH_FILE 328718334Speter /* ??? This has a problem: the total number of 328818334Speter values mktemp can return is limited. 328918334Speter That matters for the names of object files. 329018334Speter In 2.4, do something about that. */ 329118334Speter struct temp_name *t; 329218334Speter char *suffix = p; 329318334Speter while (*p == '.' || isalpha (*p) 329418334Speter || (p[0] == '%' && p[1] == 'O')) 329518334Speter p++; 329618334Speter 329718334Speter /* See if we already have an association of %g/%u/%U and 329818334Speter suffix. */ 329918334Speter for (t = temp_names; t; t = t->next) 330018334Speter if (t->length == p - suffix 330118334Speter && strncmp (t->suffix, suffix, p - suffix) == 0 330218334Speter && t->unique == (c != 'g')) 330318334Speter break; 330418334Speter 330518334Speter /* Make a new association if needed. %u requires one. */ 330618334Speter if (t == 0 || c == 'u') 330718334Speter { 330818334Speter if (t == 0) 330918334Speter { 331018334Speter t = (struct temp_name *) xmalloc (sizeof (struct temp_name)); 331118334Speter t->next = temp_names; 331218334Speter temp_names = t; 331318334Speter } 331418334Speter t->length = p - suffix; 331518334Speter t->suffix = save_string (suffix, p - suffix); 331618334Speter t->unique = (c != 'g'); 331718334Speter choose_temp_base (); 331818334Speter t->filename = temp_filename; 331918334Speter t->filename_length = temp_filename_length; 332018334Speter } 332118334Speter 332218334Speter obstack_grow (&obstack, t->filename, t->filename_length); 332318334Speter delete_this_arg = 1; 332418334Speter#else 332518334Speter obstack_grow (&obstack, temp_filename, temp_filename_length); 332618334Speter if (c == 'u' || c == 'U') 332718334Speter { 332818334Speter static int unique; 332918334Speter char buff[9]; 333018334Speter if (c == 'u') 333118334Speter unique++; 333218334Speter sprintf (buff, "%d", unique); 333318334Speter obstack_grow (&obstack, buff, strlen (buff)); 333418334Speter } 333518334Speter#endif 333618334Speter delete_this_arg = 1; 333718334Speter } 333818334Speter arg_going = 1; 333918334Speter break; 334018334Speter 334118334Speter case 'i': 334218334Speter obstack_grow (&obstack, input_filename, input_filename_length); 334318334Speter arg_going = 1; 334418334Speter break; 334518334Speter 334618334Speter case 'I': 334718334Speter { 334818334Speter struct prefix_list *pl = include_prefixes.plist; 334918334Speter 335018334Speter if (gcc_exec_prefix) 335118334Speter { 335218334Speter do_spec_1 ("-iprefix", 1, NULL_PTR); 335318334Speter /* Make this a separate argument. */ 335418334Speter do_spec_1 (" ", 0, NULL_PTR); 335518334Speter do_spec_1 (gcc_exec_prefix, 1, NULL_PTR); 335618334Speter do_spec_1 (" ", 0, NULL_PTR); 335718334Speter } 335818334Speter 335918334Speter for (; pl; pl = pl->next) 336018334Speter { 336118334Speter do_spec_1 ("-isystem", 1, NULL_PTR); 336218334Speter /* Make this a separate argument. */ 336318334Speter do_spec_1 (" ", 0, NULL_PTR); 336418334Speter do_spec_1 (pl->prefix, 1, NULL_PTR); 336518334Speter do_spec_1 (" ", 0, NULL_PTR); 336618334Speter } 336718334Speter } 336818334Speter break; 336918334Speter 337018334Speter case 'o': 337118334Speter for (i = 0; i < n_infiles; i++) 337218334Speter store_arg (outfiles[i], 0, 0); 337318334Speter break; 337418334Speter 337518334Speter case 'O': 337618334Speter obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX)); 337718334Speter arg_going = 1; 337818334Speter break; 337918334Speter 338018334Speter case 's': 338118334Speter this_is_library_file = 1; 338218334Speter break; 338318334Speter 338418334Speter case 'w': 338518334Speter this_is_output_file = 1; 338618334Speter break; 338718334Speter 338818334Speter case 'W': 338918334Speter { 339018334Speter int index = argbuf_index; 339118334Speter /* Handle the {...} following the %W. */ 339218334Speter if (*p != '{') 339318334Speter abort (); 339418334Speter p = handle_braces (p + 1); 339518334Speter if (p == 0) 339618334Speter return -1; 339718334Speter /* If any args were output, mark the last one for deletion 339818334Speter on failure. */ 339918334Speter if (argbuf_index != index) 340018334Speter record_temp_file (argbuf[argbuf_index - 1], 0, 1); 340118334Speter break; 340218334Speter } 340318334Speter 340418334Speter /* %x{OPTION} records OPTION for %X to output. */ 340518334Speter case 'x': 340618334Speter { 340718334Speter char *p1 = p; 340818334Speter char *string; 340918334Speter 341018334Speter /* Skip past the option value and make a copy. */ 341118334Speter if (*p != '{') 341218334Speter abort (); 341318334Speter while (*p++ != '}') 341418334Speter ; 341518334Speter string = save_string (p1 + 1, p - p1 - 2); 341618334Speter 341718334Speter /* See if we already recorded this option. */ 341818334Speter for (i = 0; i < n_linker_options; i++) 341918334Speter if (! strcmp (string, linker_options[i])) 342018334Speter { 342118334Speter free (string); 342218334Speter return 0; 342318334Speter } 342418334Speter 342518334Speter /* This option is new; add it. */ 342618334Speter n_linker_options++; 342718334Speter if (!linker_options) 342818334Speter linker_options 342918334Speter = (char **) xmalloc (n_linker_options * sizeof (char **)); 343018334Speter else 343118334Speter linker_options 343218334Speter = (char **) xrealloc (linker_options, 343318334Speter n_linker_options * sizeof (char **)); 343418334Speter 343518334Speter linker_options[n_linker_options - 1] = string; 343618334Speter } 343718334Speter break; 343818334Speter 343918334Speter /* Dump out the options accumulated previously using %x. */ 344018334Speter case 'X': 344118334Speter for (i = 0; i < n_linker_options; i++) 344218334Speter { 344318334Speter do_spec_1 (linker_options[i], 1, NULL_PTR); 344418334Speter /* Make each accumulated option a separate argument. */ 344518334Speter do_spec_1 (" ", 0, NULL_PTR); 344618334Speter } 344718334Speter break; 344818334Speter 344918334Speter /* Dump out the options accumulated previously using -Wa,. */ 345018334Speter case 'Y': 345118334Speter for (i = 0; i < n_assembler_options; i++) 345218334Speter { 345318334Speter do_spec_1 (assembler_options[i], 1, NULL_PTR); 345418334Speter /* Make each accumulated option a separate argument. */ 345518334Speter do_spec_1 (" ", 0, NULL_PTR); 345618334Speter } 345718334Speter break; 345818334Speter 345918334Speter /* Dump out the options accumulated previously using -Wp,. */ 346018334Speter case 'Z': 346118334Speter for (i = 0; i < n_preprocessor_options; i++) 346218334Speter { 346318334Speter do_spec_1 (preprocessor_options[i], 1, NULL_PTR); 346418334Speter /* Make each accumulated option a separate argument. */ 346518334Speter do_spec_1 (" ", 0, NULL_PTR); 346618334Speter } 346718334Speter break; 346818334Speter 346918334Speter /* Here are digits and numbers that just process 347018334Speter a certain constant string as a spec. */ 347118334Speter 347218334Speter case '1': 347318334Speter value = do_spec_1 (cc1_spec, 0, NULL_PTR); 347418334Speter if (value != 0) 347518334Speter return value; 347618334Speter break; 347718334Speter 347818334Speter case '2': 347918334Speter value = do_spec_1 (cc1plus_spec, 0, NULL_PTR); 348018334Speter if (value != 0) 348118334Speter return value; 348218334Speter break; 348318334Speter 348418334Speter case 'a': 348518334Speter value = do_spec_1 (asm_spec, 0, NULL_PTR); 348618334Speter if (value != 0) 348718334Speter return value; 348818334Speter break; 348918334Speter 349018334Speter case 'A': 349118334Speter value = do_spec_1 (asm_final_spec, 0, NULL_PTR); 349218334Speter if (value != 0) 349318334Speter return value; 349418334Speter break; 349518334Speter 349618334Speter case 'c': 349718334Speter value = do_spec_1 (signed_char_spec, 0, NULL_PTR); 349818334Speter if (value != 0) 349918334Speter return value; 350018334Speter break; 350118334Speter 350218334Speter case 'C': 350318334Speter value = do_spec_1 (cpp_spec, 0, NULL_PTR); 350418334Speter if (value != 0) 350518334Speter return value; 350618334Speter break; 350718334Speter 350818334Speter case 'E': 350918334Speter value = do_spec_1 (endfile_spec, 0, NULL_PTR); 351018334Speter if (value != 0) 351118334Speter return value; 351218334Speter break; 351318334Speter 351418334Speter case 'l': 351518334Speter value = do_spec_1 (link_spec, 0, NULL_PTR); 351618334Speter if (value != 0) 351718334Speter return value; 351818334Speter break; 351918334Speter 352018334Speter case 'L': 352118334Speter value = do_spec_1 (lib_spec, 0, NULL_PTR); 352218334Speter if (value != 0) 352318334Speter return value; 352418334Speter break; 352518334Speter 352618334Speter case 'G': 352718334Speter value = do_spec_1 (libgcc_spec, 0, NULL_PTR); 352818334Speter if (value != 0) 352918334Speter return value; 353018334Speter break; 353118334Speter 353218334Speter case 'p': 353318334Speter { 353418334Speter char *x = (char *) alloca (strlen (cpp_predefines) + 1); 353518334Speter char *buf = x; 353618334Speter char *y; 353718334Speter 353818334Speter /* Copy all of the -D options in CPP_PREDEFINES into BUF. */ 353918334Speter y = cpp_predefines; 354018334Speter while (*y != 0) 354118334Speter { 354218334Speter if (! strncmp (y, "-D", 2)) 354318334Speter /* Copy the whole option. */ 354418334Speter while (*y && *y != ' ' && *y != '\t') 354518334Speter *x++ = *y++; 354618334Speter else if (*y == ' ' || *y == '\t') 354718334Speter /* Copy whitespace to the result. */ 354818334Speter *x++ = *y++; 354918334Speter /* Don't copy other options. */ 355018334Speter else 355118334Speter y++; 355218334Speter } 355318334Speter 355418334Speter *x = 0; 355518334Speter 355618334Speter value = do_spec_1 (buf, 0, NULL_PTR); 355718334Speter if (value != 0) 355818334Speter return value; 355918334Speter } 356018334Speter break; 356118334Speter 356218334Speter case 'P': 356318334Speter { 356418334Speter char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1); 356518334Speter char *buf = x; 356618334Speter char *y; 356718334Speter 356818334Speter /* Copy all of CPP_PREDEFINES into BUF, 356918334Speter but put __ after every -D and at the end of each arg. */ 357018334Speter y = cpp_predefines; 357118334Speter while (*y != 0) 357218334Speter { 357318334Speter if (! strncmp (y, "-D", 2)) 357418334Speter { 357518334Speter int flag = 0; 357618334Speter 357718334Speter *x++ = *y++; 357818334Speter *x++ = *y++; 357918334Speter 358018334Speter if (*y != '_' 358118334Speter || (*(y+1) != '_' && ! isupper (*(y+1)))) 358218334Speter { 358318334Speter /* Stick __ at front of macro name. */ 358418334Speter *x++ = '_'; 358518334Speter *x++ = '_'; 358618334Speter /* Arrange to stick __ at the end as well. */ 358718334Speter flag = 1; 358818334Speter } 358918334Speter 359018334Speter /* Copy the macro name. */ 359118334Speter while (*y && *y != '=' && *y != ' ' && *y != '\t') 359218334Speter *x++ = *y++; 359318334Speter 359418334Speter if (flag) 359518334Speter { 359618334Speter *x++ = '_'; 359718334Speter *x++ = '_'; 359818334Speter } 359918334Speter 360018334Speter /* Copy the value given, if any. */ 360118334Speter while (*y && *y != ' ' && *y != '\t') 360218334Speter *x++ = *y++; 360318334Speter } 360418334Speter else if (*y == ' ' || *y == '\t') 360518334Speter /* Copy whitespace to the result. */ 360618334Speter *x++ = *y++; 360718334Speter /* Don't copy -A options */ 360818334Speter else 360918334Speter y++; 361018334Speter } 361118334Speter *x++ = ' '; 361218334Speter 361318334Speter /* Copy all of CPP_PREDEFINES into BUF, 361418334Speter but put __ after every -D. */ 361518334Speter y = cpp_predefines; 361618334Speter while (*y != 0) 361718334Speter { 361818334Speter if (! strncmp (y, "-D", 2)) 361918334Speter { 362018334Speter y += 2; 362118334Speter 362218334Speter if (*y != '_' 362318334Speter || (*(y+1) != '_' && ! isupper (*(y+1)))) 362418334Speter { 362518334Speter /* Stick -D__ at front of macro name. */ 362618334Speter *x++ = '-'; 362718334Speter *x++ = 'D'; 362818334Speter *x++ = '_'; 362918334Speter *x++ = '_'; 363018334Speter 363118334Speter /* Copy the macro name. */ 363218334Speter while (*y && *y != '=' && *y != ' ' && *y != '\t') 363318334Speter *x++ = *y++; 363418334Speter 363518334Speter /* Copy the value given, if any. */ 363618334Speter while (*y && *y != ' ' && *y != '\t') 363718334Speter *x++ = *y++; 363818334Speter } 363918334Speter else 364018334Speter { 364118334Speter /* Do not copy this macro - we have just done it before */ 364218334Speter while (*y && *y != ' ' && *y != '\t') 364318334Speter y++; 364418334Speter } 364518334Speter } 364618334Speter else if (*y == ' ' || *y == '\t') 364718334Speter /* Copy whitespace to the result. */ 364818334Speter *x++ = *y++; 364918334Speter /* Don't copy -A options */ 365018334Speter else 365118334Speter y++; 365218334Speter } 365318334Speter *x++ = ' '; 365418334Speter 365518334Speter /* Copy all of the -A options in CPP_PREDEFINES into BUF. */ 365618334Speter y = cpp_predefines; 365718334Speter while (*y != 0) 365818334Speter { 365918334Speter if (! strncmp (y, "-A", 2)) 366018334Speter /* Copy the whole option. */ 366118334Speter while (*y && *y != ' ' && *y != '\t') 366218334Speter *x++ = *y++; 366318334Speter else if (*y == ' ' || *y == '\t') 366418334Speter /* Copy whitespace to the result. */ 366518334Speter *x++ = *y++; 366618334Speter /* Don't copy other options. */ 366718334Speter else 366818334Speter y++; 366918334Speter } 367018334Speter 367118334Speter *x = 0; 367218334Speter 367318334Speter value = do_spec_1 (buf, 0, NULL_PTR); 367418334Speter if (value != 0) 367518334Speter return value; 367618334Speter } 367718334Speter break; 367818334Speter 367918334Speter case 'S': 368018334Speter value = do_spec_1 (startfile_spec, 0, NULL_PTR); 368118334Speter if (value != 0) 368218334Speter return value; 368318334Speter break; 368418334Speter 368518334Speter /* Here we define characters other than letters and digits. */ 368618334Speter 368718334Speter case '{': 368818334Speter p = handle_braces (p); 368918334Speter if (p == 0) 369018334Speter return -1; 369118334Speter break; 369218334Speter 369318334Speter case '%': 369418334Speter obstack_1grow (&obstack, '%'); 369518334Speter break; 369618334Speter 369718334Speter case '*': 369818334Speter do_spec_1 (soft_matched_part, 1, NULL_PTR); 369918334Speter do_spec_1 (" ", 0, NULL_PTR); 370018334Speter break; 370118334Speter 370218334Speter /* Process a string found as the value of a spec given by name. 370318334Speter This feature allows individual machine descriptions 370418334Speter to add and use their own specs. 370518334Speter %[...] modifies -D options the way %P does; 370618334Speter %(...) uses the spec unmodified. */ 370718334Speter case '(': 370818334Speter case '[': 370918334Speter { 371018334Speter char *name = p; 371118334Speter struct spec_list *sl; 371218334Speter int len; 371318334Speter 371418334Speter /* The string after the S/P is the name of a spec that is to be 371518334Speter processed. */ 371618334Speter while (*p && *p != ')' && *p != ']') 371718334Speter p++; 371818334Speter 371918334Speter /* See if it's in the list */ 372018334Speter for (len = p - name, sl = specs; sl; sl = sl->next) 372118334Speter if (strncmp (sl->name, name, len) == 0 && !sl->name[len]) 372218334Speter { 372318334Speter name = sl->spec; 372418334Speter break; 372518334Speter } 372618334Speter 372718334Speter if (sl) 372818334Speter { 372918334Speter if (c == '(') 373018334Speter { 373118334Speter value = do_spec_1 (name, 0, NULL_PTR); 373218334Speter if (value != 0) 373318334Speter return value; 373418334Speter } 373518334Speter else 373618334Speter { 373718334Speter char *x = (char *) alloca (strlen (name) * 2 + 1); 373818334Speter char *buf = x; 373918334Speter char *y = name; 374018334Speter 374118334Speter /* Copy all of NAME into BUF, but put __ after 374218334Speter every -D and at the end of each arg, */ 374318334Speter while (1) 374418334Speter { 374518334Speter if (! strncmp (y, "-D", 2)) 374618334Speter { 374718334Speter *x++ = '-'; 374818334Speter *x++ = 'D'; 374918334Speter *x++ = '_'; 375018334Speter *x++ = '_'; 375118334Speter y += 2; 375218334Speter } 375318334Speter else if (*y == ' ' || *y == 0) 375418334Speter { 375518334Speter *x++ = '_'; 375618334Speter *x++ = '_'; 375718334Speter if (*y == 0) 375818334Speter break; 375918334Speter else 376018334Speter *x++ = *y++; 376118334Speter } 376218334Speter else 376318334Speter *x++ = *y++; 376418334Speter } 376518334Speter *x = 0; 376618334Speter 376718334Speter value = do_spec_1 (buf, 0, NULL_PTR); 376818334Speter if (value != 0) 376918334Speter return value; 377018334Speter } 377118334Speter } 377218334Speter 377318334Speter /* Discard the closing paren or bracket. */ 377418334Speter if (*p) 377518334Speter p++; 377618334Speter } 377718334Speter break; 377818334Speter 377918334Speter case 'v': 378018334Speter { 378118334Speter int c1 = *p++; /* Select first or second version number. */ 378218334Speter char *v = compiler_version; 378318346Speter char *q; 378418334Speter /* If desired, advance to second version number. */ 378518334Speter if (c1 == '2') 378618334Speter { 378718334Speter /* Set P after the first period. */ 378818334Speter while (*v != 0 && *v != ' ' && *v != '.') 378918334Speter v++; 379018334Speter if (*v == '.') 379118334Speter v++; 379218334Speter } 379318334Speter /* Set Q at the next period or at the end. */ 379418334Speter q = v; 379518334Speter while (*q != 0 && *q != ' ' && *q != '.') 379618334Speter q++; 379718334Speter /* Empty string means zero. */ 379818334Speter if (p == q) 379918334Speter { 380018334Speter v = "0"; 380118334Speter q = v + 1; 380218334Speter } 380318334Speter /* Put that part into the command. */ 380418334Speter obstack_grow (&obstack, v, q - v); 380518334Speter arg_going = 1; 380618334Speter } 380718334Speter break; 380818334Speter 380918334Speter case '|': 381018334Speter if (input_from_pipe) 381118334Speter do_spec_1 ("-", 0, NULL_PTR); 381218334Speter break; 381318334Speter 381418334Speter default: 381518334Speter abort (); 381618334Speter } 381718334Speter break; 381818334Speter 381918334Speter case '\\': 382018334Speter /* Backslash: treat next character as ordinary. */ 382118334Speter c = *p++; 382218334Speter 382318334Speter /* fall through */ 382418334Speter default: 382518334Speter /* Ordinary character: put it into the current argument. */ 382618334Speter obstack_1grow (&obstack, c); 382718334Speter arg_going = 1; 382818334Speter } 382918334Speter 383018334Speter return 0; /* End of string */ 383118334Speter} 383218334Speter 383318334Speter/* Return 0 if we call do_spec_1 and that returns -1. */ 383418334Speter 383518334Speterstatic char * 383618334Speterhandle_braces (p) 383718334Speter register char *p; 383818334Speter{ 383918334Speter register char *q; 384018334Speter char *filter; 384118334Speter int pipe = 0; 384218334Speter int negate = 0; 384318334Speter int suffix = 0; 384418334Speter 384518334Speter if (*p == '|') 384618334Speter /* A `|' after the open-brace means, 384718334Speter if the test fails, output a single minus sign rather than nothing. 384818334Speter This is used in %{|!pipe:...}. */ 384918334Speter pipe = 1, ++p; 385018334Speter 385118334Speter if (*p == '!') 385218334Speter /* A `!' after the open-brace negates the condition: 385318334Speter succeed if the specified switch is not present. */ 385418334Speter negate = 1, ++p; 385518334Speter 385618334Speter if (*p == '.') 385718334Speter /* A `.' after the open-brace means test against the current suffix. */ 385818334Speter { 385918334Speter if (pipe) 386018334Speter abort (); 386118334Speter 386218334Speter suffix = 1; 386318334Speter ++p; 386418334Speter } 386518334Speter 386618334Speter filter = p; 386718334Speter while (*p != ':' && *p != '}') p++; 386818334Speter if (*p != '}') 386918334Speter { 387018334Speter register int count = 1; 387118334Speter q = p + 1; 387218334Speter while (count > 0) 387318334Speter { 387418334Speter if (*q == '{') 387518334Speter count++; 387618334Speter else if (*q == '}') 387718334Speter count--; 387818334Speter else if (*q == 0) 387918334Speter abort (); 388018334Speter q++; 388118334Speter } 388218334Speter } 388318334Speter else 388418334Speter q = p + 1; 388518334Speter 388618334Speter if (suffix) 388718334Speter { 388818334Speter int found = (input_suffix != 0 388918334Speter && strlen (input_suffix) == p - filter 389018334Speter && strncmp (input_suffix, filter, p - filter) == 0); 389118334Speter 389218334Speter if (p[0] == '}') 389318334Speter abort (); 389418334Speter 389518334Speter if (negate != found 389618334Speter && do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0) 389718334Speter return 0; 389818334Speter 389918334Speter return q; 390018334Speter } 390118334Speter else if (p[-1] == '*' && p[0] == '}') 390218334Speter { 390318334Speter /* Substitute all matching switches as separate args. */ 390418334Speter register int i; 390518334Speter --p; 390618334Speter for (i = 0; i < n_switches; i++) 390718334Speter if (!strncmp (switches[i].part1, filter, p - filter) 390818334Speter && check_live_switch (i, p - filter)) 390918334Speter give_switch (i, 0); 391018334Speter } 391118334Speter else 391218334Speter { 391318334Speter /* Test for presence of the specified switch. */ 391418334Speter register int i; 391518334Speter int present = 0; 391618334Speter 391718334Speter /* If name specified ends in *, as in {x*:...}, 391818334Speter check for %* and handle that case. */ 391918334Speter if (p[-1] == '*' && !negate) 392018334Speter { 392118334Speter int substitution; 392218334Speter char *r = p; 392318334Speter 392418334Speter /* First see whether we have %*. */ 392518334Speter substitution = 0; 392618334Speter while (r < q) 392718334Speter { 392818334Speter if (*r == '%' && r[1] == '*') 392918334Speter substitution = 1; 393018334Speter r++; 393118334Speter } 393218334Speter /* If we do, handle that case. */ 393318334Speter if (substitution) 393418334Speter { 393518334Speter /* Substitute all matching switches as separate args. 393618334Speter But do this by substituting for %* 393718334Speter in the text that follows the colon. */ 393818334Speter 393918334Speter unsigned hard_match_len = p - filter - 1; 394018334Speter char *string = save_string (p + 1, q - p - 2); 394118334Speter 394218334Speter for (i = 0; i < n_switches; i++) 394318334Speter if (!strncmp (switches[i].part1, filter, hard_match_len) 394418334Speter && check_live_switch (i, -1)) 394518334Speter { 394618334Speter do_spec_1 (string, 0, &switches[i].part1[hard_match_len]); 394718334Speter /* Pass any arguments this switch has. */ 394818334Speter give_switch (i, 1); 394918334Speter } 395018334Speter 395118334Speter return q; 395218334Speter } 395318334Speter } 395418334Speter 395518334Speter /* If name specified ends in *, as in {x*:...}, 395618334Speter check for presence of any switch name starting with x. */ 395718334Speter if (p[-1] == '*') 395818334Speter { 395918334Speter for (i = 0; i < n_switches; i++) 396018334Speter { 396118334Speter unsigned hard_match_len = p - filter - 1; 396218334Speter 396318334Speter if (!strncmp (switches[i].part1, filter, hard_match_len) 396418334Speter && check_live_switch (i, hard_match_len)) 396518334Speter { 396618334Speter present = 1; 396718334Speter } 396818334Speter } 396918334Speter } 397018334Speter /* Otherwise, check for presence of exact name specified. */ 397118334Speter else 397218334Speter { 397318334Speter for (i = 0; i < n_switches; i++) 397418334Speter { 397518334Speter if (!strncmp (switches[i].part1, filter, p - filter) 397618334Speter && switches[i].part1[p - filter] == 0 397718334Speter && check_live_switch (i, -1)) 397818334Speter { 397918334Speter present = 1; 398018334Speter break; 398118334Speter } 398218334Speter } 398318334Speter } 398418334Speter 398518334Speter /* If it is as desired (present for %{s...}, absent for %{-s...}) 398618334Speter then substitute either the switch or the specified 398718334Speter conditional text. */ 398818334Speter if (present != negate) 398918334Speter { 399018334Speter if (*p == '}') 399118334Speter { 399218334Speter give_switch (i, 0); 399318334Speter } 399418334Speter else 399518334Speter { 399618334Speter if (do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0) 399718334Speter return 0; 399818334Speter } 399918334Speter } 400018334Speter else if (pipe) 400118334Speter { 400218334Speter /* Here if a %{|...} conditional fails: output a minus sign, 400318334Speter which means "standard output" or "standard input". */ 400418334Speter do_spec_1 ("-", 0, NULL_PTR); 400518334Speter } 400618334Speter } 400718334Speter 400818334Speter return q; 400918334Speter} 401018334Speter 401118334Speter/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch 401218334Speter on the command line. PREFIX_LENGTH is the length of XXX in an {XXX*} 401318334Speter spec, or -1 if either exact match or %* is used. 401418334Speter 401518334Speter A -O switch is obsoleted by a later -O switch. A -f, -m, or -W switch 401618334Speter whose value does not begin with "no-" is obsoleted by the same value 401718334Speter with the "no-", similarly for a switch with the "no-" prefix. */ 401818334Speter 401918334Speterstatic int 402018334Spetercheck_live_switch (switchnum, prefix_length) 402118334Speter int switchnum; 402218334Speter int prefix_length; 402318334Speter{ 402418334Speter char *name = switches[switchnum].part1; 402518334Speter int i; 402618334Speter 402718334Speter /* In the common case of {<at-most-one-letter>*}, a negating 402818334Speter switch would always match, so ignore that case. We will just 402918334Speter send the conflicting switches to the compiler phase. */ 403018334Speter if (prefix_length >= 0 && prefix_length <= 1) 403118334Speter return 1; 403218334Speter 403318334Speter /* If we already processed this switch and determined if it was 403418334Speter live or not, return our past determination. */ 403518334Speter if (switches[switchnum].live_cond != 0) 403618334Speter return switches[switchnum].live_cond > 0; 403718334Speter 403818334Speter /* Now search for duplicate in a manner that depends on the name. */ 403918334Speter switch (*name) 404018334Speter { 404118334Speter case 'O': 404218334Speter for (i = switchnum + 1; i < n_switches; i++) 404318334Speter if (switches[i].part1[0] == 'O') 404418334Speter { 404518334Speter switches[switchnum].valid = 1; 404618334Speter switches[switchnum].live_cond = -1; 404718334Speter return 0; 404818334Speter } 404918334Speter break; 405018334Speter 405118334Speter case 'W': case 'f': case 'm': 405218334Speter if (! strncmp (name + 1, "no-", 3)) 405318334Speter { 405418334Speter /* We have Xno-YYY, search for XYYY. */ 405518334Speter for (i = switchnum + 1; i < n_switches; i++) 405618334Speter if (switches[i].part1[0] == name[0] 405718334Speter && ! strcmp (&switches[i].part1[1], &name[4])) 405818334Speter { 405918334Speter switches[switchnum].valid = 1; 406018334Speter switches[switchnum].live_cond = -1; 406118334Speter return 0; 406218334Speter } 406318334Speter } 406418334Speter else 406518334Speter { 406618334Speter /* We have XYYY, search for Xno-YYY. */ 406718334Speter for (i = switchnum + 1; i < n_switches; i++) 406818334Speter if (switches[i].part1[0] == name[0] 406918334Speter && switches[i].part1[1] == 'n' 407018334Speter && switches[i].part1[2] == 'o' 407118334Speter && switches[i].part1[3] == '-' 407218334Speter && !strcmp (&switches[i].part1[4], &name[1])) 407318334Speter { 407418334Speter switches[switchnum].valid = 1; 407518334Speter switches[switchnum].live_cond = -1; 407618334Speter return 0; 407718334Speter } 407818334Speter } 407918334Speter break; 408018334Speter } 408118334Speter 408218334Speter /* Otherwise the switch is live. */ 408318334Speter switches[switchnum].live_cond = 1; 408418334Speter return 1; 408518334Speter} 408618334Speter 408718334Speter/* Pass a switch to the current accumulating command 408818334Speter in the same form that we received it. 408918334Speter SWITCHNUM identifies the switch; it is an index into 409018334Speter the vector of switches gcc received, which is `switches'. 409118334Speter This cannot fail since it never finishes a command line. 409218334Speter 409318334Speter If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. */ 409418334Speter 409518334Speterstatic void 409618334Spetergive_switch (switchnum, omit_first_word) 409718334Speter int switchnum; 409818334Speter int omit_first_word; 409918334Speter{ 410018334Speter if (!omit_first_word) 410118334Speter { 410218334Speter do_spec_1 ("-", 0, NULL_PTR); 410318334Speter do_spec_1 (switches[switchnum].part1, 1, NULL_PTR); 410418334Speter } 410518334Speter do_spec_1 (" ", 0, NULL_PTR); 410618334Speter if (switches[switchnum].args != 0) 410718334Speter { 410818334Speter char **p; 410918334Speter for (p = switches[switchnum].args; *p; p++) 411018334Speter { 411118334Speter do_spec_1 (*p, 1, NULL_PTR); 411218334Speter do_spec_1 (" ", 0, NULL_PTR); 411318334Speter } 411418334Speter } 411518334Speter switches[switchnum].valid = 1; 411618334Speter} 411718334Speter 411818334Speter/* Search for a file named NAME trying various prefixes including the 411918334Speter user's -B prefix and some standard ones. 412018334Speter Return the absolute file name found. If nothing is found, return NAME. */ 412118334Speter 412218334Speterstatic char * 412318334Speterfind_file (name) 412418334Speter char *name; 412518334Speter{ 412618334Speter char *newname; 412718334Speter 412818334Speter /* Try multilib_dir if it is defined. */ 412918334Speter if (multilib_dir != NULL) 413018334Speter { 413118334Speter char *try; 413218334Speter 413318334Speter try = (char *) alloca (strlen (multilib_dir) + strlen (name) + 2); 413418334Speter strcpy (try, multilib_dir); 413518334Speter strcat (try, dir_separator_str); 413618334Speter strcat (try, name); 413718334Speter 413818334Speter newname = find_a_file (&startfile_prefixes, try, R_OK); 413918334Speter 414018334Speter /* If we don't find it in the multi library dir, then fall 414118334Speter through and look for it in the normal places. */ 414218334Speter if (newname != NULL) 414318334Speter return newname; 414418334Speter } 414518334Speter 414618334Speter newname = find_a_file (&startfile_prefixes, name, R_OK); 414718334Speter return newname ? newname : name; 414818334Speter} 414918334Speter 415018334Speter/* Determine whether a directory exists. If LINKER, return 0 for 415118334Speter certain fixed names not needed by the linker. If not LINKER, it is 415218334Speter only important to return 0 if the host machine has a small ARG_MAX 415318334Speter limit. */ 415418334Speter 415518334Speterstatic int 415618334Speteris_directory (path1, path2, linker) 415718334Speter char *path1; 415818334Speter char *path2; 415918334Speter int linker; 416018334Speter{ 416118334Speter int len1 = strlen (path1); 416218334Speter int len2 = strlen (path2); 416318334Speter char *path = (char *) alloca (3 + len1 + len2); 416418334Speter char *cp; 416518334Speter struct stat st; 416618334Speter 416718334Speter#ifndef SMALL_ARG_MAX 416818334Speter if (! linker) 416918334Speter return 1; 417018334Speter#endif 417118334Speter 417218334Speter /* Construct the path from the two parts. Ensure the string ends with "/.". 417318334Speter The resulting path will be a directory even if the given path is a 417418334Speter symbolic link. */ 417518334Speter bcopy (path1, path, len1); 417618334Speter bcopy (path2, path + len1, len2); 417718334Speter cp = path + len1 + len2; 417818334Speter if (cp[-1] != '/' && cp[-1] != DIR_SEPARATOR) 417918334Speter *cp++ = DIR_SEPARATOR; 418018334Speter *cp++ = '.'; 418118334Speter *cp = '\0'; 418218334Speter 418318334Speter /* Exclude directories that the linker is known to search. */ 418418334Speter if (linker 418518334Speter && ((cp - path == 6 418618334Speter && strcmp (path, concat4 (dir_separator_str, "lib", 418718334Speter dir_separator_str, ".")) == 0) 418818334Speter || (cp - path == 10 418918334Speter && strcmp (path, concat6 (dir_separator_str, "usr", 419018334Speter dir_separator_str, "lib", 419118334Speter dir_separator_str, ".")) == 0))) 419218334Speter return 0; 419318334Speter 419418334Speter return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode)); 419518334Speter} 419618334Speter 419718334Speter/* On fatal signals, delete all the temporary files. */ 419818334Speter 419918334Speterstatic void 420018334Speterfatal_error (signum) 420118334Speter int signum; 420218334Speter{ 420318334Speter signal (signum, SIG_DFL); 420418334Speter delete_failure_queue (); 420518334Speter delete_temp_files (); 420618334Speter /* Get the same signal again, this time not handled, 420718334Speter so its normal effect occurs. */ 420818334Speter kill (getpid (), signum); 420918334Speter} 421018334Speter 421118334Speterint 421218334Spetermain (argc, argv) 421318334Speter int argc; 421418334Speter char **argv; 421518334Speter{ 421618334Speter register int i; 421718334Speter int j; 421818334Speter int value; 421918334Speter int linker_was_run = 0; 422018334Speter char *explicit_link_files; 422118334Speter char *specs_file; 422218334Speter char *p; 422318334Speter 422418334Speter p = argv[0] + strlen (argv[0]); 422518334Speter while (p != argv[0] && p[-1] != '/' && p[-1] != DIR_SEPARATOR) --p; 422618334Speter programname = p; 422718334Speter 422818334Speter if (signal (SIGINT, SIG_IGN) != SIG_IGN) 422918334Speter signal (SIGINT, fatal_error); 423018334Speter#ifdef SIGHUP 423118334Speter if (signal (SIGHUP, SIG_IGN) != SIG_IGN) 423218334Speter signal (SIGHUP, fatal_error); 423318334Speter#endif 423418334Speter if (signal (SIGTERM, SIG_IGN) != SIG_IGN) 423518334Speter signal (SIGTERM, fatal_error); 423618334Speter#ifdef SIGPIPE 423718334Speter if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) 423818334Speter signal (SIGPIPE, fatal_error); 423918334Speter#endif 424018334Speter 424118334Speter argbuf_length = 10; 424218334Speter argbuf = (char **) xmalloc (argbuf_length * sizeof (char *)); 424318334Speter 424418334Speter obstack_init (&obstack); 424518334Speter 424618334Speter /* Set up to remember the pathname of gcc and any options 424718334Speter needed for collect. We use argv[0] instead of programname because 424818334Speter we need the complete pathname. */ 424918334Speter obstack_init (&collect_obstack); 425018334Speter obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=")-1); 425118334Speter obstack_grow (&collect_obstack, argv[0], strlen (argv[0])+1); 425218334Speter putenv (obstack_finish (&collect_obstack)); 425318334Speter 425418334Speter#ifdef INIT_ENVIRONMENT 425518334Speter /* Set up any other necessary machine specific environment variables. */ 425618334Speter putenv (INIT_ENVIRONMENT); 425718334Speter#endif 425818334Speter 425918334Speter /* Choose directory for temp files. */ 426018334Speter 426118334Speter choose_temp_base (); 426218334Speter 426318334Speter /* Make a table of what switches there are (switches, n_switches). 426418334Speter Make a table of specified input files (infiles, n_infiles). 426518334Speter Decode switches that are handled locally. */ 426618334Speter 426718334Speter process_command (argc, argv); 426818334Speter 426918334Speter /* Initialize the vector of specs to just the default. 427018334Speter This means one element containing 0s, as a terminator. */ 427118334Speter 427218334Speter compilers = (struct compiler *) xmalloc (sizeof default_compilers); 427318334Speter bcopy ((char *) default_compilers, (char *) compilers, 427418334Speter sizeof default_compilers); 427518334Speter n_compilers = n_default_compilers; 427618334Speter 427718334Speter /* Read specs from a file if there is one. */ 427818334Speter 427918346Speter#ifndef FREEBSD_NATIVE 428018334Speter machine_suffix = concat4 (spec_machine, dir_separator_str, 428118334Speter spec_version, dir_separator_str); 428218334Speter just_machine_suffix = concat (spec_machine, dir_separator_str); 428318346Speter#endif 428418334Speter 428518334Speter specs_file = find_a_file (&startfile_prefixes, "specs", R_OK); 428618334Speter /* Read the specs file unless it is a default one. */ 428718334Speter if (specs_file != 0 && strcmp (specs_file, "specs")) 428818334Speter read_specs (specs_file); 428918334Speter 429018334Speter /* If not cross-compiling, look for startfiles in the standard places. */ 429118334Speter /* The fact that these are done here, after reading the specs file, 429218334Speter means that it cannot be found in these directories. 429318334Speter But that's okay. It should never be there anyway. */ 429418334Speter if (!cross_compile) 429518334Speter { 429618334Speter#ifdef MD_EXEC_PREFIX 429718334Speter add_prefix (&exec_prefixes, md_exec_prefix, 0, 0, NULL_PTR); 429818334Speter add_prefix (&startfile_prefixes, md_exec_prefix, 0, 0, NULL_PTR); 429918334Speter#endif 430018334Speter 430118334Speter#ifdef MD_STARTFILE_PREFIX 430218334Speter add_prefix (&startfile_prefixes, md_startfile_prefix, 0, 0, NULL_PTR); 430318334Speter#endif 430418334Speter 430518334Speter#ifdef MD_STARTFILE_PREFIX_1 430618334Speter add_prefix (&startfile_prefixes, md_startfile_prefix_1, 0, 0, NULL_PTR); 430718334Speter#endif 430818334Speter 430918334Speter /* If standard_startfile_prefix is relative, base it on 431018334Speter standard_exec_prefix. This lets us move the installed tree 431118334Speter as a unit. If GCC_EXEC_PREFIX is defined, base 431218334Speter standard_startfile_prefix on that as well. */ 431318334Speter if (*standard_startfile_prefix == '/' 431418334Speter || *standard_startfile_prefix == DIR_SEPARATOR) 431518334Speter add_prefix (&startfile_prefixes, standard_startfile_prefix, 0, 0, 431618334Speter NULL_PTR); 431718334Speter else 431818334Speter { 431918334Speter if (gcc_exec_prefix) 432018334Speter add_prefix (&startfile_prefixes, 432118334Speter concat3 (gcc_exec_prefix, machine_suffix, 432218334Speter standard_startfile_prefix), 432318334Speter 0, 0, NULL_PTR); 432418334Speter add_prefix (&startfile_prefixes, 432518334Speter concat3 (standard_exec_prefix, 432618334Speter machine_suffix, 432718334Speter standard_startfile_prefix), 432818334Speter 0, 0, NULL_PTR); 432918334Speter } 433018334Speter 433118346Speter#ifndef FREEBSD_NATIVE 433218334Speter add_prefix (&startfile_prefixes, standard_startfile_prefix_1, 0, 0, 433318334Speter NULL_PTR); 433418334Speter add_prefix (&startfile_prefixes, standard_startfile_prefix_2, 0, 0, 433518334Speter NULL_PTR); 433618334Speter#if 0 /* Can cause surprises, and one can use -B./ instead. */ 433718334Speter add_prefix (&startfile_prefixes, "./", 0, 1, NULL_PTR); 433818334Speter#endif 433918346Speter#endif /* FREEBSD_NATIVE */ 434018346Speter 434118334Speter } 434218334Speter else 434318334Speter { 434418334Speter if (*standard_startfile_prefix != DIR_SEPARATOR && gcc_exec_prefix) 434518334Speter add_prefix (&startfile_prefixes, 434618334Speter concat3 (gcc_exec_prefix, machine_suffix, 434718334Speter standard_startfile_prefix), 434818334Speter 0, 0, NULL_PTR); 434918334Speter } 435018334Speter 435118334Speter /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */ 435218334Speter if (gcc_exec_prefix) 435318334Speter { 435418334Speter char * temp = (char *) xmalloc (strlen (gcc_exec_prefix) 435518334Speter + strlen (spec_version) 435618334Speter + strlen (spec_machine) + 3); 435718334Speter strcpy (temp, gcc_exec_prefix); 435818334Speter strcat (temp, spec_machine); 435918334Speter strcat (temp, dir_separator_str); 436018334Speter strcat (temp, spec_version); 436118334Speter strcat (temp, dir_separator_str); 436218334Speter gcc_exec_prefix = temp; 436318334Speter } 436418334Speter 436518334Speter /* Now we have the specs. 436618334Speter Set the `valid' bits for switches that match anything in any spec. */ 436718334Speter 436818334Speter validate_all_switches (); 436918334Speter 437018334Speter /* Now that we have the switches and the specs, set 437118334Speter the subdirectory based on the options. */ 437218334Speter set_multilib_dir (); 437318334Speter 437418334Speter /* Warn about any switches that no pass was interested in. */ 437518334Speter 437618334Speter for (i = 0; i < n_switches; i++) 437718334Speter if (! switches[i].valid) 437818334Speter error ("unrecognized option `-%s'", switches[i].part1); 437918334Speter 438018334Speter /* Obey some of the options. */ 438118334Speter 438218334Speter if (print_search_dirs) 438318334Speter { 438418334Speter printf ("install: %s%s\n", standard_exec_prefix, machine_suffix); 438518334Speter printf ("programs: %s\n", build_search_list (&exec_prefixes, "", 0)); 438618334Speter printf ("libraries: %s\n", build_search_list (&startfile_prefixes, "", 0)); 438718334Speter exit (0); 438818334Speter } 438918334Speter 439018334Speter if (print_file_name) 439118334Speter { 439218334Speter printf ("%s\n", find_file (print_file_name)); 439318334Speter exit (0); 439418334Speter } 439518334Speter 439618334Speter if (print_prog_name) 439718334Speter { 439818334Speter char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK); 439918334Speter printf ("%s\n", (newname ? newname : print_prog_name)); 440018334Speter exit (0); 440118334Speter } 440218334Speter 440318334Speter if (print_multi_lib) 440418334Speter { 440518334Speter print_multilib_info (); 440618334Speter exit (0); 440718334Speter } 440818334Speter 440918334Speter if (print_multi_directory) 441018334Speter { 441118334Speter if (multilib_dir == NULL) 441218334Speter printf (".\n"); 441318334Speter else 441418334Speter printf ("%s\n", multilib_dir); 441518334Speter exit (0); 441618334Speter } 441718334Speter 441818334Speter if (verbose_flag) 441918334Speter { 442018334Speter if (! strcmp (version_string, compiler_version)) 442118334Speter fprintf (stderr, "gcc version %s\n", version_string); 442218334Speter else 442318334Speter fprintf (stderr, "gcc driver version %s executing gcc version %s\n", 442418334Speter version_string, compiler_version); 442518334Speter 442618334Speter if (n_infiles == 0) 442718334Speter exit (0); 442818334Speter } 442918334Speter 443018334Speter if (n_infiles == 0) 443118346Speter fatal ("No input files specified"); 443218334Speter 443318334Speter /* Make a place to record the compiler output file names 443418334Speter that correspond to the input files. */ 443518334Speter 443618334Speter outfiles = (char **) xmalloc (n_infiles * sizeof (char *)); 443718334Speter bzero ((char *) outfiles, n_infiles * sizeof (char *)); 443818334Speter 443918334Speter /* Record which files were specified explicitly as link input. */ 444018334Speter 444118334Speter explicit_link_files = xmalloc (n_infiles); 444218334Speter bzero (explicit_link_files, n_infiles); 444318334Speter 444418334Speter for (i = 0; i < n_infiles; i++) 444518334Speter { 444618334Speter register struct compiler *cp = 0; 444718334Speter int this_file_error = 0; 444818334Speter 444918334Speter /* Tell do_spec what to substitute for %i. */ 445018334Speter 445118334Speter input_filename = infiles[i].name; 445218334Speter input_filename_length = strlen (input_filename); 445318334Speter input_file_number = i; 445418334Speter 445518334Speter /* Use the same thing in %o, unless cp->spec says otherwise. */ 445618334Speter 445718334Speter outfiles[i] = input_filename; 445818334Speter 445918334Speter /* Figure out which compiler from the file's suffix. */ 446018334Speter 446118334Speter cp = lookup_compiler (infiles[i].name, input_filename_length, 446218334Speter infiles[i].language); 446318334Speter 446418334Speter if (cp) 446518334Speter { 446618334Speter /* Ok, we found an applicable compiler. Run its spec. */ 446718334Speter /* First say how much of input_filename to substitute for %b */ 446818334Speter register char *p; 446918334Speter int len; 447018334Speter 447118334Speter input_basename = input_filename; 447218334Speter for (p = input_filename; *p; p++) 447318334Speter if (*p == '/' || *p == DIR_SEPARATOR) 447418334Speter input_basename = p + 1; 447518334Speter 447618334Speter /* Find a suffix starting with the last period, 447718334Speter and set basename_length to exclude that suffix. */ 447818334Speter basename_length = strlen (input_basename); 447918334Speter p = input_basename + basename_length; 448018334Speter while (p != input_basename && *p != '.') --p; 448118334Speter if (*p == '.' && p != input_basename) 448218334Speter { 448318334Speter basename_length = p - input_basename; 448418334Speter input_suffix = p + 1; 448518334Speter } 448618334Speter else 448718334Speter input_suffix = ""; 448818334Speter 448918334Speter len = 0; 449018334Speter for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++) 449118334Speter if (cp->spec[j]) 449218334Speter len += strlen (cp->spec[j]); 449318334Speter 449418334Speter p = (char *) xmalloc (len + 1); 449518334Speter 449618334Speter len = 0; 449718334Speter for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++) 449818334Speter if (cp->spec[j]) 449918334Speter { 450018334Speter strcpy (p + len, cp->spec[j]); 450118334Speter len += strlen (cp->spec[j]); 450218334Speter } 450318334Speter 450418334Speter value = do_spec (p); 450518334Speter free (p); 450618334Speter if (value < 0) 450718334Speter this_file_error = 1; 450818334Speter } 450918334Speter 451018334Speter /* If this file's name does not contain a recognized suffix, 451118334Speter record it as explicit linker input. */ 451218334Speter 451318334Speter else 451418334Speter explicit_link_files[i] = 1; 451518334Speter 451618334Speter /* Clear the delete-on-failure queue, deleting the files in it 451718334Speter if this compilation failed. */ 451818334Speter 451918334Speter if (this_file_error) 452018334Speter { 452118334Speter delete_failure_queue (); 452218334Speter error_count++; 452318334Speter } 452418334Speter /* If this compilation succeeded, don't delete those files later. */ 452518334Speter clear_failure_queue (); 452618334Speter } 452718334Speter 452818334Speter /* Run ld to link all the compiler output files. */ 452918334Speter 453018334Speter if (error_count == 0) 453118334Speter { 453218334Speter int tmp = execution_count; 453318334Speter int i; 453418334Speter int first_time; 453518334Speter 453618334Speter /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables 453718334Speter for collect. */ 453818334Speter putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH="); 453918334Speter putenv_from_prefixes (&startfile_prefixes, "LIBRARY_PATH="); 454018334Speter 454118334Speter /* Build COLLECT_GCC_OPTIONS to have all of the options specified to 454218334Speter the compiler. */ 454318334Speter obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=", 454418334Speter sizeof ("COLLECT_GCC_OPTIONS=")-1); 454518334Speter 454618334Speter first_time = TRUE; 454718334Speter for (i = 0; i < n_switches; i++) 454818334Speter { 454918334Speter char **args; 455018334Speter if (!first_time) 455118334Speter obstack_grow (&collect_obstack, " ", 1); 455218334Speter 455318334Speter first_time = FALSE; 455418334Speter obstack_grow (&collect_obstack, "-", 1); 455518334Speter obstack_grow (&collect_obstack, switches[i].part1, 455618334Speter strlen (switches[i].part1)); 455718334Speter 455818334Speter for (args = switches[i].args; args && *args; args++) 455918334Speter { 456018334Speter obstack_grow (&collect_obstack, " ", 1); 456118334Speter obstack_grow (&collect_obstack, *args, strlen (*args)); 456218334Speter } 456318334Speter } 456418334Speter obstack_grow (&collect_obstack, "\0", 1); 456518334Speter putenv (obstack_finish (&collect_obstack)); 456618334Speter 456718334Speter value = do_spec (link_command_spec); 456818334Speter if (value < 0) 456918334Speter error_count = 1; 457018334Speter linker_was_run = (tmp != execution_count); 457118334Speter } 457218334Speter 457318334Speter /* Warn if a -B option was specified but the prefix was never used. */ 457418334Speter unused_prefix_warnings (&exec_prefixes); 457518334Speter unused_prefix_warnings (&startfile_prefixes); 457618334Speter 457718334Speter /* If options said don't run linker, 457818334Speter complain about input files to be given to the linker. */ 457918334Speter 458018334Speter if (! linker_was_run && error_count == 0) 458118334Speter for (i = 0; i < n_infiles; i++) 458218334Speter if (explicit_link_files[i]) 458318334Speter error ("%s: linker input file unused since linking not done", 458418334Speter outfiles[i]); 458518334Speter 458618334Speter /* Delete some or all of the temporary files we made. */ 458718334Speter 458818334Speter if (error_count) 458918334Speter delete_failure_queue (); 459018334Speter delete_temp_files (); 459118334Speter 459218334Speter exit (error_count > 0 ? (signal_count ? 2 : 1) : 0); 459318334Speter /* NOTREACHED */ 459418334Speter return 0; 459518334Speter} 459618334Speter 459718334Speter/* Find the proper compilation spec for the file name NAME, 459818334Speter whose length is LENGTH. LANGUAGE is the specified language, 459918334Speter or 0 if none specified. */ 460018334Speter 460118334Speterstatic struct compiler * 460218334Speterlookup_compiler (name, length, language) 460318334Speter char *name; 460418334Speter int length; 460518334Speter char *language; 460618334Speter{ 460718334Speter struct compiler *cp; 460818334Speter 460918334Speter /* Look for the language, if one is spec'd. */ 461018334Speter if (language != 0) 461118334Speter { 461218334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 461318334Speter { 461418334Speter if (language != 0) 461518334Speter { 461618334Speter if (cp->suffix[0] == '@' 461718334Speter && !strcmp (cp->suffix + 1, language)) 461818334Speter return cp; 461918334Speter } 462018334Speter } 462118334Speter error ("language %s not recognized", language); 462218334Speter } 462318334Speter 462418334Speter /* Look for a suffix. */ 462518334Speter for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) 462618334Speter { 462718334Speter if (/* The suffix `-' matches only the file name `-'. */ 462818334Speter (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) 462918334Speter || 463018334Speter (strlen (cp->suffix) < length 463118334Speter /* See if the suffix matches the end of NAME. */ 463218334Speter#ifdef OS2 463318334Speter && (!strcmp (cp->suffix, 463418334Speter name + length - strlen (cp->suffix)) 463518334Speter || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") 463618334Speter && !strcasecmp (cp->suffix, 463718334Speter name + length - strlen (cp->suffix))))) 463818334Speter#else 463918334Speter && !strcmp (cp->suffix, 464018334Speter name + length - strlen (cp->suffix)))) 464118334Speter#endif 464218334Speter { 464318334Speter if (cp->spec[0][0] == '@') 464418334Speter { 464518334Speter struct compiler *new; 464618334Speter /* An alias entry maps a suffix to a language. 464718334Speter Search for the language; pass 0 for NAME and LENGTH 464818334Speter to avoid infinite recursion if language not found. 464918334Speter Construct the new compiler spec. */ 465018334Speter language = cp->spec[0] + 1; 465118334Speter new = (struct compiler *) xmalloc (sizeof (struct compiler)); 465218334Speter new->suffix = cp->suffix; 465318334Speter bcopy ((char *) lookup_compiler (NULL_PTR, 0, language)->spec, 465418334Speter (char *) new->spec, sizeof new->spec); 465518334Speter return new; 465618334Speter } 465718334Speter /* A non-alias entry: return it. */ 465818334Speter return cp; 465918334Speter } 466018334Speter } 466118334Speter 466218334Speter return 0; 466318334Speter} 466418334Speter 466518334Speterchar * 466618334Speterxmalloc (size) 466718334Speter unsigned size; 466818334Speter{ 466918334Speter register char *value = (char *) malloc (size); 467018334Speter if (value == 0) 467118334Speter fatal ("virtual memory exhausted"); 467218334Speter return value; 467318334Speter} 467418334Speter 467518334Speterchar * 467618334Speterxrealloc (ptr, size) 467718334Speter char *ptr; 467818334Speter unsigned size; 467918334Speter{ 468018334Speter register char *value = (char *) realloc (ptr, size); 468118334Speter if (value == 0) 468218334Speter fatal ("virtual memory exhausted"); 468318334Speter return value; 468418334Speter} 468518334Speter 468618334Speter/* Return a newly-allocated string whose contents concatenate those of s1, s2 */ 468718334Speter 468818334Speterstatic char * 468918334Speterconcat (s1, s2) 469018334Speter char *s1, *s2; 469118334Speter{ 469218334Speter int len1 = strlen (s1); 469318334Speter int len2 = strlen (s2); 469418334Speter char *result = xmalloc (len1 + len2 + 1); 469518334Speter 469618334Speter strcpy (result, s1); 469718334Speter strcpy (result + len1, s2); 469818334Speter *(result + len1 + len2) = 0; 469918334Speter 470018334Speter return result; 470118334Speter} 470218334Speter 470318334Speterstatic char * 470418334Speterconcat3 (s1, s2, s3) 470518334Speter char *s1, *s2, *s3; 470618334Speter{ 470718334Speter return concat (concat (s1, s2), s3); 470818334Speter} 470918334Speter 471018334Speterstatic char * 471118334Speterconcat4 (s1, s2, s3, s4) 471218334Speter char *s1, *s2, *s3, *s4; 471318334Speter{ 471418334Speter return concat (concat (s1, s2), concat (s3, s4)); 471518334Speter} 471618334Speter 471718334Speterstatic char * 471818334Speterconcat6 (s1, s2, s3, s4, s5, s6) 471918334Speter char *s1, *s2, *s3, *s4, *s5, *s6; 472018334Speter{ 472118334Speter return concat3 (concat (s1, s2), concat (s3, s4), concat (s5, s6)); 472218334Speter} 472318334Speter 472418334Speterstatic char * 472518334Spetersave_string (s, len) 472618334Speter char *s; 472718334Speter int len; 472818334Speter{ 472918334Speter register char *result = xmalloc (len + 1); 473018334Speter 473118334Speter bcopy (s, result, len); 473218334Speter result[len] = 0; 473318334Speter return result; 473418334Speter} 473518334Speter 473618334Speterstatic void 473718334Speterpfatal_with_name (name) 473818334Speter char *name; 473918334Speter{ 474018334Speter char *s; 474118334Speter 474218334Speter if (errno < sys_nerr) 474318334Speter s = concat ("%s: ", my_strerror( errno )); 474418334Speter else 474518334Speter s = "cannot open `%s'"; 474618334Speter fatal (s, name); 474718334Speter} 474818334Speter 474918334Speterstatic void 475018334Speterperror_with_name (name) 475118334Speter char *name; 475218334Speter{ 475318334Speter char *s; 475418334Speter 475518334Speter if (errno < sys_nerr) 475618334Speter s = concat ("%s: ", my_strerror( errno )); 475718334Speter else 475818334Speter s = "cannot open `%s'"; 475918334Speter error (s, name); 476018334Speter} 476118334Speter 476218334Speterstatic void 476318334Speterperror_exec (name) 476418334Speter char *name; 476518334Speter{ 476618334Speter char *s; 476718334Speter 476818334Speter if (errno < sys_nerr) 476918334Speter s = concat ("installation problem, cannot exec `%s': ", 477018334Speter my_strerror (errno)); 477118334Speter else 477218334Speter s = "installation problem, cannot exec `%s'"; 477318334Speter error (s, name); 477418334Speter} 477518334Speter 477618334Speter/* More 'friendly' abort that prints the line and file. 477718334Speter config.h can #define abort fancy_abort if you like that sort of thing. */ 477818334Speter 477918334Spetervoid 478018334Speterfancy_abort () 478118334Speter{ 478218334Speter fatal ("Internal gcc abort."); 478318334Speter} 478418334Speter 478518334Speter#ifdef HAVE_VPRINTF 478618334Speter 478718334Speter/* Output an error message and exit */ 478818334Speter 478918334Speterstatic void 479018334Speterfatal VPROTO((char *format, ...)) 479118334Speter{ 479218334Speter#ifndef __STDC__ 479318334Speter char *format; 479418334Speter#endif 479518334Speter va_list ap; 479618334Speter 479718334Speter VA_START (ap, format); 479818334Speter 479918334Speter#ifndef __STDC__ 480018334Speter format = va_arg (ap, char*); 480118334Speter#endif 480218334Speter 480318334Speter fprintf (stderr, "%s: ", programname); 480418334Speter vfprintf (stderr, format, ap); 480518334Speter va_end (ap); 480618334Speter fprintf (stderr, "\n"); 480718334Speter delete_temp_files (); 480818334Speter exit (1); 480918334Speter} 481018334Speter 481118334Speterstatic void 481218334Spetererror VPROTO((char *format, ...)) 481318334Speter{ 481418334Speter#ifndef __STDC__ 481518334Speter char *format; 481618334Speter#endif 481718334Speter va_list ap; 481818334Speter 481918334Speter VA_START (ap, format); 482018334Speter 482118334Speter#ifndef __STDC__ 482218334Speter format = va_arg (ap, char*); 482318334Speter#endif 482418334Speter 482518334Speter fprintf (stderr, "%s: ", programname); 482618334Speter vfprintf (stderr, format, ap); 482718334Speter va_end (ap); 482818334Speter 482918334Speter fprintf (stderr, "\n"); 483018334Speter} 483118334Speter 483218334Speter#else /* not HAVE_VPRINTF */ 483318334Speter 483418334Speterstatic void 483518334Speterfatal (msg, arg1, arg2) 483618334Speter char *msg, *arg1, *arg2; 483718334Speter{ 483818334Speter error (msg, arg1, arg2); 483918334Speter delete_temp_files (); 484018334Speter exit (1); 484118334Speter} 484218334Speter 484318334Speterstatic void 484418334Spetererror (msg, arg1, arg2) 484518334Speter char *msg, *arg1, *arg2; 484618334Speter{ 484718334Speter fprintf (stderr, "%s: ", programname); 484818334Speter fprintf (stderr, msg, arg1, arg2); 484918334Speter fprintf (stderr, "\n"); 485018334Speter} 485118334Speter 485218334Speter#endif /* not HAVE_VPRINTF */ 485318334Speter 485418334Speter 485518334Speterstatic void 485618334Spetervalidate_all_switches () 485718334Speter{ 485818334Speter struct compiler *comp; 485918334Speter register char *p; 486018334Speter register char c; 486118334Speter struct spec_list *spec; 486218334Speter 486318334Speter for (comp = compilers; comp->spec[0]; comp++) 486418334Speter { 486518334Speter int i; 486618334Speter for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++) 486718334Speter { 486818334Speter p = comp->spec[i]; 486918334Speter while (c = *p++) 487018334Speter if (c == '%' && *p == '{') 487118334Speter /* We have a switch spec. */ 487218334Speter validate_switches (p + 1); 487318334Speter } 487418334Speter } 487518334Speter 487618334Speter /* look through the linked list of extra specs read from the specs file */ 487718334Speter for (spec = specs; spec ; spec = spec->next) 487818334Speter { 487918334Speter p = spec->spec; 488018334Speter while (c = *p++) 488118334Speter if (c == '%' && *p == '{') 488218334Speter /* We have a switch spec. */ 488318334Speter validate_switches (p + 1); 488418334Speter } 488518334Speter 488618334Speter p = link_command_spec; 488718334Speter while (c = *p++) 488818334Speter if (c == '%' && *p == '{') 488918334Speter /* We have a switch spec. */ 489018334Speter validate_switches (p + 1); 489118334Speter 489218334Speter /* Now notice switches mentioned in the machine-specific specs. */ 489318334Speter 489418334Speter p = asm_spec; 489518334Speter while (c = *p++) 489618334Speter if (c == '%' && *p == '{') 489718334Speter /* We have a switch spec. */ 489818334Speter validate_switches (p + 1); 489918334Speter 490018334Speter p = asm_final_spec; 490118334Speter while (c = *p++) 490218334Speter if (c == '%' && *p == '{') 490318334Speter /* We have a switch spec. */ 490418334Speter validate_switches (p + 1); 490518334Speter 490618334Speter p = cpp_spec; 490718334Speter while (c = *p++) 490818334Speter if (c == '%' && *p == '{') 490918334Speter /* We have a switch spec. */ 491018334Speter validate_switches (p + 1); 491118334Speter 491218334Speter p = signed_char_spec; 491318334Speter while (c = *p++) 491418334Speter if (c == '%' && *p == '{') 491518334Speter /* We have a switch spec. */ 491618334Speter validate_switches (p + 1); 491718334Speter 491818334Speter p = cc1_spec; 491918334Speter while (c = *p++) 492018334Speter if (c == '%' && *p == '{') 492118334Speter /* We have a switch spec. */ 492218334Speter validate_switches (p + 1); 492318334Speter 492418334Speter p = cc1plus_spec; 492518334Speter while (c = *p++) 492618334Speter if (c == '%' && *p == '{') 492718334Speter /* We have a switch spec. */ 492818334Speter validate_switches (p + 1); 492918334Speter 493018334Speter p = link_spec; 493118334Speter while (c = *p++) 493218334Speter if (c == '%' && *p == '{') 493318334Speter /* We have a switch spec. */ 493418334Speter validate_switches (p + 1); 493518334Speter 493618334Speter p = lib_spec; 493718334Speter while (c = *p++) 493818334Speter if (c == '%' && *p == '{') 493918334Speter /* We have a switch spec. */ 494018334Speter validate_switches (p + 1); 494118334Speter 494218334Speter p = libgcc_spec; 494318334Speter while (c = *p++) 494418334Speter if (c == '%' && *p == '{') 494518334Speter /* We have a switch spec. */ 494618334Speter validate_switches (p + 1); 494718334Speter 494818334Speter p = startfile_spec; 494918334Speter while (c = *p++) 495018334Speter if (c == '%' && *p == '{') 495118334Speter /* We have a switch spec. */ 495218334Speter validate_switches (p + 1); 495318334Speter} 495418334Speter 495518334Speter/* Look at the switch-name that comes after START 495618334Speter and mark as valid all supplied switches that match it. */ 495718334Speter 495818334Speterstatic void 495918334Spetervalidate_switches (start) 496018334Speter char *start; 496118334Speter{ 496218334Speter register char *p = start; 496318334Speter char *filter; 496418334Speter register int i; 496518334Speter int suffix = 0; 496618334Speter 496718334Speter if (*p == '|') 496818334Speter ++p; 496918334Speter 497018334Speter if (*p == '!') 497118334Speter ++p; 497218334Speter 497318334Speter if (*p == '.') 497418334Speter suffix = 1, ++p; 497518334Speter 497618334Speter filter = p; 497718334Speter while (*p != ':' && *p != '}') p++; 497818334Speter 497918334Speter if (suffix) 498018334Speter ; 498118334Speter else if (p[-1] == '*') 498218334Speter { 498318334Speter /* Mark all matching switches as valid. */ 498418334Speter --p; 498518334Speter for (i = 0; i < n_switches; i++) 498618334Speter if (!strncmp (switches[i].part1, filter, p - filter)) 498718334Speter switches[i].valid = 1; 498818334Speter } 498918334Speter else 499018334Speter { 499118334Speter /* Mark an exact matching switch as valid. */ 499218334Speter for (i = 0; i < n_switches; i++) 499318334Speter { 499418334Speter if (!strncmp (switches[i].part1, filter, p - filter) 499518334Speter && switches[i].part1[p - filter] == 0) 499618334Speter switches[i].valid = 1; 499718334Speter } 499818334Speter } 499918334Speter} 500018334Speter 500118334Speter/* Check whether a particular argument was used. */ 500218334Speter 500318334Speterstatic int 500418334Speterused_arg (p, len) 500518334Speter char *p; 500618334Speter int len; 500718334Speter{ 500818334Speter int i; 500918334Speter 501018334Speter for (i = 0; i < n_switches; i++) 501118334Speter if (! strncmp (switches[i].part1, p, len) 501218334Speter && strlen (switches[i].part1) == len) 501318334Speter return 1; 501418334Speter return 0; 501518334Speter} 501618334Speter 501718334Speter/* Check whether a particular argument is a default argument. */ 501818334Speter 501918334Speter#ifndef MULTILIB_DEFAULTS 502018334Speter#define MULTILIB_DEFAULTS { NULL } 502118334Speter#endif 502218334Speter 502318334Speterstatic char *multilib_defaults[] = MULTILIB_DEFAULTS; 502418334Speter 502518334Speterstatic int 502618334Speterdefault_arg (p, len) 502718334Speter char *p; 502818334Speter int len; 502918334Speter{ 503018334Speter int count = sizeof multilib_defaults / sizeof multilib_defaults[0]; 503118334Speter int i; 503218334Speter 503318334Speter for (i = 0; i < count; i++) 503418334Speter if (multilib_defaults[i] != NULL 503518334Speter && strncmp (multilib_defaults[i], p, len) == 0 503618334Speter && multilib_defaults[i][len] == '\0') 503718334Speter return 1; 503818334Speter 503918334Speter return 0; 504018334Speter} 504118334Speter 504218334Speter/* Work out the subdirectory to use based on the 504318334Speter options. The format of multilib_select is a list of elements. 504418334Speter Each element is a subdirectory name followed by a list of options 504518334Speter followed by a semicolon. gcc will consider each line in turn. If 504618334Speter none of the options beginning with an exclamation point are 504718334Speter present, and all of the other options are present, that 504818334Speter subdirectory will be used. */ 504918334Speter 505018334Speterstatic void 505118334Speterset_multilib_dir () 505218334Speter{ 505318334Speter char *p = multilib_select; 505418334Speter int this_path_len; 505518334Speter char *this_path, *this_arg; 505618334Speter int not_arg; 505718334Speter int ok; 505818334Speter 505918334Speter while (*p != '\0') 506018334Speter { 506118334Speter /* Ignore newlines. */ 506218334Speter if (*p == '\n') 506318334Speter { 506418334Speter ++p; 506518334Speter continue; 506618334Speter } 506718334Speter 506818334Speter /* Get the initial path. */ 506918334Speter this_path = p; 507018334Speter while (*p != ' ') 507118334Speter { 507218334Speter if (*p == '\0') 507318334Speter abort (); 507418334Speter ++p; 507518334Speter } 507618334Speter this_path_len = p - this_path; 507718334Speter 507818334Speter /* Check the arguments. */ 507918334Speter ok = 1; 508018334Speter ++p; 508118334Speter while (*p != ';') 508218334Speter { 508318334Speter if (*p == '\0') 508418334Speter abort (); 508518334Speter 508618334Speter if (! ok) 508718334Speter { 508818334Speter ++p; 508918334Speter continue; 509018334Speter } 509118334Speter 509218334Speter this_arg = p; 509318334Speter while (*p != ' ' && *p != ';') 509418334Speter { 509518334Speter if (*p == '\0') 509618334Speter abort (); 509718334Speter ++p; 509818334Speter } 509918334Speter 510018334Speter if (*this_arg != '!') 510118334Speter not_arg = 0; 510218334Speter else 510318334Speter { 510418334Speter not_arg = 1; 510518334Speter ++this_arg; 510618334Speter } 510718334Speter 510818334Speter /* If this is a default argument, we can just ignore it. 510918334Speter This is true even if this_arg begins with '!'. Beginning 511018334Speter with '!' does not mean that this argument is necessarily 511118334Speter inappropriate for this library: it merely means that 511218334Speter there is a more specific library which uses this 511318334Speter argument. If this argument is a default, we need not 511418334Speter consider that more specific library. */ 511518334Speter if (! default_arg (this_arg, p - this_arg)) 511618334Speter { 511718334Speter ok = used_arg (this_arg, p - this_arg); 511818334Speter if (not_arg) 511918334Speter ok = ! ok; 512018334Speter } 512118334Speter 512218334Speter if (*p == ' ') 512318334Speter ++p; 512418334Speter } 512518334Speter 512618334Speter if (ok) 512718334Speter { 512818334Speter if (this_path_len != 1 512918334Speter || this_path[0] != '.') 513018334Speter { 513118334Speter multilib_dir = xmalloc (this_path_len + 1); 513218334Speter strncpy (multilib_dir, this_path, this_path_len); 513318334Speter multilib_dir[this_path_len] = '\0'; 513418334Speter } 513518334Speter break; 513618334Speter } 513718334Speter 513818334Speter ++p; 513918334Speter } 514018334Speter} 514118334Speter 514218334Speter/* Print out the multiple library subdirectory selection 514318334Speter information. This prints out a series of lines. Each line looks 514418334Speter like SUBDIRECTORY;@OPTION@OPTION, with as many options as is 514518334Speter required. Only the desired options are printed out, the negative 514618334Speter matches. The options are print without a leading dash. There are 514718334Speter no spaces to make it easy to use the information in the shell. 514818334Speter Each subdirectory is printed only once. This assumes the ordering 514918334Speter generated by the genmultilib script. */ 515018334Speter 515118334Speterstatic void 515218334Speterprint_multilib_info () 515318334Speter{ 515418334Speter char *p = multilib_select; 515518334Speter char *last_path = 0, *this_path; 515618334Speter int skip; 515718334Speter int last_path_len = 0; 515818334Speter 515918334Speter while (*p != '\0') 516018334Speter { 516118334Speter /* Ignore newlines. */ 516218334Speter if (*p == '\n') 516318334Speter { 516418334Speter ++p; 516518334Speter continue; 516618334Speter } 516718334Speter 516818334Speter /* Get the initial path. */ 516918334Speter this_path = p; 517018334Speter while (*p != ' ') 517118334Speter { 517218334Speter if (*p == '\0') 517318334Speter abort (); 517418334Speter ++p; 517518334Speter } 517618334Speter 517718334Speter /* If this is a duplicate, skip it. */ 517818334Speter skip = (last_path != 0 && p - this_path == last_path_len 517918334Speter && ! strncmp (last_path, this_path, last_path_len)); 518018334Speter 518118334Speter last_path = this_path; 518218334Speter last_path_len = p - this_path; 518318334Speter 518418334Speter /* If this directory requires any default arguments, we can skip 518518334Speter it. We will already have printed a directory identical to 518618334Speter this one which does not require that default argument. */ 518718334Speter if (! skip) 518818334Speter { 518918334Speter char *q; 519018334Speter 519118334Speter q = p + 1; 519218334Speter while (*q != ';') 519318334Speter { 519418334Speter char *arg; 519518334Speter 519618334Speter if (*q == '\0') 519718334Speter abort (); 519818334Speter 519918334Speter if (*q == '!') 520018334Speter arg = NULL; 520118334Speter else 520218334Speter arg = q; 520318334Speter 520418334Speter while (*q != ' ' && *q != ';') 520518334Speter { 520618334Speter if (*q == '\0') 520718334Speter abort (); 520818334Speter ++q; 520918334Speter } 521018334Speter 521118334Speter if (arg != NULL 521218334Speter && default_arg (arg, q - arg)) 521318334Speter { 521418334Speter skip = 1; 521518334Speter break; 521618334Speter } 521718334Speter 521818334Speter if (*q == ' ') 521918334Speter ++q; 522018334Speter } 522118334Speter } 522218334Speter 522318334Speter if (! skip) 522418334Speter { 522518334Speter char *p1; 522618334Speter 522718334Speter for (p1 = last_path; p1 < p; p1++) 522818334Speter putchar (*p1); 522918334Speter putchar (';'); 523018334Speter } 523118334Speter 523218334Speter ++p; 523318334Speter while (*p != ';') 523418334Speter { 523518334Speter int use_arg; 523618334Speter 523718334Speter if (*p == '\0') 523818334Speter abort (); 523918334Speter 524018334Speter if (skip) 524118334Speter { 524218334Speter ++p; 524318334Speter continue; 524418334Speter } 524518334Speter 524618334Speter use_arg = *p != '!'; 524718334Speter 524818334Speter if (use_arg) 524918334Speter putchar ('@'); 525018334Speter 525118334Speter while (*p != ' ' && *p != ';') 525218334Speter { 525318334Speter if (*p == '\0') 525418334Speter abort (); 525518334Speter if (use_arg) 525618334Speter putchar (*p); 525718334Speter ++p; 525818334Speter } 525918334Speter 526018334Speter if (*p == ' ') 526118334Speter ++p; 526218334Speter } 526318334Speter 526418334Speter if (! skip) 526518334Speter putchar ('\n'); 526618334Speter 526718334Speter ++p; 526818334Speter } 526918334Speter} 5270