#include "config.h"
#include "system.h"
#include <signal.h>
#if defined(NeXT) || defined(__APPLE__)
#include <sys/param.h>
#endif
#include "obstack.h"
#include "intl.h"
#include "prefix.h"
#ifdef REPORT_EVENT
#include "apple/make-support.h"
#endif
#if defined (_WIN32) && defined (NEXT_PDO)
#undef X_OK
#define X_OK 1
#endif
#ifdef VMS
#define exit __posix_exit
#endif
#define HAVE_GETRUSAGE
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE
extern int getrusage PARAMS ((int, struct rusage *));
#endif
#ifdef EXECUTABLE_SUFFIX
#define HAVE_EXECUTABLE_SUFFIX
#else
#define EXECUTABLE_SUFFIX ""
#endif
#ifdef OBJECT_SUFFIX
#define HAVE_OBJECT_SUFFIX
#else
#define OBJECT_SUFFIX ".o"
#endif
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR ':'
#endif
#ifndef DIR_SEPARATOR
#define DIR_SEPARATOR '/'
#endif
#ifndef DIR_SEPARATOR_2
# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
#else
# define IS_DIR_SEPARATOR(ch) \
(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
#endif
static char dir_separator_str[] = {DIR_SEPARATOR, 0};
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
#ifndef GET_ENV_PATH_LIST
#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
#endif
#ifndef HAVE_KILL
#define kill(p,s) raise(s)
#endif
#define MIN_FATAL_STATUS 1
static int print_search_dirs;
static const char *print_file_name = NULL;
static const char *print_prog_name = NULL;
static int print_multi_directory;
static int print_multi_lib;
static int print_help_list;
static int verbose_flag;
static int report_times;
static int save_temps_flag;
static char *compiler_version;
static char *spec_version = DEFAULT_TARGET_VERSION;
static const char *spec_machine = DEFAULT_TARGET_MACHINE;
#ifdef CROSS_COMPILE
static char *cross_compile = "1";
#else
static char *cross_compile = "0";
#endif
#ifdef NEXT_FAT_OUTPUT
#include <mach-o/arch.h>
unsigned int current_arch;
unsigned int arch_count = 0;
NXArchInfo const **arch_array = NULL;
char **arch_family = NULL;
unsigned int multi_arch = 0;
char *final_output = "a.out";
#endif
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
static unsigned int n_filelists = 0;
static char **filelists = NULL;
static unsigned int n_dynamiclib_options = 0;
static char **dynamiclib_options = NULL;
#endif
#ifdef REPORT_EVENT
int re_type, re_line, re_arg1, re_arg2, re_arg3, re_ok;
const char *re_name, *re_file, *re_msg;
#define SAVE_REPORT_EVENT(TYPE, NAME, FILE, LINE, MSG, ARG1, ARG2, ARG3) \
re_type = (TYPE), re_name = (NAME), re_file = (FILE), re_line = (LINE), \
re_msg = (MSG), re_arg1 = (int)(ARG1), re_arg2 = (int)(ARG2), \
re_arg3 = (int)(ARG3), re_ok = 1
#define DO_REPORT_EVENT() \
do { \
if (re_ok) \
REPORT_EVENT (re_type, re_name, re_file, re_line, \
re_msg, re_arg1, re_arg2, re_arg3); \
re_ok = 0; \
} while (0)
#define DO_REPORT_STAGE(STAGE) \
do { \
if (multi_arch) \
REPORT_EVENT (re_type, re_name, re_file, re_line, \
STAGE " for %s", \
arch_array[current_arch]->name, re_arg2, re_arg3); \
else \
REPORT_EVENT (re_type, re_name, re_file, re_line, \
STAGE, re_arg1, re_arg2, re_arg3); \
} while (0)
#endif
static int error_count = 0;
static struct obstack obstack;
static struct obstack collect_obstack;
#ifdef HAVE_GETRUSAGE
static struct rusage rus, prus;
#endif
extern char *version_string;
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 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));
extern int do_spec PROTO((const char *));
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 *))
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));
void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
extern void lang_specific_driver PROTO ((void (*) PVPROTO((const char *, ...)),
int *, char ***, int *));
extern int lang_specific_pre_link ();
extern int lang_specific_extra_outfiles;
#ifndef ASM_SPEC
#define ASM_SPEC ""
#endif
#ifndef ASM_FINAL_SPEC
#define ASM_FINAL_SPEC ""
#endif
#ifndef CPP_SPEC
#define CPP_SPEC ""
#endif
#ifndef CC1_SPEC
#define CC1_SPEC ""
#endif
#ifndef CC1PLUS_SPEC
#define CC1PLUS_SPEC ""
#endif
#ifndef LINK_SPEC
#define LINK_SPEC ""
#endif
#ifndef LIB_SPEC
#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
#endif
#ifndef LIBGCC_SPEC
#if defined(LINK_LIBGCC_SPECIAL) || defined(LINK_LIBGCC_SPECIAL_1)
#define LIBGCC_SPEC "libgcc.a%s"
#else
#define LIBGCC_SPEC "-lgcc"
#endif
#endif
#ifndef STARTFILE_SPEC
#define STARTFILE_SPEC \
"%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
#endif
#ifndef SWITCHES_NEED_SPACES
#define SWITCHES_NEED_SPACES ""
#endif
#ifndef ENDFILE_SPEC
#define ENDFILE_SPEC ""
#endif
#ifndef SIGNED_CHAR_SPEC
#if DEFAULT_SIGNED_CHAR
#define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}"
#else
#define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}"
#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 *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;
static struct obstack multilib_obstack;
static char *multilib_select;
static char *multilib_matches;
static char *multilib_defaults;
#include "multilib.h"
#ifndef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS { "" }
#endif
static char *multilib_defaults_raw[] = MULTILIB_DEFAULTS;
struct user_specs {
struct user_specs *next;
const char *filename;
};
static struct user_specs *user_specs_head, *user_specs_tail;
#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
|| (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
|| (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
|| (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
|| (CHAR) == 'B' || (CHAR) == 'b')
#ifndef SWITCH_TAKES_ARG
#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
#endif
#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \
(!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \
|| !strcmp (STR, "Tbss") || !strcmp (STR, "include") \
|| !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"))
#ifndef WORD_SWITCH_TAKES_ARG
#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
#endif
#ifdef HAVE_EXECUTABLE_SUFFIX
#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
struct compiler
{
const char *suffix;
const char *spec[4];
};
static struct compiler *compilers;
static int n_compilers;
static struct compiler default_compilers[] =
{
{".m", {"#Objective-C"}},
{".cc", {"#C++"}}, {".cxx", {"#C++"}}, {".cpp", {"#C++"}},
{".c++", {"#C++"}}, {".cp", {"#C++"}}, {".C", {"#C++"}},
{".ads", {"#Ada"}}, {".adb", {"#Ada"}}, {".ada", {"#Ada"}},
{".f", {"#Fortran"}}, {".for", {"#Fortran"}}, {".F", {"#Fortran"}},
{".fpp", {"#Fortran"}},
{".p", {"#Pascal"}}, {".pas", {"#Pascal"}},
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
#include "apple/apple-specs.h"
#else
{".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__}\
%{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
"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}\
%{faltivec:-D__VEC__=10205 -D__ALTIVEC__}\
%{!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*} %{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
}},
{"-",
{"%{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}\
%{faltivec:-D__VEC__=10205 -D__ALTIVEC__}\
%{!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}"}},
{".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}}\
%{faltivec:-D__VEC__=10205 -D__ALTIVEC__}\
%{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"}},
{"@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}\
%{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"}},
{"@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"}},
{"@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__}\
%{traditional} %{ftraditional:-traditional}\
%{faltivec:-Dvector=__vector -Dpixel=__pixel -D__VEC__=10205 -D__ALTIVEC__}\
%{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 }}}}"}},
#include "specs.h"
#endif
{0, {0}}
};
static int n_default_compilers
= (sizeof default_compilers / sizeof (struct compiler)) - 1;
#ifdef LINK_COMMAND_SPEC
static const char *link_command_spec =
LINK_COMMAND_SPEC;
#else
#ifdef LINK_LIBGCC_SPECIAL
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}}\
%{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
%{T*}\
\n }}}}}}";
#else
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
#ifdef NEXT_FAT_OUTPUT
static char *ofile_merge_spec = "\
%{!M:%{!MM:%{!E:%{!precomp:%{!S:lipo -create %F \
%{c:%W{o}%{!o:-o %w%b%O}}%{!c:-o %w%u%O}\n}}}}}";
static char *exec_merge_spec = "\
%{!M:%{!MM:%{!E:%{!precomp:%{!S:%{!c:lipo -create %F \
%{o}%{!o:-o a.out}\n}}}}}}";
static char *precomp_merge_spec = "\
%{!M:%{!MM:%{!E:%{precomp:%{!S:%{!c:lipo -create %F \
%{o}%{!o:-o %b.p}\n}}}}}}";
#endif
static int n_linker_options;
static char **linker_options;
static int n_assembler_options;
static char **assembler_options;
static int n_preprocessor_options;
static char **preprocessor_options;
struct option_map
{
const char *name;
const char *equivalent;
const char *arg_info;
};
struct option_map option_map[] =
{
{"--all-warnings", "-Wall", 0},
{"--ansi", "-ansi", 0},
{"--assemble", "-S", 0},
{"--assert", "-A", "a"},
{"--classpath", "-fclasspath=", "aj"},
{"--CLASSPATH", "-fCLASSPATH=", "aj"},
{"--comments", "-C", 0},
{"--compile", "-c", 0},
{"--debug", "-g", "oj"},
{"--define-macro", "-D", "aj"},
{"--dependencies", "-M", 0},
{"--dump", "-d", "a"},
{"--dumpbase", "-dumpbase", "a"},
{"--entry", "-e", 0},
{"--extra-warnings", "-W", 0},
{"--for-assembler", "-Wa", "a"},
{"--for-linker", "-Xlinker", "a"},
{"--force-link", "-u", "a"},
{"--imacros", "-imacros", "a"},
{"--include", "-include", "a"},
{"--include-barrier", "-I-", 0},
{"--include-directory", "-I", "aj"},
{"--include-directory-after", "-idirafter", "a"},
{"--include-prefix", "-iprefix", "a"},
{"--include-with-prefix", "-iwithprefix", "a"},
{"--include-with-prefix-before", "-iwithprefixbefore", "a"},
{"--include-with-prefix-after", "-iwithprefix", "a"},
{"--language", "-x", "a"},
{"--library-directory", "-L", "a"},
{"--machine", "-m", "aj"},
{"--machine-", "-m", "*j"},
{"--no-line-commands", "-P", 0},
{"--no-precompiled-includes", "-noprecomp", 0},
{"--no-standard-includes", "-nostdinc", 0},
{"--no-standard-libraries", "-nostdlib", 0},
{"--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},
{"--prefix", "-B", "a"},
{"--preprocess", "-E", 0},
{"--print-search-dirs", "-print-search-dirs", 0},
{"--print-file-name", "-print-file-name=", "aj"},
{"--print-libgcc-file-name", "-print-libgcc-file-name", 0},
{"--print-missing-file-dependencies", "-MG", 0},
{"--print-multi-lib", "-print-multi-lib", 0},
{"--print-multi-directory", "-print-multi-directory", 0},
{"--print-prog-name", "-print-prog-name=", "aj"},
{"--profile", "-p", 0},
{"--profile-blocks", "-a", 0},
{"--quiet", "-q", 0},
{"--save-temps", "-save-temps", 0},
{"--shared", "-shared", 0},
{"--silent", "-q", 0},
{"--specs", "-specs=", "aj"},
{"--static", "-static", 0},
{"--std", "-std=", "aj"},
{"--symbolic", "-symbolic", 0},
{"--target", "-b", "a"},
{"--time", "-time", 0},
{"--trace-includes", "-H", 0},
{"--traditional", "-traditional", 0},
{"--traditional-cpp", "-traditional-cpp", 0},
{"--trigraphs", "-trigraphs", 0},
{"--undefine-macro", "-U", "aj"},
{"--use-version", "-V", "a"},
{"--user-dependencies", "-MM", 0},
{"--verbose", "-v", 0},
{"--version", "-dumpversion", 0},
{"--warn-", "-W", "*j"},
{"--write-dependencies", "-MD", 0},
{"--write-user-dependencies", "-MMD", 0},
{"--", "-f", "*j"}
};
static void
translate_options (argcp, argvp)
int *argcp;
const char ***argvp;
{
int i;
int argc = *argcp;
const char **argv = *argvp;
const char **newv =
(const char **) xmalloc ((argc + 2) * 2 * sizeof (const char *));
int newindex = 0;
i = 0;
newv[newindex++] = argv[i++];
while (i < argc)
{
if (argv[i][0] == '-' && argv[i][1] == '-')
{
size_t j;
for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
{
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))
{
const char *arg = 0;
if (arglen < optlen)
{
size_t k;
for (k = j + 1;
k < sizeof (option_map) / sizeof (option_map[0]);
k++)
if (strlen (option_map[k].name) >= arglen
&& !strncmp (argv[i], option_map[k].name, arglen))
{
error ("Ambiguous abbreviation %s", argv[i]);
break;
}
if (k != sizeof (option_map) / sizeof (option_map[0]))
break;
}
if (arglen > optlen)
{
if (argv[i][optlen] == '=')
arg = argv[i] + optlen + 1;
else if (index (arginfo, '*') != 0)
arg = argv[i] + optlen;
else
continue;
}
else if (index (arginfo, '*') != 0)
{
error ("Incomplete `%s' option", option_map[j].name);
break;
}
if (index (arginfo, 'a') != 0)
{
if (arg == 0)
{
if (i + 1 == argc)
{
error ("Missing argument to `%s' option",
option_map[j].name);
break;
}
arg = argv[++i];
}
}
else if (index (arginfo, '*') != 0)
;
else if (index (arginfo, 'o') == 0)
{
if (arg != 0)
error ("Extraneous argument to `%s' option",
option_map[j].name);
arg = 0;
}
if (arg != 0 && index (arginfo, 'j') != 0)
newv[newindex++] = concat (option_map[j].equivalent, arg,
NULL_PTR);
else if (arg != 0)
{
newv[newindex++] = option_map[j].equivalent;
newv[newindex++] = arg;
}
else
newv[newindex++] = option_map[j].equivalent;
break;
}
}
i++;
}
else if (argv[i][0] == '-')
{
const char *p = argv[i] + 1;
int c = *p;
int nskip = 1;
if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0);
else if (WORD_SWITCH_TAKES_ARG (p))
nskip += WORD_SWITCH_TAKES_ARG (p);
else if ((c == 'B' || c == 'b' || c == 'V' || c == 'x')
&& p[1] == 0)
nskip += 1;
else if (! strcmp (p, "Xlinker"))
nskip += 1;
if (nskip + i > argc)
nskip = argc - i;
while (nskip > 0)
{
newv[newindex++] = argv[i++];
nskip--;
}
}
else
newv[newindex++] = argv[i++];
}
newv[newindex] = 0;
*argvp = newv;
*argcp = newindex;
}
char *
xstrerror(e)
int e;
{
#ifdef HAVE_STRERROR
return strerror(e);
#else
if (!e)
return "errno = 0";
if (e > 0 && e < sys_nerr)
return sys_errlist[e];
return "errno = ?";
#endif
}
static char *
skip_whitespace (p)
char *p;
{
while (1)
{
if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
return p + 1;
else if (*p == '\n' || *p == ' ' || *p == '\t')
p++;
else if (*p == '#')
{
while (*p != '\n') p++;
p++;
}
else
break;
}
return p;
}
struct spec_list
{
char *name;
char *ptr;
char **ptr_spec;
struct spec_list *next;
int name_len;
int alloc_p;
};
#define INIT_STATIC_SPEC(NAME,PTR) \
{ NAME, NULL_PTR, PTR, (struct spec_list *)0, sizeof (NAME)-1, 0 }
static struct spec_list static_specs[] = {
INIT_STATIC_SPEC ("asm", &asm_spec),
INIT_STATIC_SPEC ("asm_final", &asm_final_spec),
INIT_STATIC_SPEC ("cpp", &cpp_spec),
INIT_STATIC_SPEC ("cc1", &cc1_spec),
INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec),
INIT_STATIC_SPEC ("endfile", &endfile_spec),
INIT_STATIC_SPEC ("link", &link_spec),
INIT_STATIC_SPEC ("lib", &lib_spec),
INIT_STATIC_SPEC ("libgcc", &libgcc_spec),
INIT_STATIC_SPEC ("startfile", &startfile_spec),
INIT_STATIC_SPEC ("switches_need_spaces", &switches_need_spaces),
INIT_STATIC_SPEC ("signed_char", &signed_char_spec),
INIT_STATIC_SPEC ("predefines", &cpp_predefines),
INIT_STATIC_SPEC ("cross_compile", &cross_compile),
INIT_STATIC_SPEC ("version", &compiler_version),
INIT_STATIC_SPEC ("multilib", &multilib_select),
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
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
static struct spec_list *specs = (struct spec_list *)0;
static void
init_spec ()
{
struct spec_list *next = (struct spec_list *)0;
struct spec_list *sl = (struct spec_list *)0;
int i;
if (specs)
return;
if (verbose_flag)
notice ("Using builtin specs.\n");
#ifdef EXTRA_SPECS
extra_specs = (struct spec_list *)
xmalloc (sizeof(struct spec_list) *
(sizeof(extra_specs_1)/sizeof(extra_specs_1[0])));
bzero ((PTR) extra_specs, 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;
next = sl;
}
#endif
for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1; i >= 0; i--)
{
sl = &static_specs[i];
sl->next = next;
next = sl;
}
specs = sl;
}
static void
set_spec (name, spec)
const char *name;
const char *spec;
{
struct spec_list *sl;
char *old_spec;
int name_len = strlen (name);
int i;
if (!specs)
{
struct spec_list *next = (struct spec_list *)0;
for (i = (sizeof (static_specs) / sizeof (static_specs[0])) - 1;
i >= 0; i--)
{
sl = &static_specs[i];
sl->next = next;
next = sl;
}
specs = sl;
}
for (sl = specs; sl; sl = sl->next)
if (name_len == sl->name_len && !strcmp (sl->name, name))
break;
if (!sl)
{
sl = (struct spec_list *) xmalloc (sizeof (struct spec_list));
sl->name = save_string (name, strlen (name));
sl->name_len = name_len;
sl->ptr_spec = &sl->ptr;
sl->alloc_p = 0;
*(sl->ptr_spec) = "";
sl->next = specs;
specs = sl;
}
old_spec = *(sl->ptr_spec);
*(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
? concat (old_spec, spec + 1, NULL_PTR)
: save_string (spec, strlen (spec)));
#ifdef DEBUG_SPECS
if (verbose_flag)
notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
#endif
if (old_spec && sl->alloc_p)
free (old_spec);
sl->alloc_p = 1;
}
static char **argbuf;
static int argbuf_length;
static int argbuf_index;
#define MKTEMP_EACH_FILE
#ifdef MKTEMP_EACH_FILE
extern char *make_temp_file PROTO((const char *));
static struct temp_name {
const char *suffix;
int length;
int unique;
const char *filename;
int filename_length;
struct temp_name *next;
} *temp_names;
#endif
static int execution_count;
static int signal_count;
static const char *programname;
struct prefix_list
{
char *prefix;
struct prefix_list *next;
int require_machine_suffix;
int *used_flag_ptr;
};
struct path_prefix
{
struct prefix_list *plist;
int max_len;
const char *name;
};
static struct path_prefix exec_prefixes = { 0, 0, "exec" };
static struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
static struct path_prefix include_prefixes = { 0, 0, "include" };
#ifdef NEXT_FRAMEWORK
static struct path_prefix framework_paths = {0, 0, "frameworks"};
static struct path_prefix default_framework_paths = {0, 0, "default_frameworks"};
static struct { char *path; int u1; }
framework_paths_defaults_array [] = {
#ifdef NEXT_FRAMEWORKS_DEFAULT
NEXT_FRAMEWORKS_DEFAULT
#elif defined (OPENSTEP)
{"/LocalLibrary/Frameworks", 0},
{"/NextLibrary/Frameworks", 0},
#else
{"/Local/Library/Frameworks", 0},
#ifdef NEXT_PDO
{"/Library/Frameworks", 0},
#else
{"/Network/Library/Frameworks", 0},
{"/System/Library/Frameworks", 0},
#endif
#endif
{NULL, 0}
};
#endif
static const char *machine_suffix = 0;
static const char *just_machine_suffix = 0;
static const char *gcc_exec_prefix;
#ifdef CROSS_COMPILE
#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
#ifndef STANDARD_EXEC_PREFIX_1
#define STANDARD_EXEC_PREFIX_1 "/usr/lib/gcc/"
#endif
static const char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
static const char *standard_exec_prefix_1 = STANDARD_EXEC_PREFIX_1;
#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
#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;
static const char *multilib_dir;
static void
clear_args ()
{
argbuf_index = 0;
}
static void
store_arg (arg, delete_always, delete_failure)
char *arg;
int delete_always, delete_failure;
{
if (argbuf_index + 1 == argbuf_length)
argbuf
= (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *));
argbuf[argbuf_index++] = arg;
argbuf[argbuf_index] = 0;
if (delete_always || delete_failure)
record_temp_file (arg, delete_always, delete_failure);
}
static void
read_specs (filename, main_p)
const char *filename;
int main_p;
{
int desc;
int readlen;
struct stat statbuf;
char *buffer;
register char *p;
if (verbose_flag)
notice ("Reading specs from %s\n", filename);
desc = open (filename, O_RDONLY, 0);
if (desc < 0)
pfatal_with_name (filename);
if (stat (filename, &statbuf) < 0)
pfatal_with_name (filename);
buffer = xmalloc ((unsigned) statbuf.st_size + 1);
readlen = read (desc, buffer, (unsigned) statbuf.st_size);
if (readlen < 0)
pfatal_with_name (filename);
buffer[readlen] = 0;
close (desc);
p = buffer;
while (1)
{
char *suffix;
char *spec;
char *in, *out, *p1, *p2, *p3;
p = skip_whitespace (p);
if (*p == 0)
break;
if (*p == '%' && !main_p)
{
p1 = p;
while (*p && *p != '\n')
p++;
p++;
if (!strncmp (p1, "%include", sizeof ("%include")-1)
&& (p1[sizeof "%include" - 1] == ' '
|| p1[sizeof "%include" - 1] == '\t'))
{
char *new_filename;
p1 += sizeof ("%include");
while (*p1 == ' ' || *p1 == '\t')
p1++;
if (*p1++ != '<' || p[-2] != '>')
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);
read_specs (new_filename ? new_filename : p1, FALSE);
continue;
}
else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
&& (p1[sizeof "%include_noerr" - 1] == ' '
|| p1[sizeof "%include_noerr" - 1] == '\t'))
{
char *new_filename;
p1 += sizeof "%include_noerr";
while (*p1 == ' ' || *p1 == '\t') p1++;
if (*p1++ != '<' || p[-2] != '>')
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)
notice ("Could not find specs file %s\n", p1);
continue;
}
else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
&& (p1[sizeof "%rename" - 1] == ' '
|| p1[sizeof "%rename" - 1] == '\t'))
{
int name_len;
struct spec_list *sl;
p1 += sizeof "%rename";
while (*p1 == ' ' || *p1 == '\t')
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))
p2++;
if (*p2 != ' ' && *p2 != '\t')
fatal ("specs %%rename syntax malformed after %ld characters",
(long) (p2 - buffer));
name_len = p2 - p1;
*p2++ = '\0';
while (*p2 == ' ' || *p2 == '\t')
p2++;
if (! ISALPHA ((unsigned char)*p2))
fatal ("specs %%rename syntax malformed after %ld characters",
(long) (p2 - buffer));
p3 = p2;
while (*p3 && !ISSPACE ((unsigned char)*p3))
p3++;
if (p3 != p-1)
fatal ("specs %%rename syntax malformed after %ld characters",
(long) (p3 - buffer));
*p3 = '\0';
for (sl = specs; sl; sl = sl->next)
if (name_len == sl->name_len && !strcmp (sl->name, p1))
break;
if (!sl)
fatal ("specs %s spec was not found to be renamed", p1);
if (strcmp (p1, p2) == 0)
continue;
if (verbose_flag)
{
notice ("rename spec %s to %s\n", p1, p2);
#ifdef DEBUG_SPECS
notice ("spec is '%s'\n\n", *(sl->ptr_spec));
#endif
}
set_spec (p2, *(sl->ptr_spec));
if (sl->alloc_p)
free (*(sl->ptr_spec));
*(sl->ptr_spec) = "";
sl->alloc_p = 0;
continue;
}
else
fatal ("specs unknown %% command after %ld characters",
(long) (p1 - buffer));
}
p1 = p;
while (*p1 && *p1 != ':' && *p1 != '\n')
p1++;
if (*p1 != ':')
fatal ("specs file malformed after %ld characters",
(long) (p1 - buffer));
p2 = p1;
while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
p2--;
suffix = save_string (p, p2 - p);
p = skip_whitespace (p1 + 1);
if (p[1] == 0)
fatal ("specs file malformed after %ld characters",
(long) (p - buffer));
p1 = p;
while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
p1++;
spec = save_string (p, p1 - p);
p = p1;
in = spec;
out = spec;
while (*in != 0)
{
if (in[0] == '\\' && in[1] == '\n')
in += 2;
else if (in[0] == '#')
while (*in && *in != '\n')
in++;
else
*out++ = *in++;
}
*out = 0;
if (suffix[0] == '*')
{
if (! strcmp (suffix, "*link_command"))
link_command_spec = spec;
else
set_spec (suffix + 1, spec);
}
else
{
compilers
= ((struct compiler *)
xrealloc (compilers,
(n_compilers + 2) * sizeof (struct compiler)));
compilers[n_compilers].suffix = suffix;
bzero ((char *) compilers[n_compilers].spec,
sizeof compilers[n_compilers].spec);
compilers[n_compilers].spec[0] = spec;
n_compilers++;
bzero ((char *) &compilers[n_compilers],
sizeof compilers[n_compilers]);
}
if (*suffix == 0)
link_command_spec = spec;
}
if (link_command_spec == 0)
fatal ("spec file has no spec for linking");
}
static const char *temp_filename;
static int temp_filename_length;
struct temp_file
{
const char *name;
struct temp_file *next;
};
static struct temp_file *always_delete_queue;
static struct temp_file *failure_delete_queue;
static void
record_temp_file (filename, always_delete, fail_delete)
const char *filename;
int always_delete;
int fail_delete;
{
register char *name;
name = xmalloc (strlen (filename) + 1);
strcpy (name, filename);
if (always_delete)
{
register struct temp_file *temp;
for (temp = always_delete_queue; temp; temp = temp->next)
if (! strcmp (name, temp->name))
goto already1;
temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
temp->next = always_delete_queue;
temp->name = name;
always_delete_queue = temp;
already1:;
}
if (fail_delete)
{
register struct temp_file *temp;
for (temp = failure_delete_queue; temp; temp = temp->next)
if (! strcmp (name, temp->name))
goto already2;
temp = (struct temp_file *) xmalloc (sizeof (struct temp_file));
temp->next = failure_delete_queue;
temp->name = name;
failure_delete_queue = temp;
already2:;
}
}
static void
delete_if_ordinary (name)
const char *name;
{
struct stat st;
#ifdef DEBUG
int i, c;
printf ("Delete %s? (y or n) ", name);
fflush (stdout);
i = getchar ();
if (i != '\n')
while ((c = getchar ()) != '\n' && c != EOF)
;
if (i == 'y' || i == 'Y')
#endif
if (stat (name, &st) >= 0 && S_ISREG (st.st_mode))
if (unlink (name) < 0)
if (verbose_flag)
perror_with_name (name);
}
static void
delete_temp_files ()
{
register struct temp_file *temp;
for (temp = always_delete_queue; temp; temp = temp->next)
delete_if_ordinary (temp->name);
always_delete_queue = 0;
}
static void
delete_failure_queue ()
{
register struct temp_file *temp;
for (temp = failure_delete_queue; temp; temp = temp->next)
delete_if_ordinary (temp->name);
}
static void
clear_failure_queue ()
{
failure_delete_queue = 0;
}
#ifndef HAVE_PUTENV
void
putenv (str)
char *str;
{
#ifndef VMS
extern char **environ;
char **old_environ = environ;
char **envp;
int num_envs = 0;
int name_len = 1;
int str_len = strlen (str);
char *p = str;
int ch;
while ((ch = *p++) != '\0' && ch != '=')
name_len++;
if (!ch)
abort ();
for (envp = old_environ; *envp; envp++)
{
num_envs++;
if (!strncmp (str, *envp, name_len))
{
*envp = str;
return;
}
}
environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
*environ = str;
memcpy ((char *) (environ + 1), (char *) old_environ,
sizeof (char *) * (num_envs+1));
#endif
}
#endif
static char *
build_search_list (paths, prefix, check_dir_p)
struct path_prefix *paths;
const char *prefix;
int check_dir_p;
{
int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
int just_suffix_len
= (just_machine_suffix) ? strlen (just_machine_suffix) : 0;
int first_time = TRUE;
struct prefix_list *pprefix;
obstack_grow (&collect_obstack, prefix, strlen (prefix));
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);
}
static void
putenv_from_prefixes (paths, env_var)
struct path_prefix *paths;
const char *env_var;
{
putenv (build_search_list (paths, env_var, 1));
}
#ifdef NEXT_CPP_PRECOMP
struct switchstr
{
char *part1;
char **args;
int live_cond;
int validated;
};
static struct switchstr *switches;
static int n_switches;
struct infile
{
char *name;
char *language;
};
#endif
static char *
find_a_file (pprefix, name, mode)
struct path_prefix *pprefix;
const char *name;
int mode;
{
char *temp;
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;
#if defined (_WIN32) && defined (NEXT_PDO)
if (mode & X_OK)
mode = mode & ~X_OK;
#endif
#ifdef DEFAULT_ASSEMBLER
if (! strcmp(name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) {
name = DEFAULT_ASSEMBLER;
len = strlen(name)+1;
temp = xmalloc (len);
strcpy (temp, name);
return temp;
}
#endif
#ifdef DEFAULT_LINKER
if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) {
name = DEFAULT_LINKER;
len = strlen(name)+1;
temp = xmalloc (len);
strcpy (temp, name);
return temp;
}
#endif
if (machine_suffix)
len += strlen (machine_suffix);
temp = xmalloc (len);
if (IS_DIR_SEPARATOR (*name)
#ifdef HAVE_DOS_BASED_FILESYSTEM
|| (name[0] && name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
#endif
)
{
if (access (name, mode) == 0)
{
strcpy (temp, name);
return temp;
}
}
else
for (pl = pprefix->plist; pl; pl = pl->next)
{
if (machine_suffix)
{
if (file_suffix[0] != 0)
{
strcpy (temp, pl->prefix);
strcat (temp, machine_suffix);
strcat (temp, name);
strcat (temp, file_suffix);
if (access (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
return temp;
}
}
strcpy (temp, pl->prefix);
strcat (temp, machine_suffix);
strcat (temp, name);
if (access (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
return temp;
}
}
if (just_machine_suffix && pl->require_machine_suffix == 2)
{
if (file_suffix[0] != 0)
{
strcpy (temp, pl->prefix);
strcat (temp, just_machine_suffix);
strcat (temp, name);
strcat (temp, file_suffix);
if (access (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
return temp;
}
}
strcpy (temp, pl->prefix);
strcat (temp, just_machine_suffix);
strcat (temp, name);
if (access (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
return temp;
}
}
if (! pl->require_machine_suffix)
{
if (file_suffix[0] != 0)
{
strcpy (temp, pl->prefix);
strcat (temp, name);
strcat (temp, file_suffix);
if (access (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
return temp;
}
}
strcpy (temp, pl->prefix);
strcat (temp, name);
if (access (temp, mode) == 0)
{
if (pl->used_flag_ptr != 0)
*pl->used_flag_ptr = 1;
return temp;
}
}
}
#ifdef NEXT_CPP_PRECOMP
if (strcmp(name, "cpp-precomp") == 0)
{
#if 0
int i = 0;
while (i < n_switches
&& (switches[i].part1[0] != 'p'
|| strcmp (switches[i].part1, "precomp")))
i++;
if (i == n_switches)
#endif
return find_a_file (pprefix, "cpp", X_OK);
}
#endif
free (temp);
return 0;
}
#ifdef NEXT_SEMANTICS
static void add_dynamiclib_option(first, second)
char * first;
char * second;
{
n_dynamiclib_options+=2;
if (dynamiclib_options == NULL)
dynamiclib_options = (char **)
xmalloc (n_dynamiclib_options * sizeof (char*));
else
dynamiclib_options = (char **)
xrealloc (dynamiclib_options,
n_dynamiclib_options * sizeof (char*));
dynamiclib_options[n_dynamiclib_options-2] = first;
if (second)
dynamiclib_options[n_dynamiclib_options-1] = second;
else
n_dynamiclib_options--;
}
#endif
static void
add_prefix (pprefix, prefix, component, first, require_machine_suffix, warn)
struct path_prefix *pprefix;
const char *prefix;
const char *component;
int first;
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;
prefix = update_path (prefix, component);
len = strlen (prefix);
if (len > pprefix->max_len)
pprefix->max_len = len;
pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
pl->prefix = save_string (prefix, len);
pl->require_machine_suffix = require_machine_suffix;
pl->used_flag_ptr = warn;
if (warn)
*warn = 0;
if (*prev)
pl->next = *prev;
else
pl->next = (struct prefix_list *) 0;
*prev = pl;
}
#ifdef NEXT_FRAMEWORK
static void
safe_add_prefix (pprefix, prefix, first, require_machine_suffix, warn)
struct path_prefix *pprefix;
char *prefix;
int first;
int require_machine_suffix;
int *warn;
{
int len = strlen (prefix);
char *temp = prefix;
if (prefix[len - 1] != '/')
{
temp = xmalloc (len+2);
strcpy (temp, prefix);
temp[len] = '/';
temp[len+1] = 0;
}
add_prefix (pprefix, temp, "GCC", first, require_machine_suffix, warn);
}
#endif
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);
*pl->used_flag_ptr = 1;
}
pl = pl->next;
}
}
static int
execute ()
{
int i;
int n_commands;
char *string;
struct command
{
const char *prog;
char **argv;
int pid;
};
struct command *commands;
for (n_commands = 1, i = 0; i < argbuf_index; i++)
if (strcmp (argbuf[i], "|") == 0)
n_commands++;
commands
= (struct command *) alloca (n_commands * sizeof (struct command));
commands[0].prog = argbuf[0];
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)
{
#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
fatal ("-pipe not supported");
#endif
argbuf[i] = 0;
commands[n_commands].prog = argbuf[i + 1];
commands[n_commands].argv = &argbuf[i + 1];
string = find_a_file (&exec_prefixes, commands[n_commands].prog, X_OK);
if (string)
commands[n_commands].argv[0] = string;
n_commands++;
}
argbuf[argbuf_index] = 0;
if (verbose_flag)
{
if (print_help_list)
fputc ('\n', stderr);
for (i = 0; i < n_commands ; i++)
{
char **j;
for (j = commands[i].argv; *j; j++)
fprintf (stderr, " %s", *j);
if (i + 1 != n_commands)
fprintf (stderr, " |");
fprintf (stderr, "\n");
}
fflush (stderr);
#ifdef DEBUG
notice ("\nGo ahead? (y or n) ");
fflush (stderr);
i = getchar ();
if (i != '\n')
while (getchar () != '\n')
;
if (i != 'y' && i != 'Y')
return 0;
#endif
}
#ifdef DO_REPORT_EVENT
DO_REPORT_EVENT ();
#endif
for (i = 0; i < n_commands; i++)
{
char *errmsg_fmt, *errmsg_arg;
char *string = commands[i].argv[0];
commands[i].pid = pexecute (string, commands[i].argv,
programname, temp_filename,
&errmsg_fmt, &errmsg_arg,
((i == 0 ? PEXECUTE_FIRST : 0)
| (i + 1 == n_commands ? PEXECUTE_LAST : 0)
| (string == commands[i].prog
? PEXECUTE_SEARCH : 0)
| (verbose_flag ? PEXECUTE_VERBOSE : 0)));
if (commands[i].pid == -1)
pfatal_pexecute (errmsg_fmt, errmsg_arg);
if (string != commands[i].prog)
free (string);
}
execution_count++;
{
int ret_code = 0;
#ifdef HAVE_GETRUSAGE
struct timeval d;
double ut = 0.0, st = 0.0;
#endif
for (i = 0; i < n_commands; )
{
int j;
int status;
int pid;
pid = pwait (commands[i].pid, &status, 0);
if (pid < 0)
abort ();
#ifdef HAVE_GETRUSAGE
if (report_times)
{
prus = rus;
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;
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;
}
#endif
for (j = 0; j < n_commands; j++)
if (commands[j].pid == pid)
{
i++;
if (status != 0)
{
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)
ret_code = -1;
}
#ifdef HAVE_GETRUSAGE
if (report_times )
fprintf (stderr, "# %s %.2f %.2f\n", commands[j].prog, ut, st);
#endif
break;
}
}
return ret_code;
}
}
#ifndef NEXT_CPP_PRECOMP
struct switchstr
{
const char *part1;
char **args;
int live_cond;
int validated;
};
static struct switchstr *switches;
static int n_switches;
struct infile
{
const char *name;
const char *language;
};
#endif
static struct infile *infiles;
static int n_infiles;
static int added_libraries;
static const char **outfiles;
static int warn_B;
static int warn_std;
static int *warn_std_ptr = 0;
#if defined(HAVE_OBJECT_SUFFIX) || defined(HAVE_EXECUTABLE_SUFFIX)
static char *
convert_filename (name, do_exe)
char *name;
int do_exe;
{
int i;
int len;
if (name == NULL)
return NULL;
len = strlen (name);
#ifdef HAVE_OBJECT_SUFFIX
if (len > 2
&& name[len - 2] == '.'
&& name[len - 1] == 'o')
{
obstack_grow (&obstack, name, len - 2);
obstack_grow0 (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
name = obstack_finish (&obstack);
}
#endif
#ifdef HAVE_EXECUTABLE_SUFFIX
if (! do_exe || EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
return name;
for (i = len - 1; i >= 0; i--)
if (IS_DIR_SEPARATOR (name[i]))
break;
for (i++; i < len; i++)
if (name[i] == '.')
return name;
obstack_grow (&obstack, name, len);
obstack_grow0 (&obstack, EXECUTABLE_SUFFIX, strlen (EXECUTABLE_SUFFIX));
name = obstack_finish (&obstack);
#endif
return name;
}
#endif
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");
}
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);
}
#ifdef NEXT_FAT_OUTPUT
const char **arch_merge_files;
static const char *dependency_output_file = NULL;
#endif
#ifdef NEXT_FRAMEWORK
static char *
find_a_framework (pprefix, name, postfix)
struct path_prefix *pprefix;
char *name;
char *postfix;
{
int len = pprefix->max_len + strlen (name) * 2
+ strlen (".framework/") + 4 + (postfix ? strlen (postfix) : 0);
char *temp = xmalloc (len);
struct prefix_list *pl;
for (pl = pprefix->plist; pl; pl = pl->next)
{
strcpy (temp, pl->prefix);
strcat (temp, name);
strcat (temp, ".framework/");
strcat (temp, name);
if (postfix)
strcat (temp, postfix);
if (access (temp, R_OK) == 0)
return temp;
}
free (temp);
return 0;
}
#endif
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
static char *default_language = NULL;
#endif
static void
process_command (argc, argv)
int argc;
char **argv;
{
#ifdef NEXT_SEMANTICS
int code_gen_style_dynamic = -1;
char *install_name = "a.out";
#endif
register int i;
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;
GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX");
n_switches = 0;
n_infiles = 0;
added_libraries = 0;
compiler_version = temp1 =
save_string (version_string, strlen (version_string));
for (; *temp1; ++temp1)
{
if (*temp1 == ' ')
{
*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);
}
#ifdef NEXT_FRAMEWORK
{
int i = 0;
const char *path;
char *next_root = getenv ("NEXT_ROOT");
if (next_root && *next_root && next_root[strlen (next_root) - 1] == '/')
next_root[strlen (next_root) - 1] = '\0';
while (path = framework_paths_defaults_array[i++].path)
{
char *new_fname = NULL;
if (next_root && *next_root)
new_fname = (char *) xmalloc (strlen (next_root) + strlen (path) + 1);
if (new_fname)
sprintf (new_fname, "%s%s", next_root, path);
else
new_fname = path;
safe_add_prefix (&default_framework_paths, new_fname, 0, 0, 0);
}
}
#endif
GET_ENV_PATH_LIST (temp, "COMPILER_PATH");
if (temp)
{
const char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
while (1)
{
if (*endp == PATH_SEPARATOR || *endp == 0)
{
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;
}
else
nstore[endp-startp] = 0;
add_prefix (&exec_prefixes, nstore, 0, 0, 0, NULL_PTR);
add_prefix (&include_prefixes,
concat (nstore, "include", NULL_PTR),
0, 0, 0, NULL_PTR);
if (*endp == 0)
break;
endp = startp = endp + 1;
}
else
endp++;
}
}
GET_ENV_PATH_LIST (temp, "LIBRARY_PATH");
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
while (1)
{
if (*endp == PATH_SEPARATOR || *endp == 0)
{
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;
}
else
nstore[endp-startp] = 0;
add_prefix (&startfile_prefixes, nstore, NULL_PTR,
0, 0, NULL_PTR);
if (*endp == 0)
break;
endp = startp = endp + 1;
}
else
endp++;
}
}
GET_ENV_PATH_LIST (temp, "LPATH");
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
while (1)
{
if (*endp == PATH_SEPARATOR || *endp == 0)
{
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;
}
else
nstore[endp-startp] = 0;
add_prefix (&startfile_prefixes, nstore, NULL_PTR,
0, 0, NULL_PTR);
if (*endp == 0)
break;
endp = startp = endp + 1;
}
else
endp++;
}
}
translate_options (&argc, &argv);
lang_specific_driver (fatal, &argc, &argv, &added_libraries);
for (i = 1; i < argc; i++)
{
if (! strcmp (argv[i], "-dumpspecs"))
{
struct spec_list *sl;
init_spec ();
for (sl = specs; sl; sl = sl->next)
printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
#ifdef NEXT_CPP_PRECOMP
#ifndef PTRDIFF_TYPE
#define PTRDIFF_TYPE "long int"
#endif
#ifndef SIZE_TYPE
#define SIZE_TYPE "long unsigned int"
#endif
#ifndef WCHAR_TYPE
#define WCHAR_TYPE "int"
#endif
printf ("*builtin_predefines:\n%s\n\n",
"\"-D__PTRDIFF_TYPE__=" PTRDIFF_TYPE
"\" \"-D__SIZE_TYPE__=" SIZE_TYPE
"\" \"-D__WCHAR_TYPE__=" WCHAR_TYPE "\"");
#endif
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", spec_version);
exit (0);
}
else if (! strcmp (argv[i], "-dumpmachine"))
{
printf ("%s\n", spec_machine);
exit (0);
}
else if (strcmp (argv[i], "-fhelp") == 0)
{
print_help_list = 1;
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"))
print_file_name = "libgcc.a";
else if (! strncmp (argv[i], "-print-file-name=", 17))
print_file_name = argv[i] + 17;
else if (! strncmp (argv[i], "-print-prog-name=", 17))
print_prog_name = argv[i] + 17;
else if (! strcmp (argv[i], "-print-multi-lib"))
print_multi_lib = 1;
else if (! strcmp (argv[i], "-print-multi-directory"))
print_multi_directory = 1;
else if (! strncmp (argv[i], "-Wa,", 4))
{
int prev, j;
prev = 4;
for (j = 4; argv[i][j]; j++)
if (argv[i][j] == ',')
{
add_assembler_option (argv[i] + prev, j - prev);
prev = j + 1;
}
add_assembler_option (argv[i] + prev, j - prev);
}
else if (! strncmp (argv[i], "-Wp,", 4))
{
int prev, j;
prev = 4;
for (j = 4; argv[i][j]; j++)
if (argv[i][j] == ',')
{
add_preprocessor_option (argv[i] + prev, j - prev);
prev = j + 1;
}
add_preprocessor_option (argv[i] + prev, j - prev);
}
else if (argv[i][0] == '+' && argv[i][1] == 'e')
n_switches++;
else if (strncmp (argv[i], "-Wl,", 4) == 0)
{
int j;
for (j = 3; argv[i][j]; j++)
n_infiles += (argv[i][j] == ',');
}
else if (strcmp (argv[i], "-Xlinker") == 0)
{
if (i + 1 == argc)
fatal ("argument to `-Xlinker' is missing");
n_infiles++;
i++;
}
#ifdef NEXT_PDO
else if (! strncmp (argv[i], "-F", 2))
{
if (argv[i][2] == 0)
fatal ("argument to `-F' is missing");
#ifdef NEXT_FRAMEWORK
safe_add_prefix (&framework_paths, argv[i]+2, 0, 0, 0);
#endif
n_switches++;
}
#endif
else if (strncmp (argv[i], "-l", 2) == 0)
n_infiles++;
else if (strcmp (argv[i], "-time") == 0)
report_times = 1;
else if (strcmp (argv[i], "-save-temps") == 0)
{
save_temps_flag = 1;
n_switches++;
}
else if (strcmp (argv[i], "-specs") == 0)
{
struct user_specs *user = (struct user_specs *)
xmalloc (sizeof (struct user_specs));
if (++i >= argc)
fatal ("argument to `-specs' is missing");
user->next = (struct user_specs *)0;
user->filename = argv[i];
if (user_specs_tail)
user_specs_tail->next = user;
else
user_specs_head = user;
user_specs_tail = user;
}
else if (strncmp (argv[i], "-specs=", 7) == 0)
{
struct user_specs *user = (struct user_specs *)
xmalloc (sizeof (struct user_specs));
if (strlen (argv[i]) == 7)
fatal ("argument to `-specs=' is missing");
user->next = (struct user_specs *)0;
user->filename = argv[i]+7;
if (user_specs_tail)
user_specs_tail->next = user;
else
user_specs_head = user;
user_specs_tail = user;
}
else if (argv[i][0] == '-' && argv[i][1] != 0)
{
register char *p = &argv[i][1];
register int c = *p;
switch (c)
{
case 'b':
n_switches++;
if (p[1] == 0 && i + 1 == argc)
fatal ("argument to `-b' is missing");
if (p[1] == 0)
spec_machine = argv[++i];
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else if (WORD_SWITCH (p))
i += WORD_SWITCH_TAKES_ARG (p);
#endif
else
spec_machine = p + 1;
warn_std_ptr = &warn_std;
break;
case 'B':
{
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);
{
int len = strlen (value);
if ((len == 7
|| (len > 7
&& (IS_DIR_SEPARATOR (value[len - 8]))))
&& strncmp (value + len - 7, "stage", 5) == 0
&& ISDIGIT (value[len - 2])
&& (IS_DIR_SEPARATOR (value[len - 1])))
{
if (len == 7)
add_prefix (&include_prefixes, "include", NULL_PTR,
1, 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);
}
}
}
n_switches++;
}
break;
case 'v':
n_switches++;
if (p[1] != 0)
break;
verbose_flag++;
break;
case 'V':
n_switches++;
if (p[1] == 0 && i + 1 == argc)
fatal ("argument to `-V' is missing");
if (p[1] == 0)
spec_version = argv[++i];
else
spec_version = p + 1;
compiler_version = spec_version;
warn_std_ptr = &warn_std;
{
const char *v = compiler_version;
while (! ISDIGIT (*v))
v++;
if (v > compiler_version && v[-1] != '-')
fatal ("invalid version number format");
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;
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
case 'f':
if (!strcmp (p, "framework"))
{
#ifndef NEXT_FRAMEWORK
n_infiles++;
#endif
if (WORD_SWITCH_TAKES_ARG (p))
{
n_infiles += WORD_SWITCH_TAKES_ARG (p);
i += WORD_SWITCH_TAKES_ARG (p);
if (i >= argc)
fatal ("argument to `-framework' is missing");
}
break;
}
else if (!strcmp (p, "filelist"))
{
#if defined (NEXT_SEMANTICS) || defined (hpux) || defined (_WIN32)
n_infiles++;
if (WORD_SWITCH_TAKES_ARG (p))
{
n_infiles += WORD_SWITCH_TAKES_ARG (p);
i += WORD_SWITCH_TAKES_ARG (p);
if (i >= argc)
fatal ("argument to `-filelist' is missing");
}
#else
if (i + 1 == argc)
fatal ("argument to `-filelist' is missing");
n_filelists++;
if (filelists == NULL)
filelists = (char **)
xmalloc (n_filelists * sizeof (char*));
else
filelists = (char **)
xrealloc (filelists,
n_filelists * sizeof (char*));
filelists[n_filelists-1] = argv[++i];
n_switches++;
#endif
break;
}
else if (!strncmp (p, "fgen-index=", 11))
{
if (!p[11])
fatal ("Missing argument to -fgen-index=");
n_switches++;
break;
}
#ifdef NEXT_SEMANTICS
case 'i':
if (!strcmp (p, "install_name"))
{
if (i + 1 == argc)
fatal ("argument to `-install_name' is missing");
add_dynamiclib_option(argv[i], argv[i+1]);
i++;
n_switches++;
install_name = NULL;
break;
}
else if (!strcmp (p, "image_base"))
{
if (i + 1 == argc)
fatal ("argument to `-image_base' is missing");
add_dynamiclib_option(argv[i], argv[i+1]);
i++;
n_switches++;
break;
}
#endif
#endif
#if defined (NEXT_FAT_OUTPUT) || defined (NEXT_PDO)
case 'a':
if (!strcmp (p, "arch") || !strcmp (p, "arch_only"))
{
#ifdef NEXT_FAT_OUTPUT
NXArchInfo const* temp;
int j, duplicate = 0;
#endif
if (i + 1 == argc)
fatal ("argument to `-arch' is missing");
#ifdef NEXT_PDO
i++;
#ifdef _WIN32
if (strcmp (argv[i], "i386")
#ifdef ARCH
&& strcmp (argv[i], ARCH)
#endif
)
fatal ("unknown architecture `%s'", argv[i]);
#else
error ("Warning: This version of gcc ignores the -arch flag");
#endif
#else
temp = NXGetArchInfoFromName (argv[++i]);
if (temp == 0 && !strcmp (argv[i], "ppc"))
temp = NXGetArchInfoFromName ("m98k");
if (temp == 0)
fatal ("unknown architecture `%s'", argv[i]);
for (j = 0; j < arch_count; j++)
if (!strcmp (temp->name, arch_array[j]->name))
duplicate = 1;
if (!duplicate)
{
arch_count++;
if (arch_array == NULL)
arch_array = (NXArchInfo const **)
xmalloc (arch_count * sizeof (NXArchInfo*));
else
arch_array = (NXArchInfo const **)
xrealloc (arch_array,
arch_count * sizeof (NXArchInfo*));
arch_array[arch_count - 1] = temp;
}
#endif
n_switches++;
break;
}
#endif
#if defined (NEXT_FAT_OUTPUT) || defined (NEXT_SEMANTICS)
case 'd':
if (p[1] == '\0')
break;
#ifdef NEXT_FAT_OUTPUT
else if (!strcmp (p, "dependency-file"))
{
if (i + 1 == argc)
fatal ("argument to `-dependency-file' is missing");
dependency_output_file = argv[++i];
break;
}
#endif
#ifdef NEXT_SEMANTICS
else if (!strcmp (p, "dynamic"))
{
n_switches++;
if (code_gen_style_dynamic == 0)
fatal ("conflicting code gen style switches");
code_gen_style_dynamic = 1;
break;
}
#endif
#endif
case 'c':
#ifdef NEXT_SEMANTICS
if (!strcmp (p, "current_version"))
{
if (i + 1 == argc)
fatal ("argument to `-current_version' is missing");
add_dynamiclib_option(argv[i], argv[i+1]);
i++;
n_switches++;
break;
}
else if (!strcmp (p, "compatibility_version"))
{
if (i + 1 == argc)
fatal ("argument to `-compatibility_version' is missing");
add_dynamiclib_option(argv[i], argv[i+1]);
i++;
n_switches++;
break;
}
#endif
case 'S':
if (p[1] == 0)
{
have_c = 1;
n_switches++;
break;
}
goto normal_switch;
case 'o':
have_o = 1;
#if defined(HAVE_EXECUTABLE_SUFFIX)
if (! have_c)
{
int skip;
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)
if (p[1] == 0)
argv[i+1] = convert_filename (argv[i+1], ! have_c);
else
argv[i] = convert_filename (argv[i], ! have_c);
#endif
goto normal_switch;
#if defined (NEXT_SEMANTICS) || (defined (NEXT_PDO) && defined (_WIN32))
case 's':
if (!strcmp (p, "static"))
#ifdef NEXT_SEMANTICS
{
if (code_gen_style_dynamic == 1)
fatal ("conflicting code gen style switches");
code_gen_style_dynamic = 0;
}
#elif defined (NEXT_PDO) && defined (_WIN32)
error ("Warning: This version of gcc does not support the -static flag");
#endif
#endif
default:
normal_switch:
n_switches++;
#ifdef NEXT_SEMANTICS
if (p[0] == 'o' && p[1] == '\0' && i + 1 < argc)
{
if (install_name)
install_name = argv[i+1];
#ifdef NEXT_FAT_OUTPUT
final_output = argv[i+1];
#endif
}
#endif
if (SWITCH_TAKES_ARG (c) > (p[1] != 0))
i += SWITCH_TAKES_ARG (c) - (p[1] != 0);
else if (WORD_SWITCH_TAKES_ARG (p))
i += WORD_SWITCH_TAKES_ARG (p);
}
}
else
{
n_infiles++;
lang_n_infiles++;
}
}
#ifdef NEXT_SEMANTICS
if (install_name)
add_dynamiclib_option ("-install_name", install_name);
#endif
if (have_c && have_o && lang_n_infiles > 1)
fatal ("cannot specify -o with -c or -S and multiple compilations");
#ifdef NEXT_PDO
{
char *next_root = getenv ("NEXT_ROOT");
if (next_root && next_root[strlen (next_root)-1] == '/')
next_root[strlen (next_root)-1] = '\0';
if (next_root && *next_root)
{
char *new_standard_exec_prefix = (char*)malloc(strlen(next_root) + strlen(standard_exec_prefix) + 1);
char* new_standard_startfile_prefix = (char*)malloc(strlen(next_root) + strlen(standard_startfile_prefix) + 1);
char* new_tooldir_base_prefix = (char*)malloc(strlen(next_root) + strlen(tooldir_base_prefix) + 1);
sprintf (new_standard_exec_prefix, "%s%s",
next_root, standard_exec_prefix);
sprintf (new_standard_startfile_prefix, "%s%s",
next_root, standard_startfile_prefix);
sprintf (new_tooldir_base_prefix, "%s%s",
next_root, tooldir_base_prefix);
if (new_standard_exec_prefix && *new_standard_exec_prefix)
standard_exec_prefix = new_standard_exec_prefix;
if (new_standard_startfile_prefix && *new_standard_startfile_prefix)
standard_startfile_prefix = new_standard_startfile_prefix;
if (new_tooldir_base_prefix && *new_tooldir_base_prefix)
tooldir_base_prefix = new_tooldir_base_prefix;
}
}
#endif
#ifndef OS2
add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
0, 2, warn_std_ptr);
add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
0, 2, warn_std_ptr);
#endif
add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
0, 1, warn_std_ptr);
add_prefix (&startfile_prefixes, standard_exec_prefix_1, "BINUTILS",
0, 1, warn_std_ptr);
tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
dir_separator_str, NULL_PTR);
if (!IS_DIR_SEPARATOR (*tooldir_prefix))
{
if (gcc_exec_prefix)
{
char *gcc_exec_tooldir_prefix
= concat (gcc_exec_prefix, spec_machine, dir_separator_str,
spec_version, dir_separator_str, tooldir_prefix, NULL_PTR);
add_prefix (&exec_prefixes,
concat (gcc_exec_tooldir_prefix, "bin",
dir_separator_str, NULL_PTR),
NULL_PTR, 0, 0, NULL_PTR);
add_prefix (&startfile_prefixes,
concat (gcc_exec_tooldir_prefix, "lib",
dir_separator_str, NULL_PTR),
NULL_PTR, 0, 0, NULL_PTR);
}
tooldir_prefix = concat (standard_exec_prefix, spec_machine,
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 (&startfile_prefixes,
concat (tooldir_prefix, "lib", dir_separator_str, NULL_PTR),
"BINUTILS", 0, 0, NULL_PTR);
switches = ((struct switchstr *)
xmalloc ((n_switches + 1) * sizeof (struct switchstr)));
infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile));
n_switches = 0;
n_infiles = 0;
last_language_n_infiles = -1;
for (i = 1; i < argc; i++)
{
if (! strncmp (argv[i], "-Wa,", 4))
;
else if (! strncmp (argv[i], "-Wp,", 4))
;
else if (! strcmp (argv[i], "-print-search-dirs"))
;
else if (! strcmp (argv[i], "-print-libgcc-file-name"))
;
else if (strcmp (argv[i], "-time") == 0)
;
else if (! strncmp (argv[i], "-print-file-name=", 17))
;
else if (! strncmp (argv[i], "-print-prog-name=", 17))
;
else if (! strcmp (argv[i], "-print-multi-lib"))
;
else if (! strcmp (argv[i], "-print-multi-directory"))
;
else if (strcmp (argv[i], "-fhelp") == 0)
{
if (verbose_flag)
{
infiles[n_infiles].language = "c";
infiles[n_infiles++].name = "help-dummy";
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')
{
switches[n_switches].part1 = &argv[i][0];
switches[n_switches].args = 0;
switches[n_switches].live_cond = 0;
switches[n_switches].validated = 0;
n_switches++;
}
else if (strncmp (argv[i], "-Wl,", 4) == 0)
{
int prev, j;
prev = 4;
for (j = 4; argv[i][j]; j++)
if (argv[i][j] == ',')
{
infiles[n_infiles].language = "*";
infiles[n_infiles++].name
= save_string (argv[i] + prev, j - prev);
prev = j + 1;
}
infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[i] + prev;
}
else if (strcmp (argv[i], "-Xlinker") == 0)
{
infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[++i];
}
else if (strncmp (argv[i], "-l", 2) == 0)
{
infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[i];
}
else if (strcmp (argv[i], "-specs") == 0)
i++;
else if (strncmp (argv[i], "-specs=", 7) == 0)
;
else if (save_temps_flag && strcmp (argv[i], "-pipe") == 0)
error ("Warning: -pipe ignored since -save-temps specified");
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else if (strcmp (argv[i], "-flat_namespace") == 0
|| strcmp (argv[i], "-force_flat_namespace") == 0)
{
infiles[n_infiles].language = "*";
infiles[n_infiles++].name = argv[i];
}
else if (strcmp (argv[i], "-framework") == 0)
{
int j, n;
#ifndef NEXT_FRAMEWORK
infiles[n_infiles].language = 0;
infiles[n_infiles++].name = argv[i];
#endif
for (j = 0, n = WORD_SWITCH_TAKES_ARG (argv[i]+1);
j < n && i + 1 < argc; j++)
{
infiles[n_infiles].language = 0;
#ifndef NEXT_FRAMEWORK
infiles[n_infiles++].name = argv[++i];
#else
{
const char *fw = argv[++i];
char *fw_path = 0, *suffix;
if (suffix = (char *) index (fw, ','))
*suffix++ = 0;
if (suffix)
fw_path = find_a_framework (&framework_paths, fw, suffix);
if (!fw_path)
fw_path = find_a_framework (&framework_paths, fw, 0);
if (suffix && !fw_path)
fw_path = find_a_framework (&default_framework_paths, fw,
suffix);
if (!fw_path)
fw_path = find_a_framework (&default_framework_paths, fw, 0);
if (!fw_path)
error ("framework %s not found", fw);
else
infiles[n_infiles++].name = (char *) fw_path;
}
#endif
}
}
#if defined (NEXT_SEMANTICS) || defined (hpux) || defined (_WIN32)
else if (strcmp (argv[i], "-filelist") == 0)
{
int j, n;
infiles[n_infiles].language = 0;
#ifdef hpux
infiles[n_infiles++].name = index (argv[i+1], ',') ? argv[i] : "-c";
#else
infiles[n_infiles++].name = argv[i];
#endif
for (j = 0, n = WORD_SWITCH_TAKES_ARG (argv[i]+1);
j < n && i + 1 < argc; j++)
{
infiles[n_infiles].language = 0;
infiles[n_infiles++].name = argv[++i];
}
}
#endif
else if (strncmp (argv[i], "-fgen-index=", 12) == 0)
{
int arg_len = 0;
char *part1 = (char *) xmalloc (13);
strcpy (part1, "-fgen-index=");
arg_len = strlen (&argv[i][12]);
switches[n_switches].part1 = &argv[i][1];
switches[n_switches].args = 0;
switches[n_switches].live_cond = 1;
switches[n_switches].validated = 1;
add_preprocessor_option (argv[i], strlen (argv[i]));
n_switches++;
}
#endif
else if (argv[i][0] == '-' && argv[i][1] != 0)
{
register char *p = &argv[i][1];
register int c = *p;
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
#if 0
if ((c == 'B' || c == 'b' || c == 'V')
&& ! WORD_SWITCH (p))
{
if (p[1] == 0)
i++;
continue;
}
#endif
if (c == 'd' && !strcmp (p, "dependency-file"))
{
i++;
continue;
}
#endif
if (c == 'x')
{
if (p[1] == 0 && i + 1 == argc)
fatal ("argument to `-x' is missing");
if (p[1] == 0)
spec_lang = argv[++i];
else
spec_lang = p + 1;
if (! strcmp (spec_lang, "none"))
spec_lang = 0;
else
last_language_n_infiles = n_infiles;
continue;
}
switches[n_switches].part1 = p;
if ((SWITCH_TAKES_ARG (c) > (p[1] != 0))
|| WORD_SWITCH_TAKES_ARG (p))
{
int j = 0;
int n_args = WORD_SWITCH_TAKES_ARG (p);
if (n_args == 0)
{
n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0);
}
if (i + n_args >= argc)
fatal ("argument to `-%s' is missing", p);
switches[n_switches].args
= (char **) xmalloc ((n_args + 1) * sizeof (char *));
while (j < n_args)
switches[n_switches].args[j++] = argv[++i];
switches[n_switches].args[j] = 0;
}
else if (index (switches_need_spaces, c))
{
char *part1 = (char *) xmalloc (2);
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[1] = 0;
}
else
{
switches[n_switches].args = 0;
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
if (!strcmp (p, "ObjC"))
default_language = "objective-c";
else if (!strcmp (p, "ObjC++"))
default_language = "objective-c++";
#endif
}
switches[n_switches].live_cond = 0;
switches[n_switches].validated = 0;
if (!strcmp (p, "save-temps"))
switches[n_switches].validated = 1;
else
{
char ch = switches[n_switches].part1[0];
if (ch == 'V' || ch == 'b' || ch == 'B')
switches[n_switches].validated = 1;
}
n_switches++;
}
else
{
#ifdef HAVE_OBJECT_SUFFIX
argv[i] = convert_filename (argv[i], 0);
#endif
if (strcmp (argv[i], "-") != 0 && access (argv[i], R_OK) < 0)
{
perror_with_name (argv[i]);
error_count++;
}
else
{
infiles[n_infiles].language = spec_lang;
infiles[n_infiles++].name = argv[i];
}
}
}
if (n_infiles == last_language_n_infiles && spec_lang != 0)
error ("Warning: `-x %s' after last input file has no effect", spec_lang);
switches[n_switches].part1 = 0;
infiles[n_infiles].name = 0;
}
const char *input_filename;
static int input_file_number;
size_t input_filename_length;
static int basename_length;
static const char *input_basename;
static const char *input_suffix;
static struct stat input_stat;
static int input_stat_set;
static int arg_going;
static int delete_this_arg;
static int this_is_output_file;
#ifdef NEXT_FAT_OUTPUT
static int this_is_arch_merge_file;
#endif
static int this_is_library_file;
static int input_from_pipe;
int
do_spec (spec)
const char *spec;
{
int value;
clear_args ();
arg_going = 0;
delete_this_arg = 0;
this_is_output_file = 0;
#ifdef NEXT_FAT_OUTPUT
this_is_arch_merge_file = 0;
#endif
this_is_library_file = 0;
input_from_pipe = 0;
value = do_spec_1 (spec, 0, NULL_PTR);
if (value == 0)
{
if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
argbuf_index--;
if (argbuf_index > 0)
value = execute ();
}
return value;
}
static int
do_spec_1 (spec, inswitch, soft_matched_part)
const char *spec;
int inswitch;
const char *soft_matched_part;
{
register const char *p = spec;
register int c;
int i;
const char *string;
int value;
while ((c = *p++))
switch (inswitch ? 'a' : c)
{
case '\n':
if (arg_going)
{
obstack_1grow (&obstack, 0);
string = obstack_finish (&obstack);
if (this_is_library_file)
string = find_file (string);
store_arg (string, delete_this_arg, this_is_output_file
#ifdef NEXT_FAT_OUTPUT
|| this_is_arch_merge_file
#endif
);
if (this_is_output_file)
outfiles[input_file_number] = string;
#ifdef NEXT_FAT_OUTPUT
else if (this_is_arch_merge_file)
arch_merge_files[current_arch] = string;
#endif
}
arg_going = 0;
if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|"))
{
for (i = 0; i < n_switches; i++)
if (!strcmp (switches[i].part1, "pipe"))
break;
if (i < n_switches)
{
input_from_pipe = 1;
switches[i].validated = 1;
break;
}
else
argbuf_index--;
}
if (argbuf_index > 0)
{
value = execute ();
if (value)
return value;
}
clear_args ();
arg_going = 0;
delete_this_arg = 0;
this_is_output_file = 0;
this_is_library_file = 0;
#ifdef NEXT_FAT_OUTPUT
this_is_arch_merge_file = 0;
#endif
input_from_pipe = 0;
break;
case '|':
if (arg_going)
{
obstack_1grow (&obstack, 0);
string = obstack_finish (&obstack);
if (this_is_library_file)
string = find_file (string);
store_arg (string, delete_this_arg, this_is_output_file
#ifdef NEXT_FAT_OUTPUT
|| this_is_arch_merge_file
#endif
);
if (this_is_output_file)
outfiles[input_file_number] = string;
#ifdef NEXT_FAT_OUTPUT
else if (this_is_arch_merge_file)
arch_merge_files[current_arch] = string;
#endif
}
obstack_1grow (&obstack, c);
arg_going = 1;
break;
case '\t':
case ' ':
if (arg_going)
{
obstack_1grow (&obstack, 0);
string = obstack_finish (&obstack);
if (this_is_library_file)
string = find_file (string);
store_arg (string, delete_this_arg, this_is_output_file
#ifdef NEXT_FAT_OUTPUT
|| this_is_arch_merge_file
#endif
);
if (this_is_output_file)
outfiles[input_file_number] = string;
#ifdef NEXT_FAT_OUTPUT
else if (this_is_arch_merge_file)
arch_merge_files[current_arch] = string;
#endif
}
arg_going = 0;
delete_this_arg = 0;
this_is_output_file = 0;
#ifdef NEXT_FAT_OUTPUT
this_is_arch_merge_file = 0;
#endif
this_is_library_file = 0;
break;
case '%':
switch (c = *p++)
{
case 0:
fatal ("Invalid specification! Bug in cc.");
case 'b':
obstack_grow (&obstack, input_basename, basename_length);
arg_going = 1;
break;
case 'd':
delete_this_arg = 2;
break;
case 'D':
{
struct prefix_list *pl = startfile_prefixes.plist;
size_t bufsize = 100;
char *buffer = (char *) xmalloc (bufsize);
int idx;
for (; pl; pl = pl->next)
{
#ifdef RELATIVE_PREFIX_NOT_LINKDIR
if (!IS_DIR_SEPARATOR (pl->prefix[0]))
continue;
#endif
if (multilib_dir != NULL)
{
if (machine_suffix)
{
if (strlen (pl->prefix) + strlen (machine_suffix)
>= bufsize)
bufsize = (strlen (pl->prefix)
+ strlen (machine_suffix)) * 2 + 1;
buffer = (char *) xrealloc (buffer, bufsize);
strcpy (buffer, pl->prefix);
strcat (buffer, machine_suffix);
if (is_directory (buffer, multilib_dir, 1))
{
do_spec_1 ("-L", 0, NULL_PTR);
#ifdef SPACE_AFTER_L_OPTION
do_spec_1 (" ", 0, NULL_PTR);
#endif
do_spec_1 (buffer, 1, NULL_PTR);
do_spec_1 (multilib_dir, 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
}
}
if (!pl->require_machine_suffix)
{
if (is_directory (pl->prefix, multilib_dir, 1))
{
do_spec_1 ("-L", 0, NULL_PTR);
#ifdef SPACE_AFTER_L_OPTION
do_spec_1 (" ", 0, NULL_PTR);
#endif
do_spec_1 (pl->prefix, 1, NULL_PTR);
do_spec_1 (multilib_dir, 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
}
}
}
if (machine_suffix)
{
if (is_directory (pl->prefix, machine_suffix, 1))
{
do_spec_1 ("-L", 0, NULL_PTR);
#ifdef SPACE_AFTER_L_OPTION
do_spec_1 (" ", 0, NULL_PTR);
#endif
do_spec_1 (pl->prefix, 1, NULL_PTR);
if (strlen (machine_suffix) >= bufsize)
bufsize = strlen (machine_suffix) * 2 + 1;
buffer = (char *) xrealloc (buffer, bufsize);
strcpy (buffer, machine_suffix);
idx = strlen (buffer);
if (IS_DIR_SEPARATOR (buffer[idx - 1]))
buffer[idx - 1] = 0;
do_spec_1 (buffer, 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
}
}
if (!pl->require_machine_suffix)
{
if (is_directory (pl->prefix, "", 1))
{
do_spec_1 ("-L", 0, NULL_PTR);
#ifdef SPACE_AFTER_L_OPTION
do_spec_1 (" ", 0, NULL_PTR);
#endif
if (strlen (pl->prefix) >= bufsize)
bufsize = strlen (pl->prefix) * 2 + 1;
buffer = (char *) xrealloc (buffer, bufsize);
strcpy (buffer, pl->prefix);
idx = strlen (buffer);
if (IS_DIR_SEPARATOR (buffer[idx - 1]))
buffer[idx - 1] = 0;
do_spec_1 (buffer, 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
}
}
}
free (buffer);
}
break;
case 'e':
{
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 (buf);
return -1;
}
break;
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
case 'B':
{
const char *q = p;
char *buf;
while (*p != 0 && *p != '\n') p++;
buf = (char *) xmalloc (p - q + 1 + 30);
strncpy (buf, q, p - q);
buf[p - q] = 0;
#ifdef NEXT_SEMANTICS
if (multi_arch)
{
const char *curr = arch_array[current_arch]->name;
strcat (buf, " %%s for ");
if (! strcmp (curr, "i386"))
strcat (buf, "Intel");
else if (! strcmp (curr, "hppa"))
strcat (buf, "HPPA");
else if (! strcmp (curr, "sparc"))
strcat (buf, "SPARC");
else if (! strcmp (curr, "m68k"))
strcat (buf, "NeXT");
else
strcat (buf, curr);
}
#endif
#ifdef SAVE_REPORT_EVENT
SAVE_REPORT_EVENT (-1, NULL, input_basename, \
0, buf, 0, 0, 0);
#endif
}
break;
#endif
case 'g':
case 'u':
case 'U':
{
#ifdef MKTEMP_EACH_FILE
struct temp_name *t;
int suffix_length;
const char *suffix = p;
if (p[0] == '%' && p[1] == 'O')
{
p += 2;
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 (save_temps_flag)
{
temp_filename_length = basename_length + suffix_length;
temp_filename = alloca (temp_filename_length + 1);
strncpy ((char *) temp_filename, input_basename, basename_length);
strncpy ((char *) temp_filename + basename_length, suffix,
suffix_length);
*((char *) temp_filename + temp_filename_length) = '\0';
if (strcmp (temp_filename, input_filename) != 0)
{
struct stat st_temp;
if (input_stat_set == 0)
{
input_stat_set = stat (input_filename, &input_stat);
if (input_stat_set >= 0)
input_stat_set = 1;
}
if (input_stat_set != 1
|| stat (temp_filename, &st_temp) < 0
|| input_stat.st_dev != st_temp.st_dev
|| input_stat.st_ino != st_temp.st_ino)
{
temp_filename = save_string (temp_filename,
temp_filename_length + 1);
obstack_grow (&obstack, temp_filename,
temp_filename_length);
arg_going = 1;
break;
}
}
}
for (t = temp_names; t; t = t->next)
if (t->length == suffix_length
&& strncmp (t->suffix, suffix, suffix_length) == 0
&& t->unique == (c != 'g'))
break;
if (t == 0 || c == 'u')
{
if (t == 0)
{
t = (struct temp_name *) xmalloc (sizeof (struct temp_name));
t->next = temp_names;
temp_names = t;
}
t->length = suffix_length;
t->suffix = save_string (suffix, suffix_length);
t->unique = (c != 'g');
temp_filename = make_temp_file (t->suffix);
temp_filename_length = strlen (temp_filename);
t->filename = temp_filename;
t->filename_length = temp_filename_length;
}
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;
case 'i':
obstack_grow (&obstack, input_filename, input_filename_length);
arg_going = 1;
break;
case 'I':
{
struct prefix_list *pl = include_prefixes.plist;
if (gcc_exec_prefix)
{
do_spec_1 ("-iprefix", 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
do_spec_1 (gcc_exec_prefix, 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
}
#ifndef NEXT_OBJC_RUNTIME
for (; pl; pl = pl->next)
{
do_spec_1 ("-isystem", 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
do_spec_1 (pl->prefix, 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
}
#endif
}
break;
case 'y':
{
char *tmpstr = xmalloc (strlen (STANDARD_EXEC_PREFIX)
+ strlen (DEFAULT_TARGET_VERSION)
+ strlen (DEFAULT_TARGET_MACHINE) + 25);
do_spec_1 ("-isystem", 1, NULL);
do_spec_1 (" ", 0, NULL);
sprintf (tmpstr, "/usr/include/gcc/darwin/%s",
DEFAULT_TARGET_VERSION);
do_spec_1 (tmpstr, 1, NULL);
do_spec_1 (" ", 0, NULL);
sprintf (tmpstr,
"-ispecs=/usr/libexec/gcc/darwin/%s/%s/specs",
arch_array[current_arch]->name,
DEFAULT_TARGET_VERSION);
do_spec_1 (tmpstr, 1, NULL);
do_spec_1 (" ", 0, NULL);
free (tmpstr);
}
break;
case 'o':
{
int max = n_infiles;
max += lang_specific_extra_outfiles;
for (i = 0; i < max; i++)
if (outfiles[i])
store_arg (outfiles[i], 0, 0);
#ifdef NEXT_FAT_OUTPUT
if (multi_arch)
{
store_arg ("-final_output", 0, 0);
store_arg (final_output, 0, 0);
}
#endif
break;
}
case 'O':
obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
arg_going = 1;
break;
case 's':
this_is_library_file = 1;
break;
case 'w':
this_is_output_file = 1;
break;
#ifdef NEXT_FAT_OUTPUT
case 'f':
this_is_arch_merge_file = 1;
break;
#endif
case 'W':
{
int cur_index = argbuf_index;
if (*p != '{')
abort ();
p = handle_braces (p + 1);
if (p == 0)
return -1;
if (argbuf_index != cur_index)
record_temp_file (argbuf[argbuf_index - 1], 0, 1);
break;
}
case 'x':
{
const char *p1 = p;
char *string;
if (*p != '{')
abort ();
while (*p++ != '}')
;
string = save_string (p1 + 1, p - p1 - 2);
for (i = 0; i < n_linker_options; i++)
if (! strcmp (string, linker_options[i]))
{
free (string);
return 0;
}
add_linker_option (string, strlen (string));
}
break;
case 'X':
for (i = 0; i < n_linker_options; i++)
{
do_spec_1 (linker_options[i], 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
}
break;
#ifdef NEXT_SEMANTICS
case 'J':
for (i = 0; i < n_dynamiclib_options; i++)
{
do_spec_1 (dynamiclib_options[i], 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
}
break;
#endif
case 'Y':
for (i = 0; i < n_assembler_options; i++)
{
do_spec_1 (assembler_options[i], 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
}
break;
#ifdef NEXT_FAT_OUTPUT
case 'T':
if (1) {
int current_arch_name_len =
strlen (strcmp (arch_array[current_arch]->name, "m98k") ?
arch_array[current_arch]->name : "ppc");
obstack_grow (&obstack,
strcmp (arch_array[current_arch]->name, "m98k") ?
arch_array[current_arch]->name : "ppc",
current_arch_name_len);
}
arg_going = 1;
break;
case 'F':
{
register int i;
for (i = 0; i < arch_count; i++) {
store_arg ("-arch", 0, 0);
store_arg (arch_array[i]->name, 0, 0);
store_arg (arch_merge_files[i], 0, 0);
}
}
break;
case 'M':
{
if (dependency_output_file == NULL)
{
obstack_grow (&obstack, input_basename, basename_length);
obstack_grow (&obstack, ".d", 2);
}
else
obstack_grow (&obstack, dependency_output_file,
strlen (dependency_output_file));
arg_going = 1;
}
break;
#endif
case 'Z':
for (i = 0; i < n_preprocessor_options; i++)
{
do_spec_1 (preprocessor_options[i], 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
}
break;
case '1':
value = do_spec_1 (cc1_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case '2':
value = do_spec_1 (cc1plus_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case 'a':
value = do_spec_1 (asm_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case 'A':
value = do_spec_1 (asm_final_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case 'c':
value = do_spec_1 (signed_char_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case 'C':
value = do_spec_1 (cpp_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case 'E':
value = do_spec_1 (endfile_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case 'l':
value = do_spec_1 (link_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case 'L':
value = do_spec_1 (lib_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case 'G':
value = do_spec_1 (libgcc_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case 'p':
{
char *x = (char *) alloca (strlen (cpp_predefines) + 1);
char *buf = x;
char *y;
y = cpp_predefines;
while (*y != 0)
{
if (! strncmp (y, "-D", 2))
while (*y && *y != ' ' && *y != '\t')
*x++ = *y++;
else if (*y == ' ' || *y == '\t')
*x++ = *y++;
else
y++;
}
*x = 0;
value = do_spec_1 (buf, 0, NULL_PTR);
if (value != 0)
return value;
}
break;
case 'P':
{
char *x = (char *) alloca (strlen (cpp_predefines) * 4 + 1);
char *buf = x;
char *y;
y = cpp_predefines;
while (*y != 0)
{
if (! strncmp (y, "-D", 2))
{
int flag = 0;
*x++ = *y++;
*x++ = *y++;
if (*y != '_'
|| (*(y+1) != '_'
&& ! ISUPPER ((unsigned char)*(y+1))))
{
*x++ = '_';
*x++ = '_';
flag = 1;
}
while (*y && *y != '=' && *y != ' ' && *y != '\t')
*x++ = *y++;
if (flag)
{
*x++ = '_';
*x++ = '_';
}
while (*y && *y != ' ' && *y != '\t')
*x++ = *y++;
}
else if (*y == ' ' || *y == '\t')
*x++ = *y++;
else
y++;
}
*x++ = ' ';
y = cpp_predefines;
while (*y != 0)
{
if (! strncmp (y, "-D", 2))
{
y += 2;
if (*y != '_'
|| (*(y+1) != '_'
&& ! ISUPPER ((unsigned char)*(y+1))))
{
*x++ = '-';
*x++ = 'D';
*x++ = '_';
*x++ = '_';
while (*y && *y != '=' && *y != ' ' && *y != '\t')
*x++ = *y++;
while (*y && *y != ' ' && *y != '\t')
*x++ = *y++;
}
else
{
while (*y && *y != ' ' && *y != '\t')
y++;
}
}
else if (*y == ' ' || *y == '\t')
*x++ = *y++;
else
y++;
}
*x++ = ' ';
y = cpp_predefines;
while (*y != 0)
{
if (! strncmp (y, "-A", 2))
while (*y && *y != ' ' && *y != '\t')
*x++ = *y++;
else if (*y == ' ' || *y == '\t')
*x++ = *y++;
else
y++;
}
*x = 0;
value = do_spec_1 (buf, 0, NULL_PTR);
if (value != 0)
return value;
}
break;
case 'S':
value = do_spec_1 (startfile_spec, 0, NULL_PTR);
if (value != 0)
return value;
break;
case '{':
p = handle_braces (p);
if (p == 0)
return -1;
break;
case '%':
obstack_1grow (&obstack, '%');
break;
case '*':
do_spec_1 (soft_matched_part, 1, NULL_PTR);
do_spec_1 (" ", 0, NULL_PTR);
break;
case '[':
error ("Warning: use of obsolete %%[ operator in specs");
case '(':
{
const char *name = p;
struct spec_list *sl;
int len;
while (*p && *p != ')' && *p != ']')
p++;
for (len = p - name, sl = specs; sl; sl = sl->next)
if (sl->name_len == len && !strncmp (sl->name, name, len))
{
name = *(sl->ptr_spec);
#ifdef DEBUG_SPECS
notice ("Processing spec %c%s%c, which is '%s'\n",
c, sl->name, (c == '(') ? ')' : ']', name);
#endif
break;
}
if (sl)
{
if (c == '(')
{
value = do_spec_1 (name, 0, NULL_PTR);
if (value != 0)
return value;
}
else
{
char *x = (char *) alloca (strlen (name) * 2 + 1);
char *buf = x;
const char *y = name;
int flag = 0;
while (1)
{
if (! strncmp (y, "-D", 2))
{
*x++ = '-';
*x++ = 'D';
*x++ = '_';
*x++ = '_';
y += 2;
flag = 1;
continue;
}
else if (flag && (*y == ' ' || *y == '\t' || *y == '='
|| *y == '}' || *y == 0))
{
*x++ = '_';
*x++ = '_';
flag = 0;
}
if (*y == 0)
break;
else
*x++ = *y++;
}
*x = 0;
value = do_spec_1 (buf, 0, NULL_PTR);
if (value != 0)
return value;
}
}
if (*p)
p++;
}
break;
case 'v':
{
int c1 = *p++;
char *v = compiler_version;
char *q;
while (! ISDIGIT (*v))
v++;
if (v > compiler_version && v[-1] != '-')
abort ();
if (c1 == '2')
{
while (ISDIGIT (*v))
v++;
if (*v != '.')
abort ();
v++;
}
q = v;
while (ISDIGIT (*q))
q++;
if (*q != 0 && *q != ' ' && *q != '.' && *q != '-')
abort ();
obstack_grow (&obstack, v, q - v);
arg_going = 1;
}
break;
case '|':
if (input_from_pipe)
do_spec_1 ("-", 0, NULL_PTR);
break;
default:
abort ();
}
break;
case '\\':
c = *p++;
default:
obstack_1grow (&obstack, c);
arg_going = 1;
}
return 0;
}
static const char *
handle_braces (p)
register const char *p;
{
const char *filter, *body = NULL, *endbody = NULL;
int pipe_p = 0;
int negate;
int suffix;
int include_blanks = 1;
if (*p == '^')
include_blanks = 0, ++p;
if (*p == '|')
pipe_p = 1, ++p;
next_member:
negate = suffix = 0;
if (*p == '!')
negate = 1, ++p;
if (*p == '.')
{
if (pipe_p)
abort ();
suffix = 1;
++p;
}
filter = p;
while (*p != ':' && *p != '}' && *p != '|') p++;
if (*p == '|' && pipe_p)
abort ();
if (!body)
{
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;
}
#ifdef NEXT_FAT_OUTPUT
if (*filter == '@')
{
if (*p == '}')
fatal ("Internal compiler error: empty body in `@' conditioned spec");
if (p - filter > 1)
fatal ("Internal compiler error: `@' condition illegal in spec");
if (negate != multi_arch
&& do_spec_1 (save_string (p + 1, endbody - p - 2), 0, NULL) < 0)
return 0;
return endbody;
}
#endif
if (suffix)
{
int found = (input_suffix != 0
&& (long) strlen (input_suffix) == (long)(p - filter)
&& strncmp (input_suffix, filter, p - filter) == 0);
if (body[0] == '}')
abort ();
if (negate != found
&& do_spec_1 (save_string (body, endbody-body-1), 0, NULL_PTR) < 0)
return 0;
}
else if (p[-1] == '*' && p[0] == '}')
{
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);
}
else
{
register int i;
int present = 0;
if (p[-1] == '*' && !negate)
{
int substitution;
const char *r = body;
substitution = 0;
while (r < endbody)
{
if (*r == '%' && r[1] == '*')
substitution = 1;
r++;
}
if (substitution)
{
unsigned hard_match_len = p - filter - 1;
char *string = save_string (body, endbody - body - 1);
for (i = 0; i < n_switches; i++)
if (!strncmp (switches[i].part1, filter, hard_match_len)
&& check_live_switch (i, -1))
{
do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
give_switch (i, 1, 1);
}
if (*p++ == '|')
goto next_member;
return endbody;
}
}
if (p[-1] == '*')
{
for (i = 0; i < n_switches; i++)
{
unsigned hard_match_len = p - filter - 1;
if (!strncmp (switches[i].part1, filter, hard_match_len)
&& check_live_switch (i, hard_match_len))
{
present = 1;
}
}
}
else
{
for (i = 0; i < n_switches; i++)
{
if (!strncmp (switches[i].part1, filter, p - filter)
&& switches[i].part1[p - filter] == 0
&& check_live_switch (i, -1))
{
present = 1;
break;
}
}
}
if (present != negate)
{
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;
}
}
else if (pipe_p)
{
do_spec_1 ("-", 0, NULL_PTR);
return endbody;
}
}
if (*p++ == '|')
goto next_member;
return endbody;
}
static int
check_live_switch (switchnum, prefix_length)
int switchnum;
int prefix_length;
{
const char *name = switches[switchnum].part1;
int i;
if (prefix_length >= 0 && prefix_length <= 1)
return 1;
if (switches[switchnum].live_cond != 0)
return switches[switchnum].live_cond > 0;
switch (*name)
{
case 'O':
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
if (strncmp (name, "ObjC", 4))
#endif
for (i = switchnum + 1; i < n_switches; i++)
if (switches[i].part1[0] == 'O'
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
&& strncmp (switches[i].part1, "ObjC", 4)
#endif
)
{
switches[switchnum].validated = 1;
switches[switchnum].live_cond = -1;
return 0;
}
break;
case 'W': case 'f': case 'm':
if (! strncmp (name + 1, "no-", 3))
{
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;
}
}
else
{
for (i = switchnum + 1; i < n_switches; i++)
if (switches[i].part1[0] == name[0]
&& switches[i].part1[1] == 'n'
&& 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;
}
}
break;
}
switches[switchnum].live_cond = 1;
return 1;
}
static void
give_switch (switchnum, omit_first_word, include_blanks)
int switchnum;
int omit_first_word;
int include_blanks;
{
if (!omit_first_word)
{
do_spec_1 ("-", 0, NULL_PTR);
do_spec_1 (switches[switchnum].part1, 1, NULL_PTR);
}
if (switches[switchnum].args != 0)
{
char **p;
for (p = switches[switchnum].args; *p; p++)
{
if (include_blanks)
do_spec_1 (" ", 0, NULL_PTR);
do_spec_1 (*p, 1, NULL_PTR);
}
}
do_spec_1 (" ", 0, NULL_PTR);
switches[switchnum].validated = 1;
}
static const char *
find_file (name)
const char *name;
{
char *newname;
if (multilib_dir != NULL)
{
char *try;
try = (char *) alloca (strlen (multilib_dir) + strlen (name) + 2);
strcpy (try, multilib_dir);
strcat (try, dir_separator_str);
strcat (try, name);
newname = find_a_file (&startfile_prefixes, try, R_OK);
if (newname != NULL)
return newname;
}
newname = find_a_file (&startfile_prefixes, name, R_OK);
return newname ? newname : name;
}
static int
is_directory (path1, path2, linker)
const char *path1;
const char *path2;
int linker;
{
int len1 = strlen (path1);
int len2 = strlen (path2);
char *path = (char *) alloca (3 + len1 + len2);
char *cp;
struct stat st;
#ifndef SMALL_ARG_MAX
if (! linker)
return 1;
#endif
memcpy (path, path1, len1);
memcpy (path + len1, path2, len2);
cp = path + len1 + len2;
if (!IS_DIR_SEPARATOR (cp[-1]))
*cp++ = DIR_SEPARATOR;
*cp++ = '.';
*cp = '\0';
if (linker
&& ((cp - path == 6
&& 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",
dir_separator_str, ".", NULL_PTR)) == 0)))
return 0;
return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
}
static void
fatal_error (signum)
int signum;
{
signal (signum, SIG_DFL);
delete_failure_queue ();
delete_temp_files ();
kill (getpid (), signum);
}
int
main (argc, argv)
int argc;
char **argv;
{
register size_t i;
size_t j;
int value;
int linker_was_run = 0;
char *explicit_link_files;
char *specs_file;
#ifdef REPORT_EVENT
char *link_output = "a.out";
#endif
const char *p;
struct user_specs *uptr;
#if defined (NEXT_PDO) && !defined (hpux) && !defined (_WIN32)
for( j = 0 ; j < argc ; j++ )
{
if (!strcmp (argv[j], "-filelist"))
{
char* filename;
char* prefixString;
FILE* atFile;
int argsToSkip = 0;
if (j + 1 == argc)
error ("Missing argument to -filelist");
filename = argv[j+1];
argsToSkip = 1;
if (prefixString = strchr (filename, ','))
{
*prefixString = '\0';
prefixString++;
}
else
{
prefixString = "";
}
if( atFile = fopen( filename, "rt" ) )
{
int numOfItems = 0;
int letterCount = 0;
char c;
char** newArgv;
char* tempString;
char tempBuffer[1024];
while( ((c = fgetc( atFile )) != EOF))
if( c == '\n')
numOfItems++;
newArgv = (char**)malloc( (numOfItems + argc) * sizeof(char*) );
memset( newArgv, 0, (numOfItems + argc) * sizeof( char*) );
memmove( &newArgv[0], &argv[0], j * sizeof( char* ) );
if( j+1 < argc )
memmove( &newArgv[j + numOfItems], &argv[j+1+argsToSkip], (argc - j) * sizeof( char* ) );
fseek( atFile, 0, SEEK_SET );
numOfItems = 0;
while( (c = fgetc( atFile )) != EOF )
{
if( c != '\n' )
{
tempBuffer[letterCount] = c;
letterCount++;
}
else
{
tempBuffer[letterCount] = '\0';
letterCount++;
tempString = (char*)malloc( (strlen(prefixString) + 1 + letterCount) * sizeof( char ) );
if (strlen(prefixString) > 0)
sprintf( tempString, "%s/", prefixString );
else
strcpy( tempString, "" );
strncat( tempString, tempBuffer, letterCount );
if( tempString[0] == '@' )
if( strcmp( tempString, argv[j] ) == 0 )
{
tempString[0] = '\0';
}
newArgv[j + numOfItems] = tempString;
numOfItems++;
letterCount = 0;
}
}
if( newArgv )
{
argv = newArgv;
argc = argc + numOfItems - 1 - argsToSkip;
}
fclose( atFile );
}
}
}
#endif
p = argv[0] + strlen (argv[0]);
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
if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
signal (SIGHUP, fatal_error);
#endif
if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
signal (SIGTERM, fatal_error);
#ifdef SIGPIPE
if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
signal (SIGPIPE, fatal_error);
#endif
argbuf_length = 10;
argbuf = (char **) xmalloc (argbuf_length * sizeof (char *));
obstack_init (&obstack);
{
char **q = multilib_raw;
int need_space;
obstack_init (&multilib_obstack);
while ((p = *q++) != (char *) 0)
obstack_grow (&multilib_obstack, p, strlen (p));
obstack_1grow (&multilib_obstack, 0);
multilib_select = obstack_finish (&multilib_obstack);
q = multilib_matches_raw;
while ((p = *q++) != (char *) 0)
obstack_grow (&multilib_obstack, p, strlen (p));
obstack_1grow (&multilib_obstack, 0);
multilib_matches = obstack_finish (&multilib_obstack);
need_space = FALSE;
for (i = 0;
i < sizeof (multilib_defaults_raw) / sizeof (multilib_defaults_raw[0]);
i++)
{
if (need_space)
obstack_1grow (&multilib_obstack, ' ');
obstack_grow (&multilib_obstack,
multilib_defaults_raw[i],
strlen (multilib_defaults_raw[i]));
need_space = TRUE;
}
obstack_1grow (&multilib_obstack, 0);
multilib_defaults = obstack_finish (&multilib_obstack);
}
obstack_init (&collect_obstack);
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
#ifndef MKTEMP_EACH_FILE
temp_filename = choose_temp_base ();
temp_filename_length = strlen (temp_filename);
#endif
process_command (argc, argv);
{
int first_time;
obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
sizeof ("COLLECT_GCC_OPTIONS=")-1);
first_time = TRUE;
for (i = 0; (int)i < n_switches; i++)
{
char **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));
obstack_grow (&collect_obstack, "'", 1);
for (args = switches[i].args; args && *args; args++)
{
obstack_grow (&collect_obstack, " '", 2);
q = *args;
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));
obstack_grow (&collect_obstack, "'", 1);
}
}
obstack_grow (&collect_obstack, "\0", 1);
putenv (obstack_finish (&collect_obstack));
}
compilers = (struct compiler *) xmalloc (sizeof default_compilers);
bcopy ((char *) default_compilers, (char *) compilers,
sizeof default_compilers);
n_compilers = n_default_compilers;
#ifdef NEXT_FAT_OUTPUT
if (arch_array == NULL)
{
#ifndef DEFAULT_TARGET_ARCH
const NXArchInfo *family_arch;
#endif
arch_family = (char **) xmalloc (sizeof (char *));
arch_array = (NXArchInfo const **) xmalloc (sizeof (NXArchInfo*));
arch_count = 1;
#ifdef DEFAULT_TARGET_ARCH
arch_family[0] = DEFAULT_TARGET_ARCH;
arch_array[0] = NXGetArchInfoFromName (arch_family[0]);
if (arch_array[0] == 0 && !strcmp (arch_family[0], "ppc"))
arch_array[0] = NXGetArchInfoFromName ("m98k");
if (arch_array[0] == 0)
fatal ("unknown default architecture");
#else
arch_family = (char **) xmalloc (sizeof (char *));
arch_count = 1;
arch_array = (NXArchInfo const **) xmalloc (sizeof (NXArchInfo*));
if ((arch_array[0] = NXGetLocalArchInfo ()) == 0)
fatal ("unknown default architecture");
family_arch = NXGetArchInfoFromCpuType (arch_array[0]->cputype,
CPU_SUBTYPE_MULTIPLE);
arch_family[0] = (char*) (family_arch == NULL
? arch_array[0]->name
: family_arch->name);
#endif
}
else
{
arch_family = (char **) xmalloc (sizeof (char *) * arch_count);
for (i = 0; i < arch_count; i++)
{
const NXArchInfo *family_arch;
family_arch = NXGetArchInfoFromCpuType (arch_array[i]->cputype,
CPU_SUBTYPE_MULTIPLE);
arch_family[i] = (char *) (family_arch == NULL
? arch_array[i]->name
: family_arch->name);
if (!strcmp (arch_family[i], "m98k"))
arch_family[i] = "ppc";
}
}
multi_arch = (arch_count > 1);
arch_merge_files = (const char **) xmalloc (arch_count * sizeof (char *));
machine_suffix = concat (arch_family[0], dir_separator_str,
spec_version, dir_separator_str, NULL);
just_machine_suffix = concat (arch_family[0], dir_separator_str, NULL_PTR);
#else
machine_suffix = concat (spec_machine, dir_separator_str,
spec_version, dir_separator_str, NULL_PTR);
just_machine_suffix = concat (spec_machine, dir_separator_str, NULL_PTR);
#endif
specs_file = find_a_file (&startfile_prefixes, "specs", R_OK);
if (specs_file != 0 && strcmp (specs_file, "specs"))
read_specs (specs_file, TRUE);
else
init_spec ();
specs_file = (char *) alloca (strlen (standard_exec_prefix)
+ strlen (just_machine_suffix)
+ sizeof ("specs"));
strcpy (specs_file, standard_exec_prefix);
strcat (specs_file, just_machine_suffix);
strcat (specs_file, "specs");
if (access (specs_file, R_OK) == 0)
read_specs (specs_file, TRUE);
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
#ifdef MD_STARTFILE_PREFIX
add_prefix (&startfile_prefixes, md_startfile_prefix, "GCC",
0, 0, NULL_PTR);
#endif
#ifdef MD_STARTFILE_PREFIX_1
add_prefix (&startfile_prefixes, md_startfile_prefix_1, "GCC",
0, 0, NULL_PTR);
#endif
if (IS_DIR_SEPARATOR (*standard_startfile_prefix)
|| *standard_startfile_prefix == '$'
#ifdef HAVE_DOS_BASED_FILESYSTEM
|| (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
{
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);
add_prefix (&startfile_prefixes,
concat (standard_exec_prefix,
machine_suffix,
standard_startfile_prefix, NULL_PTR),
NULL_PTR, 0, 0, NULL_PTR);
}
add_prefix (&startfile_prefixes, standard_startfile_prefix_1,
"BINUTILS", 0, 0, NULL_PTR);
add_prefix (&startfile_prefixes, standard_startfile_prefix_2,
"BINUTILS", 0, 0, NULL_PTR);
#if 0
add_prefix (&startfile_prefixes, "./", NULL_PTR, 0, 1, NULL_PTR);
#endif
}
else
{
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);
}
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 (gcc_exec_prefix)
{
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);
strcat (temp, spec_version);
strcat (temp, dir_separator_str);
gcc_exec_prefix = temp;
}
validate_all_switches ();
set_multilib_dir ();
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));
exit (0);
}
if (print_file_name)
{
printf ("%s\n", find_file (print_file_name));
exit (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);
}
if (print_multi_lib)
{
print_multilib_info ();
exit (0);
}
if (print_multi_directory)
{
if (multilib_dir == NULL)
printf (".\n");
else
printf ("%s\n", multilib_dir);
exit (0);
}
if (print_help_list)
{
display_help ();
if (! verbose_flag)
{
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
printf ("Report bugs via the "
"<URL:http://developer.apple.com/bugreporter> web page.\n");
#else
printf ("\nFor bug reporting instructions, please see:\n");
printf ("<URL:http://www.gnu.org/software/gcc/faq.html#bugreport>.\n");
#endif
exit (0);
}
}
if (verbose_flag)
{
int n;
#ifdef NEXT_SEMANTICS
extern char *apple_version;
notice ("Apple Computer, Inc. version %s, based on ", apple_version);
#endif
for (n = 0; version_string[n]; n++)
if (version_string[n] == ' ')
break;
if (! strncmp (version_string, compiler_version, n)
&& compiler_version[n] == 0)
#ifdef NEXT_PDO
notice ("gcc version %s for Apple PDO\n", version_string);
else
notice ("gcc driver version %s executing gcc version %s for Apple PDO\n",
version_string, compiler_version);
#else
notice ("gcc version %s\n", version_string);
else
notice ("gcc driver version %s executing gcc version %s\n",
version_string, compiler_version);
#endif
if (n_infiles == 0)
exit (0);
}
if (n_infiles == added_libraries)
fatal ("No input files");
i = n_infiles;
i += lang_specific_extra_outfiles;
outfiles = (const char **) xmalloc (i * sizeof (char *));
bzero ((char *) outfiles, i * sizeof (char *));
explicit_link_files = xmalloc (n_infiles);
bzero (explicit_link_files, n_infiles);
for (i = 0; (int)i < n_infiles; i++)
{
register struct compiler *cp = 0;
int this_file_error = 0;
input_filename = infiles[i].name;
input_filename_length = strlen (input_filename);
input_file_number = i;
outfiles[i] = input_filename;
cp = lookup_compiler (infiles[i].name, input_filename_length,
infiles[i].language);
#ifdef NEXT_SEMANTICS
if (! cp)
{
int i;
for (i = 0; i < n_switches; i++)
{
if (!strcmp (switches[i].part1, "E"))
{
cp = lookup_compiler (0, 0, "c");
for ( i = 0; i < n_switches; i++ ) {
if (!strcmp (switches[i].part1, "traditional-cpp")
|| !strcmp (switches[i].part1, "traditional")
|| !strcmp (switches[i].part1, "cpp"))
break;
}
if (i == n_switches)
{
switches
= ((struct switchstr*)
xrealloc (switches,
sizeof (struct switchstr) * ++n_switches));
switches[n_switches-1].part1 = "traditional-cpp";
switches[n_switches-1].args = 0;
switches[n_switches-1].validated = 1;
}
}
}
}
#endif
if (cp)
{
register const char *p;
int len;
if (cp->spec[0][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;
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 = "";
input_stat_set = 0;
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]);
}
#ifdef NEXT_FAT_OUTPUT
bzero (arch_merge_files, arch_count * sizeof (char *));
for (current_arch = 0; current_arch < arch_count; current_arch++)
{
#if defined(SAVE_REPORT_EVENT) && 0
SAVE_REPORT_EVENT (-1, NULL, input_basename, 0,
(multi_arch ? "Compiling for %s:"
: "Compiling"),
arch_array[current_arch]->name, 0, 0);
#endif
if (multi_arch)
{
machine_suffix = concat (arch_family[current_arch],
dir_separator_str, spec_version,
dir_separator_str, NULL_PTR);
just_machine_suffix = concat (arch_family[current_arch],
dir_separator_str, NULL_PTR);
specs_file = find_a_file (&startfile_prefixes,
"specs", R_OK);
if (specs_file != 0 && strcmp (specs_file, "specs"))
read_specs (specs_file, FALSE);
else
fatal ("cannot read specs file.");
}
#endif
value = do_spec (p1);
#ifdef NEXT_FAT_OUTPUT
if (value < 0)
{
this_file_error = 1;
break;
}
}
#endif
free (p1);
}
#ifdef NEXT_FAT_OUTPUT
if (multi_arch && !this_file_error)
{
#ifdef SAVE_REPORT_EVENT
SAVE_REPORT_EVENT (-1, NULL, input_basename, 0,
"Combining", 0, 0, 0);
#endif
value = do_spec (ofile_merge_spec);
if (value < 0)
this_file_error = 1;
value = do_spec (precomp_merge_spec);
#elif defined(SAVE_REPORT_EVENT) && 0
SAVE_REPORT_EVENT (-1, NULL, input_basename, 0, "Compiling", 0, 0, 0);
#endif
if (value < 0)
this_file_error = 1;
#ifdef NEXT_FAT_OUTPUT
}
#endif
}
else
explicit_link_files[i] = 1;
if (this_file_error)
{
delete_failure_queue ();
error_count++;
}
clear_failure_queue ();
}
if (error_count == 0)
{
input_file_number = n_infiles;
if (lang_specific_pre_link ())
error_count++;
}
if (error_count == 0)
{
int tmp = execution_count;
if (! strcmp (linker_name_spec, "collect2"))
{
char *s = find_a_file (&exec_prefixes, "collect2", X_OK);
if (s == NULL)
linker_name_spec = "ld";
}
putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH=");
putenv_from_prefixes (&startfile_prefixes, "LIBRARY_PATH=");
#ifndef NEXT_FAT_OUTPUT
#ifdef SAVE_REPORT_EVENT
SAVE_REPORT_EVENT (-1, NULL, NULL, 0, "Linking %s", link_output, 0, 0);
#endif
value = do_spec (link_command_spec);
if (value < 0)
error_count = 1;
#else
bzero (arch_merge_files, arch_count * sizeof (char *));
for (current_arch = 0; current_arch < arch_count; current_arch++)
{
#ifdef SAVE_REPORT_EVENT
SAVE_REPORT_EVENT (-1, NULL, NULL, 0,
(multi_arch ? "Linking %s for %s" : "Linking %s"),
link_output, arch_array[current_arch]->name, 0);
#endif
machine_suffix = concat (spec_version,
dir_separator_str, NULL);
value = do_spec (link_command_spec);
if (value < 0)
{
error_count = 1;
break;
}
}
#endif
linker_was_run = (tmp != execution_count);
}
#ifdef NEXT_FAT_OUTPUT
if (multi_arch && error_count == 0)
{
#ifdef SAVE_REPORT_EVENT
SAVE_REPORT_EVENT (-1, NULL, NULL, 0,
"Combining into %s", link_output, 0, 0);
#endif
value = do_spec (exec_merge_spec);
if (value < 0)
error_count = 1;
}
#endif
unused_prefix_warnings (&exec_prefixes);
unused_prefix_warnings (&startfile_prefixes);
if (! linker_was_run && error_count == 0)
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]);
if (error_count)
delete_failure_queue ();
delete_temp_files ();
if (print_help_list)
{
printf ("\nFor bug reporting instructions, please see:\n");
printf ("<URL:http://www.gnu.org/software/gcc/faq.html#bugreport>\n");
}
exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
return 0;
}
static struct compiler *
lookup_compiler (name, length, language)
const char *name;
size_t length;
const char *language;
{
struct compiler *cp;
if (language != 0 && language[0] == '*')
return 0;
if (language != 0)
{
for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
return cp;
error ("language %s not recognized", language);
return 0;
}
for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
{
if (
(!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
|| (strlen (cp->suffix) < length
#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 defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
if (default_language)
return lookup_compiler (0, 0, default_language);
#endif
if (cp->spec[0][0] == '@')
{
struct compiler *new;
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);
return new;
}
return cp;
}
}
return 0;
}
PTR
xmalloc (size)
size_t size;
{
register PTR value = (PTR) malloc (size);
if (value == 0)
fatal ("virtual memory exhausted");
return value;
}
PTR
xrealloc (old, size)
PTR old;
size_t size;
{
register PTR ptr;
if (old)
ptr = (PTR) realloc (old, size);
else
ptr = (PTR) malloc (size);
if (ptr == 0)
fatal ("virtual memory exhausted");
return ptr;
}
static char *
save_string (s, len)
const char *s;
int len;
{
register char *result = xmalloc (len + 1);
bcopy (s, result, len);
result[len] = 0;
return result;
}
static void
pfatal_with_name (name)
const char *name;
{
perror_with_name (name);
delete_temp_files ();
exit (1);
}
static void
perror_with_name (name)
const char *name;
{
error ("%s: %s", name, xstrerror (errno));
}
static void
pfatal_pexecute (errmsg_fmt, errmsg_arg)
const char *errmsg_fmt;
const char *errmsg_arg;
{
if (errmsg_arg)
{
int save_errno = errno;
char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg));
sprintf (msg, errmsg_fmt, errmsg_arg);
errmsg_fmt = msg;
errno = save_errno;
}
pfatal_with_name (errmsg_fmt);
}
void
fancy_abort ()
{
fatal ("Internal gcc abort.");
}
void
fatal VPROTO((const char *msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char *msgid;
#endif
va_list ap;
VA_START (ap, msgid);
#ifndef ANSI_PROTOTYPES
msgid = va_arg (ap, const char *);
#endif
fprintf (stderr, "%s: ", programname);
vfprintf (stderr, _(msgid), ap);
va_end (ap);
fprintf (stderr, "\n");
delete_temp_files ();
exit (1);
}
static void
error VPROTO((const char *msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char *msgid;
#endif
va_list ap;
VA_START (ap, msgid);
#ifndef ANSI_PROTOTYPES
msgid = va_arg (ap, const char *);
#endif
fprintf (stderr, "%s: ", programname);
vfprintf (stderr, _(msgid), ap);
va_end (ap);
fprintf (stderr, "\n");
}
static void
notice VPROTO((const char *msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char *msgid;
#endif
va_list ap;
VA_START (ap, msgid);
#ifndef ANSI_PROTOTYPES
msgid = va_arg (ap, const char *);
#endif
vfprintf (stderr, _(msgid), ap);
va_end (ap);
}
static void
validate_all_switches ()
{
struct compiler *comp;
register const char *p;
register char c;
struct spec_list *spec;
for (comp = compilers; comp->spec[0]; 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 == '{')
validate_switches (p + 1);
}
}
for (spec = specs; spec ; spec = spec->next)
{
p = *(spec->ptr_spec);
while ((c = *p++))
if (c == '%' && *p == '{')
validate_switches (p + 1);
}
p = link_command_spec;
while ((c = *p++))
if (c == '%' && *p == '{')
validate_switches (p + 1);
}
static void
validate_switches (start)
const char *start;
{
register const char *p = start;
const char *filter;
register int i;
int suffix = 0;
if (*p == '|')
++p;
if (*p == '!')
++p;
if (*p == '.')
suffix = 1, ++p;
filter = p;
while (*p != ':' && *p != '}') p++;
if (suffix)
;
else if (p[-1] == '*')
{
--p;
for (i = 0; i < n_switches; i++)
if (!strncmp (switches[i].part1, filter, p - filter))
switches[i].validated = 1;
}
else
{
for (i = 0; i < n_switches; i++)
{
if (!strncmp (switches[i].part1, filter, p - filter)
&& switches[i].part1[p - filter] == 0)
switches[i].validated = 1;
}
}
}
static int
used_arg (p, len)
const char *p;
int len;
{
struct mswitchstr {
char *str;
char *replace;
int len;
int rep_len;
};
static struct mswitchstr *mswitches;
static int n_mswitches;
int i, j;
if (!mswitches)
{
struct mswitchstr *matches;
char *q;
int cnt = 0;
for (q = multilib_matches; *q != '\0'; q++)
if (*q == ';')
cnt++;
matches = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
i = 0;
q = multilib_matches;
while (*q != '\0')
{
matches[i].str = q;
while (*q != ' ')
{
if (*q == '\0')
abort ();
q++;
}
*q = '\0';
matches[i].len = q - matches[i].str;
matches[i].replace = ++q;
while (*q != ';' && *q != '\0')
{
if (*q == ' ')
abort ();
q++;
}
matches[i].rep_len = q - matches[i].replace;
i++;
if (*q == ';')
*q++ = '\0';
else
break;
}
mswitches
= (struct mswitchstr *) xmalloc ((sizeof (struct mswitchstr))
* (n_switches ? n_switches : 1));
for (i = 0; i < n_switches; i++)
{
int xlen = strlen (switches[i].part1);
for (j = 0; j < cnt; j++)
if (xlen == matches[j].len && ! strcmp (switches[i].part1, matches[j].str))
{
mswitches[n_mswitches].str = matches[j].replace;
mswitches[n_mswitches].len = matches[j].rep_len;
mswitches[n_mswitches].replace = (char *)0;
mswitches[n_mswitches].rep_len = 0;
n_mswitches++;
break;
}
}
}
for (i = 0; i < n_mswitches; i++)
if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
return 1;
return 0;
}
static int
default_arg (p, len)
const char *p;
int len;
{
char *start, *end;
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++)
;
if ((end - start) == len && strncmp (p, start, len) == 0)
return 1;
if (*end == '\0')
break;
}
return 0;
}
static void
set_multilib_dir ()
{
char *p = multilib_select;
int this_path_len;
char *this_path, *this_arg;
int not_arg;
int ok;
while (*p != '\0')
{
if (*p == '\n')
{
++p;
continue;
}
this_path = p;
while (*p != ' ')
{
if (*p == '\0')
abort ();
++p;
}
this_path_len = p - this_path;
ok = 1;
++p;
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;
}
if (! default_arg (this_arg, p - this_arg))
{
ok = used_arg (this_arg, p - this_arg);
if (not_arg)
ok = ! ok;
}
if (*p == ' ')
++p;
}
if (ok)
{
if (this_path_len != 1
|| this_path[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;
}
++p;
}
}
static void
print_multilib_info ()
{
char *p = multilib_select;
char *last_path = 0, *this_path;
int skip;
int last_path_len = 0;
while (*p != '\0')
{
if (*p == '\n')
{
++p;
continue;
}
this_path = p;
while (*p != ' ')
{
if (*p == '\0')
abort ();
++p;
}
skip = (last_path != 0 && 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 (! skip)
{
char *q;
q = p + 1;
while (*q != ';')
{
char *arg;
if (*q == '\0')
abort ();
if (*q == '!')
arg = NULL;
else
arg = q;
while (*q != ' ' && *q != ';')
{
if (*q == '\0')
abort ();
++q;
}
if (arg != NULL
&& default_arg (arg, q - arg))
{
skip = 1;
break;
}
if (*q == ' ')
++q;
}
}
if (! skip)
{
char *p1;
for (p1 = last_path; p1 < p; p1++)
putchar (*p1);
putchar (';');
}
++p;
while (*p != ';')
{
int use_arg;
if (*p == '\0')
abort ();
if (skip)
{
++p;
continue;
}
use_arg = *p != '!';
if (use_arg)
putchar ('@');
while (*p != ' ' && *p != ';')
{
if (*p == '\0')
abort ();
if (use_arg)
putchar (*p);
++p;
}
if (*p == ' ')
++p;
}
if (! skip)
{
if (multilib_extra && *multilib_extra)
{
int print_at = TRUE;
char *q;
for (q = multilib_extra; *q != '\0'; q++)
{
if (*q == ' ')
print_at = TRUE;
else
{
if (print_at)
putchar ('@');
putchar (*q);
print_at = FALSE;
}
}
}
putchar ('\n');
}
++p;
}
}