#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME)
#endif
-extern char *choose_temp_base PROTO((void));
-
-#ifndef HAVE_STRERROR
-extern int sys_nerr;
-extern char *sys_errlist[];
-#else
-extern char *strerror();
-#endif
+extern char *my_strerror PROTO((int));
#ifndef HAVE_KILL
#define kill(p,s) raise(s)
static char *handle_braces PROTO((char *));
static char *save_string PROTO((char *, int));
static char *concat PVPROTO((char *, ...));
-static int do_spec PROTO((char *));
+extern int do_spec PROTO((char *));
static int do_spec_1 PROTO((char *, int, char *));
static char *find_file PROTO((char *));
static int is_directory PROTO((char *, char *, int));
char *xrealloc ();
#ifdef LANG_SPECIFIC_DRIVER
+/* Called before processing to change/add/remove arguments. */
extern void lang_specific_driver PROTO ((void (*) PVPROTO((char *, ...)), int *, char ***, int *));
+
+/* Called before linking. Returns 0 on success and -1 on failure. */
+extern int lang_specific_pre_link ();
+
+/* Number of extra output files that lang_specific_pre_link may generate. */
+extern int lang_specific_extra_outfiles;
#endif
\f
/* Specs are strings containing lines, each of which (if not blank)
%{|!S:X} like %{!S:X}, but if there is an S switch, substitute `-'.
%{.S:X} substitutes X, but only if processing a file with suffix S.
%{!.S:X} substitutes X, but only if NOT processing a file with suffix S.
+ %{S|P:X} substitutes X if either -S or -P was given to CC. This may be
+ combined with ! and . as above binding stronger than the OR.
%(Spec) processes a specification defined in a specs file as *Spec:
%[Spec] as above, but put __ around -D arguments
value is ignored, except with {S*} where S is just one letter; this
passes all matching options.
-The character | is used to indicate that a command should be piped to
-the following command, but only if -pipe is specified.
+The character | at the beginning of the predicate text is used to indicate
+that a command should be piped to the following command, but only if -pipe
+is specified.
Note that it is built into CC which switches take arguments and which
do not. You might think it would be useful to generalize this to
/* Next come the entries for C. */
{".c", {"@c"}},
{"@c",
- {"cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ {
+#if USE_CPPLIB
+ "%{E|M|MM:cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ %{C:%{!E:%eGNU C does not support -C without using -E}}\
+ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
+ %{ansi:-trigraphs -D__STRICT_ANSI__}\
+ %{!undef:%{!ansi:%p} %P} %{trigraphs} \
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{traditional} %{ftraditional:-traditional}\
+ %{traditional-cpp:-traditional}\
+ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
+ %i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}\
+ %{!E:%{!M:%{!MM:cc1 %i %1 \
+ -lang-c%{ansi:89} %{nostdinc*} %{A*} %{I*} %I\
+ %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
+ %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
+ %{ansi:-trigraphs -D__STRICT_ANSI__}\
+ %{!undef:%{!ansi:%p} %P} %{trigraphs} \
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{H} %C %{D*} %{U*} %{i*} %Z\
+ %{ftraditional:-traditional}\
+ %{traditional-cpp:-traditional}\
+ %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
+ %{aux-info*}\
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
+ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
+ %{!S:as %a %Y\
+ %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
+ %{!pipe:%g.s} %A\n }}}}"
+ }},
+#else /* ! USE_CPPLIB */
+ "cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
-undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
%{traditional-cpp:-traditional}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
- "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
+ "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
%{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
%{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
%{!S:as %a %Y\
%{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"}},
+ %{!pipe:%g.s} %A\n }}}}"
+ }},
+#endif /* ! USE_CPPLIB */
{"-",
{"%{E:cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
static int argbuf_index;
+/* We want this on by default all the time now. */
+#define MKTEMP_EACH_FILE
+
#ifdef MKTEMP_EACH_FILE
+
+extern char *make_temp_file PROTO((void));
+
/* This is the list of suffixes and codes (%g/%u/%U) and the associated
temp file. */
int filename_length; /* strlen (filename). */
struct temp_name *next;
} *temp_names;
+#else
+extern char *choose_temp_base PROTO((void));
#endif
+
/* Number of commands executed so far. */
static int execution_count;
sans all directory names, and basename_length is the number
of characters starting there excluding the suffix .c or whatever. */
-static char *input_filename;
+char *input_filename;
static int input_file_number;
-static size_t input_filename_length;
+size_t input_filename_length;
static int basename_length;
static char *input_basename;
static char *input_suffix;
/* Process the spec SPEC and run the commands specified therein.
Returns 0 if the spec is successfully processed; -1 if failed. */
-static int
+int
do_spec (spec)
char *spec;
{
t->length = p - suffix;
t->suffix = save_string (suffix, p - suffix);
t->unique = (c != 'g');
- temp_filename = choose_temp_base ();
+ temp_filename = make_temp_file ();
temp_filename_length = strlen (temp_filename);
t->filename = temp_filename;
t->filename_length = temp_filename_length;
handle_braces (p)
register char *p;
{
- register char *q;
- char *filter;
+ char *filter, *body = NULL, *endbody;
int pipe_p = 0;
- int negate = 0;
- int suffix = 0;
+ int negate;
+ int suffix;
int include_blanks = 1;
if (*p == '^')
This is used in %{|!pipe:...}. */
pipe_p = 1, ++p;
+next_member:
+ negate = suffix = 0;
+
if (*p == '!')
/* A `!' after the open-brace negates the condition:
succeed if the specified switch is not present. */
}
filter = p;
- while (*p != ':' && *p != '}') p++;
- if (*p != '}')
+ while (*p != ':' && *p != '}' && *p != '|') p++;
+
+ if (*p == '|' && pipe_p)
+ abort ();
+
+ if (!body)
{
- register int count = 1;
- q = p + 1;
- while (count > 0)
- {
- if (*q == '{')
- count++;
- else if (*q == '}')
- count--;
- else if (*q == 0)
- abort ();
- q++;
+ if (*p != '}')
+ {
+ register int count = 1;
+ register char *q = p;
+
+ while (*q++ != ':') continue;
+ body = q;
+
+ while (count > 0)
+ {
+ if (*q == '{')
+ count++;
+ else if (*q == '}')
+ count--;
+ else if (*q == 0)
+ abort ();
+ q++;
+ }
+ endbody = q;
}
+ else
+ body = p, endbody = p+1;
}
- else
- q = p + 1;
if (suffix)
{
&& strlen (input_suffix) == p - filter
&& strncmp (input_suffix, filter, p - filter) == 0);
- if (p[0] == '}')
+ if (body[0] == '}')
abort ();
if (negate != found
- && do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
+ && do_spec_1 (save_string (body, endbody-body-1), 0, NULL_PTR) < 0)
return 0;
-
- return q;
}
else if (p[-1] == '*' && p[0] == '}')
{
if (p[-1] == '*' && !negate)
{
int substitution;
- char *r = p;
+ char *r = body;
/* First see whether we have %*. */
substitution = 0;
- while (r < q)
+ while (r < endbody)
{
if (*r == '%' && r[1] == '*')
substitution = 1;
in the text that follows the colon. */
unsigned hard_match_len = p - filter - 1;
- char *string = save_string (p + 1, q - p - 2);
+ char *string = save_string (body, endbody - body - 1);
for (i = 0; i < n_switches; i++)
if (!strncmp (switches[i].part1, filter, hard_match_len)
give_switch (i, 1, 1);
}
- return q;
+ /* We didn't match. Try again. */
+ if (*p++ == '|')
+ goto next_member;
+ return endbody;
}
}
}
}
- /* If it is as desired (present for %{s...}, absent for %{-s...})
+ /* If it is as desired (present for %{s...}, absent for %{!s...})
then substitute either the switch or the specified
conditional text. */
if (present != negate)
}
else
{
- if (do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0)
+ if (do_spec_1 (save_string (body, endbody - body - 1),
+ 0, NULL_PTR) < 0)
return 0;
}
}
/* Here if a %{|...} conditional fails: output a minus sign,
which means "standard output" or "standard input". */
do_spec_1 ("-", 0, NULL_PTR);
+ return endbody;
}
}
- return q;
+ /* We didn't match; try again. */
+ if (*p++ == '|')
+ goto next_member;
+
+ return endbody;
}
\f
/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
/* Choose directory for temp files. */
+#ifndef MKTEMP_EACH_FILE
temp_filename = choose_temp_base ();
temp_filename_length = strlen (temp_filename);
+#endif
/* Make a table of what switches there are (switches, n_switches).
Make a table of specified input files (infiles, n_infiles).
/* Make a place to record the compiler output file names
that correspond to the input files. */
- outfiles = (char **) xmalloc (n_infiles * sizeof (char *));
+ i = n_infiles;
+#ifdef LANG_SPECIFIC_DRIVER
+ i += lang_specific_extra_outfiles;
+#endif
+ outfiles = (char **) xmalloc (i * sizeof (char *));
bzero ((char *) outfiles, n_infiles * sizeof (char *));
/* Record which files were specified explicitly as link input. */
clear_failure_queue ();
}
+#ifdef LANG_SPECIFIC_DRIVER
+ if (error_count == 0
+ && lang_specific_pre_link ())
+ error_count++;
+#endif
+
/* Run ld to link all the compiler output files. */
if (error_count == 0)