/* Compiler driver program that can handle many languages.
- Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
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 <signal.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#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. */
#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. */
+#ifndef DIR_UP
+#define DIR_UP ".."
+#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
#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
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. */
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). */
/* 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. */
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;
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 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 init_spec PARAMS ((void));
+#ifndef VMS
+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 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 *));
+static void init_gcc_specs PARAMS ((struct obstack *,
+ const char *,
+ const char *));
\f
/* Specs are strings containing lines, each of which (if not blank)
is made up of a program name, and arguments separated by spaces.
%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
chosen in a way that is hard to predict even when previously
chosen file names are known. For example, `%g.s ... %g.o ... %g.s'
might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'. SUFFIX matches
- the regexp "[.A-Za-z]*" or the special string "%O", which is
- treated exactly as if %O had been pre-processed. Previously, %g
- was simply substituted with a file name chosen once per compilation,
- without regard to any appended suffix (which was therefore treated
- just like ordinary text), making such attacks more likely to succeed.
+ the regexp "[.A-Za-z]*%O"; "%O" is treated exactly as if it
+ had been pre-processed. Previously, %g was simply substituted
+ with a file name chosen once per compilation, without regard
+ to any appended suffix (which was therefore treated just like
+ ordinary text), making such attacks more likely to succeed.
%uSUFFIX
like %g, but generates a new temporary file name even if %uSUFFIX
was already seen.
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.
+ %.SUFFIX
+ substitutes .SUFFIX for the suffixes of a matched switch's args when
+ it is subsequently output with %*. SUFFIX is terminated by the next
+ space or %.
%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.
at all, but they are included among the output files, so they will
be linked.
%O substitutes the suffix for object files. Note that this is
- handled specially when it immediately follows %g, %u, or %U,
- because of the need for those to form complete file names. The
- handling is such that %O is treated exactly as if it had already
- been substituted, except that %g, %u, and %U do not currently
- support additional SUFFIX characters following %O as they would
- following, for example, `.o'.
+ handled specially when it immediately follows %g, %u, or %U
+ (with or without a suffix argument) because of the need for
+ those to form complete file names. The handling is such that
+ %O is treated exactly as if it had already been substituted,
+ except that %g, %u, and %U do not currently support additional
+ SUFFIX characters following %O as they would following, for
+ example, `.o'.
%p substitutes the standard macro predefinitions for the
current target machine. Use this when running cpp.
%P like %p, but puts `__' before and after the name of each macro.
and substitute the full name found.
%eSTR Print STR as an error message. STR is terminated by a newline.
Use this when inconsistent options are detected.
+ %nSTR Print STR as an notice. STR is terminated by a newline.
%x{OPTION} Accumulate an option for %X.
%X Output the accumulated linker options specified by compilations.
%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
%l process LINK_SPEC as a spec.
%L process LIB_SPEC as a spec.
%G process LIBGCC_SPEC as a spec.
+ %M output multilib_dir with directory separators replaced with "_";
+ if multilib_dir is not set or is ".", output "".
%S process STARTFILE_SPEC as a spec. A capital S is actually used here.
%E process ENDFILE_SPEC as a spec. A capital E is actually used here.
%c process SIGNED_CHAR_SPEC as a spec.
- %C process CPP_SPEC as a spec. A capital C is actually used here.
+ %C process CPP_SPEC as a spec.
%1 process CC1_SPEC as a spec.
%2 process CC1PLUS_SPEC as a spec.
%| output "-" if the input for the current command is coming from a pipe.
If that switch was not specified, this substitutes nothing.
Here S is a metasyntactic variable.
%{S*} substitutes all the switches specified to CC whose names start
- with -S. This is used for -o, -D, -I, etc; switches that take
+ with -S. This is used for -o, -I, etc; switches that take
arguments. CC considers `-o foo' as being one switch whose
name starts with `o'. %{o*} would substitute this text,
including the space; thus, two arguments would be generated.
%{^S*} likewise, but don't put a blank between a switch and any args.
+ %{S*&T*} likewise, but preserve order of S and T options (the order
+ of S and T in the spec is not significant). Can be any number
+ of ampersand-separated variables; for each the wild card is
+ optional. Useful for CPP as %{D*&U*&A*}.
%{S*:X} substitutes X if one or more switches whose names start with -S are
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.
+ %{<S} remove all occurences of -S from the command line.
+ Note - this option is position dependent. % commands in the
+ spec string before this option will see -S, % commands in the
+ spec string after this option will not.
%{S:X} substitutes X, but only if the -S switch was given to CC.
%{!S:X} substitutes X, but only if the -S switch was NOT given to CC.
%{|S:X} like %{S:X}, but if no S switch, substitute `-'.
#define LINKER_NAME "collect2"
#endif
-static char *cpp_spec = CPP_SPEC;
-static char *cpp_predefines = CPP_PREDEFINES;
-static char *cc1_spec = CC1_SPEC;
-static char *cc1plus_spec = CC1PLUS_SPEC;
-static char *signed_char_spec = SIGNED_CHAR_SPEC;
-static char *asm_spec = ASM_SPEC;
-static char *asm_final_spec = ASM_FINAL_SPEC;
-static char *link_spec = LINK_SPEC;
-static char *lib_spec = LIB_SPEC;
-static char *libgcc_spec = LIBGCC_SPEC;
-static char *endfile_spec = ENDFILE_SPEC;
-static char *startfile_spec = STARTFILE_SPEC;
-static char *switches_need_spaces = SWITCHES_NEED_SPACES;
-static char *linker_name_spec = LINKER_NAME;
+/* Here is the spec for running the linker, after compiling all files. */
+
+/* -u* was put back because both BSD and SysV seem to support it. */
+/* %{static:} simply prevents an error message if the target machine
+ doesn't handle -static. */
+/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
+ scripts which exist in user specified directories, or in standard
+ directories. */
+#ifndef LINK_COMMAND_SPEC
+#define LINK_COMMAND_SPEC "\
+%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+ %(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r} %{s} %{t}\
+ %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
+ %{static:} %{L*} %(link_libgcc) %o %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
+ %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
+#endif
+
+#ifndef LINK_LIBGCC_SPEC
+# ifdef LINK_LIBGCC_SPECIAL
+/* Don't generate -L options for startfile prefix list. */
+# define LINK_LIBGCC_SPEC ""
+# else
+/* Do generate them. */
+# define LINK_LIBGCC_SPEC "%D"
+# endif
+#endif
+
+static const char *cpp_spec = CPP_SPEC;
+static const char *cpp_predefines = CPP_PREDEFINES;
+static const char *cc1_spec = CC1_SPEC;
+static const char *cc1plus_spec = CC1PLUS_SPEC;
+static const char *signed_char_spec = SIGNED_CHAR_SPEC;
+static const char *asm_spec = ASM_SPEC;
+static const char *asm_final_spec = ASM_FINAL_SPEC;
+static const char *link_spec = LINK_SPEC;
+static const char *lib_spec = LIB_SPEC;
+static const char *libgcc_spec = LIBGCC_SPEC;
+static const char *endfile_spec = ENDFILE_SPEC;
+static const char *startfile_spec = STARTFILE_SPEC;
+static const char *switches_need_spaces = SWITCHES_NEED_SPACES;
+static const char *linker_name_spec = LINKER_NAME;
+static const char *link_command_spec = LINK_COMMAND_SPEC;
+static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
+
+/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
+ There should be no need to override these in target dependent files,
+ but we need to copy them to the specs file so that newer versions
+ of the GCC driver can correctly drive older tool chains with the
+ appropriate -B options. */
+
+static const char *trad_capable_cpp =
+"%{traditional|ftraditional|traditional-cpp:trad}cpp0";
+
+static const char *cpp_options =
+"%{C:%{!E:%eGNU C does not support -C without using -E}}\
+ %{std*} %{nostdinc*}\
+ %{C} %{v} %{I*} %{P} %{$} %I\
+ %{MD:-M -MF %W{!o: %b.d}%W{o*:%.d%*}}\
+ %{MMD:-MM -MF %W{!o: %b.d}%W{o*:%.d%*}}\
+ %{M} %{MM} %W{MF*} %{MG} %{MP} %{MQ*} %{MT*} %{M|MD|MM|MMD:%{o*:-MQ %*}}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
+ %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
+ %{fshort-wchar:-U__WCHAR_TYPE__ -D__WCHAR_TYPE__=short\\ unsigned\\ int}\
+ %{ffreestanding:-D__STDC_HOSTED__=0} %{fno-hosted:-D__STDC_HOSTED__=0}\
+ %{!ffreestanding:%{!fno-hosted:-D__STDC_HOSTED__=1}}\
+ %{fshow-column} %{fno-show-column}\
+ %{fleading-underscore} %{fno-leading-underscore}\
+ %{fno-operator-names} %{ftabstop=*} %{remap}\
+ %{g3:-dD} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*&U*&A*} %{i*} %Z %i\
+ %{E:%{!M*:%W{o*}}}";
+
+/* NB: This is shared amongst all front-ends. */
+static const char *cc1_options =
+"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+ %1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*} %{ansi}\
+ %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
+ %{aux-info*} %{Qn:-fno-ident} %{--help:--help}\
+ %{--target-help:--target-help}\
+ %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
+ %{fsyntax-only:-o %j}";
+
+static const char *asm_options =
+"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
+
+static const char *invoke_as =
+"%{!S:-o %{|!pipe:%g.s} |\n as %(asm_options) %{!pipe:%g.s} %A }";
/* Some compilers have limits on line lengths, and the multilib_select
and/or multilib_matches strings can be very long, so we build them at
run time. */
static struct obstack multilib_obstack;
-static char *multilib_select;
-static char *multilib_matches;
-static char *multilib_defaults;
+static const char *multilib_select;
+static const char *multilib_matches;
+static const char *multilib_defaults;
+static const char *multilib_exclusions;
#include "multilib.h"
/* Check whether a particular argument is a default argument. */
#define MULTILIB_DEFAULTS { "" }
#endif
-static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
+static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
-struct user_specs {
+struct user_specs
+{
struct user_specs *next;
const char *filename;
};
|| !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
|| !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
|| !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
- || !strcmp (STR, "isystem") || !strcmp (STR, "specs"))
+ || !strcmp (STR, "isystem") || !strcmp (STR, "specs") \
+ || !strcmp (STR, "MF") || !strcmp (STR, "MT") || !strcmp (STR, "MQ"))
#ifndef WORD_SWITCH_TAKES_ARG
#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
#endif
\f
-
#ifdef HAVE_EXECUTABLE_SUFFIX
/* This defines which switches stop a full compilation. */
#define DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR) \
const char *suffix; /* Use this compiler for input files
whose names end in this suffix. */
- const char *spec[4]; /* To use this compiler, concatenate these
- specs and pass to do_spec. */
+ const char *spec; /* To use this compiler, run this spec. */
+
+ const char *cpp_spec; /* If non-NULL, substitute this spec
+ for `%C', rather than the usual
+ cpp_spec. */
};
/* Pointer to a vector of `struct compiler' that gives the spec for
were not present when we built the driver, we will hit these copies
and be given a more meaningful error than "file not used since
linking is not done". */
- {".m", {"#Objective-C"}},
- {".cc", {"#C++"}}, {".cxx", {"#C++"}}, {".cpp", {"#C++"}},
- {".c++", {"#C++"}}, {".C", {"#C++"}},
- {".ads", {"#Ada"}}, {".adb", {"#Ada"}}, {".ada", {"#Ada"}},
- {".f", {"#Fortran"}}, {".for", {"#Fortran"}}, {".F", {"#Fortran"}},
- {".fpp", {"#Fortran"}},
- {".p", {"#Pascal"}}, {".pas", {"#Pascal"}},
+ {".m", "#Objective-C"}, {".mi", "#Objective-C"},
+ {".cc", "#C++"}, {".cxx", "#C++"}, {".cpp", "#C++"}, {".cp", "#C++"},
+ {".c++", "#C++"}, {".C", "#C++"}, {".ii", "#C++"},
+ {".ads", "#Ada"}, {".adb", "#Ada"}, {".ada", "#Ada"},
+ {".f", "#Fortran"}, {".for", "#Fortran"}, {".fpp", "#Fortran"},
+ {".F", "#Fortran"}, {".FOR", "#Fortran"}, {".FPP", "#Fortran"},
+ {".r", "#Ratfor"},
+ {".p", "#Pascal"}, {".pas", "#Pascal"},
+ {".ch", "#Chill"}, {".chi", "#Chill"},
+ {".java", "#Java"}, {".class", "#Java"},
+ {".zip", "#Java"}, {".jar", "#Java"},
/* Next come the entries for C. */
- {".c", {"@c"}},
+ {".c", "@c"},
{"@c",
- {
-#if USE_CPPLIB
- "%{E|M|MM:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
- %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
- %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
- %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
- %i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}\
- %{!E:%{!M:%{!MM:cc1 %i %1 \
- %{std*} %{nostdinc*} %{A*} %{I*} %I\
- %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
- %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
- %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
- %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{H} %C %{D*} %{U*} %{i*} %Z\
- %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
- %{aux-info*} %{Qn:-fno-ident}\
- %{--help:--help}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*}\
- %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
- %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
- %{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"
-#else /* ! USE_CPPLIB */
- "cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
- %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
- %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
- %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
- %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
- "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
- %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
- %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
- %{aux-info*} %{Qn:-fno-ident}\
- %{--help:--help} \
- %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
- %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
- %{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"
-#endif /* ! USE_CPPLIB */
- }},
+ /* cc1 has an integrated ISO C preprocessor. We should invoke the
+ external preprocessor if -save-temps or -traditional is given. */
+ "%{E|M|MM:%(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)}\
+ %{!E:%{!M:%{!MM:\
+ %{save-temps:%(trad_capable_cpp) -lang-c %{ansi:-std=c89}\
+ %(cpp_options) %b.i \n\
+ cc1 -fpreprocessed %b.i %(cc1_options)}\
+ %{!save-temps:\
+ %{traditional|ftraditional|traditional-cpp:\
+ tradcpp0 -lang-c %{ansi:-std=c89} %(cpp_options) %{!pipe:%g.i} |\n\
+ cc1 -fpreprocessed %{!pipe:%g.i} %(cc1_options)}\
+ %{!traditional:%{!ftraditional:%{!traditional-cpp:\
+ cc1 -lang-c %{ansi:-std=c89} %(cpp_options) %(cc1_options)}}}}\
+ %{!fsyntax-only:%(invoke_as)}}}}"},
{"-",
- {"%{E:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
- %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
- %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
- %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
- %i %W{o*}}\
- %{!E:%e-E required when input is from standard input}"}},
- {".h", {"@c-header"}},
+ "%{!E:%e-E required when input is from standard input}\
+ %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)"},
+ {".h", "@c-header"},
{"@c-header",
- {"%{!E:%eCompilation of header file requested} \
- cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
- %{std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
- %{!undef:%{!std=*:%p}%{std=gnu*:%p} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
- %i %W{o*}"}},
- {".i", {"@cpp-output"}},
+ "%{!E:%eCompilation of header file requested} \
+ %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)"},
+ {".i", "@cpp-output"},
{"@cpp-output",
- {"%{!M:%{!MM:%{!E:cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a*}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
- %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
- %{aux-info*} %{Qn:-fno-ident} -fpreprocessed\
- %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
- %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
- %{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"}},
- {".s", {"@assembler"}},
+ "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}"},
+ {".s", "@assembler"},
{"@assembler",
- {"%{!M:%{!MM:%{!E:%{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %i %A\n }}}}"}},
- {".S", {"@assembler-with-cpp"}},
+ "%{!M:%{!MM:%{!E:%{!S:as %(asm_options) %i %A }}}}"},
+ {".S", "@assembler-with-cpp"},
{"@assembler-with-cpp",
- {"cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} %{trigraphs}\
- -$ %{!undef:%p %P} -D__ASSEMBLER__ \
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{ffast-math:-D__FAST_MATH__}\
- %{fshort-wchar:-D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
- %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
- "%{!M:%{!MM:%{!E:%{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"}},
+ "%(trad_capable_cpp) -lang-asm %(cpp_options)\
+ %{!M:%{!MM:%{!E:%(invoke_as)}}}"},
#include "specs.h"
/* Mark end of table */
- {0, {0}}
+ {0, 0}
};
/* Number of elements in default_compilers, not counting the terminator. */
static int n_default_compilers
= (sizeof default_compilers / sizeof (struct compiler)) - 1;
-/* Here is the spec for running the linker, after compiling all files. */
-
-/* -u* was put back because both BSD and SysV seem to support it. */
-/* %{static:} simply prevents an error message if the target machine
- doesn't handle -static. */
-/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
- scripts which exist in user specified directories, or in standard
- directories. */
-#ifdef LINK_COMMAND_SPEC
-/* Provide option to override link_command_spec from machine specific
- configuration files. */
-static const char *link_command_spec =
- LINK_COMMAND_SPEC;
-#else
-#ifdef LINK_LIBGCC_SPECIAL
-/* Don't generate -L options. */
-static const char *link_command_spec = "\
-%{!fsyntax-only: \
- %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
- %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
- %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
- %{static:} %{L*} %o\
- %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
- {"--pass-exit-codes", "-pass-exit-codes", 0},
- %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
- %{T*}\
- \n }}}}}}";
-#else
-/* Use -L. */
-static const char *link_command_spec = "\
-%{!fsyntax-only: \
- %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
- %{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
- %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
- %{static:} %{L*} %D %o\
- %{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
- %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
- %{T*}\
- \n }}}}}}";
-#endif
-#endif
-
/* A vector of options to give to the linker.
These options are accumulated by %x,
and substituted into the linker command with %X. */
static void
translate_options (argcp, argvp)
int *argcp;
- const char ***argvp;
+ const char *const **argvp;
{
int i;
int argc = *argcp;
- const char **argv = *argvp;
+ const char *const *argv = *argvp;
const char **newv =
(const char **) xmalloc ((argc + 2) * 2 * sizeof (const char *));
int newindex = 0;
{
size_t j;
/* Find a mapping that applies to this option. */
- for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
+ for (j = 0; j < ARRAY_SIZE (option_map); j++)
{
size_t optlen = strlen (option_map[j].name);
size_t arglen = strlen (argv[i]);
if (arglen < optlen)
{
size_t k;
- for (k = j + 1;
- k < sizeof (option_map) / sizeof (option_map[0]);
- k++)
+ for (k = j + 1; k < ARRAY_SIZE (option_map); k++)
if (strlen (option_map[k].name) >= arglen
&& !strncmp (argv[i], option_map[k].name, arglen))
{
break;
}
- if (k != sizeof (option_map) / sizeof (option_map[0]))
+ if (k != ARRAY_SIZE (option_map))
break;
}
/* 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.
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)
{
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",
}
/* 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)
p++;
else if (*p == '#')
{
- while (*p != '\n') p++;
+ while (*p != '\n')
+ p++;
p++;
}
else
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;
\f
/* Structure to keep track of the specs that have been defined so far.
These are accessed using %(specname) or %[specname] in a compiler
{
/* 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),
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;
\f
+/* Add appropriate libgcc specs to OBSTACK, taking into account
+ various permutations of -shared-libgcc, -shared, and such. */
+
+static void
+init_gcc_specs (obstack, shared_name, static_name)
+ struct obstack *obstack;
+ const char *shared_name;
+ const char *static_name;
+{
+ char buffer[128];
+
+ /* If we see -shared-libgcc, then use the shared version. */
+ sprintf (buffer, "%%{shared-libgcc:%s}", shared_name);
+ obstack_grow (obstack, buffer, strlen (buffer));
+ /* If we see -static-libgcc, then use the shared version. */
+ sprintf (buffer, "%%{static-libgcc:%s}", static_name);
+ obstack_grow (obstack, buffer, strlen (buffer));
+ /* Otherwise, if we see -shared, then use the shared version. */
+ sprintf (buffer,
+ "%%{!shared-libgcc:%%{!static-libgcc:%%{shared:%s}}}",
+ shared_name);
+ obstack_grow (obstack, buffer, strlen (buffer));
+ /* Otherwise, use the static version. */
+ sprintf (buffer,
+ "%%{!shared-libgcc:%%{!static-libgcc:%%{!shared:%s}}}",
+ static_name);
+ obstack_grow (obstack, buffer, strlen (buffer));
+}
+
/* 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;
}
#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;
next = sl;
}
+#ifdef ENABLE_SHARED_LIBGCC
+ /* ??? If neither -shared-libgcc nor --static-libgcc was
+ seen, then we should be making an educated guess. Some proposed
+ heuristics for ELF include:
+
+ (1) If "-Wl,--export-dynamic", then it's a fair bet that the
+ program will be doing dynamic loading, which will likely
+ need the shared libgcc.
+
+ (2) If "-ldl", then it's also a fair bet that we're doing
+ dynamic loading.
+
+ (3) For each ET_DYN we're linking against (either through -lfoo
+ or /some/path/foo.so), check to see whether it or one of
+ its dependancies depends on a shared libgcc.
+
+ (4) If "-shared"
+
+ If the runtime is fixed to look for program headers instead
+ of calling __register_frame_info at all, for each object,
+ use the shared libgcc if any EH symbol referenced.
+
+ If crtstuff is fixed to not invoke __register_frame_info
+ automatically, for each object, use the shared libgcc if
+ any non-empty unwind section found.
+
+ Doing any of this probably requires invoking an external program to
+ do the actual object file scanning. */
+ {
+ const char *p = libgcc_spec;
+ int in_sep = 1;
+
+ /* Transform the extant libgcc_spec into one that uses the shared libgcc
+ when given the proper command line arguments. */
+ while (*p)
+ {
+ if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
+ {
+ init_gcc_specs (&obstack,
+#ifdef NO_SHARED_LIBGCC_MULTILIB
+ "-lgcc_s"
+#else
+ "-lgcc_s%M"
+#endif
+ ,
+ "-lgcc");
+ p += 5;
+ in_sep = 0;
+ }
+ else if (in_sep && *p == 'l' && strncmp (p, "libgcc.a%s", 10) == 0)
+ {
+ /* Ug. We don't know shared library extensions. Hope that
+ systems that use this form don't do shared libraries. */
+ init_gcc_specs (&obstack,
+#ifdef NO_SHARED_LIBGCC_MULTILIB
+ "-lgcc_s"
+#else
+ "-lgcc_s%M"
+#endif
+ ,
+ "libgcc.a%s");
+ p += 10;
+ in_sep = 0;
+ }
+ else
+ {
+ obstack_1grow (&obstack, *p);
+ in_sep = (*p == ' ');
+ p += 1;
+ }
+ }
+
+ obstack_1grow (&obstack, '\0');
+ libgcc_spec = obstack_finish (&obstack);
+ }
+#endif
+
specs = sl;
}
-
\f
/* 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
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;
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;
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;
}
/* Vector of pointers to arguments in the current line of specifications. */
-static char **argbuf;
+static const char **argbuf;
/* Number of elements allocated in argbuf. */
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. */
int filename_length; /* strlen (filename). */
struct temp_name *next;
} *temp_names;
-#endif
-
/* Number of commands executed so far. */
static const char *programname;
\f
-/* 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;
-
-/* 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
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;
record_temp_file (arg, delete_always, delete_failure);
}
\f
-/* 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);
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)
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'))
{
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",
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')
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';
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;
(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]);
}
/* 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.
int always_delete;
int fail_delete;
{
- register char * const name = xstrdup (filename);
+ register char *const name = xstrdup (filename);
if (always_delete)
{
}
/* 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 */
\f
/* Build a list of search directories from PATHS.
PREFIX is a string to prepend to the list.
int first_time = TRUE;
struct prefix_list *pprefix;
- obstack_grow (&collect_obstack, prefix, strlen (prefix));
+ obstack_grow (&collect_obstack, prefix, strlen (prefix));
+ obstack_1grow (&collect_obstack, '=');
+
+ for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
+ {
+ int len = strlen (pprefix->prefix);
+
+ if (machine_suffix
+ && (! check_dir_p
+ || is_directory (pprefix->prefix, machine_suffix, 0)))
+ {
+ 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);
+ }
+
+ if (just_machine_suffix
+ && pprefix->require_machine_suffix == 2
+ && (! check_dir_p
+ || is_directory (pprefix->prefix, just_machine_suffix, 0)))
+ {
+ 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,
+ just_suffix_len);
+ }
+
+ if (! pprefix->require_machine_suffix)
+ {
+ if (! first_time)
+ obstack_1grow (&collect_obstack, PATH_SEPARATOR);
+
+ first_time = FALSE;
+ obstack_grow (&collect_obstack, pprefix->prefix, len);
+ }
+ }
+
+ obstack_1grow (&collect_obstack, '\0');
+ return obstack_finish (&collect_obstack);
+}
+
+/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
+ for collect. */
+
+static void
+putenv_from_prefixes (paths, env_var)
+ struct path_prefix *paths;
+ const char *env_var;
+{
+ putenv (build_search_list (paths, env_var, 1));
+}
+\f
+#ifndef VMS
+
+/* FIXME: the location independence code for VMS is hairier than this,
+ and hasn't been written. */
+
+/* Split a filename into component directories. */
+
+static char **
+split_directories (name, ptr_num_dirs)
+ const char *name;
+ int *ptr_num_dirs;
+{
+ int num_dirs = 0;
+ char **dirs;
+ const char *p, *q;
+ int ch;
+
+ /* Count the number of directories. Special case MSDOS disk names as part
+ of the initial directory. */
+ p = name;
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+ if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
+ {
+ p += 3;
+ num_dirs++;
+ }
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
+
+ while ((ch = *p++) != '\0')
+ {
+ if (IS_DIR_SEPARATOR (ch))
+ {
+ num_dirs++;
+ while (IS_DIR_SEPARATOR (*p))
+ p++;
+ }
+ }
+
+ dirs = (char **) xmalloc (sizeof (char *) * (num_dirs + 2));
+
+ /* Now copy the directory parts. */
+ num_dirs = 0;
+ p = name;
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+ if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
+ {
+ dirs[num_dirs++] = save_string (p, 3);
+ p += 3;
+ }
+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
+
+ q = p;
+ while ((ch = *p++) != '\0')
+ {
+ if (IS_DIR_SEPARATOR (ch))
+ {
+ while (IS_DIR_SEPARATOR (*p))
+ p++;
+
+ dirs[num_dirs++] = save_string (q, p - q);
+ q = p;
+ }
+ }
+
+ if (p - 1 - q > 0)
+ dirs[num_dirs++] = save_string (q, p - 1 - q);
+
+ dirs[num_dirs] = NULL_PTR;
+ if (ptr_num_dirs)
+ *ptr_num_dirs = num_dirs;
+
+ return dirs;
+}
+
+/* Release storage held by split directories. */
+
+static void
+free_split_directories (dirs)
+ char **dirs;
+{
+ int i = 0;
+
+ while (dirs[i] != NULL_PTR)
+ free (dirs[i++]);
+
+ free ((char *) dirs);
+}
+
+/* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string that gets
+ to PREFIX starting with the directory portion of PROGNAME and a relative
+ pathname of the difference between BIN_PREFIX and PREFIX.
+
+ 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 /red/green/blue/../omega.
+
+ If no relative prefix can be found, return NULL. */
+
+static char *
+make_relative_prefix (progname, bin_prefix, prefix)
+ const char *progname;
+ const char *bin_prefix;
+ const char *prefix;
+{
+ char **prog_dirs, **bin_dirs, **prefix_dirs;
+ int prog_num, bin_num, prefix_num, std_loc_p;
+ int i, n, common;
+
+ prog_dirs = split_directories (progname, &prog_num);
+ bin_dirs = split_directories (bin_prefix, &bin_num);
- for (pprefix = paths->plist; pprefix != 0; pprefix = pprefix->next)
+ /* If there is no full pathname, try to find the program by checking in each
+ of the directories specified in the PATH environment variable. */
+ if (prog_num == 1)
{
- int len = strlen (pprefix->prefix);
+ char *temp;
- if (machine_suffix
- && (! check_dir_p
- || is_directory (pprefix->prefix, machine_suffix, 0)))
+ GET_ENV_PATH_LIST (temp, "PATH");
+ if (temp)
{
- 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);
+ char *startp, *endp;
+ char *nstore = (char *) alloca (strlen (temp) + strlen (progname) + 1);
+
+ startp = endp = temp;
+ while (1)
+ {
+ if (*endp == PATH_SEPARATOR || *endp == 0)
+ {
+ if (endp == startp)
+ {
+ nstore[0] = '.';
+ nstore[1] = DIR_SEPARATOR;
+ nstore[2] = '\0';
+ }
+ else
+ {
+ strncpy (nstore, startp, endp - startp);
+ if (! IS_DIR_SEPARATOR (endp[-1]))
+ {
+ nstore[endp - startp] = DIR_SEPARATOR;
+ nstore[endp - startp + 1] = 0;
+ }
+ else
+ nstore[endp - startp] = 0;
+ }
+ strcat (nstore, progname);
+ if (! access (nstore, X_OK)
+#ifdef HAVE_EXECUTABLE_SUFFIX
+ || ! access (strcat (nstore, EXECUTABLE_SUFFIX), X_OK)
+#endif
+ )
+ {
+ free_split_directories (prog_dirs);
+ progname = nstore;
+ prog_dirs = split_directories (progname, &prog_num);
+ break;
+ }
+
+ if (*endp == 0)
+ break;
+ endp = startp = endp + 1;
+ }
+ else
+ endp++;
+ }
}
+ }
- if (just_machine_suffix
- && pprefix->require_machine_suffix == 2
- && (! check_dir_p
- || is_directory (pprefix->prefix, just_machine_suffix, 0)))
+ /* Remove the program name from comparison of directory names. */
+ prog_num--;
+
+ /* Determine if the compiler is installed in the standard location, and if
+ so, we don't need to specify relative directories. Also, if argv[0]
+ doesn't contain any directory specifiers, there is not much we can do. */
+ std_loc_p = 0;
+ if (prog_num == bin_num)
+ {
+ for (i = 0; i < bin_num; i++)
{
- 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,
- just_suffix_len);
+ if (strcmp (prog_dirs[i], bin_dirs[i]) != 0)
+ break;
}
- if (! pprefix->require_machine_suffix)
+ if (prog_num <= 0 || i == bin_num)
{
- if (! first_time)
- obstack_1grow (&collect_obstack, PATH_SEPARATOR);
-
- first_time = FALSE;
- obstack_grow (&collect_obstack, pprefix->prefix, len);
+ std_loc_p = 1;
+ free_split_directories (prog_dirs);
+ free_split_directories (bin_dirs);
+ prog_dirs = bin_dirs = (char **) 0;
+ return NULL_PTR;
}
}
- obstack_1grow (&collect_obstack, '\0');
- return obstack_finish (&collect_obstack);
-}
+ prefix_dirs = split_directories (prefix, &prefix_num);
-/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
- for collect. */
+ /* 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++)
+ {
+ if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0)
+ break;
+ }
-static void
-putenv_from_prefixes (paths, env_var)
- struct path_prefix *paths;
- const char *env_var;
-{
- putenv (build_search_list (paths, env_var, 1));
+ /* If there are no common directories, there can be no relative prefix. */
+ if (common == 0)
+ {
+ free_split_directories (prog_dirs);
+ free_split_directories (bin_dirs);
+ free_split_directories (prefix_dirs);
+ return NULL_PTR;
+ }
+
+ /* Build up the pathnames in argv[0]. */
+ for (i = 0; i < prog_num; i++)
+ obstack_grow (&obstack, prog_dirs[i], strlen (prog_dirs[i]));
+
+ /* Now build up the ..'s. */
+ for (i = common; i < n; i++)
+ {
+ obstack_grow (&obstack, DIR_UP, sizeof (DIR_UP) - 1);
+ obstack_1grow (&obstack, DIR_SEPARATOR);
+ }
+
+ /* Put in directories to move over to prefix. */
+ for (i = common; i < prefix_num; i++)
+ obstack_grow (&obstack, prefix_dirs[i], strlen (prefix_dirs[i]));
+
+ free_split_directories (prog_dirs);
+ free_split_directories (bin_dirs);
+ free_split_directories (prefix_dirs);
+
+ obstack_1grow (&obstack, '\0');
+ return obstack_finish (&obstack);
}
+#endif /* VMS */
\f
/* Check whether NAME can be accessed in MODE. This is like access,
except that it never considers directories to be executable. */
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
/* Determine the filename to execute (special case for absolute paths). */
- if (IS_DIR_SEPARATOR (*name)
-#ifdef HAVE_DOS_BASED_FILESYSTEM
- /* 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)
{
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
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 */
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;
}
-
\f
/* Execute the command specified by the arguments on the current line of spec.
When using pipes, this includes several piped-together commands
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. */
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.
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];
/* 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);
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)
pfatal_pexecute (errmsg_fmt, errmsg_arg);
if (string != commands[i].prog)
- free (string);
+ free ((PTR) string);
}
execution_count++;
int ret_code = 0;
#ifdef HAVE_GETRUSAGE
struct timeval d;
- double ut, st;
+ double ut = 0.0, st = 0.0;
#endif
- for (i = 0; i < n_commands; )
+ for (i = 0; i < n_commands;)
{
int j;
int status;
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
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)
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 %{<S})
The `validated' field is nonzero if any spec has looked at this switch;
if it remains zero at the end of the run, it must be meaningless. */
+#define SWITCH_OK 0
+#define SWITCH_FALSE -1
+#define SWITCH_IGNORE -2
+#define SWITCH_LIVE 1
+
struct switchstr
{
const char *part1;
- char **args;
+ const char **args;
int live_cond;
- int validated;
+ unsigned char validated;
+ unsigned char ordering;
};
static struct switchstr *switches;
/* Gives value to pass as "warn" to add_prefix for standard prefixes. */
static int *warn_std_ptr = 0;
-
\f
#if defined(HAVE_OBJECT_SUFFIX) || defined(HAVE_EXECUTABLE_SUFFIX)
if (name == NULL)
return NULL;
-
+
len = strlen (name);
#ifdef HAVE_OBJECT_SUFFIX
}
#endif
-#ifdef HAVE_EXECUTABLE_SUFFIX
+#if defined(HAVE_EXECUTABLE_SUFFIX) && !defined(NO_AUTO_EXE_SUFFIX)
/* If there is no filetype, make it the executable suffix (which includes
the "."). But don't get confused if we have just "-o". */
if (! do_exe || EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
static void
display_help ()
{
- printf ("Usage: %s [options] file...\n", programname);
- printf ("Options:\n");
+ printf (_("Usage: %s [options] file...\n"), programname);
+ fputs (_("Options:\n"), stdout);
- printf (" -pass-exit-codes Exit with highest error code from a phase\n");
- printf (" --help Display this information\n");
+ fputs (_(" -pass-exit-codes Exit with highest error code from a phase\n"), stdout);
+ fputs (_(" --help Display this information\n"), stdout);
+ fputs (_(" --target-help Display target specific command line options\n"), stdout);
if (! verbose_flag)
- printf (" (Use '-v --help' to display command line options of sub-processes)\n");
- printf (" -dumpspecs Display all of the built in spec strings\n");
- printf (" -dumpversion Display the version of the compiler\n");
- printf (" -dumpmachine Display the compiler's target processor\n");
- printf (" -print-search-dirs Display the directories in the compiler's search path\n");
- printf (" -print-libgcc-file-name Display the name of the compiler's companion library\n");
- printf (" -print-file-name=<lib> Display the full path to library <lib>\n");
- printf (" -print-prog-name=<prog> Display the full path to compiler component <prog>\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,<options> Pass comma-separated <options> on to the assembler\n");
- printf (" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n");
- printf (" -Wl,<options> Pass comma-separated <options> on to the linker\n");
- printf (" -Xlinker <arg> Pass <arg> 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=<file> Override builtin specs with the contents of <file>\n");
- printf (" -std=<standard> Assume that the input sources are for <standard>\n");
- printf (" -B <directory> Add <directory> to the compiler's search paths\n");
- printf (" -b <machine> Run gcc for target <machine>, if installed\n");
- printf (" -V <version> Run gcc version number <version>, 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 <file> Place the output into <file>\n");
- printf (" -x <language> 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<letter> 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=<lib> Display the full path to library <lib>\n"), stdout);
+ fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>\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,<options> Pass comma-separated <options> on to the assembler\n"), stdout);
+ fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout);
+ fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker\n"), stdout);
+ fputs (_(" -Xlinker <arg> Pass <arg> 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=<file> Override builtin specs with the contents of <file>\n"), stdout);
+ fputs (_(" -std=<standard> Assume that the input sources are for <standard>\n"), stdout);
+ fputs (_(" -B <directory> Add <directory> to the compiler's search paths\n"), stdout);
+ fputs (_(" -b <machine> Run gcc for target <machine>, if installed\n"), stdout);
+ fputs (_(" -V <version> Run gcc version number <version>, 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 <file> Place the output into <file>\n"), stdout);
+ fputs (_("\
+ -x <language> 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<letter> 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 *));
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++;
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++;
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");
/* Figure compiler version from version string. */
- compiler_version = temp1 = xstrdup (version_string);
+ compiler_version = temp1 = xstrdup (version_string);
for (; *temp1; ++temp1)
{
}
}
- /* Set up the default search paths. */
+ /* Set up the default search paths. If there is no GCC_EXEC_PREFIX,
+ see if we can create it from the pathname specified in argv[0]. */
+
+#ifndef VMS
+ /* FIXME: make_relative_prefix doesn't yet work for VMS. */
+ if (!gcc_exec_prefix)
+ {
+ gcc_exec_prefix = make_relative_prefix (argv[0], standard_bindir_prefix,
+ standard_exec_prefix);
+ if (gcc_exec_prefix)
+ putenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL_PTR));
+ }
+#endif
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
{
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;
}
}
- GET_ENV_PATH_LIST (temp, "LIBRARY_PATH");
+ GET_ENV_PATH_LIST (temp, LIBRARY_PATH_ENV);
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
{
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;
{
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;
/* 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++)
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"))
else if (! strcmp (argv[i], "-dumpmachine"))
{
printf ("%s\n", spec_machine);
- exit (0);
+ exit (0);
}
else if (strcmp (argv[i], "-fhelp") == 0)
{
/* 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;
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);
}
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);
}
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;
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
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)
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
{
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;
if (! have_c)
{
int skip;
-
+
/* Forward scan, just in case -S or -c is specified
after -o. */
int j = i + 1;
#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
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))
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
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)
{
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 *)
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))
;
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)
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].validated = 0;
-
+ switches[n_switches].live_cond = SWITCH_OK;
+ switches[n_switches].validated = 0;
+
n_switches++;
}
}
-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++;
}
{
/* -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')
{
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].ordering = 0;
+ /* These are always valid, since gcc.c itself understands it. */
+ if (!strcmp (p, "save-temps")
+ || !strcmp (p, "static-libgcc")
+ || !strcmp (p, "shared-libgcc"))
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
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++;
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;
+/* The compiler used to process the current input file. */
+static struct compiler *input_file_compiler;
+
/* These are variables used within do_spec and do_spec_1. */
/* Nonzero if an arg has been started and not yet terminated
/* Nonzero means that the input of this command is coming from a pipe. */
static int input_from_pipe;
+/* Nonnull means substitute this for any suffix when outputting a switches
+ arguments. */
+static const char *suffix_subst;
+
/* Process the spec SPEC and run the commands specified therein.
Returns 0 if the spec is successfully processed; -1 if failed. */
this_is_output_file = 0;
this_is_library_file = 0;
input_from_pipe = 0;
+ suffix_subst = NULL;
value = do_spec_1 (spec, 0, NULL_PTR);
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;
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. */
{
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;
- error (buf);
+ error ("%s", buf);
return -1;
}
break;
+ case 'n':
+ /* %nfoo means report an notice with `foo' on stderr. */
+ {
+ const char *q = p;
+ char *buf;
+ while (*p != 0 && *p != '\n')
+ p++;
+ buf = (char *) alloca (p - q + 1);
+ strncpy (buf, q, p - q);
+ buf[p - q] = 0;
+ notice ("%s\n", buf);
+ if (*p)
+ p++;
+ }
+ 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':
}
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))
+ 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 ();
- suffix = OBJECT_SUFFIX;
- suffix_length = strlen (OBJECT_SUFFIX);
- }
- else
- {
- while (*p == '.' || ISALPHA ((unsigned char)*p))
- p++;
- suffix_length = p - suffix;
+ if (suffix_length == 0)
+ suffix = OBJECT_SUFFIX;
+ else
+ {
+ saved_suffix
+ = (char *) xmalloc (suffix_length
+ + strlen (OBJECT_SUFFIX));
+ strncpy (saved_suffix, suffix, suffix_length);
+ strcpy (saved_suffix + suffix_length,
+ OBJECT_SUFFIX);
+ }
+ suffix_length += strlen (OBJECT_SUFFIX);
}
/* See if we already have an association of %g/%u/%U and
&& 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)
{
t->filename_length = temp_filename_length;
}
+ 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
- delete_this_arg = 1;
}
arg_going = 1;
break;
break;
case 'C':
- value = do_spec_1 (cpp_spec, 0, NULL_PTR);
- if (value != 0)
- return value;
+ {
+ const char* spec
+ = (input_file_compiler->cpp_spec
+ ? input_file_compiler->cpp_spec
+ : cpp_spec);
+ value = do_spec_1 (spec, 0, NULL_PTR);
+ if (value != 0)
+ return value;
+ }
break;
case 'E':
return value;
break;
+ case 'M':
+ if (multilib_dir && strcmp (multilib_dir, ".") != 0)
+ {
+ char *p;
+ const char *q;
+ size_t len;
+
+ len = strlen (multilib_dir);
+ obstack_blank (&obstack, len + 1);
+ p = obstack_next_free (&obstack) - (len + 1);
+
+ *p++ = '_';
+ for (q = multilib_dir; *q ; ++q, ++p)
+ *p = (IS_DIR_SEPARATOR (*q) ? '_' : *q);
+ }
+ break;
+
case 'p':
{
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;
{
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)
{
*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;
*x++ = *y++;
if (flag)
- {
- *x++ = '_';
- *x++ = '_';
+ {
+ if (x[-1] != '_')
+ {
+ if (x[-2] != '_')
+ *x++ = '_';
+ *x++ = '_';
+ }
}
/* Copy the value given, if any. */
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. */
else if (*y == ' ' || *y == '\t')
/* Copy whitespace to the result. */
*x++ = *y++;
- /* Don't copy -A options */
+ /* Don't copy -A options. */
else
y++;
}
obstack_1grow (&obstack, '%');
break;
+ case '.':
+ {
+ unsigned len = 0;
+
+ while (p[len] && p[len] != ' ' && p[len] != '%')
+ len++;
+ suffix_subst = save_string (p - 1, len + 1);
+ p += len;
+ }
+ 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.
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))
{
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))
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++;
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]+)?([- ].*)? */
abort ();
/* If desired, advance to second version number. */
- if (c1 == '2')
+ if (c1 >= '2')
{
/* Set V after the first period. */
while (ISDIGIT (*v))
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;
break;
default:
- abort ();
+ error ("Spec failure: Unrecognised spec option '%c'", c);
+ break;
}
break;
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. */
{
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;
+ int ordered = 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;
++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 ();
+ }
+
+ next_ampersand:
filter = p;
- while (*p != ':' && *p != '}' && *p != '|') p++;
+ while (*p != ':' && *p != '}' && *p != '|' && *p != '&')
+ p++;
- if (*p == '|' && pipe_p)
+ if (*p == '|' && (pipe_p || ordered))
abort ();
if (!body)
{
- if (*p != '}')
- {
+ if (*p != '}' && *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] == '}')
&& do_spec_1 (save_string (body, endbody-body-1), 0, NULL_PTR) < 0)
return 0;
}
- else if (p[-1] == '*' && p[0] == '}')
+ else if (p[-1] == '*' && (p[0] == '}' || p[0] == '&'))
{
/* Substitute all matching switches as separate args. */
register int i;
- --p;
+
for (i = 0; i < n_switches; i++)
- if (!strncmp (switches[i].part1, filter, p - filter)
- && check_live_switch (i, p - filter))
- give_switch (i, 0, include_blanks);
+ if (!strncmp (switches[i].part1, filter, p - 1 - filter)
+ && check_live_switch (i, p - 1 - filter))
+ {
+ if (elide_switch)
+ {
+ switches[i].live_cond = SWITCH_IGNORE;
+ switches[i].validated = 1;
+ }
+ else
+ ordered = 1, switches[i].ordering = 1;
+ }
}
else
{
do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
/* Pass any arguments this switch has. */
give_switch (i, 1, 1);
+ suffix_subst = NULL;
}
/* We didn't match. Try again. */
&& check_live_switch (i, hard_match_len))
{
present = 1;
+ break;
}
}
}
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 if (ordered || *p == '&')
+ ordered = 1, switches[i].ordering = 1;
+ else if (*p == '}')
+ give_switch (i, 0, include_blanks);
else
- {
- if (do_spec_1 (save_string (body, endbody - body - 1),
- 0, NULL_PTR) < 0)
- return 0;
- }
+ /* Even if many alternatives are matched, only output once. */
+ true_once = 1;
}
else if (pipe_p)
{
if (*p++ == '|')
goto next_member;
+ if (p[-1] == '&')
+ {
+ body = 0;
+ goto next_ampersand;
+ }
+
+ if (ordered)
+ {
+ int i;
+ /* Doing this set of switches later preserves their command-line
+ ordering. This is needed for e.g. -U, -D and -A. */
+ for (i = 0; i < n_switches; i++)
+ if (switches[i].ordering == 1)
+ {
+ switches[i].ordering = 0;
+ give_switch (i, 0, include_blanks);
+ }
+ }
+ /* Process the spec just once, regardless of match count. */
+ else if (true_once)
+ {
+ if (do_spec_1 (save_string (body, endbody - body - 1),
+ 0, NULL_PTR) < 0)
+ return 0;
+ }
+
return endbody;
}
\f
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':
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
{
&& 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;
}
\f
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);
if (switches[switchnum].args != 0)
{
- char **p;
+ const char **p;
for (p = switches[switchnum].args; *p; p++)
{
+ const char *arg = *p;
+
if (include_blanks)
do_spec_1 (" ", 0, NULL_PTR);
- do_spec_1 (*p, 1, NULL_PTR);
+ if (suffix_subst)
+ {
+ unsigned length = strlen (arg);
+
+ while (length-- && !IS_DIR_SEPARATOR (arg[length]))
+ if (arg[length] == '.')
+ {
+ ((char *)arg)[length] = 0;
+ break;
+ }
+ do_spec_1 (arg, 1, NULL_PTR);
+ if (!arg[length])
+ {
+ ((char *)arg)[length] = '.';
+ do_spec_1 (suffix_subst, 1, NULL_PTR);
+ }
+ }
+ else
+ do_spec_1 (arg, 1, NULL_PTR);
}
}
/* 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 = "";
+}
\f
/* On fatal signals, delete all the temporary files. */
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;
--p;
programname = p;
+ xmalloc_set_program_name (programname);
+
+#ifdef GCC_DRIVER_HOST_INITIALIZATION
+ /* Perform host dependant initialization when needed. */
+ GCC_DRIVER_HOST_INITIALIZATION;
+#endif
+
+/* LC_CTYPE determines the character set used by the terminal so it has be set
+ to output messages correctly. */
+
#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_CTYPE, "");
setlocale (LC_MESSAGES, "");
+#else
+ setlocale (LC_ALL, "");
#endif
+
(void) bindtextdomain (PACKAGE, localedir);
(void) textdomain (PACKAGE);
if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
signal (SIGPIPE, fatal_error);
#endif
+ /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
+ receive the signal. A different setting is inheritable */
+ signal (SIGCHLD, SIG_DFL);
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);
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, ' ');
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
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. */
/* 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;
}
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. */
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"));
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_FILESYSTEM
- /* 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
/* 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);
/* 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);
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);
}
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 ("<URL:http://www.gnu.org/software/gcc/faq.html#bugreport>.\n");
-
+ printf (_("\nFor bug reporting instructions, please see:\n"));
+ printf ("%s.\n", GCCBUGURL);
+
return (0);
}
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. */
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. */
/* Figure out which compiler from the file's suffix. */
- cp = lookup_compiler (infiles[i].name, input_filename_length,
- infiles[i].language);
-
- if (cp)
+ input_file_compiler
+ = lookup_compiler (infiles[i].name, input_filename_length,
+ infiles[i].language);
+
+ if (input_file_compiler)
{
/* 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 (input_file_compiler->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, &input_file_compiler->spec[1]);
+ value = do_spec (input_file_compiler->spec);
if (value < 0)
this_file_error = 1;
}
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
{
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);
}
/* 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)
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. */
if (print_help_list)
{
- printf ("\nFor bug reporting instructions, please see:\n");
- printf ("<URL:http://www.gnu.org/software/gcc/faq.html#bugreport>\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);
{
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;
(!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;
}
\f
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;
}
/* Output an error message and exit */
void
-fatal VPROTO((const char *msgid, ...))
+fatal VPARAMS ((const char *msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char *msgid;
}
static void
-error VPROTO((const char *msgid, ...))
+error VPARAMS ((const char *msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char *msgid;
}
static void
-notice VPROTO((const char *msgid, ...))
+notice VPARAMS ((const char *msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char *msgid;
vfprintf (stderr, _(msgid), ap);
va_end (ap);
}
-
\f
static void
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++))
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 != '&')
+ 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
switches[i].validated = 1;
}
}
+
+ if (*p++ == '|' || p[-1] == '&')
+ goto next_member;
}
\f
/* Check whether a particular argument was used. The first time we
const char *p;
int len;
{
- struct mswitchstr {
- char *str;
- char *replace;
+ struct mswitchstr
+ {
+ const char *str;
+ const char *replace;
int len;
int rep_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')
abort ();
q++;
}
- *q = '\0';
matches[i].len = q - matches[i].str;
matches[i].replace = ++q;
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
{
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;
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++;
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)
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. */
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;
}
++p;
- }
+ }
}
/* Print out the multiple library subdirectory selection
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')
{
++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 ();
if (! skip)
{
- char *p1;
+ const char *p1;
for (p1 = last_path; p1 < p; p1++)
putchar (*p1);
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++)
{
}
}
}
+
putchar ('\n');
}