X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgcc.c;h=d3066b95e73f22a25a72aa285544a23b8400e87a;hb=10c0611466c6e2c29a7c300cdd22ed4be0217e32;hp=15064ebf66f61bcdc6bad62e1c67917de1c5d0c9;hpb=ef2c4a29c2658395106b6bae4970feb7da338132;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/gcc.c b/gcc/gcc.c index 15064ebf66f..d3066b95e73 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -1,5 +1,6 @@ /* Compiler driver program that can handle many languages. - Copyright (C) 1987, 89, 92-99, 2000 Free Software Foundation, Inc. + Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000 Free Software Foundation, Inc. This file is part of GNU CC. @@ -31,7 +32,6 @@ CC recognizes how to compile each input file by suffixes in the file names. Once it knows which kind of compilation to perform, the procedure for compilation is specified by a string called a "spec". */ - #include "config.h" #include "system.h" #include @@ -47,8 +47,8 @@ compilation is specified by a string called a "spec". */ #ifdef HAVE_SYS_RESOURCE_H #include #endif -#ifdef NEED_DECLARATION_GETRUSAGE -extern int getrusage PROTO ((int, struct rusage *)); +#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE +extern int getrusage PARAMS ((int, struct rusage *)); #endif /* By default there is no special suffix for executables. */ @@ -65,15 +65,6 @@ extern int getrusage PROTO ((int, struct rusage *)); #define OBJECT_SUFFIX ".o" #endif -/* By default, colon separates directories in a path. */ -#ifndef PATH_SEPARATOR -#define PATH_SEPARATOR ':' -#endif - -#ifndef DIR_SEPARATOR -#define DIR_SEPARATOR '/' -#endif - #ifndef VMS /* FIXME: the location independence code for VMS is hairier than this, and hasn't been written. */ @@ -82,15 +73,7 @@ extern int getrusage PROTO ((int, struct rusage *)); #endif /* DIR_UP */ #endif /* VMS */ -/* Define IS_DIR_SEPARATOR. */ -#ifndef DIR_SEPARATOR_2 -# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) -#else /* DIR_SEPARATOR_2 */ -# define IS_DIR_SEPARATOR(ch) \ - (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) -#endif /* DIR_SEPARATOR_2 */ - -static char dir_separator_str[] = {DIR_SEPARATOR, 0}; +static char dir_separator_str[] = { DIR_SEPARATOR, 0 }; #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free @@ -99,6 +82,11 @@ static char dir_separator_str[] = {DIR_SEPARATOR, 0}; #define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0) #endif +/* Most every one is fine with LIBRARY_PATH. For some, it conflicts. */ +#ifndef LIBRARY_PATH_ENV +#define LIBRARY_PATH_ENV "LIBRARY_PATH" +#endif + #ifndef HAVE_KILL #define kill(p,s) raise(s) #endif @@ -112,6 +100,9 @@ static char dir_separator_str[] = {DIR_SEPARATOR, 0}; to the calling program. */ static int pass_exit_codes; +/* Definition of string containing the arguments given to configure. */ +#include "configargs.h" + /* Flag saying to print the directories gcc will search through looking for programs, libraries, etc. */ @@ -145,6 +136,10 @@ static int print_help_list; static int verbose_flag; +/* Flag indicating to print target specific command line options. */ + +static int target_help_flag; + /* Flag indicating whether we should report subprocess execution times (if this is supported by the system - see pexecute.c). */ @@ -157,11 +152,11 @@ static int save_temps_flag; /* The compiler version. */ -static char *compiler_version; +static const char *compiler_version; /* The target version specified with -V */ -static char *spec_version = DEFAULT_TARGET_VERSION; +static const char *spec_version = DEFAULT_TARGET_VERSION; /* The target machine specified with -b. */ @@ -171,11 +166,26 @@ static const char *spec_machine = DEFAULT_TARGET_MACHINE; When -b is used, the value comes from the `specs' file. */ #ifdef CROSS_COMPILE -static char *cross_compile = "1"; +static const char *cross_compile = "1"; #else -static char *cross_compile = "0"; +static const char *cross_compile = "0"; #endif +#ifdef MODIFY_TARGET_NAME + +/* Information on how to alter the target name based on a command-line + switch. The only case we support now is simply appending or deleting a + string to or from the end of the first part of the configuration name. */ + +struct modify_target +{ + const char *sw; + enum add_del {ADD, DELETE} add_del; + const char *str; +} +modify_target[] = MODIFY_TARGET_NAME; +#endif + /* The number of errors that have occurred; the link phase will not be run if this is non-zero. */ static int error_count = 0; @@ -201,62 +211,63 @@ static struct obstack collect_obstack; static struct rusage rus, prus; #endif -extern char *version_string; - /* Forward declaration for prototypes. */ struct path_prefix; -static void init_spec PROTO((void)); +static void init_spec PARAMS ((void)); #ifndef VMS -static char **split_directories PROTO((const char *, int *)); -static void free_split_directories PROTO((char **)); -static char *make_relative_prefix PROTO((const char *, const char *, const char *)); +static char **split_directories PARAMS ((const char *, int *)); +static void free_split_directories PARAMS ((char **)); +static char *make_relative_prefix PARAMS ((const char *, const char *, const char *)); #endif /* VMS */ -static void read_specs PROTO((const char *, int)); -static void set_spec PROTO((const char *, const char *)); -static struct compiler *lookup_compiler PROTO((const char *, size_t, const char *)); -static char *build_search_list PROTO((struct path_prefix *, const char *, int)); -static void putenv_from_prefixes PROTO((struct path_prefix *, const char *)); -static int access_check PROTO((const char *, int)); -static char *find_a_file PROTO((struct path_prefix *, const char *, int)); -static void add_prefix PROTO((struct path_prefix *, const char *, - const char *, int, int, int *)); -static char *skip_whitespace PROTO((char *)); -static void record_temp_file PROTO((const char *, int, int)); -static void delete_if_ordinary PROTO((const char *)); -static void delete_temp_files PROTO((void)); -static void delete_failure_queue PROTO((void)); -static void clear_failure_queue PROTO((void)); -static int check_live_switch PROTO((int, int)); -static const char *handle_braces PROTO((const char *)); -static char *save_string PROTO((const char *, int)); -static int do_spec_1 PROTO((const char *, int, const char *)); -static const char *find_file PROTO((const char *)); -static int is_directory PROTO((const char *, const char *, int)); -static void validate_switches PROTO((const char *)); -static void validate_all_switches PROTO((void)); -static void give_switch PROTO((int, int, int)); -static int used_arg PROTO((const char *, int)); -static int default_arg PROTO((const char *, int)); -static void set_multilib_dir PROTO((void)); -static void print_multilib_info PROTO((void)); -static void pfatal_with_name PROTO((const char *)) ATTRIBUTE_NORETURN; -static void perror_with_name PROTO((const char *)); -static void pfatal_pexecute PROTO((const char *, const char *)) +static void store_arg PARAMS ((const char *, int, int)); +static char *load_specs PARAMS ((const char *)); +static void read_specs PARAMS ((const char *, int)); +static void set_spec PARAMS ((const char *, const char *)); +static struct compiler *lookup_compiler PARAMS ((const char *, size_t, const char *)); +static char *build_search_list PARAMS ((struct path_prefix *, const char *, int)); +static void putenv_from_prefixes PARAMS ((struct path_prefix *, const char *)); +static int access_check PARAMS ((const char *, int)); +static char *find_a_file PARAMS ((struct path_prefix *, const char *, int)); +static void add_prefix PARAMS ((struct path_prefix *, const char *, + const char *, int, int, int *)); +static void translate_options PARAMS ((int *, const char *const **)); +static char *skip_whitespace PARAMS ((char *)); +static void record_temp_file PARAMS ((const char *, int, int)); +static void delete_if_ordinary PARAMS ((const char *)); +static void delete_temp_files PARAMS ((void)); +static void delete_failure_queue PARAMS ((void)); +static void clear_failure_queue PARAMS ((void)); +static int check_live_switch PARAMS ((int, int)); +static const char *handle_braces PARAMS ((const char *)); +static char *save_string PARAMS ((const char *, int)); +static int do_spec_1 PARAMS ((const char *, int, const char *)); +static const char *find_file PARAMS ((const char *)); +static int is_directory PARAMS ((const char *, const char *, int)); +static void validate_switches PARAMS ((const char *)); +static void validate_all_switches PARAMS ((void)); +static void give_switch PARAMS ((int, int, int)); +static int used_arg PARAMS ((const char *, int)); +static int default_arg PARAMS ((const char *, int)); +static void set_multilib_dir PARAMS ((void)); +static void print_multilib_info PARAMS ((void)); +static void pfatal_with_name PARAMS ((const char *)) ATTRIBUTE_NORETURN; +static void perror_with_name PARAMS ((const char *)); +static void pfatal_pexecute PARAMS ((const char *, const char *)) ATTRIBUTE_NORETURN; -static void error PVPROTO((const char *, ...)) +static void error PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1; -static void notice PVPROTO((const char *, ...)) +static void notice PARAMS ((const char *, ...)) ATTRIBUTE_PRINTF_1; -static void display_help PROTO((void)); -static void add_preprocessor_option PROTO ((const char *, int)); -static void add_assembler_option PROTO ((const char *, int)); -static void add_linker_option PROTO ((const char *, int)); -static void process_command PROTO ((int, char **)); -static int execute PROTO ((void)); -static void unused_prefix_warnings PROTO ((struct path_prefix *)); -static void clear_args PROTO ((void)); -static void fatal_error PROTO ((int)); +static void display_help PARAMS ((void)); +static void add_preprocessor_option PARAMS ((const char *, int)); +static void add_assembler_option PARAMS ((const char *, int)); +static void add_linker_option PARAMS ((const char *, int)); +static void process_command PARAMS ((int, const char *const *)); +static int execute PARAMS ((void)); +static void clear_args PARAMS ((void)); +static void fatal_error PARAMS ((int)); +static void set_input PARAMS ((const char *)); /* Specs are strings containing lines, each of which (if not blank) is made up of a program name, and arguments separated by spaces. @@ -276,6 +287,7 @@ or with constant text in a single argument. %b substitute the basename of the input file being processed. This is the substring up to (and not including) the last period and not including the directory. + %B same as %b, but include the file suffix (text after the last period). %gSUFFIX substitute a file name that has suffix SUFFIX and is chosen once per compilation, and mark the argument a la %d. To reduce @@ -300,6 +312,12 @@ or with constant text in a single argument. for each `%g.s' and another for each `%U.s'. Previously, %U was simply substituted with a file name chosen for the previous %u, without regard to any appended suffix. + %jSUFFIX + substitutes the name of the HOST_BIT_BUCKET, if any, and if it is + writable, and if save-temps is off; otherwise, substitute the name + of a temporary file, just like %u. This temporary file is not + meant for communication between processes, but rather as a junk + disposal mechanism. %d marks the argument containing or following the %d as a temporary file name, so that that file will be deleted if CC exits successfully. Unlike %g, this contributes no text to the argument. @@ -340,9 +358,11 @@ or with constant text in a single argument. %Y Output the accumulated assembler options specified by compilations. %Z Output the accumulated preprocessor options specified by compilations. %v1 Substitute the major version number of GCC. - (For version 2.5.n, this is 2.) + (For version 2.5.3, this is 2.) %v2 Substitute the minor version number of GCC. - (For version 2.5.n, this is 5.) + (For version 2.5.3, this is 5.) + %v3 Substitute the patch level number of GCC. + (For version 2.5.3, this is 3.) %a process ASM_SPEC as a spec. This allows config.h to specify part of the spec for running as. %A process ASM_FINAL_SPEC as a spec. A capital A is actually @@ -376,6 +396,10 @@ or with constant text in a single argument. specified to CC. Note that the tail part of the -S option (i.e. the part matched by the `*') will be substituted for each occurrence of %* within X. + %{= arglen && !strncmp (argv[i], option_map[k].name, arglen)) { @@ -976,7 +933,7 @@ translate_options (argcp, argvp) break; } - if (k != sizeof (option_map) / sizeof (option_map[0])) + if (k != ARRAY_SIZE (option_map)) break; } @@ -988,7 +945,7 @@ translate_options (argcp, argvp) /* If this mapping requires extra text at end of name, accept that as "argument". */ - else if (index (arginfo, '*') != 0) + else if (strchr (arginfo, '*') != 0) arg = argv[i] + optlen; /* Otherwise, extra text at end means mismatch. @@ -997,14 +954,14 @@ translate_options (argcp, argvp) continue; } - else if (index (arginfo, '*') != 0) + else if (strchr (arginfo, '*') != 0) { error ("Incomplete `%s' option", option_map[j].name); break; } /* Handle arguments. */ - if (index (arginfo, 'a') != 0) + if (strchr (arginfo, 'a') != 0) { if (arg == 0) { @@ -1018,9 +975,9 @@ translate_options (argcp, argvp) arg = argv[++i]; } } - else if (index (arginfo, '*') != 0) + else if (strchr (arginfo, '*') != 0) ; - else if (index (arginfo, 'o') == 0) + else if (strchr (arginfo, 'o') == 0) { if (arg != 0) error ("Extraneous argument to `%s' option", @@ -1029,7 +986,7 @@ translate_options (argcp, argvp) } /* Store the translation as one argv elt or as two. */ - if (arg != 0 && index (arginfo, 'j') != 0) + if (arg != 0 && strchr (arginfo, 'j') != 0) newv[newindex++] = concat (option_map[j].equivalent, arg, NULL_PTR); else if (arg != 0) @@ -1101,7 +1058,8 @@ skip_whitespace (p) p++; else if (*p == '#') { - while (*p != '\n') p++; + while (*p != '\n') + p++; p++; } else @@ -1110,6 +1068,104 @@ skip_whitespace (p) return p; } +/* Structures to keep track of prefixes to try when looking for files. */ + +struct prefix_list +{ + char *prefix; /* String to prepend to the path. */ + struct prefix_list *next; /* Next in linked list. */ + int require_machine_suffix; /* Don't use without machine_suffix. */ + /* 2 means try both machine_suffix and just_machine_suffix. */ + int *used_flag_ptr; /* 1 if a file was found with this prefix. */ + int priority; /* Sort key - priority within list */ +}; + +struct path_prefix +{ + struct prefix_list *plist; /* List of prefixes to try */ + int max_len; /* Max length of a prefix in PLIST */ + const char *name; /* Name of this list (used in config stuff) */ +}; + +/* List of prefixes to try when looking for executables. */ + +static struct path_prefix exec_prefixes = { 0, 0, "exec" }; + +/* List of prefixes to try when looking for startup (crt0) files. */ + +static struct path_prefix startfile_prefixes = { 0, 0, "startfile" }; + +/* List of prefixes to try when looking for include files. */ + +static struct path_prefix include_prefixes = { 0, 0, "include" }; + +/* Suffix to attach to directories searched for commands. + This looks like `MACHINE/VERSION/'. */ + +static const char *machine_suffix = 0; + +/* Suffix to attach to directories searched for commands. + This is just `MACHINE/'. */ + +static const char *just_machine_suffix = 0; + +/* Adjusted value of GCC_EXEC_PREFIX envvar. */ + +static const char *gcc_exec_prefix; + +/* Default prefixes to attach to command names. */ + +#ifdef CROSS_COMPILE /* Don't use these prefixes for a cross compiler. */ +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX +#undef MD_STARTFILE_PREFIX_1 +#endif + +/* If no prefixes defined, use the null string, which will disable them. */ +#ifndef MD_EXEC_PREFIX +#define MD_EXEC_PREFIX "" +#endif +#ifndef MD_STARTFILE_PREFIX +#define MD_STARTFILE_PREFIX "" +#endif +#ifndef MD_STARTFILE_PREFIX_1 +#define MD_STARTFILE_PREFIX_1 "" +#endif + +/* Supply defaults for the standard prefixes. */ + +#ifndef STANDARD_EXEC_PREFIX +#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/" +#endif +#ifndef STANDARD_STARTFILE_PREFIX +#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/" +#endif +#ifndef TOOLDIR_BASE_PREFIX +#define TOOLDIR_BASE_PREFIX "/usr/local/" +#endif +#ifndef STANDARD_BINDIR_PREFIX +#define STANDARD_BINDIR_PREFIX "/usr/local/bin" +#endif + +static const char *standard_exec_prefix = STANDARD_EXEC_PREFIX; +static const char *standard_exec_prefix_1 = "/usr/lib/gcc/"; +static const char *md_exec_prefix = MD_EXEC_PREFIX; + +static const char *md_startfile_prefix = MD_STARTFILE_PREFIX; +static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1; +static const char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; +static const char *standard_startfile_prefix_1 = "/lib/"; +static const char *standard_startfile_prefix_2 = "/usr/lib/"; + +static const char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX; +static const char *tooldir_prefix; + +static const char *standard_bindir_prefix = STANDARD_BINDIR_PREFIX; + +/* Subdirectory to use for locating libraries. Set by + set_multilib_dir based on the compilation options. */ + +static const char *multilib_dir; /* Structure to keep track of the specs that have been defined so far. These are accessed using %(specname) or %[specname] in a compiler @@ -1119,26 +1175,32 @@ struct spec_list { /* The following 2 fields must be first */ /* to allow EXTRA_SPECS to be initialized */ - char *name; /* name of the spec. */ - char *ptr; /* available ptr if no static pointer */ + const char *name; /* name of the spec. */ + const char *ptr; /* available ptr if no static pointer */ /* The following fields are not initialized */ /* by EXTRA_SPECS */ - char **ptr_spec; /* pointer to the spec itself. */ + const char **ptr_spec; /* pointer to the spec itself. */ struct spec_list *next; /* Next spec in linked list. */ int name_len; /* length of the name */ int alloc_p; /* whether string was allocated */ }; #define INIT_STATIC_SPEC(NAME,PTR) \ -{ NAME, NULL_PTR, PTR, (struct spec_list *)0, sizeof (NAME)-1, 0 } +{ NAME, NULL_PTR, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 } -/* List of statically defined specs */ -static struct spec_list static_specs[] = { +/* List of statically defined specs. */ +static struct spec_list static_specs[] = +{ INIT_STATIC_SPEC ("asm", &asm_spec), INIT_STATIC_SPEC ("asm_final", &asm_final_spec), + INIT_STATIC_SPEC ("asm_options", &asm_options), + INIT_STATIC_SPEC ("invoke_as", &invoke_as), INIT_STATIC_SPEC ("cpp", &cpp_spec), + INIT_STATIC_SPEC ("cpp_options", &cpp_options), + INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp), INIT_STATIC_SPEC ("cc1", &cc1_spec), + INIT_STATIC_SPEC ("cc1_options", &cc1_options), INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec), INIT_STATIC_SPEC ("endfile", &endfile_spec), INIT_STATIC_SPEC ("link", &link_spec), @@ -1154,48 +1216,51 @@ static struct spec_list static_specs[] = { INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults), INIT_STATIC_SPEC ("multilib_extra", &multilib_extra), INIT_STATIC_SPEC ("multilib_matches", &multilib_matches), + INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions), INIT_STATIC_SPEC ("linker", &linker_name_spec), + INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec), + INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix), + INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix), + INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1), }; #ifdef EXTRA_SPECS /* additional specs needed */ /* Structure to keep track of just the first two args of a spec_list. - That is all that the EXTRA_SPECS macro gives us. */ + That is all that the EXTRA_SPECS macro gives us. */ struct spec_list_1 { - char *name; - char *ptr; + const char *name; + const char *ptr; }; static struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS }; -static struct spec_list * extra_specs = (struct spec_list *)0; +static struct spec_list *extra_specs = (struct spec_list *) 0; #endif /* List of dynamically allocates specs that have been defined so far. */ -static struct spec_list *specs = (struct spec_list *)0; - +static struct spec_list *specs = (struct spec_list *) 0; /* Initialize the specs lookup routines. */ static void init_spec () { - struct spec_list *next = (struct spec_list *)0; - struct spec_list *sl = (struct spec_list *)0; + struct spec_list *next = (struct spec_list *) 0; + struct spec_list *sl = (struct spec_list *) 0; int i; if (specs) - return; /* already initialized */ + return; /* Already initialized. */ if (verbose_flag) notice ("Using builtin specs.\n"); #ifdef EXTRA_SPECS extra_specs = (struct spec_list *) - xcalloc (sizeof(struct spec_list), - (sizeof(extra_specs_1)/sizeof(extra_specs_1[0]))); - - for (i = (sizeof(extra_specs_1) / sizeof(extra_specs_1[0])) - 1; i >= 0; i--) + xcalloc (sizeof (struct spec_list), ARRAY_SIZE (extra_specs_1)); + + for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--) { sl = &extra_specs[i]; sl->name = extra_specs_1[i].name; @@ -1207,7 +1272,7 @@ init_spec () } #endif - for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1; i >= 0; i--) + for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) { sl = &static_specs[i]; sl->next = next; @@ -1216,7 +1281,6 @@ init_spec () specs = sl; } - /* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is removed; If the spec starts with a + then SPEC is added to the end of the @@ -1228,16 +1292,15 @@ set_spec (name, spec) const char *spec; { struct spec_list *sl; - char *old_spec; + const char *old_spec; int name_len = strlen (name); int i; - /* If this is the first call, initialize the statically allocated specs */ + /* If this is the first call, initialize the statically allocated specs. */ if (!specs) { - struct spec_list *next = (struct spec_list *)0; - for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1; - i >= 0; i--) + struct spec_list *next = (struct spec_list *) 0; + for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--) { sl = &static_specs[i]; sl->next = next; @@ -1246,14 +1309,14 @@ set_spec (name, spec) specs = sl; } - /* See if the spec already exists */ + /* See if the spec already exists. */ for (sl = specs; sl; sl = sl->next) if (name_len == sl->name_len && !strcmp (sl->name, name)) break; if (!sl) { - /* Not found - make it */ + /* Not found - make it. */ sl = (struct spec_list *) xmalloc (sizeof (struct spec_list)); sl->name = xstrdup (name); sl->name_len = name_len; @@ -1274,9 +1337,9 @@ set_spec (name, spec) notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec)); #endif - /* Free the old spec */ + /* Free the old spec. */ if (old_spec && sl->alloc_p) - free (old_spec); + free ((PTR) old_spec); sl->alloc_p = 1; } @@ -1285,7 +1348,7 @@ set_spec (name, spec) /* Vector of pointers to arguments in the current line of specifications. */ -static char **argbuf; +static const char **argbuf; /* Number of elements allocated in argbuf. */ @@ -1295,13 +1358,9 @@ static int argbuf_length; static int argbuf_index; -/* We want this on by default all the time now. */ -#define MKTEMP_EACH_FILE - -#ifdef MKTEMP_EACH_FILE - -/* This is the list of suffixes and codes (%g/%u/%U) and the associated - temp file. */ +/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated + temp file. If the HOST_BIT_BUCKET is used for %j, no entry is made for + it here. */ static struct temp_name { const char *suffix; /* suffix associated with the code. */ @@ -1311,8 +1370,6 @@ static struct temp_name { int filename_length; /* strlen (filename). */ struct temp_name *next; } *temp_names; -#endif - /* Number of commands executed so far. */ @@ -1326,98 +1383,6 @@ static int signal_count; static const char *programname; -/* Structures to keep track of prefixes to try when looking for files. */ - -struct prefix_list -{ - char *prefix; /* String to prepend to the path. */ - struct prefix_list *next; /* Next in linked list. */ - int require_machine_suffix; /* Don't use without machine_suffix. */ - /* 2 means try both machine_suffix and just_machine_suffix. */ - int *used_flag_ptr; /* 1 if a file was found with this prefix. */ -}; - -struct path_prefix -{ - struct prefix_list *plist; /* List of prefixes to try */ - int max_len; /* Max length of a prefix in PLIST */ - const char *name; /* Name of this list (used in config stuff) */ -}; - -/* List of prefixes to try when looking for executables. */ - -static struct path_prefix exec_prefixes = { 0, 0, "exec" }; - -/* List of prefixes to try when looking for startup (crt0) files. */ - -static struct path_prefix startfile_prefixes = { 0, 0, "startfile" }; - -/* List of prefixes to try when looking for include files. */ - -static struct path_prefix include_prefixes = { 0, 0, "include" }; - -/* Suffix to attach to directories searched for commands. - This looks like `MACHINE/VERSION/'. */ - -static const char *machine_suffix = 0; - -/* Suffix to attach to directories searched for commands. - This is just `MACHINE/'. */ - -static const char *just_machine_suffix = 0; - -/* Adjusted value of GCC_EXEC_PREFIX envvar. */ - -static const char *gcc_exec_prefix; - -/* Default prefixes to attach to command names. */ - -#ifdef CROSS_COMPILE /* Don't use these prefixes for a cross compiler. */ -#undef MD_EXEC_PREFIX -#undef MD_STARTFILE_PREFIX -#undef MD_STARTFILE_PREFIX_1 -#endif - -#ifndef STANDARD_EXEC_PREFIX -#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/" -#endif /* !defined STANDARD_EXEC_PREFIX */ - -static const char *standard_exec_prefix = STANDARD_EXEC_PREFIX; -static const char *standard_exec_prefix_1 = "/usr/lib/gcc/"; -#ifdef MD_EXEC_PREFIX -static const char *md_exec_prefix = MD_EXEC_PREFIX; -#endif - -#ifndef STANDARD_STARTFILE_PREFIX -#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/" -#endif /* !defined STANDARD_STARTFILE_PREFIX */ - -#ifdef MD_STARTFILE_PREFIX -static const char *md_startfile_prefix = MD_STARTFILE_PREFIX; -#endif -#ifdef MD_STARTFILE_PREFIX_1 -static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1; -#endif -static const char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX; -static const char *standard_startfile_prefix_1 = "/lib/"; -static const char *standard_startfile_prefix_2 = "/usr/lib/"; - -#ifndef TOOLDIR_BASE_PREFIX -#define TOOLDIR_BASE_PREFIX "/usr/local/" -#endif -static const char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX; -static const char *tooldir_prefix; - -#ifndef STANDARD_BINDIR_PREFIX -#define STANDARD_BINDIR_PREFIX "/usr/local/bin" -#endif -static char *standard_bindir_prefix = STANDARD_BINDIR_PREFIX; - -/* Subdirectory to use for locating libraries. Set by - set_multilib_dir based on the compilation options. */ - -static const char *multilib_dir; - /* Clear out the vector of arguments (after a command is executed). */ static void @@ -1435,12 +1400,13 @@ clear_args () static void store_arg (arg, delete_always, delete_failure) - char *arg; + const char *arg; int delete_always, delete_failure; { if (argbuf_index + 1 == argbuf_length) argbuf - = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *)); + = (const char **) xrealloc (argbuf, + (argbuf_length *= 2) * sizeof (const char *)); argbuf[argbuf_index++] = arg; argbuf[argbuf_index] = 0; @@ -1449,27 +1415,21 @@ store_arg (arg, delete_always, delete_failure) record_temp_file (arg, delete_always, delete_failure); } -/* Read compilation specs from a file named FILENAME, - replacing the default ones. +/* Load specs from a file name named FILENAME, replacing occurances of + various different types of line-endings, \r\n, \n\r and just \r, with + a single \n. */ - A suffix which starts with `*' is a definition for - one of the machine-specific sub-specs. The "suffix" should be - *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc. - The corresponding spec is stored in asm_spec, etc., - rather than in the `compilers' vector. - - Anything invalid in the file is a fatal error. */ - -static void -read_specs (filename, main_p) +static char * +load_specs (filename) const char *filename; - int main_p; { int desc; int readlen; struct stat statbuf; char *buffer; - register char *p; + char *buffer_p; + char *specs; + char *specs_p; if (verbose_flag) notice ("Reading specs from %s\n", filename); @@ -1489,6 +1449,51 @@ read_specs (filename, main_p) buffer[readlen] = 0; close (desc); + specs = xmalloc (readlen + 1); + specs_p = specs; + for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++) + { + int skip = 0; + char c = *buffer_p; + if (c == '\r') + { + if (buffer_p > buffer && *(buffer_p - 1) == '\n') /* \n\r */ + skip = 1; + else if (*(buffer_p + 1) == '\n') /* \r\n */ + skip = 1; + else /* \r */ + c = '\n'; + } + if (! skip) + *specs_p++ = c; + } + *specs_p = '\0'; + + free (buffer); + return (specs); +} + +/* Read compilation specs from a file named FILENAME, + replacing the default ones. + + A suffix which starts with `*' is a definition for + one of the machine-specific sub-specs. The "suffix" should be + *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc. + The corresponding spec is stored in asm_spec, etc., + rather than in the `compilers' vector. + + Anything invalid in the file is a fatal error. */ + +static void +read_specs (filename, main_p) + const char *filename; + int main_p; +{ + char *buffer; + register char *p; + + buffer = load_specs (filename); + /* Scan BUFFER for specs, putting them in the vector. */ p = buffer; while (1) @@ -1511,9 +1516,10 @@ read_specs (filename, main_p) while (*p && *p != '\n') p++; - p++; /* Skip '\n' */ + /* Skip '\n'. */ + p++; - if (!strncmp (p1, "%include", sizeof ("%include")-1) + if (!strncmp (p1, "%include", sizeof ("%include") - 1) && (p1[sizeof "%include" - 1] == ' ' || p1[sizeof "%include" - 1] == '\t')) { @@ -1539,7 +1545,8 @@ read_specs (filename, main_p) char *new_filename; p1 += sizeof "%include_noerr"; - while (*p1 == ' ' || *p1 == '\t') p1++; + while (*p1 == ' ' || *p1 == '\t') + p1++; if (*p1++ != '<' || p[-2] != '>') fatal ("specs %%include syntax malformed after %ld characters", @@ -1565,12 +1572,12 @@ read_specs (filename, main_p) while (*p1 == ' ' || *p1 == '\t') p1++; - if (! ISALPHA ((unsigned char)*p1)) + if (! ISALPHA ((unsigned char) *p1)) fatal ("specs %%rename syntax malformed after %ld characters", (long) (p1 - buffer)); p2 = p1; - while (*p2 && !ISSPACE ((unsigned char)*p2)) + while (*p2 && !ISSPACE ((unsigned char) *p2)) p2++; if (*p2 != ' ' && *p2 != '\t') @@ -1582,16 +1589,16 @@ read_specs (filename, main_p) while (*p2 == ' ' || *p2 == '\t') p2++; - if (! ISALPHA ((unsigned char)*p2)) + if (! ISALPHA ((unsigned char) *p2)) fatal ("specs %%rename syntax malformed after %ld characters", (long) (p2 - buffer)); - /* Get new spec name */ + /* Get new spec name. */ p3 = p2; - while (*p3 && !ISSPACE ((unsigned char)*p3)) + while (*p3 && !ISSPACE ((unsigned char) *p3)) p3++; - if (p3 != p-1) + if (p3 != p - 1) fatal ("specs %%rename syntax malformed after %ld characters", (long) (p3 - buffer)); *p3 = '\0'; @@ -1616,7 +1623,7 @@ read_specs (filename, main_p) set_spec (p2, *(sl->ptr_spec)); if (sl->alloc_p) - free (*(sl->ptr_spec)); + free ((PTR) *(sl->ptr_spec)); *(sl->ptr_spec) = ""; sl->alloc_p = 0; @@ -1691,9 +1698,7 @@ read_specs (filename, main_p) (n_compilers + 2) * sizeof (struct compiler))); compilers[n_compilers].suffix = suffix; - memset (compilers[n_compilers].spec, 0, - sizeof compilers[n_compilers].spec); - compilers[n_compilers].spec[0] = spec; + compilers[n_compilers].spec = spec; n_compilers++; memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]); } @@ -1711,7 +1716,7 @@ read_specs (filename, main_p) /* This is the common prefix we use to make temp file names. It is chosen once for each run of this program. - It is substituted into a spec by %g. + It is substituted into a spec by %g or %j. Thus, all temp file names contain this prefix. In practice, all temp file names start with this prefix. @@ -1751,7 +1756,7 @@ record_temp_file (filename, always_delete, fail_delete) int always_delete; int fail_delete; { - register char * const name = xstrdup (filename); + register char *const name = xstrdup (filename); if (always_delete) { @@ -1880,16 +1885,15 @@ putenv (str) } /* Add a new environment variable */ - environ = (char **) xmalloc (sizeof (char *) * (num_envs+2)); + environ = (char **) xmalloc (sizeof (char *) * (num_envs + 2)); *environ = str; memcpy ((char *) (environ + 1), (char *) old_environ, - sizeof (char *) * (num_envs+1)); + sizeof (char *) * (num_envs + 1)); #endif /* VMS */ } -#endif /* HAVE_PUTENV */ - +#endif /* HAVE_PUTENV */ /* Build a list of search directories from PATHS. PREFIX is a string to prepend to the list. @@ -1910,6 +1914,7 @@ build_search_list (paths, prefix, check_dir_p) struct prefix_list *pprefix; obstack_grow (&collect_obstack, prefix, strlen (prefix)); + obstack_1grow (&collect_obstack, '='); for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next) { @@ -1921,7 +1926,7 @@ build_search_list (paths, prefix, check_dir_p) { if (!first_time) obstack_1grow (&collect_obstack, PATH_SEPARATOR); - + first_time = FALSE; obstack_grow (&collect_obstack, pprefix->prefix, len); obstack_grow (&collect_obstack, machine_suffix, suffix_len); @@ -1934,7 +1939,7 @@ build_search_list (paths, prefix, check_dir_p) { if (! first_time) obstack_1grow (&collect_obstack, PATH_SEPARATOR); - + first_time = FALSE; obstack_grow (&collect_obstack, pprefix->prefix, len); obstack_grow (&collect_obstack, just_machine_suffix, @@ -2051,7 +2056,7 @@ free_split_directories (dirs) while (dirs[i] != NULL_PTR) free (dirs[i++]); - free ((char *)dirs); + free ((char *) dirs); } /* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string that gets @@ -2060,7 +2065,7 @@ free_split_directories (dirs) For example, if BIN_PREFIX is /alpha/beta/gamma/gcc/delta, PREFIX is /alpha/beta/gamma/omega/, and PROGNAME is /red/green/blue/gcc, then this - function will return /reg/green/blue/../omega. + function will return /red/green/blue/../omega. If no relative prefix can be found, return NULL. */ @@ -2102,14 +2107,14 @@ make_relative_prefix (progname, bin_prefix, prefix) } else { - strncpy (nstore, startp, endp-startp); + strncpy (nstore, startp, endp - startp); if (! IS_DIR_SEPARATOR (endp[-1])) { - nstore[endp-startp] = DIR_SEPARATOR; - nstore[endp-startp+1] = 0; + nstore[endp - startp] = DIR_SEPARATOR; + nstore[endp - startp + 1] = 0; } else - nstore[endp-startp] = 0; + nstore[endp - startp] = 0; } strcat (nstore, progname); if (! access (nstore, X_OK) @@ -2154,14 +2159,14 @@ make_relative_prefix (progname, bin_prefix, prefix) std_loc_p = 1; free_split_directories (prog_dirs); free_split_directories (bin_dirs); - prog_dirs = bin_dirs = (char **)0; + prog_dirs = bin_dirs = (char **) 0; return NULL_PTR; } } prefix_dirs = split_directories (prefix, &prefix_num); - /* Find how many directories are in common between bin_prefix & prefix */ + /* Find how many directories are in common between bin_prefix & prefix. */ n = (prefix_num < bin_num) ? prefix_num : bin_num; for (common = 0; common < n; common++) { @@ -2185,7 +2190,7 @@ make_relative_prefix (progname, bin_prefix, prefix) /* Now build up the ..'s. */ for (i = common; i < n; i++) { - obstack_grow (&obstack, DIR_UP, sizeof (DIR_UP)-1); + obstack_grow (&obstack, DIR_UP, sizeof (DIR_UP) - 1); obstack_1grow (&obstack, DIR_SEPARATOR); } @@ -2238,7 +2243,7 @@ find_a_file (pprefix, name, mode) int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1; #ifdef DEFAULT_ASSEMBLER - if (! strcmp(name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) + if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) return xstrdup (DEFAULT_ASSEMBLER); #endif @@ -2254,12 +2259,7 @@ find_a_file (pprefix, name, mode) /* Determine the filename to execute (special case for absolute paths). */ - if (IS_DIR_SEPARATOR (*name) -#ifdef HAVE_DOS_BASED_FILE_SYSTEM - /* Check for disk name on MS-DOS-based systems. */ - || (name[0] && name[1] == ':' && IS_DIR_SEPARATOR (name[2])) -#endif - ) + if (IS_ABSOLUTE_PATHNAME (name)) { if (access (name, mode) == 0) { @@ -2365,8 +2365,18 @@ find_a_file (pprefix, name, mode) return 0; } -/* Add an entry for PREFIX in PLIST. If FIRST is set, it goes - at the start of the list, otherwise it goes at the end. +/* Ranking of prefixes in the sort list. -B prefixes are put before + all others. */ + +enum path_prefix_priority +{ + PREFIX_PRIORITY_B_OPT, + PREFIX_PRIORITY_LAST +}; + +/* Add an entry for PREFIX in PLIST. The PLIST is kept in assending + order according to PRIORITY. Within each PRIORITY, new entries are + appended. If WARN is nonzero, we will warn if no file is found through this prefix. WARN should point to an int @@ -2379,25 +2389,21 @@ find_a_file (pprefix, name, mode) 2 means try both machine_suffix and just_machine_suffix. */ static void -add_prefix (pprefix, prefix, component, first, require_machine_suffix, warn) +add_prefix (pprefix, prefix, component, priority, require_machine_suffix, warn) struct path_prefix *pprefix; const char *prefix; const char *component; - int first; + /* enum prefix_priority */ int priority; int require_machine_suffix; int *warn; { struct prefix_list *pl, **prev; int len; - if (! first && pprefix->plist) - { - for (pl = pprefix->plist; pl->next; pl = pl->next) - ; - prev = &pl->next; - } - else - prev = &pprefix->plist; + for (prev = &pprefix->plist; + (*prev) != NULL && (*prev)->priority <= priority; + prev = &(*prev)->next) + ; /* Keep track of the longest prefix */ @@ -2410,42 +2416,14 @@ add_prefix (pprefix, prefix, component, first, require_machine_suffix, warn) pl->prefix = save_string (prefix, len); pl->require_machine_suffix = require_machine_suffix; pl->used_flag_ptr = warn; + pl->priority = priority; if (warn) *warn = 0; - if (*prev) - pl->next = *prev; - else - pl->next = (struct prefix_list *) 0; - *prev = pl; -} - -/* Print warnings for any prefixes in the list PPREFIX that were not used. */ - -static void -unused_prefix_warnings (pprefix) - struct path_prefix *pprefix; -{ - struct prefix_list *pl = pprefix->plist; - - while (pl) - { - if (pl->used_flag_ptr != 0 && !*pl->used_flag_ptr) - { - if (pl->require_machine_suffix && machine_suffix) - error ("file path prefix `%s%s' never used", pl->prefix, - machine_suffix); - else - error ("file path prefix `%s' never used", pl->prefix); - - /* Prevent duplicate warnings. */ - *pl->used_flag_ptr = 1; - } - - pl = pl->next; - } + /* Insert after PREV */ + pl->next = (*prev); + (*prev) = pl; } - /* Execute the command specified by the arguments on the current line of spec. When using pipes, this includes several piped-together commands @@ -2460,11 +2438,11 @@ execute () int n_commands; /* # of command. */ char *string; struct command - { - const char *prog; /* program name. */ - char **argv; /* vector of args. */ - int pid; /* pid of process for this command. */ - }; + { + const char *prog; /* program name. */ + const char **argv; /* vector of args. */ + int pid; /* pid of process for this command. */ + }; struct command *commands; /* each command buffer with above info. */ @@ -2474,8 +2452,7 @@ execute () n_commands++; /* Get storage for each command. */ - commands - = (struct command *) alloca (n_commands * sizeof (struct command)); + commands = (struct command *) alloca (n_commands * sizeof (struct command)); /* Split argbuf into its separate piped processes, and record info about each one. @@ -2492,7 +2469,7 @@ execute () if (strcmp (argbuf[i], "|") == 0) { /* each command. */ #if defined (__MSDOS__) || defined (OS2) || defined (VMS) - fatal ("-pipe not supported"); + fatal ("-pipe not supported"); #endif argbuf[i] = 0; /* termination of command args. */ commands[n_commands].prog = argbuf[i + 1]; @@ -2512,11 +2489,11 @@ execute () /* For help listings, put a blank line between sub-processes. */ if (print_help_list) fputc ('\n', stderr); - + /* Print each piped command as a separate line. */ - for (i = 0; i < n_commands ; i++) + for (i = 0; i < n_commands; i++) { - char **j; + const char *const *j; for (j = commands[i].argv; *j; j++) fprintf (stderr, " %s", *j); @@ -2545,9 +2522,11 @@ execute () for (i = 0; i < n_commands; i++) { char *errmsg_fmt, *errmsg_arg; - char *string = commands[i].argv[0]; + const char *string = commands[i].argv[0]; - commands[i].pid = pexecute (string, commands[i].argv, + /* For some bizarre reason, the second argument of execvp() is + char *const *, not const char *const *. */ + commands[i].pid = pexecute (string, (char *const *) commands[i].argv, programname, temp_filename, &errmsg_fmt, &errmsg_arg, ((i == 0 ? PEXECUTE_FIRST : 0) @@ -2560,7 +2539,7 @@ execute () pfatal_pexecute (errmsg_fmt, errmsg_arg); if (string != commands[i].prog) - free (string); + free ((PTR) string); } execution_count++; @@ -2578,7 +2557,7 @@ execute () double ut = 0.0, st = 0.0; #endif - for (i = 0; i < n_commands; ) + for (i = 0; i < n_commands;) { int j; int status; @@ -2599,11 +2578,11 @@ execute () getrusage (RUSAGE_CHILDREN, &rus); d.tv_sec = rus.ru_utime.tv_sec - prus.ru_utime.tv_sec; d.tv_usec = rus.ru_utime.tv_usec - prus.ru_utime.tv_usec; - ut = (double)d.tv_sec + (double)d.tv_usec / 1.0e6; - + ut = (double) d.tv_sec + (double) d.tv_usec / 1.0e6; + d.tv_sec = rus.ru_stime.tv_sec - prus.ru_stime.tv_sec; d.tv_usec = rus.ru_stime.tv_usec - prus.ru_stime.tv_usec; - st = (double)d.tv_sec + (double)d.tv_usec / 1.0e6; + st = (double) d.tv_sec + (double) d.tv_usec / 1.0e6; } #endif @@ -2611,22 +2590,35 @@ execute () if (commands[j].pid == pid) { i++; - if (status != 0) + if (WIFSIGNALED (status)) { - if (WIFSIGNALED (status)) - { - fatal ("Internal compiler error: program %s got fatal signal %d", - commands[j].prog, WTERMSIG (status)); - signal_count++; - ret_code = -1; - } - else if (WIFEXITED (status) - && WEXITSTATUS (status) >= MIN_FATAL_STATUS) - { - if (WEXITSTATUS (status) > greatest_status) - greatest_status = WEXITSTATUS (status); - ret_code = -1; - } +#ifdef SIGPIPE + /* SIGPIPE is a special case. It happens in -pipe mode + when the compiler dies before the preprocessor is + done, or the assembler dies before the compiler is + done. There's generally been an error already, and + this is just fallout. So don't generate another error + unless we would otherwise have succeeded. */ + if (WTERMSIG (status) == SIGPIPE + && (signal_count || greatest_status >= MIN_FATAL_STATUS)) + ; + else +#endif + fatal ("\ +Internal error: %s (program %s)\n\ +Please submit a full bug report.\n\ +See %s for instructions.", + strsignal (WTERMSIG (status)), commands[j].prog, + GCCBUGURL); + signal_count++; + ret_code = -1; + } + else if (WIFEXITED (status) + && WEXITSTATUS (status) >= MIN_FATAL_STATUS) + { + if (WEXITSTATUS (status) > greatest_status) + greatest_status = WEXITSTATUS (status); + ret_code = -1; } #ifdef HAVE_GETRUSAGE if (report_times && ut + st != 0) @@ -2645,15 +2637,23 @@ execute () If a switch uses following arguments, then the `part1' field is the switch itself and the `args' field is a null-terminated vector containing the following arguments. - The `live_cond' field is 1 if the switch is true in a conditional spec, - -1 if false (overridden by a later switch), and is initialized to zero. + The `live_cond' field is: + 0 when initialized + 1 if the switch is true in a conditional spec, + -1 if false (overridden by a later switch) + -2 if this switch should be ignored (used in %{ Display the full path to library \n"); - printf (" -print-prog-name= Display the full path to compiler component \n"); - printf (" -print-multi-directory Display the root directory for versions of libgcc\n"); - printf (" -print-multi-lib Display the mapping between command line options and\n"); - printf (" multiple library search directories\n"); - printf (" -Wa, Pass comma-separated on to the assembler\n"); - printf (" -Wp, Pass comma-separated on to the preprocessor\n"); - printf (" -Wl, Pass comma-separated on to the linker\n"); - printf (" -Xlinker Pass on to the linker\n"); - printf (" -save-temps Do not delete intermediate files\n"); - printf (" -pipe Use pipes rather than intermediate files\n"); - printf (" -time Time the execution of each subprocess\n"); - printf (" -specs= Override builtin specs with the contents of \n"); - printf (" -std= Assume that the input sources are for \n"); - printf (" -B Add to the compiler's search paths\n"); - printf (" -b Run gcc for target , if installed\n"); - printf (" -V Run gcc version number , if installed\n"); - printf (" -v Display the programs invoked by the compiler\n"); - printf (" -E Preprocess only; do not compile, assemble or link\n"); - printf (" -S Compile only; do not assemble or link\n"); - printf (" -c Compile and assemble, but do not link\n"); - printf (" -o Place the output into \n"); - printf (" -x Specify the language of the following input files\n"); - printf (" Permissable languages include: c c++ assembler none\n"); - printf (" 'none' means revert to the default behaviour of\n"); - printf (" guessing the language based on the file's extension\n"); - - printf ("\nOptions starting with -g, -f, -m, -O or -W are automatically passed on to\n"); - printf ("the various sub-processes invoked by %s. In order to pass other options\n", - programname); - printf ("on to these processes the -W options must be used.\n"); + fputs (_(" (Use '-v --help' to display command line options of sub-processes)\n"), stdout); + fputs (_(" -dumpspecs Display all of the built in spec strings\n"), stdout); + fputs (_(" -dumpversion Display the version of the compiler\n"), stdout); + fputs (_(" -dumpmachine Display the compiler's target processor\n"), stdout); + fputs (_(" -print-search-dirs Display the directories in the compiler's search path\n"), stdout); + fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library\n"), stdout); + fputs (_(" -print-file-name= Display the full path to library \n"), stdout); + fputs (_(" -print-prog-name= Display the full path to compiler component \n"), stdout); + fputs (_(" -print-multi-directory Display the root directory for versions of libgcc\n"), stdout); + fputs (_("\ + -print-multi-lib Display the mapping between command line options and\n\ + multiple library search directories\n"), stdout); + fputs (_(" -Wa, Pass comma-separated on to the assembler\n"), stdout); + fputs (_(" -Wp, Pass comma-separated on to the preprocessor\n"), stdout); + fputs (_(" -Wl, Pass comma-separated on to the linker\n"), stdout); + fputs (_(" -Xlinker Pass on to the linker\n"), stdout); + fputs (_(" -save-temps Do not delete intermediate files\n"), stdout); + fputs (_(" -pipe Use pipes rather than intermediate files\n"), stdout); + fputs (_(" -time Time the execution of each subprocess\n"), stdout); + fputs (_(" -specs= Override builtin specs with the contents of \n"), stdout); + fputs (_(" -std= Assume that the input sources are for \n"), stdout); + fputs (_(" -B Add to the compiler's search paths\n"), stdout); + fputs (_(" -b Run gcc for target , if installed\n"), stdout); + fputs (_(" -V Run gcc version number , if installed\n"), stdout); + fputs (_(" -v Display the programs invoked by the compiler\n"), stdout); + fputs (_(" -E Preprocess only; do not compile, assemble or link\n"), stdout); + fputs (_(" -S Compile only; do not assemble or link\n"), stdout); + fputs (_(" -c Compile and assemble, but do not link\n"), stdout); + fputs (_(" -o Place the output into \n"), stdout); + fputs (_("\ + -x Specify the language of the following input files\n\ + Permissable languages include: c c++ assembler none\n\ + 'none' means revert to the default behaviour of\n\ + guessing the language based on the file's extension\n\ +"), stdout); + + printf (_("\ +\nOptions starting with -g, -f, -m, -O or -W are automatically passed on to\n\ +the various sub-processes invoked by %s. In order to pass other options\n\ +on to these processes the -W options must be used.\n\ +"), programname); /* The rest of the options are displayed by invocations of the various sub-processes. */ } -static void -add_preprocessor_option (option, len) - const char * option; +static void +add_preprocessor_option (option, len) + const char *option; int len; -{ +{ n_preprocessor_options++; - + if (! preprocessor_options) preprocessor_options = (char **) xmalloc (n_preprocessor_options * sizeof (char *)); @@ -2812,14 +2816,14 @@ add_preprocessor_option (option, len) preprocessor_options = (char **) xrealloc (preprocessor_options, n_preprocessor_options * sizeof (char *)); - + preprocessor_options [n_preprocessor_options - 1] = save_string (option, len); } - -static void -add_assembler_option (option, len) - const char * option; + +static void +add_assembler_option (option, len) + const char *option; int len; { n_assembler_options++; @@ -2834,11 +2838,11 @@ add_assembler_option (option, len) assembler_options [n_assembler_options - 1] = save_string (option, len); } - -static void -add_linker_option (option, len) - const char * option; - int len; + +static void +add_linker_option (option, len) + const char *option; + int len; { n_linker_options++; @@ -2859,16 +2863,20 @@ add_linker_option (option, len) static void process_command (argc, argv) int argc; - char **argv; + const char *const *argv; { register int i; const char *temp; char *temp1; - char *spec_lang = 0; + const char *spec_lang = 0; int last_language_n_infiles; int have_c = 0; int have_o = 0; int lang_n_infiles = 0; +#ifdef MODIFY_TARGET_NAME + int is_modify_target_name; + int j; +#endif GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX"); @@ -2878,7 +2886,7 @@ process_command (argc, argv) /* Figure compiler version from version string. */ - compiler_version = temp1 = xstrdup (version_string); + compiler_version = temp1 = xstrdup (version_string); for (; *temp1; ++temp1) { @@ -2906,20 +2914,23 @@ process_command (argc, argv) if (gcc_exec_prefix) { int len = strlen (gcc_exec_prefix); - if (len > (int) sizeof ("/lib/gcc-lib/")-1 + + if (len > (int) sizeof ("/lib/gcc-lib/") - 1 && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1]))) { temp = gcc_exec_prefix + len - sizeof ("/lib/gcc-lib/") + 1; if (IS_DIR_SEPARATOR (*temp) - && strncmp (temp+1, "lib", 3) == 0 + && strncmp (temp + 1, "lib", 3) == 0 && IS_DIR_SEPARATOR (temp[4]) - && strncmp (temp+5, "gcc-lib", 7) == 0) + && strncmp (temp + 5, "gcc-lib", 7) == 0) len -= sizeof ("/lib/gcc-lib/") - 1; } set_std_prefix (gcc_exec_prefix, len); - add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR); - add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", 0, 0, NULL_PTR); + add_prefix (&exec_prefixes, gcc_exec_prefix, "GCC", + PREFIX_PRIORITY_LAST, 0, NULL_PTR); + add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC", + PREFIX_PRIORITY_LAST, 0, NULL_PTR); } /* COMPILER_PATH and LIBRARY_PATH have values @@ -2936,20 +2947,21 @@ process_command (argc, argv) { if (*endp == PATH_SEPARATOR || *endp == 0) { - strncpy (nstore, startp, endp-startp); + strncpy (nstore, startp, endp - startp); if (endp == startp) strcpy (nstore, concat (".", dir_separator_str, NULL_PTR)); else if (!IS_DIR_SEPARATOR (endp[-1])) { - nstore[endp-startp] = DIR_SEPARATOR; - nstore[endp-startp+1] = 0; + nstore[endp - startp] = DIR_SEPARATOR; + nstore[endp - startp + 1] = 0; } else - nstore[endp-startp] = 0; - add_prefix (&exec_prefixes, nstore, 0, 0, 0, NULL_PTR); + nstore[endp - startp] = 0; + add_prefix (&exec_prefixes, nstore, 0, + PREFIX_PRIORITY_LAST, 0, NULL_PTR); add_prefix (&include_prefixes, concat (nstore, "include", NULL_PTR), - 0, 0, 0, NULL_PTR); + 0, PREFIX_PRIORITY_LAST, 0, NULL_PTR); if (*endp == 0) break; endp = startp = endp + 1; @@ -2959,7 +2971,7 @@ process_command (argc, argv) } } - GET_ENV_PATH_LIST (temp, "LIBRARY_PATH"); + GET_ENV_PATH_LIST (temp, LIBRARY_PATH_ENV); if (temp && *cross_compile == '0') { const char *startp, *endp; @@ -2970,18 +2982,18 @@ process_command (argc, argv) { if (*endp == PATH_SEPARATOR || *endp == 0) { - strncpy (nstore, startp, endp-startp); + strncpy (nstore, startp, endp - startp); if (endp == startp) strcpy (nstore, concat (".", dir_separator_str, NULL_PTR)); else if (!IS_DIR_SEPARATOR (endp[-1])) { - nstore[endp-startp] = DIR_SEPARATOR; - nstore[endp-startp+1] = 0; + nstore[endp - startp] = DIR_SEPARATOR; + nstore[endp - startp + 1] = 0; } else - nstore[endp-startp] = 0; + nstore[endp - startp] = 0; add_prefix (&startfile_prefixes, nstore, NULL_PTR, - 0, 0, NULL_PTR); + PREFIX_PRIORITY_LAST, 0, NULL_PTR); if (*endp == 0) break; endp = startp = endp + 1; @@ -3003,18 +3015,18 @@ process_command (argc, argv) { if (*endp == PATH_SEPARATOR || *endp == 0) { - strncpy (nstore, startp, endp-startp); + strncpy (nstore, startp, endp - startp); if (endp == startp) strcpy (nstore, concat (".", dir_separator_str, NULL_PTR)); else if (!IS_DIR_SEPARATOR (endp[-1])) { - nstore[endp-startp] = DIR_SEPARATOR; - nstore[endp-startp+1] = 0; + nstore[endp - startp] = DIR_SEPARATOR; + nstore[endp - startp + 1] = 0; } else - nstore[endp-startp] = 0; + nstore[endp - startp] = 0; add_prefix (&startfile_prefixes, nstore, NULL_PTR, - 0, 0, NULL_PTR); + PREFIX_PRIORITY_LAST, 0, NULL_PTR); if (*endp == 0) break; endp = startp = endp + 1; @@ -3032,6 +3044,7 @@ process_command (argc, argv) /* Scan argv twice. Here, the first time, just count how many switches there will be in their vector, and how many input files in theirs. + Also parse any switches that determine the configuration name, such as -b. Here we also parse the switches that cc itself uses (e.g. -v). */ for (i = 1; i < argc; i++) @@ -3042,8 +3055,8 @@ process_command (argc, argv) init_spec (); for (sl = specs; sl; sl = sl->next) printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec)); - if (link_command_spec) - printf ("*link_command:\n%s\n\n", link_command_spec); + if (link_command_spec) + printf ("*link_command:\n%s\n\n", link_command_spec); exit (0); } else if (! strcmp (argv[i], "-dumpversion")) @@ -3054,7 +3067,7 @@ process_command (argc, argv) else if (! strcmp (argv[i], "-dumpmachine")) { printf ("%s\n", spec_machine); - exit (0); + exit (0); } else if (strcmp (argv[i], "-fhelp") == 0) { @@ -3064,11 +3077,24 @@ process_command (argc, argv) /* We will be passing a dummy file on to the sub-processes. */ n_infiles++; n_switches++; - + add_preprocessor_option ("--help", 6); add_assembler_option ("--help", 6); add_linker_option ("--help", 6); } + else if (strcmp (argv[i], "-ftarget-help") == 0) + { + /* translate_options() has turned --target-help into -ftarget-help. */ + target_help_flag = 1; + + /* We will be passing a dummy file on to the sub-processes. */ + n_infiles++; + n_switches++; + + add_preprocessor_option ("--target-help", 13); + add_assembler_option ("--target-help", 13); + add_linker_option ("--target-help", 13); + } else if (! strcmp (argv[i], "-pass-exit-codes")) { pass_exit_codes = 1; @@ -3099,7 +3125,7 @@ process_command (argc, argv) add_assembler_option (argv[i] + prev, j - prev); prev = j + 1; } - + /* Record the part after the last comma. */ add_assembler_option (argv[i] + prev, j - prev); } @@ -3116,7 +3142,7 @@ process_command (argc, argv) add_preprocessor_option (argv[i] + prev, j - prev); prev = j + 1; } - + /* Record the part after the last comma. */ add_preprocessor_option (argv[i] + prev, j - prev); } @@ -3152,7 +3178,7 @@ process_command (argc, argv) if (++i >= argc) fatal ("argument to `-specs' is missing"); - user->next = (struct user_specs *)0; + user->next = (struct user_specs *) 0; user->filename = argv[i]; if (user_specs_tail) user_specs_tail->next = user; @@ -3167,8 +3193,8 @@ process_command (argc, argv) if (strlen (argv[i]) == 7) fatal ("argument to `-specs=' is missing"); - user->next = (struct user_specs *)0; - user->filename = argv[i]+7; + user->next = (struct user_specs *) 0; + user->filename = argv[i] + 7; if (user_specs_tail) user_specs_tail->next = user; else @@ -3179,13 +3205,13 @@ process_command (argc, argv) report_times = 1; else if (argv[i][0] == '-' && argv[i][1] != 0) { - register char *p = &argv[i][1]; + register const char *p = &argv[i][1]; register int c = *p; switch (c) { case 'b': - n_switches++; + n_switches++; if (p[1] == 0 && i + 1 == argc) fatal ("argument to `-b' is missing"); if (p[1] == 0) @@ -3198,23 +3224,16 @@ process_command (argc, argv) case 'B': { - char *value; + const char *value; if (p[1] == 0 && i + 1 == argc) fatal ("argument to `-B' is missing"); if (p[1] == 0) value = argv[++i]; else value = p + 1; - add_prefix (&exec_prefixes, value, NULL_PTR, 1, 0, &warn_B); - add_prefix (&startfile_prefixes, value, NULL_PTR, - 1, 0, &warn_B); - add_prefix (&include_prefixes, concat (value, "include", - NULL_PTR), - NULL_PTR, 1, 0, NULL_PTR); - - /* As a kludge, if the arg is "[foo/]stageN/", just add - "[foo/]include" to the include prefix. */ { + /* As a kludge, if the arg is "[foo/]stageN/", just + add "[foo/]include" to the include prefix. */ int len = strlen (value); if ((len == 7 || (len > 7 @@ -3225,18 +3244,26 @@ process_command (argc, argv) { if (len == 7) add_prefix (&include_prefixes, "include", NULL_PTR, - 1, 0, NULL_PTR); + PREFIX_PRIORITY_B_OPT, 0, NULL_PTR); else { char *string = xmalloc (len + 1); strncpy (string, value, len-7); strcpy (string+len-7, "include"); add_prefix (&include_prefixes, string, NULL_PTR, - 1, 0, NULL_PTR); + PREFIX_PRIORITY_B_OPT, 0, NULL_PTR); } } } - n_switches++; + add_prefix (&exec_prefixes, value, NULL_PTR, + PREFIX_PRIORITY_B_OPT, 0, &warn_B); + add_prefix (&startfile_prefixes, value, NULL_PTR, + PREFIX_PRIORITY_B_OPT, 0, &warn_B); + add_prefix (&include_prefixes, concat (value, "include", + NULL_PTR), + NULL_PTR, + PREFIX_PRIORITY_B_OPT, 0, NULL_PTR); + n_switches++; } break; @@ -3307,7 +3334,7 @@ process_command (argc, argv) if (! have_c) { int skip; - + /* Forward scan, just in case -S or -c is specified after -o. */ int j = i + 1; @@ -3334,7 +3361,7 @@ process_command (argc, argv) #endif #if defined(HAVE_EXECUTABLE_SUFFIX) || defined(HAVE_OBJECT_SUFFIX) if (p[1] == 0) - argv[i+1] = convert_filename (argv[i+1], ! have_c); + argv[i + 1] = convert_filename (argv[i + 1], ! have_c); else argv[i] = convert_filename (argv[i], ! have_c); #endif @@ -3342,6 +3369,46 @@ process_command (argc, argv) default: normal_switch: + +#ifdef MODIFY_TARGET_NAME + is_modify_target_name = 0; + + for (j = 0; + j < sizeof modify_target / sizeof modify_target[0]; j++) + if (! strcmp (argv[i], modify_target[j].sw)) + { + char *new_name + = (char *) xmalloc (strlen (modify_target[j].str) + + strlen (spec_machine)); + const char *p, *r; + char *q; + int made_addition = 0; + + is_modify_target_name = 1; + for (p = spec_machine, q = new_name; *p != 0; ) + { + if (modify_target[j].add_del == DELETE + && (! strncmp (q, modify_target[j].str, + strlen (modify_target[j].str)))) + p += strlen (modify_target[j].str); + else if (modify_target[j].add_del == ADD + && ! made_addition && *p == '-') + { + for (r = modify_target[j].str; *r != 0; ) + *q++ = *r++; + made_addition = 1; + } + + *q++ = *p++; + } + + spec_machine = new_name; + } + + if (is_modify_target_name) + break; +#endif + n_switches++; if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) @@ -3368,19 +3435,19 @@ process_command (argc, argv) as well as trying the machine and the version. */ #ifndef OS2 add_prefix (&exec_prefixes, standard_exec_prefix, "GCC", - 0, 1, warn_std_ptr); + PREFIX_PRIORITY_LAST, 1, warn_std_ptr); add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS", - 0, 2, warn_std_ptr); + PREFIX_PRIORITY_LAST, 2, warn_std_ptr); add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS", - 0, 2, warn_std_ptr); + PREFIX_PRIORITY_LAST, 2, warn_std_ptr); #endif add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS", - 0, 1, warn_std_ptr); + PREFIX_PRIORITY_LAST, 1, warn_std_ptr); add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS", - 0, 1, warn_std_ptr); + PREFIX_PRIORITY_LAST, 1, warn_std_ptr); - tooldir_prefix = concat (tooldir_base_prefix, spec_machine, + tooldir_prefix = concat (tooldir_base_prefix, spec_machine, dir_separator_str, NULL_PTR); /* If tooldir is relative, base it on exec_prefixes. A relative @@ -3390,7 +3457,7 @@ process_command (argc, argv) directories, so that we can search both the user specified directory and the standard place. */ - if (!IS_DIR_SEPARATOR (*tooldir_prefix)) + if (!IS_ABSOLUTE_PATHNAME (tooldir_prefix)) { if (gcc_exec_prefix) { @@ -3399,31 +3466,30 @@ process_command (argc, argv) spec_version, dir_separator_str, tooldir_prefix, NULL_PTR); add_prefix (&exec_prefixes, - concat (gcc_exec_tooldir_prefix, "bin", + concat (gcc_exec_tooldir_prefix, "bin", dir_separator_str, NULL_PTR), - NULL_PTR, 0, 0, NULL_PTR); + NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR); add_prefix (&startfile_prefixes, - concat (gcc_exec_tooldir_prefix, "lib", + concat (gcc_exec_tooldir_prefix, "lib", dir_separator_str, NULL_PTR), - NULL_PTR, 0, 0, NULL_PTR); + NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR); } tooldir_prefix = concat (standard_exec_prefix, spec_machine, - dir_separator_str, spec_version, + dir_separator_str, spec_version, dir_separator_str, tooldir_prefix, NULL_PTR); } - add_prefix (&exec_prefixes, - concat (tooldir_prefix, "bin", dir_separator_str, NULL_PTR), - "BINUTILS", 0, 0, NULL_PTR); + add_prefix (&exec_prefixes, + concat (tooldir_prefix, "bin", dir_separator_str, NULL_PTR), + "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR); add_prefix (&startfile_prefixes, concat (tooldir_prefix, "lib", dir_separator_str, NULL_PTR), - "BINUTILS", 0, 0, NULL_PTR); + "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR); /* More prefixes are enabled in main, after we read the specs file and determine whether this is cross-compilation or not. */ - /* Then create the space for the vectors and scan again. */ switches = ((struct switchstr *) @@ -3440,6 +3506,17 @@ process_command (argc, argv) for (i = 1; i < argc; i++) { /* Just skip the switches that were handled by the preceding loop. */ +#ifdef MODIFY_TARGET_NAME + is_modify_target_name = 0; + + for (j = 0; j < sizeof modify_target / sizeof modify_target[0]; j++) + if (! strcmp (argv[i], modify_target[j].sw)) + is_modify_target_name = 1; + + if (is_modify_target_name) + ; + else +#endif if (! strncmp (argv[i], "-Wa,", 4)) ; else if (! strncmp (argv[i], "-Wp,", 4)) @@ -3458,6 +3535,22 @@ process_command (argc, argv) ; else if (! strcmp (argv[i], "-print-multi-directory")) ; + else if (strcmp (argv[i], "-ftarget-help") == 0) + { + /* Create a dummy input file, so that we can pass --target-help on to + the various sub-processes. */ + infiles[n_infiles].language = "c"; + infiles[n_infiles++].name = "target-dummy"; + + /* Preserve the --target-help switch so that it can be caught by + the cc1 spec string. */ + switches[n_switches].part1 = "--target-help"; + switches[n_switches].args = 0; + switches[n_switches].live_cond = SWITCH_OK; + switches[n_switches].validated = 0; + + n_switches++; + } else if (strcmp (argv[i], "-fhelp") == 0) { if (verbose_flag) @@ -3466,14 +3559,14 @@ process_command (argc, argv) the various sub-processes. */ infiles[n_infiles].language = "c"; infiles[n_infiles++].name = "help-dummy"; - + /* Preserve the --help switch so that it can be caught by the cc1 spec string. */ switches[n_switches].part1 = "--help"; switches[n_switches].args = 0; - switches[n_switches].live_cond = 0; + switches[n_switches].live_cond = SWITCH_OK; switches[n_switches].validated = 0; - + n_switches++; } } @@ -3486,7 +3579,7 @@ process_command (argc, argv) -e0 or -e1 down into the linker. */ switches[n_switches].part1 = &argv[i][0]; switches[n_switches].args = 0; - switches[n_switches].live_cond = 0; + switches[n_switches].live_cond = SWITCH_OK; switches[n_switches].validated = 0; n_switches++; } @@ -3528,16 +3621,16 @@ process_command (argc, argv) { /* -save-temps overrides -pipe, so that temp files are produced */ if (save_temps_flag) - error ("Warning: -pipe ignored since -save-temps specified"); + error ("Warning: -pipe ignored because -save-temps specified"); /* -time overrides -pipe because we can't get correct stats when multiple children are running at once. */ else if (report_times) - error ("Warning: -pipe ignored since -time specified"); + error ("Warning: -pipe ignored because -time specified"); } else if (argv[i][0] == '-' && argv[i][1] != 0) { - register char *p = &argv[i][1]; - register int c = *p; + const char *p = &argv[i][1]; + int c = *p; if (c == 'x') { @@ -3572,40 +3665,42 @@ process_command (argc, argv) if (i + n_args >= argc) fatal ("argument to `-%s' is missing", p); switches[n_switches].args - = (char **) xmalloc ((n_args + 1) * sizeof (char *)); + = (const char **) xmalloc ((n_args + 1) * sizeof(const char *)); while (j < n_args) switches[n_switches].args[j++] = argv[++i]; /* Null-terminate the vector. */ switches[n_switches].args[j] = 0; } - else if (index (switches_need_spaces, c)) + else if (strchr (switches_need_spaces, c)) { /* On some systems, ld cannot handle some options without a space. So split the option from its argument. */ char *part1 = (char *) xmalloc (2); + char *tmp; part1[0] = c; part1[1] = '\0'; - + switches[n_switches].part1 = part1; - switches[n_switches].args = (char **) xmalloc (2 * sizeof (char *)); - switches[n_switches].args[0] = xmalloc (strlen (p)); - strcpy (switches[n_switches].args[0], &p[1]); + switches[n_switches].args + = (const char **) xmalloc (2 * sizeof (const char *)); + switches[n_switches].args[0] = tmp = xmalloc (strlen (p)); + strcpy (tmp, &p[1]); switches[n_switches].args[1] = 0; } else switches[n_switches].args = 0; - switches[n_switches].live_cond = 0; + switches[n_switches].live_cond = SWITCH_OK; switches[n_switches].validated = 0; /* This is always valid, since gcc.c itself understands it. */ if (!strcmp (p, "save-temps")) switches[n_switches].validated = 1; - else - { - char ch = switches[n_switches].part1[0]; - if (ch == 'V' || ch == 'b' || ch == 'B') - switches[n_switches].validated = 1; - } + else + { + char ch = switches[n_switches].part1[0]; + if (ch == 'V' || ch == 'b' || ch == 'B') + switches[n_switches].validated = 1; + } n_switches++; } else @@ -3614,7 +3709,7 @@ process_command (argc, argv) argv[i] = convert_filename (argv[i], 0); #endif - if (strcmp (argv[i], "-") != 0 && access (argv[i], R_OK) < 0) + if (strcmp (argv[i], "-") != 0 && access (argv[i], F_OK) < 0) { perror_with_name (argv[i]); error_count++; @@ -3647,6 +3742,7 @@ const char *input_filename; static int input_file_number; size_t input_filename_length; static int basename_length; +static int suffixed_basename_length; static const char *input_basename; static const char *input_suffix; @@ -3831,6 +3927,11 @@ do_spec_1 (spec, inswitch, soft_matched_part) arg_going = 1; break; + case 'B': + obstack_grow (&obstack, input_basename, suffixed_basename_length); + arg_going = 1; + break; + case 'd': delete_this_arg = 2; break; @@ -3852,8 +3953,8 @@ do_spec_1 (spec, inswitch, soft_matched_part) and use them to search for dynamic linking. */ /* Relative directories always come from -B, and it is better not to use them for searching - at run time. In particular, stage1 loses */ - if (!IS_DIR_SEPARATOR (pl->prefix[0])) + at run time. In particular, stage1 loses. */ + if (!IS_ABSOLUTE_PATHNAME (pl->prefix)) continue; #endif /* Try subdirectory if there is one. */ @@ -3949,7 +4050,8 @@ do_spec_1 (spec, inswitch, soft_matched_part) { const char *q = p; char *buf; - while (*p != 0 && *p != '\n') p++; + while (*p != 0 && *p != '\n') + p++; buf = (char *) alloca (p - q + 1); strncpy (buf, q, p - q); buf[p - q] = 0; @@ -3958,6 +4060,26 @@ do_spec_1 (spec, inswitch, soft_matched_part) } break; + case 'j': + { + struct stat st; + + /* If save_temps_flag is off, and the HOST_BIT_BUCKET is defined, + and it is not a directory, and it is writable, use it. + Otherwise, fall through and treat this like any other + temporary file. */ + + if ((!save_temps_flag) + && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode)) + && (access (HOST_BIT_BUCKET, W_OK) == 0)) + { + obstack_grow (&obstack, HOST_BIT_BUCKET, + strlen (HOST_BIT_BUCKET)); + delete_this_arg = 0; + arg_going = 1; + break; + } + } case 'g': case 'u': case 'U': @@ -3968,24 +4090,19 @@ do_spec_1 (spec, inswitch, soft_matched_part) } else { -#ifdef MKTEMP_EACH_FILE - /* ??? This has a problem: the total number of - values mktemp can return is limited. - That matters for the names of object files. - In 2.4, do something about that. */ struct temp_name *t; int suffix_length; const char *suffix = p; char *saved_suffix = NULL; - while (*p == '.' || ISALPHA ((unsigned char)*p)) + while (*p == '.' || ISALPHA ((unsigned char) *p)) p++; suffix_length = p - suffix; if (p[0] == '%' && p[1] == 'O') { p += 2; /* We don't support extra suffix characters after %O. */ - if (*p == '.' || ISALPHA ((unsigned char)*p)) + if (*p == '.' || ISALPHA ((unsigned char) *p)) abort (); if (suffix_length == 0) suffix = OBJECT_SUFFIX; @@ -4009,8 +4126,8 @@ do_spec_1 (spec, inswitch, soft_matched_part) && t->unique == (c != 'g')) break; - /* Make a new association if needed. %u requires one. */ - if (t == 0 || c == 'u') + /* Make a new association if needed. %u and %j require one. */ + if (t == 0 || c == 'u' || c == 'j') { if (t == 0) { @@ -4030,20 +4147,7 @@ do_spec_1 (spec, inswitch, soft_matched_part) if (saved_suffix) free (saved_suffix); - obstack_grow (&obstack, t->filename, t->filename_length); - delete_this_arg = 1; -#else - obstack_grow (&obstack, temp_filename, temp_filename_length); - if (c == 'u' || c == 'U') - { - static int unique; - char buff[9]; - if (c == 'u') - unique++; - sprintf (buff, "%d", unique); - obstack_grow (&obstack, buff, strlen (buff)); - } -#endif + obstack_grow (&obstack, t->filename, t->filename_length); delete_this_arg = 1; } arg_going = 1; @@ -4241,7 +4345,7 @@ do_spec_1 (spec, inswitch, soft_matched_part) { char *x = (char *) alloca (strlen (cpp_predefines) + 1); char *buf = x; - char *y; + const char *y; /* Copy all of the -D options in CPP_PREDEFINES into BUF. */ y = cpp_predefines; @@ -4271,10 +4375,16 @@ do_spec_1 (spec, inswitch, soft_matched_part) { char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1); char *buf = x; - char *y; + const char *y; /* Copy all of CPP_PREDEFINES into BUF, - but put __ after every -D and at the end of each arg. */ + but force them all into the reserved name space if they + aren't already there. The reserved name space is all + identifiers beginning with two underscores or with one + underscore and a capital letter. We do the forcing by + adding up to two underscores to the beginning and end + of each symbol. e.g. mips, _mips, mips_, and _mips_ all + become __mips__. */ y = cpp_predefines; while (*y != 0) { @@ -4286,11 +4396,12 @@ do_spec_1 (spec, inswitch, soft_matched_part) *x++ = *y++; if (*y != '_' - || (*(y+1) != '_' - && ! ISUPPER ((unsigned char)*(y+1)))) - { + || (*(y + 1) != '_' + && ! ISUPPER ((unsigned char) *(y + 1)))) + { /* Stick __ at front of macro name. */ - *x++ = '_'; + if (*y != '_') + *x++ = '_'; *x++ = '_'; /* Arrange to stick __ at the end as well. */ flag = 1; @@ -4301,9 +4412,13 @@ do_spec_1 (spec, inswitch, soft_matched_part) *x++ = *y++; if (flag) - { - *x++ = '_'; - *x++ = '_'; + { + if (x[-1] != '_') + { + if (x[-2] != '_') + *x++ = '_'; + *x++ = '_'; + } } /* Copy the value given, if any. */ @@ -4329,13 +4444,14 @@ do_spec_1 (spec, inswitch, soft_matched_part) y += 2; if (*y != '_' - || (*(y+1) != '_' - && ! ISUPPER ((unsigned char)*(y+1)))) - { + || (*(y + 1) != '_' + && ! ISUPPER ((unsigned char) *(y + 1)))) + { /* Stick -D__ at front of macro name. */ *x++ = '-'; *x++ = 'D'; - *x++ = '_'; + if (*y != '_') + *x++ = '_'; *x++ = '_'; /* Copy the macro name. */ @@ -4356,7 +4472,7 @@ do_spec_1 (spec, inswitch, soft_matched_part) else if (*y == ' ' || *y == '\t') /* Copy whitespace to the result. */ *x++ = *y++; - /* Don't copy -A options */ + /* Don't copy -A options. */ else y++; } @@ -4405,8 +4521,16 @@ do_spec_1 (spec, inswitch, soft_matched_part) break; case '*': - do_spec_1 (soft_matched_part, 1, NULL_PTR); - do_spec_1 (" ", 0, NULL_PTR); + if (soft_matched_part) + { + do_spec_1 (soft_matched_part, 1, NULL_PTR); + do_spec_1 (" ", 0, NULL_PTR); + } + else + /* Catch the case where a spec string contains something like + '%{foo:%*}'. ie there is no * in the pattern on the left + hand side of the :. */ + error ("Spec failure: '%%*' has not been initialised by pattern match"); break; /* Process a string found as the value of a spec given by name. @@ -4427,7 +4551,7 @@ do_spec_1 (spec, inswitch, soft_matched_part) while (*p && *p != ')' && *p != ']') p++; - /* See if it's in the list */ + /* See if it's in the list. */ for (len = p - name, sl = specs; sl; sl = sl->next) if (sl->name_len == len && !strncmp (sl->name, name, len)) { @@ -4455,7 +4579,7 @@ do_spec_1 (spec, inswitch, soft_matched_part) int flag = 0; /* Copy all of NAME into BUF, but put __ after - every -D and at the end of each arg, */ + every -D and at the end of each arg. */ while (1) { if (! strncmp (y, "-D", 2)) @@ -4468,14 +4592,15 @@ do_spec_1 (spec, inswitch, soft_matched_part) flag = 1; continue; } - else if (flag && (*y == ' ' || *y == '\t' || *y == '=' - || *y == '}' || *y == 0)) + else if (flag + && (*y == ' ' || *y == '\t' || *y == '=' + || *y == '}' || *y == 0)) { *x++ = '_'; *x++ = '_'; flag = 0; } - if (*y == 0) + if (*y == 0) break; else *x++ = *y++; @@ -4497,8 +4622,9 @@ do_spec_1 (spec, inswitch, soft_matched_part) case 'v': { int c1 = *p++; /* Select first or second version number. */ - char *v = compiler_version; - char *q; + const char *v = compiler_version; + const char *q; + static const char zeroc = '0'; /* The format of the version string is ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */ @@ -4510,7 +4636,7 @@ do_spec_1 (spec, inswitch, soft_matched_part) abort (); /* If desired, advance to second version number. */ - if (c1 == '2') + if (c1 >= '2') { /* Set V after the first period. */ while (ISDIGIT (*v)) @@ -4520,15 +4646,32 @@ do_spec_1 (spec, inswitch, soft_matched_part) v++; } + /* If desired, advance to third version number. + But don't complain if it's not present */ + if (c1 == '3') + { + /* Set V after the second period. */ + while (ISDIGIT (*v)) + v++; + if ((*v != 0) && (*v != ' ') && (*v != '.') && (*v != '-')) + abort (); + if (*v != 0) + v++; + } + /* Set Q at the next period or at the end. */ q = v; while (ISDIGIT (*q)) q++; - if (*q != 0 && *q != ' ' && *q != '.' && *q != '-') + if (*q != 0 && q > v && *q != ' ' && *q != '.' && *q != '-') abort (); - /* Put that part into the command. */ - obstack_grow (&obstack, v, q - v); + if (q > v) + /* Put that part into the command. */ + obstack_grow (&obstack, v, q - v); + else + /* Default to "0" */ + obstack_grow (&obstack, &zeroc, 1); arg_going = 1; } break; @@ -4539,7 +4682,8 @@ do_spec_1 (spec, inswitch, soft_matched_part) break; default: - abort (); + error ("Spec failure: Unrecognised spec option '%c'", c); + break; } break; @@ -4554,7 +4698,8 @@ do_spec_1 (spec, inswitch, soft_matched_part) arg_going = 1; } - return 0; /* End of string */ + /* End of string. */ + return 0; } /* Return 0 if we call do_spec_1 and that returns -1. */ @@ -4565,19 +4710,35 @@ handle_braces (p) { const char *filter, *body = NULL, *endbody = NULL; int pipe_p = 0; + int true_once = 0; /* If, in %{a|b:d}, at least one of a,b was seen. */ int negate; int suffix; int include_blanks = 1; + int elide_switch = 0; if (*p == '^') - /* A '^' after the open-brace means to not give blanks before args. */ - include_blanks = 0, ++p; + { + /* A '^' after the open-brace means to not give blanks before args. */ + include_blanks = 0; + ++p; + } if (*p == '|') - /* A `|' after the open-brace means, - if the test fails, output a single minus sign rather than nothing. - This is used in %{|!pipe:...}. */ - pipe_p = 1, ++p; + { + /* A `|' after the open-brace means, + if the test fails, output a single minus sign rather than nothing. + This is used in %{|!pipe:...}. */ + pipe_p = 1; + ++p; + } + + if (*p == '<') + { + /* A `<' after the open-brace means that the switch should be + removed from the command-line. */ + elide_switch = 1; + ++p; + } next_member: negate = suffix = 0; @@ -4597,8 +4758,16 @@ next_member: ++p; } + if (elide_switch && (negate || pipe_p || suffix)) + { + /* It doesn't make sense to mix elision with other flags. We + could fatal() here, but the standard seems to be to abort. */ + abort (); + } + filter = p; - while (*p != ':' && *p != '}' && *p != '|') p++; + while (*p != ':' && *p != '}' && *p != '|') + p++; if (*p == '|' && pipe_p) abort (); @@ -4606,33 +4775,34 @@ next_member: if (!body) { if (*p != '}') - { + { register int count = 1; register const char *q = p; - while (*q++ != ':') continue; + while (*q++ != ':') + continue; body = q; - + while (count > 0) { if (*q == '{') - count++; + count++; else if (*q == '}') - count--; + count--; else if (*q == 0) - abort (); + abort (); q++; } endbody = q; } else - body = p, endbody = p+1; + body = p, endbody = p + 1; } if (suffix) { int found = (input_suffix != 0 - && (long) strlen (input_suffix) == (long)(p - filter) + && (long) strlen (input_suffix) == (long) (p - filter) && strncmp (input_suffix, filter, p - filter) == 0); if (body[0] == '}') @@ -4711,6 +4881,7 @@ next_member: && check_live_switch (i, hard_match_len)) { present = 1; + break; } } } @@ -4734,16 +4905,18 @@ next_member: conditional text. */ if (present != negate) { - if (*p == '}') + if (elide_switch) { - give_switch (i, 0, include_blanks); + switches[i].live_cond = SWITCH_IGNORE; + switches[i].validated = 1; } - else + else if (*p == '}') { - if (do_spec_1 (save_string (body, endbody - body - 1), - 0, NULL_PTR) < 0) - return 0; + give_switch (i, 0, include_blanks); } + else + /* Even if many alternatives are matched, only output once. */ + true_once = 1; } else if (pipe_p) { @@ -4758,6 +4931,14 @@ next_member: if (*p++ == '|') goto next_member; + /* Process the spec just once, regardless of match count. */ + if (true_once) + { + if (do_spec_1 (save_string (body, endbody - body - 1), + 0, NULL_PTR) < 0) + return 0; + } + return endbody; } @@ -4792,13 +4973,13 @@ check_live_switch (switchnum, prefix_length) switch (*name) { case 'O': - for (i = switchnum + 1; i < n_switches; i++) - if (switches[i].part1[0] == 'O') - { - switches[switchnum].validated = 1; - switches[switchnum].live_cond = -1; - return 0; - } + for (i = switchnum + 1; i < n_switches; i++) + if (switches[i].part1[0] == 'O') + { + switches[switchnum].validated = 1; + switches[switchnum].live_cond = SWITCH_FALSE; + return 0; + } break; case 'W': case 'f': case 'm': @@ -4808,11 +4989,11 @@ check_live_switch (switchnum, prefix_length) for (i = switchnum + 1; i < n_switches; i++) if (switches[i].part1[0] == name[0] && ! strcmp (&switches[i].part1[1], &name[4])) - { - switches[switchnum].validated = 1; - switches[switchnum].live_cond = -1; - return 0; - } + { + switches[switchnum].validated = 1; + switches[switchnum].live_cond = SWITCH_FALSE; + return 0; + } } else { @@ -4823,17 +5004,17 @@ check_live_switch (switchnum, prefix_length) && switches[i].part1[2] == 'o' && switches[i].part1[3] == '-' && !strcmp (&switches[i].part1[4], &name[1])) - { - switches[switchnum].validated = 1; - switches[switchnum].live_cond = -1; - return 0; - } + { + switches[switchnum].validated = 1; + switches[switchnum].live_cond = SWITCH_FALSE; + return 0; + } } break; } /* Otherwise the switch is live. */ - switches[switchnum].live_cond = 1; + switches[switchnum].live_cond = SWITCH_LIVE; return 1; } @@ -4854,6 +5035,9 @@ give_switch (switchnum, omit_first_word, include_blanks) int omit_first_word; int include_blanks; { + if (switches[switchnum].live_cond == SWITCH_IGNORE) + return; + if (!omit_first_word) { do_spec_1 ("-", 0, NULL_PTR); @@ -4862,7 +5046,7 @@ give_switch (switchnum, omit_first_word, include_blanks) if (switches[switchnum].args != 0) { - char **p; + const char **p; for (p = switches[switchnum].args; *p; p++) { if (include_blanks) @@ -4943,16 +5127,54 @@ is_directory (path1, path2, linker) /* Exclude directories that the linker is known to search. */ if (linker && ((cp - path == 6 - && strcmp (path, concat (dir_separator_str, "lib", + && strcmp (path, concat (dir_separator_str, "lib", dir_separator_str, ".", NULL_PTR)) == 0) || (cp - path == 10 - && strcmp (path, concat (dir_separator_str, "usr", - dir_separator_str, "lib", + && strcmp (path, concat (dir_separator_str, "usr", + dir_separator_str, "lib", dir_separator_str, ".", NULL_PTR)) == 0))) return 0; return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode)); } + +/* Set up the various global variables to indicate that we're processing + the input file named FILENAME. */ + +static void +set_input (filename) + const char *filename; +{ + register const char *p; + + input_filename = filename; + input_filename_length = strlen (input_filename); + + input_basename = input_filename; +#ifdef HAVE_DOS_BASED_FILE_SYSTEM + /* Skip drive name so 'x:foo' is handled properly. */ + if (input_basename[1] == ':') + input_basename += 2; +#endif + for (p = input_basename; *p; p++) + if (IS_DIR_SEPARATOR (*p)) + input_basename = p + 1; + + /* Find a suffix starting with the last period, + and set basename_length to exclude that suffix. */ + basename_length = strlen (input_basename); + suffixed_basename_length = basename_length; + p = input_basename + basename_length; + while (p != input_basename && *p != '.') + --p; + if (*p == '.' && p != input_basename) + { + basename_length = p - input_basename; + input_suffix = p + 1; + } + else + input_suffix = ""; +} /* On fatal signals, delete all the temporary files. */ @@ -4968,15 +5190,14 @@ fatal_error (signum) kill (getpid (), signum); } -extern int main PROTO ((int, char **)); +extern int main PARAMS ((int, const char *const *)); int main (argc, argv) int argc; - char **argv; + const char *const *argv; { - register size_t i; - size_t j; + size_t i; int value; int linker_was_run = 0; char *explicit_link_files; @@ -4989,6 +5210,11 @@ main (argc, argv) --p; programname = p; +#ifdef GCC_DRIVER_HOST_INITIALIZATION + /* Perform host dependant initialization when needed. */ + GCC_DRIVER_HOST_INITIALIZATION; +#endif + #ifdef HAVE_LC_MESSAGES setlocale (LC_MESSAGES, ""); #endif @@ -5009,14 +5235,14 @@ main (argc, argv) #endif argbuf_length = 10; - argbuf = (char **) xmalloc (argbuf_length * sizeof (char *)); + argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *)); obstack_init (&obstack); /* Build multilib_select, et. al from the separate lines that make up each multilib selection. */ { - char **q = multilib_raw; + const char *const *q = multilib_raw; int need_space; obstack_init (&multilib_obstack); @@ -5033,10 +5259,15 @@ main (argc, argv) obstack_1grow (&multilib_obstack, 0); multilib_matches = obstack_finish (&multilib_obstack); + q = multilib_exclusions_raw; + while ((p = *q++) != (char *) 0) + obstack_grow (&multilib_obstack, p, strlen (p)); + + obstack_1grow (&multilib_obstack, 0); + multilib_exclusions = obstack_finish (&multilib_obstack); + need_space = FALSE; - for (i = 0; - i < sizeof (multilib_defaults_raw) / sizeof (multilib_defaults_raw[0]); - i++) + for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++) { if (need_space) obstack_1grow (&multilib_obstack, ' '); @@ -5054,8 +5285,8 @@ main (argc, argv) needed for collect. We use argv[0] instead of programname because we need the complete pathname. */ obstack_init (&collect_obstack); - obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=")-1); - obstack_grow (&collect_obstack, argv[0], strlen (argv[0])+1); + obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1); + obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1); putenv (obstack_finish (&collect_obstack)); #ifdef INIT_ENVIRONMENT @@ -5063,13 +5294,6 @@ main (argc, argv) putenv (INIT_ENVIRONMENT); #endif - /* Choose directory for temp files. */ - -#ifndef MKTEMP_EACH_FILE - temp_filename = choose_temp_base (); - temp_filename_length = strlen (temp_filename); -#endif - /* Make a table of what switches there are (switches, n_switches). Make a table of specified input files (infiles, n_infiles). Decode switches that are handled locally. */ @@ -5082,35 +5306,35 @@ main (argc, argv) /* Build COLLECT_GCC_OPTIONS to have all of the options specified to the compiler. */ obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=", - sizeof ("COLLECT_GCC_OPTIONS=")-1); + sizeof ("COLLECT_GCC_OPTIONS=") - 1); first_time = TRUE; - for (i = 0; (int)i < n_switches; i++) + for (i = 0; (int) i < n_switches; i++) { - char **args; + const char *const *args; const char *p, *q; if (!first_time) obstack_grow (&collect_obstack, " ", 1); first_time = FALSE; obstack_grow (&collect_obstack, "'-", 2); - q = switches[i].part1; - while ((p = index (q,'\''))) - { - obstack_grow (&collect_obstack, q, p-q); - obstack_grow (&collect_obstack, "'\\''", 4); - q = ++p; - } - obstack_grow (&collect_obstack, q, strlen (q)); + q = switches[i].part1; + while ((p = strchr (q, '\''))) + { + obstack_grow (&collect_obstack, q, p - q); + obstack_grow (&collect_obstack, "'\\''", 4); + q = ++p; + } + obstack_grow (&collect_obstack, q, strlen (q)); obstack_grow (&collect_obstack, "'", 1); for (args = switches[i].args; args && *args; args++) { obstack_grow (&collect_obstack, " '", 2); q = *args; - while ((p = index (q,'\''))) + while ((p = strchr (q, '\''))) { - obstack_grow (&collect_obstack, q, p-q); + obstack_grow (&collect_obstack, q, p - q); obstack_grow (&collect_obstack, "'\\''", 4); q = ++p; } @@ -5126,8 +5350,8 @@ main (argc, argv) This means one element containing 0s, as a terminator. */ compilers = (struct compiler *) xmalloc (sizeof default_compilers); - bcopy ((char *) default_compilers, (char *) compilers, - sizeof default_compilers); + memcpy ((char *) compilers, (char *) default_compilers, + sizeof default_compilers); n_compilers = n_default_compilers; /* Read specs from a file if there is one. */ @@ -5144,7 +5368,7 @@ main (argc, argv) init_spec (); /* We need to check standard_exec_prefix/just_machine_suffix/specs - for any override of as, ld and libraries. */ + for any override of as, ld and libraries. */ specs_file = (char *) alloca (strlen (standard_exec_prefix) + strlen (just_machine_suffix) + sizeof ("specs")); @@ -5154,68 +5378,64 @@ main (argc, argv) strcat (specs_file, "specs"); if (access (specs_file, R_OK) == 0) read_specs (specs_file, TRUE); - + /* If not cross-compiling, look for startfiles in the standard places. */ if (*cross_compile == '0') { -#ifdef MD_EXEC_PREFIX - add_prefix (&exec_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR); - add_prefix (&startfile_prefixes, md_exec_prefix, "GCC", 0, 0, NULL_PTR); -#endif + if (*md_exec_prefix) + { + add_prefix (&exec_prefixes, md_exec_prefix, "GCC", + PREFIX_PRIORITY_LAST, 0, NULL_PTR); + add_prefix (&startfile_prefixes, md_exec_prefix, "GCC", + PREFIX_PRIORITY_LAST, 0, NULL_PTR); + } -#ifdef MD_STARTFILE_PREFIX - add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC", - 0, 0, NULL_PTR); -#endif + if (*md_startfile_prefix) + add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC", + PREFIX_PRIORITY_LAST, 0, NULL_PTR); -#ifdef MD_STARTFILE_PREFIX_1 - add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC", - 0, 0, NULL_PTR); -#endif + if (*md_startfile_prefix_1) + add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC", + PREFIX_PRIORITY_LAST, 0, NULL_PTR); /* If standard_startfile_prefix is relative, base it on standard_exec_prefix. This lets us move the installed tree as a unit. If GCC_EXEC_PREFIX is defined, base standard_startfile_prefix on that as well. */ - if (IS_DIR_SEPARATOR (*standard_startfile_prefix) - || *standard_startfile_prefix == '$' -#ifdef HAVE_DOS_BASED_FILE_SYSTEM - /* Check for disk name on MS-DOS-based systems. */ - || (standard_startfile_prefix[1] == ':' - && (IS_DIR_SEPARATOR (standard_startfile_prefix[2]))) -#endif - ) + if (IS_ABSOLUTE_PATHNAME (standard_startfile_prefix)) add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS", - 0, 0, NULL_PTR); + PREFIX_PRIORITY_LAST, 0, NULL_PTR); else { if (gcc_exec_prefix) add_prefix (&startfile_prefixes, concat (gcc_exec_prefix, machine_suffix, standard_startfile_prefix, NULL_PTR), - NULL_PTR, 0, 0, NULL_PTR); + NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR); add_prefix (&startfile_prefixes, concat (standard_exec_prefix, machine_suffix, standard_startfile_prefix, NULL_PTR), - NULL_PTR, 0, 0, NULL_PTR); - } + NULL_PTR, PREFIX_PRIORITY_LAST, 0, NULL_PTR); + } add_prefix (&startfile_prefixes, standard_startfile_prefix_1, - "BINUTILS", 0, 0, NULL_PTR); + "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR); add_prefix (&startfile_prefixes, standard_startfile_prefix_2, - "BINUTILS", 0, 0, NULL_PTR); + "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR); #if 0 /* Can cause surprises, and one can use -B./ instead. */ - add_prefix (&startfile_prefixes, "./", NULL_PTR, 0, 1, NULL_PTR); + add_prefix (&startfile_prefixes, "./", NULL_PTR, + PREFIX_PRIORITY_LAST, 1, NULL_PTR); #endif } else { - if (!IS_DIR_SEPARATOR (*standard_startfile_prefix) && gcc_exec_prefix) + if (!IS_ABSOLUTE_PATHNAME (standard_startfile_prefix) + && gcc_exec_prefix) add_prefix (&startfile_prefixes, concat (gcc_exec_prefix, machine_suffix, standard_startfile_prefix, NULL_PTR), - "BINUTILS", 0, 0, NULL_PTR); + "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL_PTR); } /* Process any user specified specs in the order given on the command @@ -5229,9 +5449,9 @@ main (argc, argv) /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */ if (gcc_exec_prefix) { - char * temp = (char *) xmalloc (strlen (gcc_exec_prefix) - + strlen (spec_version) - + strlen (spec_machine) + 3); + char *temp = (char *) xmalloc (strlen (gcc_exec_prefix) + + strlen (spec_version) + + strlen (spec_machine) + 3); strcpy (temp, gcc_exec_prefix); strcat (temp, spec_machine); strcat (temp, dir_separator_str); @@ -5251,7 +5471,7 @@ main (argc, argv) /* Warn about any switches that no pass was interested in. */ - for (i = 0; (int)i < n_switches; i++) + for (i = 0; (int) i < n_switches; i++) if (! switches[i].validated) error ("unrecognized option `-%s'", switches[i].part1); @@ -5259,9 +5479,9 @@ main (argc, argv) if (print_search_dirs) { - printf ("install: %s%s\n", standard_exec_prefix, machine_suffix); - printf ("programs: %s\n", build_search_list (&exec_prefixes, "", 0)); - printf ("libraries: %s\n", build_search_list (&startfile_prefixes, "", 0)); + printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix); + printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0)); + printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0)); return (0); } @@ -5293,15 +5513,25 @@ main (argc, argv) return (0); } + if (target_help_flag) + { + /* Print if any target specific options.*/ + + /* We do not exit here. Instead we have created a fake input file + called 'target-dummy' which needs to be compiled, and we pass this + on to the various sub-processes, along with the --target-help + switch. */ + } + if (print_help_list) { display_help (); if (! verbose_flag) { - printf ("\nFor bug reporting instructions, please see:\n"); - printf (".\n"); - + printf (_("\nFor bug reporting instructions, please see:\n")); + printf ("%s.\n", GCCBUGURL); + return (0); } @@ -5309,11 +5539,13 @@ main (argc, argv) called 'help-dummy' which needs to be compiled, and we pass this on the the various sub-processes, along with the --help switch. */ } - + if (verbose_flag) { int n; + notice ("Configured with: %s\n", configuration_arguments); + /* compiler_version is truncated at the first space when initialized from version string, so truncate version_string at the first space before comparing. */ @@ -5346,16 +5578,15 @@ main (argc, argv) explicit_link_files = xcalloc (1, n_infiles); - for (i = 0; (int)i < n_infiles; i++) + for (i = 0; (int) i < n_infiles; i++) { register struct compiler *cp = 0; int this_file_error = 0; /* Tell do_spec what to substitute for %i. */ - input_filename = infiles[i].name; - input_filename_length = strlen (input_filename); input_file_number = i; + set_input (infiles[i].name); /* Use the same thing in %o, unless cp->spec says otherwise. */ @@ -5369,51 +5600,11 @@ main (argc, argv) if (cp) { /* Ok, we found an applicable compiler. Run its spec. */ - /* First say how much of input_filename to substitute for %b */ - register const char *p; - int len; - if (cp->spec[0][0] == '#') + if (cp->spec[0] == '#') error ("%s: %s compiler not installed on this system", - input_filename, &cp->spec[0][1]); - - input_basename = input_filename; - for (p = input_filename; *p; p++) - if (IS_DIR_SEPARATOR (*p)) - input_basename = p + 1; - - /* Find a suffix starting with the last period, - and set basename_length to exclude that suffix. */ - basename_length = strlen (input_basename); - p = input_basename + basename_length; - while (p != input_basename && *p != '.') --p; - if (*p == '.' && p != input_basename) - { - basename_length = p - input_basename; - input_suffix = p + 1; - } - else - input_suffix = ""; - - len = 0; - for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++) - if (cp->spec[j]) - len += strlen (cp->spec[j]); - - { - char *p1 = (char *) xmalloc (len + 1); - - len = 0; - for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++) - if (cp->spec[j]) - { - strcpy (p1 + len, cp->spec[j]); - len += strlen (cp->spec[j]); - } - - value = do_spec (p1); - free (p1); - } + input_filename, &cp->spec[1]); + value = do_spec (cp->spec); if (value < 0) this_file_error = 1; } @@ -5436,6 +5627,12 @@ main (argc, argv) clear_failure_queue (); } + /* Reset the output file name to the first input file name, for use + with %b in LINK_SPEC on a target that prefers not to emit a.out + by default. */ + if (n_infiles > 0) + set_input (infiles[0].name); + if (error_count == 0) { /* Make sure INPUT_FILE_NUMBER points to first available open @@ -5451,7 +5648,7 @@ main (argc, argv) { int tmp = execution_count; - /* We'll use ld if we can't find collect2. */ + /* We'll use ld if we can't find collect2. */ if (! strcmp (linker_name_spec, "collect2")) { char *s = find_a_file (&exec_prefixes, "collect2", X_OK); @@ -5460,8 +5657,8 @@ main (argc, argv) } /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables for collect. */ - putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH="); - putenv_from_prefixes (&startfile_prefixes, "LIBRARY_PATH="); + putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH"); + putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV); value = do_spec (link_command_spec); if (value < 0) @@ -5469,17 +5666,13 @@ main (argc, argv) linker_was_run = (tmp != execution_count); } - /* Warn if a -B option was specified but the prefix was never used. */ - unused_prefix_warnings (&exec_prefixes); - unused_prefix_warnings (&startfile_prefixes); - /* If options said don't run linker, complain about input files to be given to the linker. */ if (! linker_was_run && error_count == 0) - for (i = 0; (int)i < n_infiles; i++) + for (i = 0; (int) i < n_infiles; i++) if (explicit_link_files[i]) - error ("%s: linker input file unused since linking not done", + error ("%s: linker input file unused because linking not done", outfiles[i]); /* Delete some or all of the temporary files we made. */ @@ -5490,10 +5683,10 @@ main (argc, argv) if (print_help_list) { - printf ("\nFor bug reporting instructions, please see:\n"); - printf ("\n"); + printf (("\nFor bug reporting instructions, please see:\n")); + printf ("%s\n", GCCBUGURL); } - + return (signal_count != 0 ? 2 : error_count > 0 ? (pass_exit_codes ? greatest_status : 1) : 0); @@ -5511,7 +5704,7 @@ lookup_compiler (name, length, language) { struct compiler *cp; - /* If this was specified by the user to be a linker input, indicate that. */ + /* If this was specified by the user to be a linker input, indicate that. */ if (language != 0 && language[0] == '*') return 0; @@ -5533,51 +5726,53 @@ lookup_compiler (name, length, language) (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) || (strlen (cp->suffix) < length /* See if the suffix matches the end of NAME. */ -#ifdef OS2 - && ((!strcmp (cp->suffix, - name + length - strlen (cp->suffix)) - || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) - && !strcasecmp (cp->suffix, - name + length - strlen (cp->suffix))) -#else && !strcmp (cp->suffix, name + length - strlen (cp->suffix)) -#endif )) - { - if (cp->spec[0][0] == '@') - { - struct compiler *new; - - /* An alias entry maps a suffix to a language. - Search for the language; pass 0 for NAME and LENGTH - to avoid infinite recursion if language not found. - Construct the new compiler spec. */ - language = cp->spec[0] + 1; - new = (struct compiler *) xmalloc (sizeof (struct compiler)); - new->suffix = cp->suffix; - memcpy (new->spec, - lookup_compiler (NULL_PTR, 0, language)->spec, - sizeof new->spec); - return new; - } - - /* A non-alias entry: return it. */ - return cp; - } + break; } +#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* look again, but case-insensitively this time. */ + if (cp < compilers) + for (cp = compilers + n_compilers - 1; cp >= compilers; cp--) + { + if (/* The suffix `-' matches only the file name `-'. */ + (!strcmp (cp->suffix, "-") && !strcmp (name, "-")) + || (strlen (cp->suffix) < length + /* See if the suffix matches the end of NAME. */ + && ((!strcmp (cp->suffix, + name + length - strlen (cp->suffix)) + || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) + && !strcasecmp (cp->suffix, + name + length - strlen (cp->suffix))) + )) + break; + } +#endif + + if (cp >= compilers) + { + if (cp->spec[0] != '@') + /* A non-alias entry: return it. */ + return cp; + + /* An alias entry maps a suffix to a language. + Search for the language; pass 0 for NAME and LENGTH + to avoid infinite recursion if language not found. */ + return lookup_compiler (NULL_PTR, 0, cp->spec + 1); + } return 0; } static char * save_string (s, len) - const char *s; - int len; + const char *s; + int len; { register char *result = xmalloc (len + 1); - bcopy (s, result, len); + memcpy (result, s, len); result[len] = 0; return result; } @@ -5629,7 +5824,7 @@ fancy_abort () /* Output an error message and exit */ void -fatal VPROTO((const char *msgid, ...)) +fatal VPARAMS ((const char *msgid, ...)) { #ifndef ANSI_PROTOTYPES const char *msgid; @@ -5651,7 +5846,7 @@ fatal VPROTO((const char *msgid, ...)) } static void -error VPROTO((const char *msgid, ...)) +error VPARAMS ((const char *msgid, ...)) { #ifndef ANSI_PROTOTYPES const char *msgid; @@ -5672,7 +5867,7 @@ error VPROTO((const char *msgid, ...)) } static void -notice VPROTO((const char *msgid, ...)) +notice VPARAMS ((const char *msgid, ...)) { #ifndef ANSI_PROTOTYPES const char *msgid; @@ -5688,7 +5883,6 @@ notice VPROTO((const char *msgid, ...)) vfprintf (stderr, _(msgid), ap); va_end (ap); } - static void validate_all_switches () @@ -5698,21 +5892,17 @@ validate_all_switches () register char c; struct spec_list *spec; - for (comp = compilers; comp->spec[0]; comp++) + for (comp = compilers; comp->spec; comp++) { - size_t i; - for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++) - { - p = comp->spec[i]; - while ((c = *p++)) - if (c == '%' && *p == '{') - /* We have a switch spec. */ - validate_switches (p + 1); - } + p = comp->spec; + while ((c = *p++)) + if (c == '%' && *p == '{') + /* We have a switch spec. */ + validate_switches (p + 1); } - /* look through the linked list of specs read from the specs file */ - for (spec = specs; spec ; spec = spec->next) + /* Look through the linked list of specs read from the specs file. */ + for (spec = specs; spec; spec = spec->next) { p = *(spec->ptr_spec); while ((c = *p++)) @@ -5738,28 +5928,30 @@ validate_switches (start) register const char *p = start; const char *filter; register int i; - int suffix = 0; + int suffix; if (*p == '|') ++p; +next_member: if (*p == '!') ++p; + suffix = 0; if (*p == '.') suffix = 1, ++p; filter = p; - while (*p != ':' && *p != '}') p++; + while (*p != ':' && *p != '}' && *p != '|') + p++; if (suffix) ; else if (p[-1] == '*') { /* Mark all matching switches as valid. */ - --p; for (i = 0; i < n_switches; i++) - if (!strncmp (switches[i].part1, filter, p - filter)) + if (!strncmp (switches[i].part1, filter, p - filter - 1)) switches[i].validated = 1; } else @@ -5772,6 +5964,9 @@ validate_switches (start) switches[i].validated = 1; } } + + if (*p++ == '|') + goto next_member; } /* Check whether a particular argument was used. The first time we @@ -5782,9 +5977,10 @@ used_arg (p, len) const char *p; int len; { - struct mswitchstr { - char *str; - char *replace; + struct mswitchstr + { + const char *str; + const char *replace; int len; int rep_len; }; @@ -5796,16 +5992,17 @@ used_arg (p, len) if (!mswitches) { struct mswitchstr *matches; - char *q; + const char *q; int cnt = 0; - /* Break multilib_matches into the component strings of string and replacement - string */ + /* Break multilib_matches into the component strings of string + and replacement string. */ for (q = multilib_matches; *q != '\0'; q++) if (*q == ';') cnt++; - matches = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt); + matches = + (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt); i = 0; q = multilib_matches; while (*q != '\0') @@ -5817,7 +6014,6 @@ used_arg (p, len) abort (); q++; } - *q = '\0'; matches[i].len = q - matches[i].str; matches[i].replace = ++q; @@ -5830,9 +6026,7 @@ used_arg (p, len) matches[i].rep_len = q - matches[i].replace; i++; if (*q == ';') - *q++ = '\0'; - else - break; + q++; } /* Now build a list of the replacement string for switches that we care @@ -5846,11 +6040,12 @@ used_arg (p, len) { int xlen = strlen (switches[i].part1); for (j = 0; j < cnt; j++) - if (xlen == matches[j].len && ! strcmp (switches[i].part1, matches[j].str)) + if (xlen == matches[j].len + && ! strncmp (switches[i].part1, matches[j].str, xlen)) { mswitches[n_mswitches].str = matches[j].replace; mswitches[n_mswitches].len = matches[j].rep_len; - mswitches[n_mswitches].replace = (char *)0; + mswitches[n_mswitches].replace = (char *) 0; mswitches[n_mswitches].rep_len = 0; n_mswitches++; break; @@ -5870,9 +6065,9 @@ default_arg (p, len) const char *p; int len; { - char *start, *end; + const char *start, *end; - for (start = multilib_defaults; *start != '\0'; start = end+1) + for (start = multilib_defaults; *start != '\0'; start = end + 1) { while (*start == ' ' || *start == '\t') start++; @@ -5880,7 +6075,7 @@ default_arg (p, len) if (*start == '\0') break; - for (end = start+1; *end != ' ' && *end != '\t' && *end != '\0'; end++) + for (end = start + 1; *end != ' ' && *end != '\t' && *end != '\0'; end++) ; if ((end - start) == len && strncmp (p, start, len) == 0) @@ -5893,23 +6088,80 @@ default_arg (p, len) return 0; } -/* Work out the subdirectory to use based on the - options. The format of multilib_select is a list of elements. - Each element is a subdirectory name followed by a list of options - followed by a semicolon. gcc will consider each line in turn. If - none of the options beginning with an exclamation point are - present, and all of the other options are present, that - subdirectory will be used. */ +/* Work out the subdirectory to use based on the options. The format of + multilib_select is a list of elements. Each element is a subdirectory + name followed by a list of options followed by a semicolon. The format + of multilib_exclusions is the same, but without the preceding + directory. First gcc will check the exclusions, if none of the options + beginning with an exclamation point are present, and all of the other + options are present, then we will ignore this completely. Passing + that, gcc will consider each multilib_select in turn using the same + rules for matching the options. If a match is found, that subdirectory + will be used. */ static void set_multilib_dir () { - char *p = multilib_select; - int this_path_len; - char *this_path, *this_arg; + const char *p; + unsigned int this_path_len; + const char *this_path, *this_arg; int not_arg; int ok; + p = multilib_exclusions; + while (*p != '\0') + { + /* Ignore newlines. */ + if (*p == '\n') + { + ++p; + continue; + } + + /* Check the arguments. */ + ok = 1; + while (*p != ';') + { + if (*p == '\0') + abort (); + + if (! ok) + { + ++p; + continue; + } + + this_arg = p; + while (*p != ' ' && *p != ';') + { + if (*p == '\0') + abort (); + ++p; + } + + if (*this_arg != '!') + not_arg = 0; + else + { + not_arg = 1; + ++this_arg; + } + + ok = used_arg (this_arg, p - this_arg); + if (not_arg) + ok = ! ok; + + if (*p == ' ') + ++p; + } + + if (ok) + return; + + ++p; + } + + p = multilib_select; while (*p != '\0') { /* Ignore newlines. */ @@ -5982,7 +6234,7 @@ set_multilib_dir () if (this_path_len != 1 || this_path[0] != '.') { - char * new_multilib_dir = xmalloc (this_path_len + 1); + char *new_multilib_dir = xmalloc (this_path_len + 1); strncpy (new_multilib_dir, this_path, this_path_len); new_multilib_dir[this_path_len] = '\0'; multilib_dir = new_multilib_dir; @@ -5991,7 +6243,7 @@ set_multilib_dir () } ++p; - } + } } /* Print out the multiple library subdirectory selection @@ -6001,18 +6253,20 @@ set_multilib_dir () matches. The options are print without a leading dash. There are no spaces to make it easy to use the information in the shell. Each subdirectory is printed only once. This assumes the ordering - generated by the genmultilib script. */ + generated by the genmultilib script. Also, we leave out ones that match + the exclusions. */ static void print_multilib_info () { - char *p = multilib_select; - char *last_path = 0, *this_path; + const char *p = multilib_select; + const char *last_path = 0, *this_path; int skip; - int last_path_len = 0; + unsigned int last_path_len = 0; while (*p != '\0') { + skip = 0; /* Ignore newlines. */ if (*p == '\n') { @@ -6029,24 +6283,115 @@ print_multilib_info () ++p; } - /* If this is a duplicate, skip it. */ - skip = (last_path != 0 && p - this_path == last_path_len - && ! strncmp (last_path, this_path, last_path_len)); + /* Check for matches with the multilib_exclusions. We don't bother + with the '!' in either list. If any of the exclusion rules match + all of its options with the select rule, we skip it. */ + { + const char *e = multilib_exclusions; + const char *this_arg; + + while (*e != '\0') + { + int m = 1; + /* Ignore newlines. */ + if (*e == '\n') + { + ++e; + continue; + } + + /* Check the arguments. */ + while (*e != ';') + { + const char *q; + int mp = 0; + + if (*e == '\0') + abort (); + + if (! m) + { + ++e; + continue; + } + + this_arg = e; + + while (*e != ' ' && *e != ';') + { + if (*e == '\0') + abort (); + ++e; + } + + q = p + 1; + while (*q != ';') + { + const char *arg; + int len = e - this_arg; + + if (*q == '\0') + abort (); + + arg = q; + + while (*q != ' ' && *q != ';') + { + if (*q == '\0') + abort (); + ++q; + } + + if (! strncmp (arg, this_arg, (len < q - arg) ? q - arg : len) || + default_arg (this_arg, e - this_arg)) + { + mp = 1; + break; + } + + if (*q == ' ') + ++q; + } + + if (! mp) + m = 0; + + if (*e == ' ') + ++e; + } + + if (m) + { + skip = 1; + break; + } - last_path = this_path; - last_path_len = p - this_path; + if (*e != '\0') + ++e; + } + } + + if (! skip) + { + /* If this is a duplicate, skip it. */ + skip = (last_path != 0 && (unsigned int) (p - this_path) == last_path_len + && ! strncmp (last_path, this_path, last_path_len)); + + last_path = this_path; + last_path_len = p - this_path; + } /* If this directory requires any default arguments, we can skip it. We will already have printed a directory identical to this one which does not require that default argument. */ if (! skip) { - char *q; + const char *q; q = p + 1; while (*q != ';') { - char *arg; + const char *arg; if (*q == '\0') abort (); @@ -6077,7 +6422,7 @@ print_multilib_info () if (! skip) { - char *p1; + const char *p1; for (p1 = last_path; p1 < p; p1++) putchar (*p1); @@ -6118,11 +6463,11 @@ print_multilib_info () if (! skip) { - /* If there are extra options, print them now */ + /* If there are extra options, print them now. */ if (multilib_extra && *multilib_extra) { int print_at = TRUE; - char *q; + const char *q; for (q = multilib_extra; *q != '\0'; q++) { @@ -6137,6 +6482,7 @@ print_multilib_info () } } } + putchar ('\n'); }