/* Compiler driver program that can handle many languages.
- Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
CC recognizes how to compile each input file by suffixes in the file names.
Once it knows which kind of compilation to perform, the procedure for
compilation is specified by a string called a "spec". */
-\f
-#include "config.h"
-
-#include <sys/types.h>
-#include <ctype.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <errno.h>
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h> /* May get R_OK, etc. on some systems. */
-#endif
+#include "config.h"
+#include "system.h"
+#include <signal.h>
#include "obstack.h"
-#include "gansidecl.h"
-
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-#include <stdio.h>
-
-#ifndef R_OK
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#endif
-
-/* ??? Need to find a GCC header to put these in. */
-extern int pexecute PROTO ((const char *, char * const *, const char *,
- const char *, char **, char **, int));
-extern int pwait PROTO ((int, int *, int));
-extern char *update_path PROTO((char *, char *));
-/* Flag arguments to pexecute. */
-#define PEXECUTE_FIRST 1
-#define PEXECUTE_LAST 2
-#define PEXECUTE_SEARCH 4
-#define PEXECUTE_VERBOSE 8
-
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
-#endif
-#ifndef WTERMSIG
-#define WTERMSIG(S) ((S) & 0x7f)
-#endif
-#ifndef WIFEXITED
-#define WIFEXITED(S) (((S) & 0xff) == 0)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
-#endif
+#include "intl.h"
+#include "prefix.h"
+#include "gcc.h"
#ifdef VMS
#define exit __posix_exit
#endif
-/* Define O_RDONLY if the system hasn't defined it for us. */
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
-#ifdef USG
-#define vfork fork
-#endif /* USG */
-
-/* Test if something is a normal file. */
-#ifndef S_ISREG
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
-
-/* Test if something is a directory. */
-#ifndef S_ISDIR
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif
-
/* By default there is no special suffix for executables. */
#ifdef EXECUTABLE_SUFFIX
#define HAVE_EXECUTABLE_SUFFIX
#define DIR_SEPARATOR '/'
#endif
+/* 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};
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-extern void free ();
-extern char *getenv ();
-
-extern char *choose_temp_base PROTO((void));
-
-#ifndef errno
-extern int errno;
-#endif
-
-#ifndef HAVE_STRERROR
-extern int sys_nerr;
-extern char *sys_errlist[];
-#else
-extern char *strerror();
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
#endif
#ifndef HAVE_KILL
/* Flag saying to print the full filename of this file
as found through our usual search mechanism. */
-static char *print_file_name = NULL;
+static const char *print_file_name = NULL;
/* As print_file_name, but search for executable file. */
-static char *print_prog_name = NULL;
+static const char *print_prog_name = NULL;
/* Flag saying to print the relative path we'd use to
find libgcc.a given the current compiler flags. */
static int print_multi_lib;
+/* Flag saying to print the command line options understood by gcc and its
+ sub-processes. */
+
+static int print_help_list;
+
/* Flag indicating whether we should print the command and arguments */
static int verbose_flag;
/* The target machine specified with -b. */
-static char *spec_machine = DEFAULT_TARGET_MACHINE;
+static const char *spec_machine = DEFAULT_TARGET_MACHINE;
/* Nonzero if cross-compiling.
When -b is used, the value comes from the `specs' file. */
struct path_prefix;
static void init_spec PROTO((void));
-static void read_specs PROTO((char *, int));
-static void set_spec PROTO((char *, char *));
-static struct compiler *lookup_compiler PROTO((char *, int, char *));
-static char *build_search_list PROTO((struct path_prefix *, char *, int));
-static void putenv_from_prefixes PROTO((struct path_prefix *, char *));
-static char *find_a_file PROTO((struct path_prefix *, char *, int));
-static void add_prefix PROTO((struct path_prefix *, char *, char *,
- int, int, int *));
+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((char *, int, int));
-static void delete_if_ordinary 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 char *handle_braces PROTO((char *));
-static char *save_string PROTO((char *, int));
-static char *concat PVPROTO((char *, ...));
-static int do_spec PROTO((char *));
-static int do_spec_1 PROTO((char *, int, char *));
-static char *find_file PROTO((char *));
-static int is_directory PROTO((char *, char *, int));
-static void validate_switches PROTO((char *));
+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((char *, int));
-static int default_arg PROTO((char *, 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((char *));
-static void perror_with_name PROTO((char *));
-static void pfatal_pexecute PROTO((char *, char *));
-#ifdef HAVE_VPRINTF
-static void fatal PVPROTO((char *, ...));
-static void error PVPROTO((char *, ...));
-#else
-/* We must not provide any prototype here, even if ANSI C. */
-static void fatal PROTO(());
-static void error PROTO(());
-#endif
-
-void fancy_abort ();
-char *xmalloc ();
-char *xrealloc ();
+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 *))
+ ATTRIBUTE_NORETURN;
+static void error PVPROTO((const char *, ...))
+ ATTRIBUTE_PRINTF_1;
+static void notice PVPROTO((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));
\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.
- %g substitute the temporary-file-name-base. This is a string chosen
- once per compilation. Different temporary file names are made by
- concatenation of constant strings on the end, as in `%g.s'.
- %g also has the same effect of %d.
- %u like %g, but make the temporary file name unique.
- %U returns the last file name generated with %u.
+ %gSUFFIX
+ substitute a file name that has suffix SUFFIX and is chosen
+ once per compilation, and mark the argument a la %d. To reduce
+ exposure to denial-of-service attacks, the file name is now
+ 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.
+ %uSUFFIX
+ like %g, but generates a new temporary file name even if %uSUFFIX
+ was already seen.
+ %USUFFIX
+ substitutes the last file name generated with %uSUFFIX, generating a
+ new one if there is no such last file name. In the absence of any
+ %uSUFFIX, this is just like %gSUFFIX, except they don't share
+ the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
+ would involve the generation of two distinct file names, one
+ 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.
%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.
Input files whose names have no recognized suffix are not compiled
at all, but they are included among the output files, so they will
be linked.
- %O substitutes the suffix for object files.
+ %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'.
%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.
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
used here. This can be used to run a post-processor after the
- assembler has done it's job.
+ assembler has done its job.
%D Dump out a -L option for each directory in startfile_prefixes.
If multilib_dir is set, extra entries are generated with it affixed.
%l process LINK_SPEC as a spec.
%{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'.
%{.S:X} substitutes X, but only if processing a file with suffix S.
%{!.S:X} substitutes X, but only if NOT processing a file with suffix S.
+ %{S|P:X} substitutes X if either -S or -P was given to CC. This may be
+ combined with ! and . as above binding stronger than the OR.
%(Spec) processes a specification defined in a specs file as *Spec:
%[Spec] as above, but put __ around -D arguments
value is ignored, except with {S*} where S is just one letter; this
passes all matching options.
-The character | is used to indicate that a command should be piped to
-the following command, but only if -pipe is specified.
+The character | at the beginning of the predicate text is used to indicate
+that a command should be piped to the following command, but only if -pipe
+is specified.
Note that it is built into CC which switches take arguments and which
do not. You might think it would be useful to generalize this to
#endif
#endif
+#ifndef LINKER_NAME
+#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 *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;
/* 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
#define MULTILIB_DEFAULTS { "" }
#endif
-static char *multilib_defaults_raw[] = MULTILIB_DEFAULTS;
+static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
struct user_specs {
struct user_specs *next;
- char *filename;
+ const char *filename;
};
static struct user_specs *user_specs_head, *user_specs_tail;
#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) \
+ ((CHAR) == 'c' || (CHAR) == 'S')
+
+#ifndef SWITCH_CURTAILS_COMPILATION
+#define SWITCH_CURTAILS_COMPILATION(CHAR) \
+ DEFAULT_SWITCH_CURTAILS_COMPILATION(CHAR)
+#endif
+#endif
+
/* Record the mapping from file suffixes for compilation specs. */
struct compiler
{
- char *suffix; /* Use this compiler for input files
+ const char *suffix; /* Use this compiler for input files
whose names end in this suffix. */
- char *spec[4]; /* To use this compiler, concatenate these
+ const char *spec[4]; /* To use this compiler, concatenate these
specs and pass to do_spec. */
};
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". */
- {".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"}},
+ {".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"}},
/* Next come the entries for C. */
- {".c", "@c"},
+ {".c", {"@c"}},
{"@c",
- "cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ {
+#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__}\
+ %{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__}\
+ %{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}\
- -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -D__STRICT_ANSI__}\
- %{!undef:%{!ansi:%p} %P} %{trigraphs} \
+ %{!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__}\
%{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*} %{ansi} \
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
%{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
- %{aux-info*}\
+ %{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 }}}}"},
+ %{!pipe:%g.s} %A\n }}}}"
+#endif /* ! USE_CPPLIB */
+ }},
{"-",
- "%{E:cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ {"%{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}\
- -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -D__STRICT_ANSI__}\
- %{!undef:%{!ansi:%p} %P} %{trigraphs}\
+ %{!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__}\
%{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}"},
- {".m", "@objective-c"},
- {"@objective-c",
- "cpp -lang-objc %{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}\
- -undef -D__OBJC__ -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -D__STRICT_ANSI__}\
- %{!undef:%{!ansi:%p} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{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:cc1obj %{!pipe:%g.i} %1 \
- %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a*}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
- %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \
- -lang-objc %{gen-decls} \
- %{aux-info*}\
- %{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 }}}}"},
- {".h", "@c-header"},
+ %{!E:%e-E required when input is from standard input}"}},
+ {".h", {"@c-header"}},
{"@c-header",
- "%{!E:%eCompilation of header file requested} \
- cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ {"%{!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}\
- -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -D__STRICT_ANSI__}\
- %{!undef:%{!ansi:%p} %P} %{trigraphs}\
+ %{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__}\
%{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"},
+ %i %W{o*}"}},
+ {".i", {"@cpp-output"}},
{"@cpp-output",
- "%{!M:%{!MM:%{!E:cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a*}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
+ {"%{!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*}\
+ %{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"},
+ %{!pipe:%g.s} %A\n }}}}"}},
+ {".s", {"@assembler"}},
{"@assembler",
- "%{!M:%{!MM:%{!E:%{!S:as %a %Y\
+ {"%{!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"},
+ %i %A\n }}}}"}},
+ {".S", {"@assembler-with-cpp"}},
{"@assembler-with-cpp",
- "cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ {"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 -$ %{!undef:%p %P} -D__ASSEMBLER__ \
+ -$ %{!undef:%p %P} -D__ASSEMBLER__ \
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
%{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\
+ "%{!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 }}}}"},
+ %{!pipe:%g.s} %A\n }}}}"}},
#include "specs.h"
/* Mark end of table */
- {0, 0}
+ {0, {0}}
};
/* Number of elements in default_compilers, not counting the terminator. */
/* 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 char *link_command_spec = "\
+static const char *link_command_spec = "\
%{!fsyntax-only: \
- %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
+ %{!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\
\n }}}}}}";
#else
/* Use -L. */
-static char *link_command_spec = "\
+static const char *link_command_spec = "\
%{!fsyntax-only: \
- %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
+ %{!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\
%{T*}\
\n }}}}}}";
#endif
+#endif
/* A vector of options to give to the linker.
These options are accumulated by %x,
struct option_map
{
/* The long option's name. */
- char *name;
+ const char *name;
/* The equivalent short option. */
- char *equivalent;
+ const char *equivalent;
/* Argument info. A string of flag chars; NULL equals no options.
a => argument required.
o => argument optional.
j => join argument to equivalent, making one word.
* => require other text after NAME as an argument. */
- char *arg_info;
+ const char *arg_info;
};
/* This is the table of mappings. Mappings are tried sequentially
{"--ansi", "-ansi", 0},
{"--assemble", "-S", 0},
{"--assert", "-A", "a"},
+ {"--classpath", "-fclasspath=", "aj"},
+ {"--CLASSPATH", "-fCLASSPATH=", "aj"},
{"--comments", "-C", 0},
{"--compile", "-c", 0},
{"--debug", "-g", "oj"},
{"--no-warnings", "-w", 0},
{"--optimize", "-O", "oj"},
{"--output", "-o", "a"},
+ {"--output-class-directory", "-foutput-class-dir=", "ja"},
{"--pedantic", "-pedantic", 0},
{"--pedantic-errors", "-pedantic-errors", 0},
{"--pipe", "-pipe", 0},
{"--silent", "-q", 0},
{"--specs", "-specs=", "aj"},
{"--static", "-static", 0},
+ {"--std", "-std=", "aj"},
{"--symbolic", "-symbolic", 0},
{"--target", "-b", "a"},
{"--trace-includes", "-H", 0},
static void
translate_options (argcp, argvp)
int *argcp;
- char ***argvp;
+ const char ***argvp;
{
- int i, j, k;
+ int i;
int argc = *argcp;
- char **argv = *argvp;
- char **newv = (char **) xmalloc ((argc + 2) * 2 * sizeof (char *));
+ const char **argv = *argvp;
+ const char **newv =
+ (const char **) xmalloc ((argc + 2) * 2 * sizeof (const char *));
int newindex = 0;
i = 0;
/* Translate -- options. */
if (argv[i][0] == '-' && argv[i][1] == '-')
{
+ size_t j;
/* Find a mapping that applies to this option. */
for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
{
- int optlen = strlen (option_map[j].name);
- int arglen = strlen (argv[i]);
- int complen = arglen > optlen ? optlen : arglen;
- char *arginfo = option_map[j].arg_info;
+ size_t optlen = strlen (option_map[j].name);
+ size_t arglen = strlen (argv[i]);
+ size_t complen = arglen > optlen ? optlen : arglen;
+ const char *arginfo = option_map[j].arg_info;
if (arginfo == 0)
arginfo = "";
if (!strncmp (argv[i], option_map[j].name, complen))
{
- char *arg = 0;
+ const char *arg = 0;
if (arglen < optlen)
{
+ size_t k;
for (k = j + 1;
k < sizeof (option_map) / sizeof (option_map[0]);
k++)
with their arguments. */
else if (argv[i][0] == '-')
{
- char *p = argv[i] + 1;
+ const char *p = argv[i] + 1;
int c = *p;
int nskip = 1;
*argcp = newindex;
}
\f
-char *
-my_strerror(e)
- int e;
-{
-#ifdef HAVE_STRERROR
-
- return strerror(e);
-
-#else
-
- static char buffer[30];
- if (!e)
- return "cannot access";
-
- if (e > 0 && e < sys_nerr)
- return sys_errlist[e];
-
- sprintf (buffer, "Unknown error %d", e);
- return buffer;
-#endif
-}
-\f
static char *
skip_whitespace (p)
char *p;
INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults),
INIT_STATIC_SPEC ("multilib_extra", &multilib_extra),
INIT_STATIC_SPEC ("multilib_matches", &multilib_matches),
+ INIT_STATIC_SPEC ("linker", &linker_name_spec),
};
#ifdef EXTRA_SPECS /* additional specs needed */
-static struct spec_list extra_specs[] = { EXTRA_SPECS };
+/* Structure to keep track of just the first two args of a spec_list.
+ That is all that the EXTRA_SPECS macro gives us. */
+struct spec_list_1
+{
+ char *name;
+ char *ptr;
+};
+
+static struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
+static struct spec_list * extra_specs = (struct spec_list *)0;
#endif
/* List of dynamically allocates specs that have been defined so far. */
return; /* already initialized */
if (verbose_flag)
- fprintf (stderr, "Using builtin specs.\n");
+ notice ("Using builtin specs.\n");
#ifdef EXTRA_SPECS
- for (i = (sizeof (extra_specs) / sizeof (extra_specs[0])) - 1; i >= 0; i--)
+ 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--)
{
sl = &extra_specs[i];
+ sl->name = extra_specs_1[i].name;
+ sl->ptr = extra_specs_1[i].ptr;
sl->next = next;
sl->name_len = strlen (sl->name);
sl->ptr_spec = &sl->ptr;
static void
set_spec (name, spec)
- char *name;
- char *spec;
+ const char *name;
+ const char *spec;
{
struct spec_list *sl;
char *old_spec;
{
/* Not found - make it */
sl = (struct spec_list *) xmalloc (sizeof (struct spec_list));
- sl->name = save_string (name, strlen (name));
+ sl->name = xstrdup (name);
sl->name_len = name_len;
sl->ptr_spec = &sl->ptr;
sl->alloc_p = 0;
}
old_spec = *(sl->ptr_spec);
- *(sl->ptr_spec) = ((spec[0] == '+' && isspace (spec[1]))
+ *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
? concat (old_spec, spec + 1, NULL_PTR)
- : save_string (spec, strlen (spec)));
+ : xstrdup (spec));
#ifdef DEBUG_SPECS
if (verbose_flag)
- fprintf (stderr, "Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
+ notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
#endif
/* Free the old spec */
static int argbuf_index;
+/* We want this on by default all the time now. */
+#define MKTEMP_EACH_FILE
+
+#ifdef MKTEMP_EACH_FILE
+
+extern char *make_temp_file PROTO((const char *));
+
/* This is the list of suffixes and codes (%g/%u/%U) and the associated
- temp file. Used only if MKTEMP_EACH_FILE. */
+ temp file. */
static struct temp_name {
- char *suffix; /* suffix associated with the code. */
+ const char *suffix; /* suffix associated with the code. */
int length; /* strlen (suffix). */
int unique; /* Indicates whether %g or %u/%U was used. */
- char *filename; /* associated filename. */
+ const char *filename; /* associated filename. */
int filename_length; /* strlen (filename). */
struct temp_name *next;
} *temp_names;
+#endif
+
/* Number of commands executed so far. */
/* Name with which this program was invoked. */
-static char *programname;
+static const char *programname;
\f
/* Structures to keep track of prefixes to try when looking for files. */
{
struct prefix_list *plist; /* List of prefixes to try */
int max_len; /* Max length of a prefix in PLIST */
- char *name; /* Name of this list (used in config stuff) */
+ const char *name; /* Name of this list (used in config stuff) */
};
/* List of prefixes to try when looking for executables. */
/* Suffix to attach to directories searched for commands.
This looks like `MACHINE/VERSION/'. */
-static char *machine_suffix = 0;
+static const char *machine_suffix = 0;
/* Suffix to attach to directories searched for commands.
This is just `MACHINE/'. */
-static char *just_machine_suffix = 0;
+static const char *just_machine_suffix = 0;
/* Adjusted value of GCC_EXEC_PREFIX envvar. */
-static char *gcc_exec_prefix;
+static const char *gcc_exec_prefix;
/* Default prefixes to attach to command names. */
#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
#endif /* !defined STANDARD_EXEC_PREFIX */
-static char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
-static char *standard_exec_prefix_1 = "/usr/lib/gcc/";
+static const char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
+static const char *standard_exec_prefix_1 = "/usr/lib/gcc/";
#ifdef MD_EXEC_PREFIX
-static char *md_exec_prefix = MD_EXEC_PREFIX;
+static const char *md_exec_prefix = MD_EXEC_PREFIX;
#endif
#ifndef STANDARD_STARTFILE_PREFIX
#endif /* !defined STANDARD_STARTFILE_PREFIX */
#ifdef MD_STARTFILE_PREFIX
-static char *md_startfile_prefix = MD_STARTFILE_PREFIX;
+static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
#endif
#ifdef MD_STARTFILE_PREFIX_1
-static char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
+static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
#endif
-static char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
-static char *standard_startfile_prefix_1 = "/lib/";
-static char *standard_startfile_prefix_2 = "/usr/lib/";
+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 char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
-static char *tooldir_prefix;
+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 char *multilib_dir;
+static const char *multilib_dir;
/* Clear out the vector of arguments (after a command is executed). */
static void
read_specs (filename, main_p)
- char *filename;
+ const char *filename;
int main_p;
{
int desc;
register char *p;
if (verbose_flag)
- fprintf (stderr, "Reading specs from %s\n", filename);
+ notice ("Reading specs from %s\n", filename);
/* Open and stat the file. */
desc = open (filename, O_RDONLY, 0);
p1++;
if (*p1++ != '<' || p[-2] != '>')
- fatal ("specs %%include syntax malformed after %d characters",
- p1 - buffer + 1);
+ fatal ("specs %%include syntax malformed after %ld characters",
+ (long) (p1 - buffer + 1));
p[-2] = '\0';
new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
while (*p1 == ' ' || *p1 == '\t') p1++;
if (*p1++ != '<' || p[-2] != '>')
- fatal ("specs %%include syntax malformed after %d characters",
- p1 - buffer + 1);
+ fatal ("specs %%include syntax malformed after %ld characters",
+ (long) (p1 - buffer + 1));
p[-2] = '\0';
new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
if (new_filename)
read_specs (new_filename, FALSE);
else if (verbose_flag)
- fprintf (stderr, "Could not find specs file %s\n", p1);
+ notice ("Could not find specs file %s\n", p1);
continue;
}
else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
while (*p1 == ' ' || *p1 == '\t')
p1++;
- if (! isalpha (*p1))
- fatal ("specs %%rename syntax malformed after %d characters",
- p1 - buffer);
+ if (! ISALPHA ((unsigned char)*p1))
+ fatal ("specs %%rename syntax malformed after %ld characters",
+ (long) (p1 - buffer));
p2 = p1;
- while (*p2 && !isspace (*p2))
+ while (*p2 && !ISSPACE ((unsigned char)*p2))
p2++;
if (*p2 != ' ' && *p2 != '\t')
- fatal ("specs %%rename syntax malformed after %d characters",
- p2 - buffer);
+ fatal ("specs %%rename syntax malformed after %ld characters",
+ (long) (p2 - buffer));
name_len = p2 - p1;
*p2++ = '\0';
while (*p2 == ' ' || *p2 == '\t')
p2++;
- if (! isalpha (*p2))
- fatal ("specs %%rename syntax malformed after %d characters",
- p2 - buffer);
+ if (! ISALPHA ((unsigned char)*p2))
+ fatal ("specs %%rename syntax malformed after %ld characters",
+ (long) (p2 - buffer));
/* Get new spec name */
p3 = p2;
- while (*p3 && !isspace (*p3))
+ while (*p3 && !ISSPACE ((unsigned char)*p3))
p3++;
if (p3 != p-1)
- fatal ("specs %%rename syntax malformed after %d characters",
- p3 - buffer);
+ fatal ("specs %%rename syntax malformed after %ld characters",
+ (long) (p3 - buffer));
*p3 = '\0';
for (sl = specs; sl; sl = sl->next)
if (verbose_flag)
{
- fprintf (stderr, "rename spec %s to %s\n", p1, p2);
+ notice ("rename spec %s to %s\n", p1, p2);
#ifdef DEBUG_SPECS
- fprintf (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));
+ notice ("spec is '%s'\n\n", *(sl->ptr_spec));
#endif
}
continue;
}
else
- fatal ("specs unknown %% command after %d characters",
- p1 - buffer);
+ fatal ("specs unknown %% command after %ld characters",
+ (long) (p1 - buffer));
}
/* Find the colon that should end the suffix. */
/* The colon shouldn't be missing. */
if (*p1 != ':')
- fatal ("specs file malformed after %d characters", p1 - buffer);
+ fatal ("specs file malformed after %ld characters",
+ (long) (p1 - buffer));
/* Skip back over trailing whitespace. */
p2 = p1;
/* Find the next line. */
p = skip_whitespace (p1 + 1);
if (p[1] == 0)
- fatal ("specs file malformed after %d characters", p - buffer);
+ fatal ("specs file malformed after %ld characters",
+ (long) (p - buffer));
p1 = p;
- /* Find next blank line. */
- while (*p1 && !(*p1 == '\n' && p1[1] == '\n'))
+ /* Find next blank line or end of string. */
+ while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
p1++;
/* Specs end at the blank line and do not include the newline. */
(n_compilers + 2) * sizeof (struct compiler)));
compilers[n_compilers].suffix = suffix;
- bzero ((char *) compilers[n_compilers].spec,
- sizeof compilers[n_compilers].spec);
+ memset (compilers[n_compilers].spec, 0,
+ sizeof compilers[n_compilers].spec);
compilers[n_compilers].spec[0] = spec;
n_compilers++;
- bzero ((char *) &compilers[n_compilers],
- sizeof compilers[n_compilers]);
+ memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
}
if (*suffix == 0)
otherwise, in /usr/tmp or /tmp;
or finally the current directory if all else fails. */
-static char *temp_filename;
+static const char *temp_filename;
/* Length of the prefix. */
struct temp_file
{
- char *name;
+ const char *name;
struct temp_file *next;
};
static void
record_temp_file (filename, always_delete, fail_delete)
- char *filename;
+ const char *filename;
int always_delete;
int fail_delete;
{
- register char *name;
- name = xmalloc (strlen (filename) + 1);
- strcpy (name, filename);
+ register char * const name = xstrdup (filename);
if (always_delete)
{
static void
delete_if_ordinary (name)
- char *name;
+ const char *name;
{
struct stat st;
#ifdef DEBUG
/* Add a new environment variable */
environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
*environ = str;
- bcopy ((char *) old_environ, (char *) (environ + 1),
+ memcpy ((char *) (environ + 1), (char *) old_environ,
sizeof (char *) * (num_envs+1));
#endif /* VMS */
static char *
build_search_list (paths, prefix, check_dir_p)
struct path_prefix *paths;
- char *prefix;
+ const char *prefix;
int check_dir_p;
{
int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
static void
putenv_from_prefixes (paths, env_var)
struct path_prefix *paths;
- char *env_var;
+ const char *env_var;
{
putenv (build_search_list (paths, env_var, 1));
}
\f
+/* Check whether NAME can be accessed in MODE. This is like access,
+ except that it never considers directories to be executable. */
+
+static int
+access_check (name, mode)
+ const char *name;
+ int mode;
+{
+ if (mode == X_OK)
+ {
+ struct stat st;
+
+ if (stat (name, &st) < 0
+ || S_ISDIR (st.st_mode))
+ return -1;
+ }
+
+ return access (name, mode);
+}
+
/* Search for NAME using the prefix list PREFIXES. MODE is passed to
access to check permissions.
Return 0 if not found, otherwise return its name, allocated with malloc. */
static char *
find_a_file (pprefix, name, mode)
struct path_prefix *pprefix;
- char *name;
+ const char *name;
int mode;
{
char *temp;
- char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : "");
+ const char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : "");
struct prefix_list *pl;
int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
+#ifdef DEFAULT_ASSEMBLER
+ if (! strcmp(name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0)
+ return xstrdup (DEFAULT_ASSEMBLER);
+#endif
+
+#ifdef DEFAULT_LINKER
+ if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0)
+ return xstrdup (DEFAULT_LINKER);
+#endif
+
if (machine_suffix)
len += strlen (machine_suffix);
/* Determine the filename to execute (special case for absolute paths). */
- if (*name == '/' || *name == DIR_SEPARATOR
+ if (IS_DIR_SEPARATOR (*name)
+#ifdef HAVE_DOS_BASED_FILESYSTEM
/* Check for disk name on MS-DOS-based systems. */
- || (DIR_SEPARATOR == '\\' && name[1] == ':'
- && (name[2] == DIR_SEPARATOR || name[2] == '/')))
+ || (name[0] && name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
+#endif
+ )
{
- if (access (name, mode))
+ if (access (name, mode) == 0)
{
strcpy (temp, name);
return temp;
strcat (temp, machine_suffix);
strcat (temp, name);
strcat (temp, file_suffix);
- if (access (temp, mode) == 0)
+ if (access_check (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
strcpy (temp, pl->prefix);
strcat (temp, machine_suffix);
strcat (temp, name);
- if (access (temp, mode) == 0)
+ if (access_check (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
strcat (temp, just_machine_suffix);
strcat (temp, name);
strcat (temp, file_suffix);
- if (access (temp, mode) == 0)
+ if (access_check (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
strcpy (temp, pl->prefix);
strcat (temp, just_machine_suffix);
strcat (temp, name);
- if (access (temp, mode) == 0)
+ if (access_check (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
strcpy (temp, pl->prefix);
strcat (temp, name);
strcat (temp, file_suffix);
- if (access (temp, mode) == 0)
+ if (access_check (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
strcpy (temp, pl->prefix);
strcat (temp, name);
- if (access (temp, mode) == 0)
+ if (access_check (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
static void
add_prefix (pprefix, prefix, component, first, require_machine_suffix, warn)
struct path_prefix *pprefix;
- char *prefix;
- char *component;
+ const char *prefix;
+ const char *component;
int first;
int require_machine_suffix;
int *warn;
}
}
-/* Get rid of all prefixes built up so far in *PLISTP. */
-
-static void
-free_path_prefix (pprefix)
- struct path_prefix *pprefix;
-{
- struct prefix_list *pl = pprefix->plist;
- struct prefix_list *temp;
-
- while (pl)
- {
- temp = pl;
- pl = pl->next;
- free (temp->prefix);
- free ((char *) temp);
- }
-
- pprefix->plist = (struct prefix_list *) 0;
-}
\f
/* Execute the command specified by the arguments on the current line of spec.
When using pipes, this includes several piped-together commands
char *string;
struct command
{
- char *prog; /* program name. */
- char **argv; /* vector of args. */
+ const char *prog; /* program name. */
+ char **argv; /* vector of args. */
int pid; /* pid of process for this command. */
};
commands[0].prog = argbuf[0]; /* first command. */
commands[0].argv = &argbuf[0];
string = find_a_file (&exec_prefixes, commands[0].prog, X_OK);
+
if (string)
commands[0].argv[0] = string;
for (n_commands = 1, i = 0; i < argbuf_index; i++)
if (strcmp (argbuf[i], "|") == 0)
{ /* each command. */
-#if defined (__MSDOS__) || (defined (_WIN32) && defined (__CYGWIN32_)) || defined (OS2) || defined (VMS)
+#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
fatal ("-pipe not supported");
#endif
argbuf[i] = 0; /* termination of command args. */
if (verbose_flag)
{
+ /* 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++)
{
}
fflush (stderr);
#ifdef DEBUG
- fprintf (stderr, "\nGo ahead? (y or n) ");
+ notice ("\nGo ahead? (y or n) ");
fflush (stderr);
i = getchar ();
if (i != '\n')
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 `valid' field is nonzero if any spec has looked at this switch;
+ 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. */
struct switchstr
{
- char *part1;
+ const char *part1;
char **args;
int live_cond;
- int valid;
+ int validated;
};
static struct switchstr *switches;
struct infile
{
- char *name;
- char *language;
+ const char *name;
+ const char *language;
};
/* Also a vector of input files specified. */
static int n_infiles;
+/* This counts the number of libraries added by lang_specific_driver, so that
+ we can tell if there were any user supplied any files or libraries. */
+
+static int added_libraries;
+
/* And a vector of corresponding output files is made up later. */
-static char **outfiles;
+static const char **outfiles;
/* Used to track if none of the -B paths are used. */
static int warn_B;
int do_exe;
{
int i;
- int len = strlen (name);
+ int len;
+
+ if (name == NULL)
+ return NULL;
+
+ len = strlen (name);
#ifdef HAVE_OBJECT_SUFFIX
/* Convert x.o to x.obj if OBJECT_SUFFIX is ".obj". */
return name;
for (i = len - 1; i >= 0; i--)
- if (name[i] == '/' || name[i] == DIR_SEPARATOR)
+ if (IS_DIR_SEPARATOR (name[i]))
break;
for (i++; i < len; i++)
}
#endif
\f
+/* Display the command line switches accepted by gcc. */
+static void
+display_help ()
+{
+ printf ("Usage: %s [options] file...\n", programname);
+ printf ("Options:\n");
+
+ printf (" --help Display this information\n");
+ 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 (" -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");
+
+ /* The rest of the options are displayed by invocations of the various
+ sub-processes. */
+}
+
+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 *));
+ else
+ 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;
+ int len;
+{
+ n_assembler_options++;
+
+ if (! assembler_options)
+ assembler_options
+ = (char **) xmalloc (n_assembler_options * sizeof (char *));
+ else
+ assembler_options
+ = (char **) xrealloc (assembler_options,
+ n_assembler_options * sizeof (char *));
+
+ assembler_options [n_assembler_options - 1] = save_string (option, len);
+}
+
+static void
+add_linker_option (option, len)
+ const char * option;
+ int len;
+{
+ n_linker_options++;
+
+ if (! linker_options)
+ linker_options
+ = (char **) xmalloc (n_linker_options * sizeof (char *));
+ else
+ linker_options
+ = (char **) xrealloc (linker_options,
+ n_linker_options * sizeof (char *));
+
+ linker_options [n_linker_options - 1] = save_string (option, len);
+}
+\f
/* Create the vector `switches' and its contents.
Store its length in `n_switches'. */
char **argv;
{
register int i;
- char *temp;
+ const char *temp;
+ char *temp1;
char *spec_lang = 0;
int last_language_n_infiles;
int have_c = 0;
int have_o = 0;
int lang_n_infiles = 0;
- gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX");
+ GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX");
n_switches = 0;
n_infiles = 0;
+ added_libraries = 0;
/* Figure compiler version from version string. */
- compiler_version = save_string (version_string, strlen (version_string));
- for (temp = compiler_version; *temp; ++temp)
+ compiler_version = temp1 = xstrdup (version_string);
+
+ for (; *temp1; ++temp1)
{
- if (*temp == ' ')
+ if (*temp1 == ' ')
{
- *temp = '\0';
+ *temp1 = '\0';
break;
}
}
if (gcc_exec_prefix)
{
+ int len = strlen (gcc_exec_prefix);
+ 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
+ && IS_DIR_SEPARATOR (temp[4])
+ && 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);
}
/* COMPILER_PATH and LIBRARY_PATH have values
that are lists of directory names with colons. */
- temp = getenv ("COMPILER_PATH");
+ GET_ENV_PATH_LIST (temp, "COMPILER_PATH");
if (temp)
{
- char *startp, *endp;
+ const char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
strncpy (nstore, startp, endp-startp);
if (endp == startp)
strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
- else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR)
+ else if (!IS_DIR_SEPARATOR (endp[-1]))
{
nstore[endp-startp] = DIR_SEPARATOR;
nstore[endp-startp+1] = 0;
}
}
- temp = getenv ("LIBRARY_PATH");
+ GET_ENV_PATH_LIST (temp, "LIBRARY_PATH");
if (temp && *cross_compile == '0')
{
- char *startp, *endp;
+ const char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
strncpy (nstore, startp, endp-startp);
if (endp == startp)
strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
- else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR)
+ else if (!IS_DIR_SEPARATOR (endp[-1]))
{
nstore[endp-startp] = DIR_SEPARATOR;
nstore[endp-startp+1] = 0;
}
/* Use LPATH like LIBRARY_PATH (for the CMU build program). */
- temp = getenv ("LPATH");
+ GET_ENV_PATH_LIST (temp, "LPATH");
if (temp && *cross_compile == '0')
{
- char *startp, *endp;
+ const char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
strncpy (nstore, startp, endp-startp);
if (endp == startp)
strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
- else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR)
+ else if (!IS_DIR_SEPARATOR (endp[-1]))
{
nstore[endp-startp] = DIR_SEPARATOR;
nstore[endp-startp+1] = 0;
/* Convert new-style -- options to old-style. */
translate_options (&argc, &argv);
-#ifdef LANG_SPECIFIC_DRIVER
/* Do language-specific adjustment/addition of flags. */
- lang_specific_driver (fatal, &argc, &argv);
-#endif
+ lang_specific_driver (&argc, &argv, &added_libraries);
/* 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.
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);
exit (0);
}
else if (! strcmp (argv[i], "-dumpversion"))
{
- printf ("%s\n", version_string);
+ printf ("%s\n", spec_version);
exit (0);
}
else if (! strcmp (argv[i], "-dumpmachine"))
printf ("%s\n", spec_machine);
exit (0);
}
+ else if (strcmp (argv[i], "-fhelp") == 0)
+ {
+ /* translate_options () has turned --help into -fhelp. */
+ print_help_list = 1;
+
+ /* 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], "-print-search-dirs"))
print_search_dirs = 1;
else if (! strcmp (argv[i], "-print-libgcc-file-name"))
int prev, j;
/* Pass the rest of this option to the assembler. */
- n_assembler_options++;
- if (!assembler_options)
- assembler_options
- = (char **) xmalloc (n_assembler_options * sizeof (char **));
- else
- assembler_options
- = (char **) xrealloc (assembler_options,
- n_assembler_options * sizeof (char **));
-
/* Split the argument at commas. */
prev = 4;
for (j = 4; argv[i][j]; j++)
if (argv[i][j] == ',')
{
- assembler_options[n_assembler_options - 1]
- = save_string (argv[i] + prev, j - prev);
- n_assembler_options++;
- assembler_options
- = (char **) xrealloc (assembler_options,
- n_assembler_options * sizeof (char **));
+ add_assembler_option (argv[i] + prev, j - prev);
prev = j + 1;
}
+
/* Record the part after the last comma. */
- assembler_options[n_assembler_options - 1] = argv[i] + prev;
+ add_assembler_option (argv[i] + prev, j - prev);
}
else if (! strncmp (argv[i], "-Wp,", 4))
{
int prev, j;
/* Pass the rest of this option to the preprocessor. */
- n_preprocessor_options++;
- if (!preprocessor_options)
- preprocessor_options
- = (char **) xmalloc (n_preprocessor_options * sizeof (char **));
- else
- preprocessor_options
- = (char **) xrealloc (preprocessor_options,
- n_preprocessor_options * sizeof (char **));
-
/* Split the argument at commas. */
prev = 4;
for (j = 4; argv[i][j]; j++)
if (argv[i][j] == ',')
{
- preprocessor_options[n_preprocessor_options - 1]
- = save_string (argv[i] + prev, j - prev);
- n_preprocessor_options++;
- preprocessor_options
- = (char **) xrealloc (preprocessor_options,
- n_preprocessor_options * sizeof (char **));
+ add_preprocessor_option (argv[i] + prev, j - prev);
prev = j + 1;
}
+
/* Record the part after the last comma. */
- preprocessor_options[n_preprocessor_options - 1] = argv[i] + prev;
+ add_preprocessor_option (argv[i] + prev, j - prev);
}
else if (argv[i][0] == '+' && argv[i][1] == 'e')
/* The +e options to the C++ front-end. */
case 'B':
{
- int *temp = (int *) xmalloc (sizeof (int));
char *value;
if (p[1] == 0 && i + 1 == argc)
fatal ("argument to `-B' is missing");
int len = strlen (value);
if ((len == 7
|| (len > 7
- && (value[len - 8] == '/'
- || value[len - 8] == DIR_SEPARATOR)))
+ && (IS_DIR_SEPARATOR (value[len - 8]))))
&& strncmp (value + len - 7, "stage", 5) == 0
- && isdigit (value[len - 2])
- && (value[len - 1] == '/'
- || value[len - 1] == DIR_SEPARATOR))
+ && ISDIGIT (value[len - 2])
+ && (IS_DIR_SEPARATOR (value[len - 1])))
{
if (len == 7)
add_prefix (&include_prefixes, "include", NULL_PTR,
spec_version = p + 1;
compiler_version = spec_version;
warn_std_ptr = &warn_std;
+
+ /* Validate the version number. Use the same checks
+ done when inserting it into a spec.
+
+ The format of the version string is
+ ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */
+ {
+ const char *v = compiler_version;
+
+ /* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */
+ while (! ISDIGIT (*v))
+ v++;
+
+ if (v > compiler_version && v[-1] != '-')
+ fatal ("invalid version number format");
+
+ /* Set V after the first period. */
+ while (ISDIGIT (*v))
+ v++;
+
+ if (*v != '.')
+ fatal ("invalid version number format");
+
+ v++;
+ while (ISDIGIT (*v))
+ v++;
+
+ if (*v != 0 && *v != ' ' && *v != '.' && *v != '-')
+ fatal ("invalid version number format");
+ }
break;
+ case 'S':
case 'c':
if (p[1] == 0)
{
case 'o':
have_o = 1;
+#if defined(HAVE_EXECUTABLE_SUFFIX)
+ if (! have_c)
+ {
+ int skip;
+
+ /* Forward scan, just in case -S or -c is specified
+ after -o. */
+ int j = i + 1;
+ if (p[1] == 0)
+ ++j;
+ while (j < argc)
+ {
+ if (argv[j][0] == '-')
+ {
+ if (SWITCH_CURTAILS_COMPILATION (argv[j][1])
+ && argv[j][2] == 0)
+ {
+ have_c = 1;
+ break;
+ }
+ else if (skip = SWITCH_TAKES_ARG (argv[j][1]))
+ j += skip - (argv[j][2] != 0);
+ else if (skip = WORD_SWITCH_TAKES_ARG (argv[j] + 1))
+ j += skip;
+ }
+ j++;
+ }
+ }
+#endif
#if defined(HAVE_EXECUTABLE_SUFFIX) || defined(HAVE_OBJECT_SUFFIX)
- argv[i] = convert_filename (argv[i], 1);
if (p[1] == 0)
- argv[i+1] = convert_filename (argv[i+1], 1);
+ argv[i+1] = convert_filename (argv[i+1], ! have_c);
+ else
+ argv[i] = convert_filename (argv[i], ! have_c);
#endif
goto normal_switch;
}
if (have_c && have_o && lang_n_infiles > 1)
- fatal ("cannot specify -o with -c and multiple compilations");
+ fatal ("cannot specify -o with -c or -S and multiple compilations");
/* Set up the search paths before we go looking for config files. */
directories, so that we can search both the user specified directory
and the standard place. */
- if (*tooldir_prefix != '/' && *tooldir_prefix != DIR_SEPARATOR)
+ if (!IS_DIR_SEPARATOR (*tooldir_prefix))
{
if (gcc_exec_prefix)
{
;
else if (! strcmp (argv[i], "-print-multi-directory"))
;
+ else if (strcmp (argv[i], "-fhelp") == 0)
+ {
+ if (verbose_flag)
+ {
+ /* Create a dummy input file, so that we can pass --help on to
+ 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;
+
+ n_switches++;
+ }
+ }
else if (argv[i][0] == '+' && argv[i][1] == 'e')
{
/* Compensate for the +e options to the C++ front-end;
switches[n_switches].part1 = &argv[i][0];
switches[n_switches].args = 0;
switches[n_switches].live_cond = 0;
- switches[n_switches].valid = 0;
+ switches[n_switches].validated = 0;
n_switches++;
}
else if (strncmp (argv[i], "-Wl,", 4) == 0)
for (j = 4; argv[i][j]; j++)
if (argv[i][j] == ',')
{
- infiles[n_infiles].language = 0;
+ infiles[n_infiles].language = "*";
infiles[n_infiles++].name
= save_string (argv[i] + prev, j - prev);
prev = j + 1;
}
/* Record the part after the last comma. */
- infiles[n_infiles].language = 0;
+ infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[i] + prev;
}
else if (strcmp (argv[i], "-Xlinker") == 0)
{
- infiles[n_infiles].language = 0;
+ infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[++i];
}
else if (strncmp (argv[i], "-l", 2) == 0)
{
- infiles[n_infiles].language = 0;
+ infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[i];
}
else if (strcmp (argv[i], "-specs") == 0)
switches[n_switches].args = 0;
switches[n_switches].live_cond = 0;
- switches[n_switches].valid = 0;
+ switches[n_switches].validated = 0;
/* This is always valid, since gcc.c itself understands it. */
if (!strcmp (p, "save-temps"))
- switches[n_switches].valid = 1;
+ switches[n_switches].validated = 1;
else
{
char ch = switches[n_switches].part1[0];
if (ch == 'V' || ch == 'b' || ch == 'B')
- switches[n_switches].valid = 1;
+ switches[n_switches].validated = 1;
}
n_switches++;
}
sans all directory names, and basename_length is the number
of characters starting there excluding the suffix .c or whatever. */
-static char *input_filename;
+const char *input_filename;
static int input_file_number;
-static int input_filename_length;
+size_t input_filename_length;
static int basename_length;
-static char *input_basename;
-static char *input_suffix;
+static const char *input_basename;
+static const char *input_suffix;
/* These are variables used within do_spec and do_spec_1. */
/* Process the spec SPEC and run the commands specified therein.
Returns 0 if the spec is successfully processed; -1 if failed. */
-static int
+int
do_spec (spec)
- char *spec;
+ const char *spec;
{
int value;
static int
do_spec_1 (spec, inswitch, soft_matched_part)
- char *spec;
+ const char *spec;
int inswitch;
- char *soft_matched_part;
+ const char *soft_matched_part;
{
- register char *p = spec;
+ register const char *p = spec;
register int c;
int i;
- char *string;
+ const char *string;
int value;
- while (c = *p++)
+ while ((c = *p++))
/* If substituting a switch, treat all chars like letters.
Otherwise, NL, SPC, TAB and % are special. */
switch (inswitch ? 'a' : c)
if (i < n_switches)
{
input_from_pipe = 1;
- switches[i].valid = 1;
+ switches[i].validated = 1;
break;
}
else
case 'D':
{
struct prefix_list *pl = startfile_prefixes.plist;
- int bufsize = 100;
+ size_t bufsize = 100;
char *buffer = (char *) xmalloc (bufsize);
int idx;
/* Relative directories always come from -B,
and it is better not to use them for searching
at run time. In particular, stage1 loses */
- if (pl->prefix[0] != '/' && pl->prefix[0] != DIR_SEPARATOR)
+ if (!IS_DIR_SEPARATOR (pl->prefix[0]))
continue;
#endif
/* Try subdirectory if there is one. */
buffer = (char *) xrealloc (buffer, bufsize);
strcpy (buffer, machine_suffix);
idx = strlen (buffer);
- if (buffer[idx - 1] == '/'
- || buffer[idx - 1] == DIR_SEPARATOR)
+ if (IS_DIR_SEPARATOR (buffer[idx - 1]))
buffer[idx - 1] = 0;
do_spec_1 (buffer, 1, NULL_PTR);
/* Make this a separate argument. */
buffer = (char *) xrealloc (buffer, bufsize);
strcpy (buffer, pl->prefix);
idx = strlen (buffer);
- if (buffer[idx - 1] == '/'
- || buffer[idx - 1] == DIR_SEPARATOR)
+ if (IS_DIR_SEPARATOR (buffer[idx - 1]))
buffer[idx - 1] = 0;
do_spec_1 (buffer, 1, NULL_PTR);
/* Make this a separate argument. */
break;
case 'e':
- /* {...:%efoo} means report an error with `foo' as error message
+ /* %efoo means report an error with `foo' as error message
and don't execute any more commands for this file. */
{
- char *q = p;
+ 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;
- error ("%s", buf);
+ error (buf);
return -1;
}
break;
That matters for the names of object files.
In 2.4, do something about that. */
struct temp_name *t;
- char *suffix = p;
- while (*p == '.' || isalpha (*p)
- || (p[0] == '%' && p[1] == 'O'))
- p++;
+ int suffix_length;
+ const char *suffix = p;
+
+ if (p[0] == '%' && p[1] == 'O')
+ {
+ p += 2;
+ /* We don't support extra suffix characters after %O. */
+ 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;
+ }
/* See if we already have an association of %g/%u/%U and
suffix. */
for (t = temp_names; t; t = t->next)
- if (t->length == p - suffix
- && strncmp (t->suffix, suffix, p - suffix) == 0
+ if (t->length == suffix_length
+ && strncmp (t->suffix, suffix, suffix_length) == 0
&& t->unique == (c != 'g'))
break;
t->next = temp_names;
temp_names = t;
}
- t->length = p - suffix;
- t->suffix = save_string (suffix, p - suffix);
+ t->length = suffix_length;
+ t->suffix = save_string (suffix, suffix_length);
t->unique = (c != 'g');
- temp_filename = choose_temp_base ();
+ temp_filename = make_temp_file (t->suffix);
temp_filename_length = strlen (temp_filename);
t->filename = temp_filename;
t->filename_length = temp_filename_length;
break;
case 'o':
- for (i = 0; i < n_infiles; i++)
- store_arg (outfiles[i], 0, 0);
- break;
+ {
+ int max = n_infiles;
+ max += lang_specific_extra_outfiles;
+
+ for (i = 0; i < max; i++)
+ if (outfiles[i])
+ store_arg (outfiles[i], 0, 0);
+ break;
+ }
case 'O':
obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
/* %x{OPTION} records OPTION for %X to output. */
case 'x':
{
- char *p1 = p;
+ const char *p1 = p;
char *string;
/* Skip past the option value and make a copy. */
}
/* This option is new; add it. */
- n_linker_options++;
- if (!linker_options)
- linker_options
- = (char **) xmalloc (n_linker_options * sizeof (char **));
- else
- linker_options
- = (char **) xrealloc (linker_options,
- n_linker_options * sizeof (char **));
-
- linker_options[n_linker_options - 1] = string;
+ add_linker_option (string, strlen (string));
}
break;
*x++ = *y++;
if (*y != '_'
- || (*(y+1) != '_' && ! isupper (*(y+1))))
+ || (*(y+1) != '_'
+ && ! ISUPPER ((unsigned char)*(y+1))))
{
/* Stick __ at front of macro name. */
*x++ = '_';
y += 2;
if (*y != '_'
- || (*(y+1) != '_' && ! isupper (*(y+1))))
+ || (*(y+1) != '_'
+ && ! ISUPPER ((unsigned char)*(y+1))))
{
/* Stick -D__ at front of macro name. */
*x++ = '-';
to add and use their own specs.
%[...] modifies -D options the way %P does;
%(...) uses the spec unmodified. */
- case '(':
case '[':
+ error ("Warning: use of obsolete %%[ operator in specs");
+ case '(':
{
- char *name = p;
+ const char *name = p;
struct spec_list *sl;
int len;
{
name = *(sl->ptr_spec);
#ifdef DEBUG_SPECS
- fprintf (stderr, "Processing spec %c%s%c, which is '%s'\n",
- c, sl->name, (c == '(') ? ')' : ']', name);
+ notice ("Processing spec %c%s%c, which is '%s'\n",
+ c, sl->name, (c == '(') ? ')' : ']', name);
#endif
break;
}
{
char *x = (char *) alloca (strlen (name) * 2 + 1);
char *buf = x;
- char *y = name;
+ const char *y = name;
+ int flag = 0;
/* Copy all of NAME into BUF, but put __ after
every -D and at the end of each arg, */
while (1)
{
- int flag;
-
if (! strncmp (y, "-D", 2))
{
*x++ = '-';
([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */
/* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */
- while (! isdigit (*v))
+ while (! ISDIGIT (*v))
v++;
if (v > compiler_version && v[-1] != '-')
abort ();
if (c1 == '2')
{
/* Set V after the first period. */
- while (isdigit (*v))
+ while (ISDIGIT (*v))
v++;
if (*v != '.')
abort ();
/* Set Q at the next period or at the end. */
q = v;
- while (isdigit (*q))
+ while (ISDIGIT (*q))
q++;
if (*q != 0 && *q != ' ' && *q != '.' && *q != '-')
abort ();
/* Return 0 if we call do_spec_1 and that returns -1. */
-static char *
+static const char *
handle_braces (p)
- register char *p;
+ register const char *p;
{
- register char *q;
- char *filter;
+ const char *filter, *body = NULL, *endbody = NULL;
int pipe_p = 0;
- int negate = 0;
- int suffix = 0;
+ int negate;
+ int suffix;
int include_blanks = 1;
if (*p == '^')
This is used in %{|!pipe:...}. */
pipe_p = 1, ++p;
+next_member:
+ negate = suffix = 0;
+
if (*p == '!')
/* A `!' after the open-brace negates the condition:
succeed if the specified switch is not present. */
}
filter = p;
- while (*p != ':' && *p != '}') p++;
- if (*p != '}')
+ while (*p != ':' && *p != '}' && *p != '|') p++;
+
+ if (*p == '|' && pipe_p)
+ abort ();
+
+ if (!body)
{
- register int count = 1;
- q = p + 1;
- while (count > 0)
- {
- if (*q == '{')
- count++;
- else if (*q == '}')
- count--;
- else if (*q == 0)
- abort ();
- q++;
+ if (*p != '}')
+ {
+ register int count = 1;
+ register const char *q = p;
+
+ while (*q++ != ':') continue;
+ body = q;
+
+ while (count > 0)
+ {
+ if (*q == '{')
+ count++;
+ else if (*q == '}')
+ count--;
+ else if (*q == 0)
+ abort ();
+ q++;
+ }
+ endbody = q;
}
+ else
+ body = p, endbody = p+1;
}
- else
- q = p + 1;
if (suffix)
{
int found = (input_suffix != 0
- && strlen (input_suffix) == p - filter
+ && (long) strlen (input_suffix) == (long)(p - filter)
&& strncmp (input_suffix, filter, p - filter) == 0);
- if (p[0] == '}')
+ if (body[0] == '}')
abort ();
if (negate != found
- && do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
+ && do_spec_1 (save_string (body, endbody-body-1), 0, NULL_PTR) < 0)
return 0;
-
- return q;
}
else if (p[-1] == '*' && p[0] == '}')
{
if (p[-1] == '*' && !negate)
{
int substitution;
- char *r = p;
+ const char *r = body;
/* First see whether we have %*. */
substitution = 0;
- while (r < q)
+ while (r < endbody)
{
if (*r == '%' && r[1] == '*')
substitution = 1;
in the text that follows the colon. */
unsigned hard_match_len = p - filter - 1;
- char *string = save_string (p + 1, q - p - 2);
+ char *string = save_string (body, endbody - body - 1);
for (i = 0; i < n_switches; i++)
if (!strncmp (switches[i].part1, filter, hard_match_len)
give_switch (i, 1, 1);
}
- return q;
+ /* We didn't match. Try again. */
+ if (*p++ == '|')
+ goto next_member;
+ return endbody;
}
}
}
}
- /* If it is as desired (present for %{s...}, absent for %{-s...})
+ /* If it is as desired (present for %{s...}, absent for %{!s...})
then substitute either the switch or the specified
conditional text. */
if (present != negate)
}
else
{
- if (do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
+ if (do_spec_1 (save_string (body, endbody - body - 1),
+ 0, NULL_PTR) < 0)
return 0;
}
}
/* Here if a %{|...} conditional fails: output a minus sign,
which means "standard output" or "standard input". */
do_spec_1 ("-", 0, NULL_PTR);
+ return endbody;
}
}
- return q;
+ /* We didn't match; try again. */
+ if (*p++ == '|')
+ goto next_member;
+
+ return endbody;
}
\f
/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
int switchnum;
int prefix_length;
{
- char *name = switches[switchnum].part1;
+ const char *name = switches[switchnum].part1;
int i;
/* In the common case of {<at-most-one-letter>*}, a negating
for (i = switchnum + 1; i < n_switches; i++)
if (switches[i].part1[0] == 'O')
{
- switches[switchnum].valid = 1;
+ switches[switchnum].validated = 1;
switches[switchnum].live_cond = -1;
return 0;
}
if (switches[i].part1[0] == name[0]
&& ! strcmp (&switches[i].part1[1], &name[4]))
{
- switches[switchnum].valid = 1;
+ switches[switchnum].validated = 1;
switches[switchnum].live_cond = -1;
return 0;
}
&& switches[i].part1[3] == '-'
&& !strcmp (&switches[i].part1[4], &name[1]))
{
- switches[switchnum].valid = 1;
+ switches[switchnum].validated = 1;
switches[switchnum].live_cond = -1;
return 0;
}
}
do_spec_1 (" ", 0, NULL_PTR);
- switches[switchnum].valid = 1;
+ switches[switchnum].validated = 1;
}
\f
/* Search for a file named NAME trying various prefixes including the
user's -B prefix and some standard ones.
Return the absolute file name found. If nothing is found, return NAME. */
-static char *
+static const char *
find_file (name)
- char *name;
+ const char *name;
{
char *newname;
static int
is_directory (path1, path2, linker)
- char *path1;
- char *path2;
+ const char *path1;
+ const char *path2;
int linker;
{
int len1 = strlen (path1);
/* Construct the path from the two parts. Ensure the string ends with "/.".
The resulting path will be a directory even if the given path is a
symbolic link. */
- bcopy (path1, path, len1);
- bcopy (path2, path + len1, len2);
+ memcpy (path, path1, len1);
+ memcpy (path + len1, path2, len2);
cp = path + len1 + len2;
- if (cp[-1] != '/' && cp[-1] != DIR_SEPARATOR)
+ if (!IS_DIR_SEPARATOR (cp[-1]))
*cp++ = DIR_SEPARATOR;
*cp++ = '.';
*cp = '\0';
int argc;
char **argv;
{
- register int i;
- int j;
+ register size_t i;
+ size_t j;
int value;
int linker_was_run = 0;
char *explicit_link_files;
char *specs_file;
- char *p;
+ const char *p;
struct user_specs *uptr;
p = argv[0] + strlen (argv[0]);
- while (p != argv[0] && p[-1] != '/' && p[-1] != DIR_SEPARATOR) --p;
+ while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
+ --p;
programname = p;
+#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_MESSAGES, "");
+#endif
+ (void) bindtextdomain (PACKAGE, localedir);
+ (void) textdomain (PACKAGE);
+
if (signal (SIGINT, SIG_IGN) != SIG_IGN)
signal (SIGINT, fatal_error);
#ifdef SIGHUP
/* 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).
process_command (argc, argv);
{
- int i;
int first_time;
/* Build COLLECT_GCC_OPTIONS to have all of the options specified to
sizeof ("COLLECT_GCC_OPTIONS=")-1);
first_time = TRUE;
- for (i = 0; i < n_switches; i++)
+ for (i = 0; (int)i < n_switches; i++)
{
char **args;
- char *p, *q;
+ 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 = (char *) index (q,'\''))
+ while ((p = index (q,'\'')))
{
obstack_grow (&collect_obstack, q, p-q);
obstack_grow (&collect_obstack, "'\\''", 4);
{
obstack_grow (&collect_obstack, " '", 2);
q = *args;
- while (p = (char *) index (q,'\''))
+ while ((p = index (q,'\'')))
{
obstack_grow (&collect_obstack, q, p-q);
obstack_grow (&collect_obstack, "'\\''", 4);
if (access (specs_file, R_OK) == 0)
read_specs (specs_file, TRUE);
- /* Process any user specified specs in the order given on the command
- line. */
- for (uptr = user_specs_head; uptr; uptr = uptr->next)
- {
- char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK);
- read_specs (filename ? filename : uptr->filename, FALSE);
- }
-
/* If not cross-compiling, look for startfiles in the standard places. */
- /* The fact that these are done here, after reading the specs file,
- means that it cannot be found in these directories.
- But that's okay. It should never be there anyway. */
if (*cross_compile == '0')
{
#ifdef MD_EXEC_PREFIX
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 (*standard_startfile_prefix == '/'
- || *standard_startfile_prefix == DIR_SEPARATOR)
+ 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
+ )
add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
0, 0, NULL_PTR);
else
}
else
{
- if (*standard_startfile_prefix != DIR_SEPARATOR && gcc_exec_prefix)
+ if (!IS_DIR_SEPARATOR (*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);
}
+ /* Process any user specified specs in the order given on the command
+ line. */
+ for (uptr = user_specs_head; uptr; uptr = uptr->next)
+ {
+ char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK);
+ read_specs (filename ? filename : uptr->filename, FALSE);
+ }
+
/* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */
if (gcc_exec_prefix)
{
/* Warn about any switches that no pass was interested in. */
- for (i = 0; i < n_switches; i++)
- if (! switches[i].valid)
+ for (i = 0; (int)i < n_switches; i++)
+ if (! switches[i].validated)
error ("unrecognized option `-%s'", switches[i].part1);
/* Obey some of the options. */
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));
- exit (0);
+ return (0);
}
if (print_file_name)
{
printf ("%s\n", find_file (print_file_name));
- exit (0);
+ return (0);
}
if (print_prog_name)
{
char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK);
printf ("%s\n", (newname ? newname : print_prog_name));
- exit (0);
+ return (0);
}
if (print_multi_lib)
{
print_multilib_info ();
- exit (0);
+ return (0);
}
if (print_multi_directory)
printf (".\n");
else
printf ("%s\n", multilib_dir);
- exit (0);
+ return (0);
}
+ 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");
+
+ return (0);
+ }
+
+ /* We do not exit here. Instead we have created a fake input file
+ 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;
if (! strncmp (version_string, compiler_version, n)
&& compiler_version[n] == 0)
- fprintf (stderr, "gcc version %s\n", version_string);
+ notice ("gcc version %s\n", version_string);
else
- fprintf (stderr, "gcc driver version %s executing gcc version %s\n",
- version_string, compiler_version);
+ notice ("gcc driver version %s executing gcc version %s\n",
+ version_string, compiler_version);
if (n_infiles == 0)
- exit (0);
+ return (0);
}
- if (n_infiles == 0)
+ if (n_infiles == added_libraries)
fatal ("No input files");
/* Make a place to record the compiler output file names
that correspond to the input files. */
- outfiles = (char **) xmalloc (n_infiles * sizeof (char *));
- bzero ((char *) outfiles, n_infiles * sizeof (char *));
+ i = n_infiles;
+ i += lang_specific_extra_outfiles;
+ outfiles = (const char **) xcalloc (i, sizeof (char *));
/* Record which files were specified explicitly as link input. */
- explicit_link_files = xmalloc (n_infiles);
- bzero (explicit_link_files, n_infiles);
+ explicit_link_files = xcalloc (1, n_infiles);
- for (i = 0; i < n_infiles; i++)
+ for (i = 0; (int)i < n_infiles; i++)
{
register struct compiler *cp = 0;
int this_file_error = 0;
{
/* Ok, we found an applicable compiler. Run its spec. */
/* First say how much of input_filename to substitute for %b */
- register char *p;
+ register const char *p;
int len;
if (cp->spec[0][0] == '#')
input_basename = input_filename;
for (p = input_filename; *p; p++)
- if (*p == '/' || *p == DIR_SEPARATOR)
+ if (IS_DIR_SEPARATOR (*p))
input_basename = p + 1;
/* Find a suffix starting with the last period,
if (cp->spec[j])
len += strlen (cp->spec[j]);
- p = (char *) xmalloc (len + 1);
-
- len = 0;
- for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
- if (cp->spec[j])
- {
- strcpy (p + len, cp->spec[j]);
- len += strlen (cp->spec[j]);
- }
-
- value = do_spec (p);
- free (p);
+ {
+ 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);
+ }
if (value < 0)
this_file_error = 1;
}
clear_failure_queue ();
}
+ if (error_count == 0)
+ {
+ /* Make sure INPUT_FILE_NUMBER points to first available open
+ slot. */
+ input_file_number = n_infiles;
+ if (lang_specific_pre_link ())
+ error_count++;
+ }
+
/* Run ld to link all the compiler output files. */
if (error_count == 0)
{
int tmp = execution_count;
- int i;
- int first_time;
+ /* 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);
+ if (s == NULL)
+ linker_name_spec = "ld";
+ }
/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
for collect. */
putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH=");
complain about input files to be given to the linker. */
if (! linker_was_run && error_count == 0)
- for (i = 0; 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",
outfiles[i]);
delete_failure_queue ();
delete_temp_files ();
- exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
- /* NOTREACHED */
- return 0;
+ if (print_help_list)
+ {
+ printf ("\nFor bug reporting instructions, please see:\n");
+ printf ("<URL:http://www.gnu.org/software/gcc/faq.html#bugreport>\n");
+ }
+
+ return (error_count > 0 ? (signal_count ? 2 : 1) : 0);
}
/* Find the proper compilation spec for the file name NAME,
whose length is LENGTH. LANGUAGE is the specified language,
- or 0 if none specified. */
+ or 0 if this file is to be passed to the linker. */
static struct compiler *
lookup_compiler (name, length, language)
- char *name;
- int length;
- char *language;
+ const char *name;
+ size_t length;
+ const char *language;
{
struct compiler *cp;
- /* Look for the language, if one is spec'd. */
+ /* If this was specified by the user to be a linker input, indicate that. */
+ if (language != 0 && language[0] == '*')
+ return 0;
+
+ /* Otherwise, look for the language, if one is spec'd. */
if (language != 0)
{
for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
- {
- if (language != 0)
- {
- if (cp->suffix[0] == '@'
- && !strcmp (cp->suffix + 1, language))
- return cp;
- }
- }
+ if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
+ return cp;
+
error ("language %s not recognized", language);
+ return 0;
}
/* Look for a suffix. */
{
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. */
+ || (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)))))
+ && ((!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))))
+ && !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.
language = cp->spec[0] + 1;
new = (struct compiler *) xmalloc (sizeof (struct compiler));
new->suffix = cp->suffix;
- bcopy ((char *) lookup_compiler (NULL_PTR, 0, language)->spec,
- (char *) new->spec, sizeof new->spec);
+ memcpy (new->spec,
+ lookup_compiler (NULL_PTR, 0, language)->spec,
+ sizeof new->spec);
return new;
}
+
/* A non-alias entry: return it. */
return cp;
}
return 0;
}
\f
-char *
-xmalloc (size)
- unsigned size;
-{
- register char *value = (char *) malloc (size);
- if (value == 0)
- fatal ("virtual memory exhausted");
- return value;
-}
-
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
-{
- register char *value = (char *) realloc (ptr, size);
- if (value == 0)
- fatal ("virtual memory exhausted");
- return value;
-}
-
-/* This function is based on the one in libiberty. */
-
-static char *
-concat VPROTO((char *first, ...))
-{
- register int length;
- register char *newstr;
- register char *end;
- register char *arg;
- va_list args;
-#ifndef __STDC__
- char *first;
-#endif
-
- /* First compute the size of the result and get sufficient memory. */
-
- VA_START (args, first);
-#ifndef __STDC__
- first = va_arg (args, char *);
-#endif
-
- arg = first;
- length = 0;
-
- while (arg != 0)
- {
- length += strlen (arg);
- arg = va_arg (args, char *);
- }
-
- newstr = (char *) xmalloc (length + 1);
- va_end (args);
-
- /* Now copy the individual pieces to the result string. */
-
- VA_START (args, first);
-#ifndef __STDC__
- first = va_arg (args, char *);
-#endif
-
- end = newstr;
- arg = first;
- while (arg != 0)
- {
- while (*arg)
- *end++ = *arg++;
- arg = va_arg (args, char *);
- }
- *end = '\000';
- va_end (args);
-
- return (newstr);
-}
-
static char *
save_string (s, len)
- char *s;
- int len;
+ const char *s;
+ int len;
{
register char *result = xmalloc (len + 1);
static void
pfatal_with_name (name)
- char *name;
+ const char *name;
{
- fatal ("%s: %s", name, my_strerror (errno));
+ perror_with_name (name);
+ delete_temp_files ();
+ exit (1);
}
static void
perror_with_name (name)
- char *name;
+ const char *name;
{
- error ("%s: %s", name, my_strerror (errno));
+ error ("%s: %s", name, xstrerror (errno));
}
static void
pfatal_pexecute (errmsg_fmt, errmsg_arg)
- char *errmsg_fmt;
- char *errmsg_arg;
+ const char *errmsg_fmt;
+ const char *errmsg_arg;
{
if (errmsg_arg)
{
+ int save_errno = errno;
+
/* Space for trailing '\0' is in %s. */
char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg));
sprintf (msg, errmsg_fmt, errmsg_arg);
errmsg_fmt = msg;
+
+ errno = save_errno;
}
- fatal ("%s: %s", errmsg_fmt, my_strerror (errno));
+ pfatal_with_name (errmsg_fmt);
}
/* More 'friendly' abort that prints the line and file.
fatal ("Internal gcc abort.");
}
\f
-#ifdef HAVE_VPRINTF
-
/* Output an error message and exit */
-static void
-fatal VPROTO((char *format, ...))
+void
+fatal VPROTO((const char *msgid, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, format);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
#endif
fprintf (stderr, "%s: ", programname);
- vfprintf (stderr, format, ap);
+ vfprintf (stderr, _(msgid), ap);
va_end (ap);
fprintf (stderr, "\n");
delete_temp_files ();
}
static void
-error VPROTO((char *format, ...))
+error VPROTO((const char *msgid, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, format);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
#endif
fprintf (stderr, "%s: ", programname);
- vfprintf (stderr, format, ap);
+ vfprintf (stderr, _(msgid), ap);
va_end (ap);
fprintf (stderr, "\n");
}
-#else /* not HAVE_VPRINTF */
-
static void
-fatal (msg, arg1, arg2)
- char *msg, *arg1, *arg2;
+notice VPROTO((const char *msgid, ...))
{
- error (msg, arg1, arg2);
- delete_temp_files ();
- exit (1);
-}
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
+#endif
+ va_list ap;
-static void
-error (msg, arg1, arg2)
- char *msg, *arg1, *arg2;
-{
- fprintf (stderr, "%s: ", programname);
- fprintf (stderr, msg, arg1, arg2);
- fprintf (stderr, "\n");
-}
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
+#endif
-#endif /* not HAVE_VPRINTF */
+ vfprintf (stderr, _(msgid), ap);
+ va_end (ap);
+}
\f
static void
validate_all_switches ()
{
struct compiler *comp;
- register char *p;
+ register const char *p;
register char c;
struct spec_list *spec;
for (comp = compilers; comp->spec[0]; comp++)
{
- int i;
+ 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++)
+ while ((c = *p++))
if (c == '%' && *p == '{')
/* We have a switch spec. */
validate_switches (p + 1);
for (spec = specs; spec ; spec = spec->next)
{
p = *(spec->ptr_spec);
- while (c = *p++)
+ while ((c = *p++))
if (c == '%' && *p == '{')
/* We have a switch spec. */
validate_switches (p + 1);
}
p = link_command_spec;
- while (c = *p++)
+ while ((c = *p++))
if (c == '%' && *p == '{')
/* We have a switch spec. */
validate_switches (p + 1);
static void
validate_switches (start)
- char *start;
+ const char *start;
{
- register char *p = start;
- char *filter;
+ register const char *p = start;
+ const char *filter;
register int i;
int suffix = 0;
--p;
for (i = 0; i < n_switches; i++)
if (!strncmp (switches[i].part1, filter, p - filter))
- switches[i].valid = 1;
+ switches[i].validated = 1;
}
else
{
{
if (!strncmp (switches[i].part1, filter, p - filter)
&& switches[i].part1[p - filter] == 0)
- switches[i].valid = 1;
+ switches[i].validated = 1;
}
}
}
static int
used_arg (p, len)
- char *p;
+ const char *p;
int len;
{
struct mswitchstr {
static int
default_arg (p, len)
- char *p;
+ const char *p;
int len;
{
char *start, *end;
- int i;
for (start = multilib_defaults; *start != '\0'; start = end+1)
{
if ((end - start) == len && strncmp (p, start, len) == 0)
return 1;
+
+ if (*end == '\0')
+ break;
}
return 0;
if (this_path_len != 1
|| this_path[0] != '.')
{
- multilib_dir = xmalloc (this_path_len + 1);
- strncpy (multilib_dir, this_path, this_path_len);
- multilib_dir[this_path_len] = '\0';
+ 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;
}
break;
}