This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[basic-improvements] N-way choice syntax in specs
- From: Zack Weinberg <zack at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 24 Sep 2002 12:59:14 -0700
- Subject: [basic-improvements] N-way choice syntax in specs
This patch adds an N-way choice syntax to specs, and ignores
whitespace in more places in a %{...} construct. As a demonstration,
I've converted rs6000/sysv4.h to use these. Instead of writing
%{mads: %(cpp_os_ads)}
%{myellowknife: %(cpp_os_yellowknife)}
%{mcall-sysv: %(cpp_os_sysv)}
... six more such here ...
%{!mads:%{!myellowknife:%{!mcall-sysv:... %(cpp_os_default) ...}}}
you can now write
%{mads : %(cpp_os_ads) ;
myellowknife : %(cpp_os_yellowknife) ;
mcall-sysv : %(cpp_os_sysv) ;
...
: %(cpp_os_default) } // null condition = "otherwise"
which, IMO, is much easier to read and maintain.
It was necessary to rewrite handle_braces() completely. I may not
have duplicated the old routine's exact behavior in all cases. One
place where the behavior has definitely changed is, only characters
from the set [A-Za-z0-9_-+=,.] are accepted as part of a switch name.
There was only one deviation from this rule, in arm/aof.h, which
appears to have been a typo.
Bootstrapped i686-linux with all languages; powerpc-eabisim simulator
run for C and C++ only. There are a number of testsuite failures,
none of which appear to be caused by this patch:
FAIL: gcc.c-torture/execute/ieee/inf-1.c execution, -O0
FAIL: gcc.c-torture/execute/ieee/inf-1.c execution, -O1
FAIL: gcc.dg/20020103-1.c scan-assembler-not LC
FAIL: gcc.dg/20020118-1.c execution test
# miscompiled
FAIL: gcc.dg/altivec-5.c (test for excess errors)
# ICE unrecognizable insn
FAIL: gcc.dg/c90-intconst-1.c (test for excess errors)
FAIL: gcc.dg/c99-intconst-1.c (test for excess errors)
# newlib header issues
FAIL: gcc.dg/noncompile/incomplete-1.c (test for excess errors)
# ICE segmentation fault -- only at -O3
FAIL: gcc.misc-tests/bprob-1.c compilation, -g -fprofile-arcs
FAIL: gcc.misc-tests/bprob-1.c compilation, -O0 -fprofile-arcs
[... and all other bprob tests ...]
# newlib lacks fcntl()
OK for basic-improvements?
zw
* gcc.c (input_suffix_matches, switch_matches,
mark_matching_switches, process_marked_switches,
process_brace_body): New functions - split from handle_braces.
(handle_braces): Rewrite; handle %{S:X;T:Y;:D} syntax; accept
and ignore whitespace in more places.
(specs documentation comment): Document %{S:X;T:Y;:D}.
Clarify other %{...} docs.
* doc/invoke.texi: Document %{S:X;T:Y;:D}. Clarify other
%{...} docs.
* config/arm/aof.h (LINK_SPEC): Change %{ov*,*} to %{ov*}.
* config/rs6000/sysv4.h: Use N-way choice spec syntax.
===================================================================
Index: gcc.c
*** gcc.c 20 Sep 2002 01:29:06 -0000 1.336.4.2
--- gcc.c 24 Sep 2002 19:54:30 -0000
*************** static void delete_failure_queue PARAMS
*** 291,296 ****
--- 291,305 ----
static void clear_failure_queue PARAMS ((void));
static int check_live_switch PARAMS ((int, int));
static const char *handle_braces PARAMS ((const char *));
+ static inline bool input_suffix_matches PARAMS ((const char *,
+ const char *));
+ static inline bool switch_matches PARAMS ((const char *,
+ const char *, int));
+ static inline void mark_matching_switches PARAMS ((const char *,
+ const char *, int));
+ static inline void process_marked_switches PARAMS ((void));
+ static const char *process_brace_body PARAMS ((const char *, const char *,
+ const char *, int, int));
static char *save_string PARAMS ((const char *, int));
static void set_collect_gcc_options PARAMS ((void));
static int do_spec_1 PARAMS ((const char *, int, const char *));
*************** or with constant text in a single argume
*** 471,492 ****
of S and T in the spec is not significant). Can be any number
of ampersand-separated variables; for each the wild card is
optional. Useful for CPP as %{D*&U*&A*}.
! %{S*:X} substitutes X if one or more switches whose names start with -S are
! specified to CC. Note that the tail part of the -S option
! (i.e. the part matched by the `*') will be substituted for each
! occurrence of %* within X.
! %{S:X} substitutes X, but only if the -S switch was given to CC.
! %{!S:X} substitutes X, but only if the -S switch was NOT given to CC.
! %{.S:X} 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
! The conditional text X in a %{S:X} or %{!S:X} construct may contain
other nested % constructs or spaces, or even newlines. They are
! processed as usual, as described above.
The -O, -f, -m, and -W switches are handled specifically in these
constructs. If another value of -O or the negated form of a -f, -m, or
--- 480,515 ----
of S and T in the spec is not significant). Can be any number
of ampersand-separated variables; for each the wild card is
optional. Useful for CPP as %{D*&U*&A*}.
!
! %{S:X} substitutes X, if the -S switch was given to CC.
! %{!S:X} substitutes X, if the -S switch was NOT given to CC.
! %{S*:X} substitutes X if one or more switches whose names start
! with -S was given to CC. Normally X is substituted only
! once, no matter how many such switches appeared. However,
! if %* appears somewhere in X, then X will be substituted
! once for each matching switch, with the %* replaced by the
! part of that switch that matched the '*'.
! %{.S:X} substitutes X, if processing a file with suffix S.
! %{!.S:X} substitutes X, if NOT processing a file with suffix S.
!
! %{S|T:X} substitutes X if either -S or -T was given to CC. This may be
! combined with !, ., and * as above binding stronger than the OR.
! If %* appears in X, all of the alternatives must be starred, and
! only the first matching alternative is substituted.
! %{S:X; if S was given to CC, substitutes X;
! T:Y; else if Y was given to CC, substitutes Y;
! :D} else substitutes D. There can be as many clauses as you need.
! This may be combined with ., !, |, and * as above.
!
%(Spec) processes a specification defined in a specs file as *Spec:
%[Spec] as above, but put __ around -D arguments
! The conditional text X in a %{S:X} or similar construct may contain
other nested % constructs or spaces, or even newlines. They are
! processed as usual, as described above. Trailing white space in X is
! ignored. White space may also appear anywhere on the left side of the
! colon in these constructs, except between . or * and the corresponding
! word.
The -O, -f, -m, and -W switches are handled specifically in these
constructs. If another value of -O or the negated form of a -f, -m, or
*************** do_spec_1 (spec, inswitch, soft_matched_
*** 5292,5510 ****
return 0;
}
! /* Return 0 if we call do_spec_1 and that returns -1. */
! static const char *
! handle_braces (p)
! const char *p;
{
! const char *filter, *body = NULL, *endbody = NULL;
! int true_once = 0; /* If, in %{a|b:d}, at least one of a,b was seen. */
! int negate;
! int suffix;
! int ordered = 0;
! next_member:
! negate = suffix = 0;
! if (*p == '!')
! /* A `!' after the open-brace negates the condition:
! succeed if the specified switch is not present. */
! negate = 1, ++p;
! if (*p == '.')
! /* A `.' after the open-brace means test against the current suffix. */
! {
! suffix = 1;
! ++p;
! }
! next_ampersand:
! filter = p;
! while (*p != ':' && *p != '}' && *p != '|' && *p != '&')
! p++;
! if (*p == '|' && ordered)
! abort ();
! if (!body)
! {
! if (*p != '}' && *p != '&')
! {
! int count = 1;
! const char *q = p;
! while (*q++ != ':')
! continue;
! body = q;
! while (count > 0)
! {
! if (*q == '{')
! count++;
! else if (*q == '}')
! count--;
! else if (*q == 0)
! fatal ("mismatched braces in specs");
! q++;
! }
! endbody = q;
! }
! else
! body = p, endbody = p + 1;
! }
! 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) < 0)
! return 0;
! }
! else if (p[-1] == '*' && (p[0] == '}' || p[0] == '&'))
{
! /* Substitute all matching switches as separate args. */
! int i;
! for (i = 0; i < n_switches; i++)
! if (!strncmp (switches[i].part1, filter, p - 1 - filter)
! && check_live_switch (i, p - 1 - filter))
! {
! ordered = 1;
! switches[i].ordering = 1;
! }
! }
! else
! {
! /* Test for presence of the specified switch. */
! int i;
! int present = 0;
!
! /* If name specified ends in *, as in {x*:...},
! check for %* and handle that case. */
! if (p[-1] == '*' && !negate)
! {
! int substitution;
! const char *r = body;
!
! /* First see whether we have %*. */
! substitution = 0;
! while (r < endbody)
! {
! if (*r == '%' && r[1] == '*')
! substitution = 1;
! r++;
! }
! /* If we do, handle that case. */
! if (substitution)
! {
! /* Substitute all matching switches as separate args.
! But do this by substituting for %*
! in the text that follows the colon. */
! 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]);
! /* Pass any arguments this switch has. */
! give_switch (i, 1);
! suffix_subst = NULL;
! }
! /* We didn't match. Try again. */
! if (*p++ == '|')
! goto next_member;
! return endbody;
! }
! }
! /* If name specified ends in *, as in {x*:...},
! check for presence of any switch name starting with x. */
! 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;
! break;
! }
}
! }
! /* Otherwise, check for presence of exact name specified. */
! 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 it is as desired (present for %{s...}, absent for %{!s...})
! then substitute either the switch or the specified
! conditional text. */
! if (present != negate)
! {
! if (ordered || *p == '&')
! ordered = 1, switches[i].ordering = 1;
! else if (*p == '}')
! give_switch (i, 0);
! else
! /* Even if many alternatives are matched, only output once. */
! true_once = 1;
}
}
! /* We didn't match; try again. */
! if (*p++ == '|')
! goto next_member;
! if (p[-1] == '&')
{
! body = 0;
! goto next_ampersand;
! }
! if (ordered)
! {
! int i;
! /* Doing this set of switches later preserves their command-line
! ordering. This is needed for e.g. -U, -D and -A. */
! for (i = 0; i < n_switches; i++)
! if (switches[i].ordering == 1)
! {
! switches[i].ordering = 0;
! give_switch (i, 0);
! }
! }
! /* Process the spec just once, regardless of match count. */
! else if (true_once)
! {
! if (do_spec_1 (save_string (body, endbody - body - 1),
! 0, NULL) < 0)
! return 0;
}
! return endbody;
}
/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
--- 5315,5617 ----
return 0;
}
! /* Inline subroutine of handle_braces. Returns true if the current
! input suffix matches the atom bracketed by ATOM and END_ATOM. */
! static inline bool
! input_suffix_matches (atom, end_atom)
! const char *atom;
! const char *end_atom;
! {
! return (input_suffix
! && !strncmp (input_suffix, atom, end_atom - atom)
! && input_suffix[end_atom - atom] == '\0');
! }
! /* Inline subroutine of handle_braces. Returns true if a switch
! matching the atom bracketed by ATOM and END_ATOM appeared on the
! command line. */
! static inline bool
! switch_matches (atom, end_atom, starred)
! const char *atom;
! const char *end_atom;
! int starred;
{
! int i;
! int len = end_atom - atom;
! int plen = starred ? len : -1;
! for (i = 0; i < n_switches; i++)
! if (!strncmp (switches[i].part1, atom, len)
! && (starred || switches[i].part1[len] == '\0')
! && check_live_switch (i, plen))
! return true;
! return false;
! }
! /* Inline subroutine of handle_braces. Mark all of the switches which
! match ATOM (extends to END_ATOM; STARRED indicates whether there
! was a star after the atom) for later processing. */
! static inline void
! mark_matching_switches (atom, end_atom, starred)
! const char *atom;
! const char *end_atom;
! int starred;
! {
! int i;
! int len = end_atom - atom;
! int plen = starred ? len : -1;
! for (i = 0; i < n_switches; i++)
! if (!strncmp (switches[i].part1, atom, len)
! && (starred || switches[i].part1[len] == '\0')
! && check_live_switch (i, plen))
! switches[i].ordering = 1;
! }
! /* Inline subroutine of handle_braces. Process all the currently
! marked switches through give_switch, and clear the marks. */
! static inline void
! process_marked_switches ()
! {
! int i;
! for (i = 0; i < n_switches; i++)
! if (switches[i].ordering == 1)
! {
! switches[i].ordering = 0;
! give_switch (i, 0);
! }
! }
! /* Handle a %{ ... } construct. P points just inside the leading {.
! Returns a pointer one past the end of the brace block, or 0
! if we call do_spec_1 and that returns -1. */
! static const char *
! handle_braces (p)
! const char *p;
! {
! const char *atom, *end_atom;
! const char *d_atom = NULL, *d_end_atom = NULL;
! bool a_is_suffix;
! bool a_is_starred;
! bool a_is_negated;
! bool a_matched;
!
! bool a_must_be_last = false;
! bool ordered_set = false;
! bool disjunct_set = false;
! bool disj_matched = false;
! bool disj_starred = true;
! bool n_way_choice = false;
! bool n_way_matched = false;
! #define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
! do
{
! if (a_must_be_last)
! abort ();
! /* Scan one "atom" (S in the description above of %{}, possibly
! with !, ., or * modifiers). */
! a_matched = a_is_suffix = a_is_starred = a_is_negated = false;
!
! SKIP_WHITE();
! if (*p == '!')
! p++, a_is_negated = true;
!
! SKIP_WHITE();
! if (*p == '.')
! p++, a_is_suffix = true;
!
! atom = p;
! while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '='
! || *p == ',' || *p == '.')
! p++;
! end_atom = p;
! if (*p == '*')
! p++, a_is_starred = 1;
! SKIP_WHITE();
! if (*p == '&' || *p == '}')
! {
! /* Substitute the switch(es) indicated by the current atom. */
! ordered_set = true;
! if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix
! || atom == end_atom)
! abort ();
! mark_matching_switches (atom, end_atom, a_is_starred);
! if (*p == '}')
! process_marked_switches ();
! }
! else if (*p == '|' || *p == ':')
{
! /* Substitute some text if the current atom appears as a switch
! or suffix. */
! disjunct_set = true;
! if (ordered_set)
! abort ();
!
! if (atom == end_atom)
{
! if (!n_way_choice || disj_matched || *p == '|'
! || a_is_negated || a_is_suffix || a_is_starred)
! abort ();
! /* An empty term may appear as the last choice of an
! N-way choice set; it means "otherwise". */
! a_must_be_last = true;
! disj_matched = !n_way_matched;
! disj_starred = false;
}
! else
{
! if (a_is_suffix && a_is_starred)
! abort ();
!
! if (!a_is_starred)
! disj_starred = false;
!
! /* Don't bother testing this atom if we already have a
! match. */
! if (!disj_matched && !n_way_matched)
! {
! if (a_is_suffix)
! a_matched = input_suffix_matches (atom, end_atom);
! else
! a_matched = switch_matches (atom, end_atom, a_is_starred);
!
! if (a_matched != a_is_negated)
! {
! disj_matched = true;
! d_atom = atom;
! d_end_atom = end_atom;
! }
! }
! }
!
! if (*p == ':')
! {
! /* Found the body, that is, the text to substitute if the
! current disjunction matches. */
! p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred,
! disj_matched && !n_way_matched);
! if (p == 0)
! return 0;
!
! /* If we have an N-way choice, reset state for the next
! disjunction. */
! if (*p == ';')
{
! n_way_choice = true;
! n_way_matched |= disj_matched;
! disj_matched = false;
! disj_starred = true;
! d_atom = d_end_atom = NULL;
}
}
}
+ else
+ abort ();
+ }
+ while (*p++ != '}');
! return p;
!
! #undef SKIP_WHITE
! }
!
! /* Subroutine of handle_braces. Scan and process a brace substitution body
! (X in the description of %{} syntax). P points one past the colon;
! ATOM and END_ATOM bracket the first atom which was found to be true
! (present) in the current disjunction; STARRED indicates whether all
! the atoms in the current disjunction were starred (for syntax validation);
! MATCHED indicates whether the disjunction matched or not, and therefore
! whether or not the body is to be processed through do_spec_1 or just
! skipped. Returns a pointer to the closing } or ;, or 0 if do_spec_1
! returns -1. */
!
! static const char *
! process_brace_body (p, atom, end_atom, starred, matched)
! const char *p;
! const char *atom;
! const char *end_atom;
! int starred;
! int matched;
! {
! const char *body, *end_body;
! unsigned int nesting_level;
! bool have_subst = false;
!
! /* Locate the closing } or ;, honoring nested braces.
! Trim trailing whitespace. */
! body = p;
! nesting_level = 1;
! for (;;)
! {
! if (*p == '{')
! nesting_level++;
! else if (*p == '}')
! {
! if (!--nesting_level)
! break;
}
+ else if (*p == ';' && nesting_level == 1)
+ break;
+ else if (*p == '%' && p[1] == '*' && nesting_level == 1)
+ have_subst = true;
+ else if (*p == '\0')
+ abort ();
+ p++;
}
+
+ end_body = p;
+ while (end_body[-1] == ' ' || end_body[-1] == '\t')
+ end_body--;
! if (have_subst && !starred)
! abort ();
! if (matched)
{
! /* Copy the substitution body to permanent storage and execute it.
! If have_subst is false, this is a simple matter of running the
! body through do_spec_1... */
! char *string = save_string (body, end_body - body);
! if (!have_subst)
! {
! if (do_spec_1 (string, 0, NULL) < 0)
! return 0;
! }
! else
! {
! /* ... but if have_subst is true, we have to process the
! body once for each matching switch, with %* set to the
! variant part of the switch. */
! unsigned int hard_match_len = end_atom - atom;
! int i;
! for (i = 0; i < n_switches; i++)
! if (!strncmp (switches[i].part1, atom, hard_match_len)
! && check_live_switch (i, hard_match_len))
! {
! if (do_spec_1 (string, 0,
! &switches[i].part1[hard_match_len]) < 0)
! return 0;
! /* Pass any arguments this switch has. */
! give_switch (i, 1);
! suffix_subst = NULL;
! }
! }
}
! return p;
}
/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
===================================================================
Index: config/arm/aof.h
*** config/arm/aof.h 16 Sep 2002 17:38:13 -0000 1.21.2.1
--- config/arm/aof.h 24 Sep 2002 19:54:30 -0000
*************** Boston, MA 02111-1307, USA. */
*** 27,33 ****
#define LINK_LIBGCC_SPECIAL 1
#define LINK_SPEC "%{aof} %{bin} %{aif} %{ihf} %{shl,*} %{reent*} %{split} \
! %{ov*,*} %{reloc*} -nodebug"
#define STARTFILE_SPEC "crtbegin.o%s"
--- 27,33 ----
#define LINK_LIBGCC_SPECIAL 1
#define LINK_SPEC "%{aof} %{bin} %{aif} %{ihf} %{shl,*} %{reent*} %{split} \
! %{ov*} %{reloc*} -nodebug"
#define STARTFILE_SPEC "crtbegin.o%s"
===================================================================
Index: config/rs6000/sysv4.h
*** config/rs6000/sysv4.h 17 Sep 2002 22:59:06 -0000 1.106.2.3
--- config/rs6000/sysv4.h 24 Sep 2002 19:54:31 -0000
*************** do { \
*** 846,860 ****
%{.s: %{mregnames} %{mno-regnames}} %{.S: %{mregnames} %{mno-regnames}} \
%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
%{mrelocatable} %{mrelocatable-lib} %{fpic:-K PIC} %{fPIC:-K PIC} \
! %{memb} %{!memb: %{msdata: -memb} %{msdata=eabi: -memb}} \
! %{mlittle} %{mlittle-endian} %{mbig} %{mbig-endian} \
! %{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: \
! %{mcall-freebsd: -mbig} \
! %{mcall-i960-old: -mlittle} \
! %{mcall-linux: -mbig} \
! %{mcall-gnu: -mbig} \
! %{mcall-netbsd: -mbig} \
! }}}}"
#define CC1_ENDIAN_BIG_SPEC ""
--- 846,860 ----
%{.s: %{mregnames} %{mno-regnames}} %{.S: %{mregnames} %{mno-regnames}} \
%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
%{mrelocatable} %{mrelocatable-lib} %{fpic:-K PIC} %{fPIC:-K PIC} \
! %{memb|msdata|msdata=eabi: -memb} \
! %{mlittle|mlittle-endian:-mlittle; \
! mbig|mbig-endian :-mbig; \
! mcall-aixdesc | \
! mcall-freebsd | \
! mcall-netbsd | \
! mcall-linux | \
! mcall-gnu :-mbig; \
! mcall-i960-old :-mlittle}"
#define CC1_ENDIAN_BIG_SPEC ""
*************** do { \
*** 869,887 ****
/* Pass -G xxx to the compiler and set correct endian mode. */
#define CC1_SPEC "%{G*} \
! %{mlittle: %(cc1_endian_little)} %{!mlittle: %{mlittle-endian: %(cc1_endian_little)}} \
! %{mbig: %(cc1_endian_big)} %{!mbig: %{mbig-endian: %(cc1_endian_big)}} \
! %{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: \
! %{mcall-aixdesc: -mbig %(cc1_endian_big) } \
! %{mcall-freebsd: -mbig %(cc1_endian_big) } \
! %{mcall-i960-old: -mlittle %(cc1_endian_little) } \
! %{mcall-linux: -mbig %(cc1_endian_big) } \
! %{mcall-gnu: -mbig %(cc1_endian_big) } \
! %{mcall-netbsd: -mbig %(cc1_endian_big) } \
! %{!mcall-aixdesc: %{!mcall-freebsd: %{!mcall-i960-old: %{!mcall-linux: %{!mcall-gnu: %{!mcall-netbsd: \
! %(cc1_endian_default) \
! }}}}}} \
! }}}} \
%{mno-sdata: -msdata=none } \
%{meabi: %{!mcall-*: -mcall-sysv }} \
%{!meabi: %{!mno-eabi: \
--- 869,883 ----
/* Pass -G xxx to the compiler and set correct endian mode. */
#define CC1_SPEC "%{G*} \
! %{mlittle|mlittle-endian: %(cc1_endian_little); \
! mbig |mbig-endian : %(cc1_endian_big); \
! mcall-aixdesc | \
! mcall-freebsd | \
! mcall-netbsd | \
! mcall-linux | \
! mcall-gnu : -mbig %(cc1_endian_big); \
! mcall-i960-old : -mlittle %(cc1_endian_little); \
! : %(cc1_endian_default)} \
%{mno-sdata: -msdata=none } \
%{meabi: %{!mcall-*: -mcall-sysv }} \
%{!meabi: %{!mno-eabi: \
*************** do { \
*** 914,931 ****
/* Default starting address if specified. */
#define LINK_START_SPEC "\
! %{mads: %(link_start_ads) } \
! %{myellowknife: %(link_start_yellowknife) } \
! %{mmvme: %(link_start_mvme) } \
! %{msim: %(link_start_sim) } \
! %{mwindiss: %(link_start_windiss) } \
! %{mcall-freebsd: %(link_start_freebsd) } \
! %{mcall-linux: %(link_start_linux) } \
! %{mcall-gnu: %(link_start_gnu) } \
! %{mcall-netbsd: %(link_start_netbsd) } \
! %{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
! %{!mcall-linux: %{!mcall-gnu: %{!mcall-netbsd: \
! %{!mcall-freebsd: %(link_start_default) }}}}}}}}}"
#define LINK_START_DEFAULT_SPEC ""
--- 910,925 ----
/* Default starting address if specified. */
#define LINK_START_SPEC "\
! %{mads : %(link_start_ads) ; \
! myellowknife : %(link_start_yellowknife) ; \
! mmvme : %(link_start_mvme) ; \
! msim : %(link_start_sim) ; \
! mwindiss : %(link_start_windiss) ; \
! mcall-freebsd: %(link_start_freebsd) ; \
! mcall-linux : %(link_start_linux) ; \
! mcall-gnu : %(link_start_gnu) ; \
! mcall-netbsd : %(link_start_netbsd) ; \
! : %(link_start_default) }"
#define LINK_START_DEFAULT_SPEC ""
*************** do { \
*** 973,990 ****
/* Any specific OS flags. */
#define LINK_OS_SPEC "\
! %{mads: %(link_os_ads) } \
! %{myellowknife: %(link_os_yellowknife) } \
! %{mmvme: %(link_os_mvme) } \
! %{msim: %(link_os_sim) } \
! %{mwindiss: %(link_os_windiss) } \
! %{mcall-freebsd: %(link_os_freebsd) } \
! %{mcall-linux: %(link_os_linux) } \
! %{mcall-gnu: %(link_os_gnu) } \
! %{mcall-netbsd: %(link_os_netbsd) } \
! %{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
! %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: \
! %{!mcall-netbsd: %(link_os_default) }}}}}}}}}"
#define LINK_OS_DEFAULT_SPEC ""
--- 967,982 ----
/* Any specific OS flags. */
#define LINK_OS_SPEC "\
! %{mads : %(link_os_ads) ; \
! myellowknife : %(link_os_yellowknife) ; \
! mmvme : %(link_os_mvme) ; \
! msim : %(link_os_sim) ; \
! mwindiss : %(link_os_windiss) ; \
! mcall-freebsd: %(link_os_freebsd) ; \
! mcall-linux : %(link_os_linux) ; \
! mcall-gnu : %(link_os_gnu) ; \
! mcall-netbsd : %(link_os_netbsd) ; \
! : %(link_os_default) }"
#define LINK_OS_DEFAULT_SPEC ""
*************** do { \
*** 996,1069 ****
/* Override rs6000.h definition. */
#undef CPP_SPEC
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} %(cpp_sysv) \
! %{mads: %(cpp_os_ads) } \
! %{myellowknife: %(cpp_os_yellowknife) } \
! %{mmvme: %(cpp_os_mvme) } \
! %{msim: %(cpp_os_sim) } \
! %{mwindiss: %(cpp_os_windiss) } \
! %{mcall-freebsd: %(cpp_os_freebsd) } \
! %{mcall-linux: %(cpp_os_linux) } \
! %{mcall-gnu: %(cpp_os_gnu) } \
! %{mcall-netbsd: %(cpp_os_netbsd) } \
! %{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
! %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: \
! %{!mcall-netbsd: %(cpp_os_default) }}}}}}}}}"
#define CPP_OS_DEFAULT_SPEC ""
/* Override svr4.h definition. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "\
! %{mads: %(startfile_ads) } \
! %{myellowknife: %(startfile_yellowknife) } \
! %{mmvme: %(startfile_mvme) } \
! %{msim: %(startfile_sim) } \
! %{mwindiss: %(startfile_windiss) } \
! %{mcall-freebsd: %(startfile_freebsd) } \
! %{mcall-linux: %(startfile_linux) } \
! %{mcall-gnu: %(startfile_gnu) } \
! %{mcall-netbsd: %(startfile_netbsd) } \
! %{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
! %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: \
! %{!mcall-netbsd: %(startfile_default) }}}}}}}}}"
#define STARTFILE_DEFAULT_SPEC ""
/* Override svr4.h definition. */
#undef LIB_SPEC
#define LIB_SPEC "\
! %{mads: %(lib_ads) } \
! %{myellowknife: %(lib_yellowknife) } \
! %{mmvme: %(lib_mvme) } \
! %{msim: %(lib_sim) } \
! %{mwindiss: %(lib_windiss) } \
! %{mcall-freebsd: %(lib_freebsd) } \
! %{mcall-linux: %(lib_linux) } \
! %{mcall-gnu: %(lib_gnu) } \
! %{mcall-netbsd: %(lib_netbsd) } \
! %{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
! %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: \
! %{!mcall-netbsd: %(lib_default) }}}}}}}}}"
#define LIB_DEFAULT_SPEC ""
/* Override svr4.h definition. */
#undef ENDFILE_SPEC
#define ENDFILE_SPEC "\
! %{mads: crtsavres.o%s %(endfile_ads)} \
! %{myellowknife: crtsavres.o%s %(endfile_yellowknife)} \
! %{mmvme: crtsavres.o%s %(endfile_mvme)} \
! %{msim: crtsavres.o%s %(endfile_sim)} \
! %{mwindiss: %(endfile_windiss)} \
! %{mcall-freebsd: crtsavres.o%s %(endfile_freebsd) } \
! %{mcall-linux: crtsavres.o%s %(endfile_linux) } \
! %{mcall-gnu: crtsavres.o%s %(endfile_gnu) } \
! %{mcall-netbsd: crtsavres.o%s %(endfile_netbsd) } \
! %{mvxworks: crtsavres.o%s %(endfile_vxworks) } \
! %{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
! %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: \
! %{!mcall-netbsd: %{!mvxworks: %(crtsavres_default) \
! %(endfile_default) }}}}}}}}}}"
#define CRTSAVRES_DEFAULT_SPEC "crtsavres.o%s"
--- 988,1052 ----
/* Override rs6000.h definition. */
#undef CPP_SPEC
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} %(cpp_sysv) \
! %{mads : %(cpp_os_ads) ; \
! myellowknife : %(cpp_os_yellowknife) ; \
! mmvme : %(cpp_os_mvme) ; \
! msim : %(cpp_os_sim) ; \
! mwindiss : %(cpp_os_windiss) ; \
! mcall-freebsd: %(cpp_os_freebsd) ; \
! mcall-linux : %(cpp_os_linux) ; \
! mcall-gnu : %(cpp_os_gnu) ; \
! mcall-netbsd : %(cpp_os_netbsd) ; \
! : %(cpp_os_default) }"
#define CPP_OS_DEFAULT_SPEC ""
/* Override svr4.h definition. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "\
! %{mads : %(startfile_ads) ; \
! myellowknife : %(startfile_yellowknife) ; \
! mmvme : %(startfile_mvme) ; \
! msim : %(startfile_sim) ; \
! mwindiss : %(startfile_windiss) ; \
! mcall-freebsd: %(startfile_freebsd) ; \
! mcall-linux : %(startfile_linux) ; \
! mcall-gnu : %(startfile_gnu) ; \
! mcall-netbsd : %(startfile_netbsd) ; \
! : %(startfile_default) }"
#define STARTFILE_DEFAULT_SPEC ""
/* Override svr4.h definition. */
#undef LIB_SPEC
#define LIB_SPEC "\
! %{mads : %(lib_ads) ; \
! myellowknife : %(lib_yellowknife) ; \
! mmvme : %(lib_mvme) ; \
! msim : %(lib_sim) ; \
! mwindiss : %(lib_windiss) ; \
! mcall-freebsd: %(lib_freebsd) ; \
! mcall-linux : %(lib_linux) ; \
! mcall-gnu : %(lib_gnu) ; \
! mcall-netbsd : %(lib_netbsd) ; \
! : %(lib_default) }"
#define LIB_DEFAULT_SPEC ""
/* Override svr4.h definition. */
#undef ENDFILE_SPEC
#define ENDFILE_SPEC "\
! %{mads : crtsavres.o%s %(endfile_ads) ; \
! myellowknife : crtsavres.o%s %(endfile_yellowknife) ; \
! mmvme : crtsavres.o%s %(endfile_mvme) ; \
! msim : crtsavres.o%s %(endfile_sim) ; \
! mwindiss : %(endfile_windiss) ; \
! mcall-freebsd: crtsavres.o%s %(endfile_freebsd) ; \
! mcall-linux : crtsavres.o%s %(endfile_linux) ; \
! mcall-gnu : crtsavres.o%s %(endfile_gnu) ; \
! mcall-netbsd : crtsavres.o%s %(endfile_netbsd) ; \
! mvxworks : crtsavres.o%s %(endfile_vxworks) ; \
! : %(crtsavres_default) %(endfile_default) }"
#define CRTSAVRES_DEFAULT_SPEC "crtsavres.o%s"
===================================================================
Index: doc/invoke.texi
*** doc/invoke.texi 20 Sep 2002 01:29:27 -0000 1.175.2.3
--- doc/invoke.texi 24 Sep 2002 19:54:34 -0000
*************** Like %@{@code{S}*@}, but preserve order
*** 4838,4866 ****
There can be any number of ampersand-separated variables; for each the
wild card is optional. Useful for CPP as @samp{%@{D*&U*&A*@}}.
- @item %@{@code{S}*:@code{X}@}
- Substitutes @code{X} if one or more switches whose names start with
- @code{-S} are specified to GCC@. Note that the tail part of the
- @code{-S} option (i.e.@: the part matched by the @samp{*}) will be substituted
- for each occurrence of @samp{%*} within @code{X}.
-
@item %@{@code{S}:@code{X}@}
! Substitutes @code{X}, but only if the @samp{-S} switch was given to GCC@.
@item %@{!@code{S}:@code{X}@}
! Substitutes @code{X}, but only if the @samp{-S} switch was @emph{not} given to GCC@.
@item %@{.@code{S}:@code{X}@}
! Substitutes @code{X}, but only if processing a file with suffix @code{S}.
@item %@{!.@code{S}:@code{X}@}
! Substitutes @code{X}, but only if @emph{not} processing a file with suffix @code{S}.
@item %@{@code{S}|@code{P}:@code{X}@}
! Substitutes @code{X} if either @code{-S} or @code{-P} was given to GCC@. This may be
! combined with @samp{!} and @samp{.} sequences as well, although they
! have a stronger binding than the @samp{|}. For example a spec string
! like this:
@smallexample
%@{.c:-foo@} %@{!.c:-bar@} %@{.c|d:-baz@} %@{!.c|d:-boggle@}
--- 4838,4871 ----
There can be any number of ampersand-separated variables; for each the
wild card is optional. Useful for CPP as @samp{%@{D*&U*&A*@}}.
@item %@{@code{S}:@code{X}@}
! Substitutes @code{X}, if the @samp{-S} switch was given to GCC@.
@item %@{!@code{S}:@code{X}@}
! Substitutes @code{X}, if the @samp{-S} switch was @emph{not} given to GCC@.
!
! @item %@{@code{S}*:@code{X}@}
! Substitutes @code{X} if one or more switches whose names start with
! @code{-S} are specified to GCC@. Normally @code{X} is substituted only
! once, no matter how many such switches appeared. However, if @code{%*}
! appears somewhere in @code{X}, then @code{X} will be substituted once
! for each matching switch, with the @code{%*} replaced by the part of
! that switch that matched the @code{*}.
@item %@{.@code{S}:@code{X}@}
! Substitutes @code{X}, if processing a file with suffix @code{S}.
@item %@{!.@code{S}:@code{X}@}
! Substitutes @code{X}, if @emph{not} processing a file with suffix @code{S}.
@item %@{@code{S}|@code{P}:@code{X}@}
! Substitutes @code{X} if either @code{-S} or @code{-P} was given to GCC@.
! This may be combined with @samp{!}, @samp{.}, and @code{*} sequences as well,
! although they have a stronger binding than the @samp{|}. If @code{%*}
! appears in @code{X}, all of the alternatives must be starred, and only
! the first matching alternative is substituted.
!
! For example, a spec string like this:
@smallexample
%@{.c:-foo@} %@{!.c:-bar@} %@{.c|d:-baz@} %@{!.c|d:-boggle@}
*************** jim.d -bar -boggle
*** 4876,4898 ****
-d jim.d -bar -baz -boggle
@end smallexample
@end table
! The conditional text @code{X} in a %@{@code{S}:@code{X}@} or
! %@{!@code{S}:@code{X}@} construct may contain other nested @samp{%} constructs
! or spaces, or even newlines. They are processed as usual, as described
! above.
!
! The @option{-O}, @option{-f}, @option{-m}, and @option{-W}
! switches are handled specifically in these
! constructs. If another value of @option{-O} or the negated form of a @option{-f}, @option{-m}, or
! @option{-W} switch is found later in the command line, the earlier switch
! value is ignored, except with @{@code{S}*@} where @code{S} is just one
! letter, which passes all matching options.
!
! The character @samp{|} at the beginning of the predicate text is used to indicate
! that a command should be piped to the following command, but only if @option{-pipe}
! is specified.
It is built into GCC which switches take arguments and which do not.
(You might think it would be useful to generalize this to allow each
--- 4881,4913 ----
-d jim.d -bar -baz -boggle
@end smallexample
+ @item %@{S:X; T:Y; :D@}
+
+ If @code{S} was given to GCC, substitues @code{X}; else if @code{T} was
+ given to GCC, substitues @code{Y}; else substitutes @code{D}. There can
+ be as many clauses as you need. This may be combined with @code{.},
+ @code{!}, @code{|}, and @code{*} as needed.
+
+
@end table
! The conditional text @code{X} in a %@{@code{S}:@code{X}@} or similar
! construct may contain other nested @samp{%} constructs or spaces, or
! even newlines. They are processed as usual, as described above.
! Trailing white space in @code{X} is ignored. White space may also
! appear anywhere on the left side of the colon in these constructs,
! except between @code{.} or @code{*} and the corresponding word.
!
! The @option{-O}, @option{-f}, @option{-m}, and @option{-W} switches are
! handled specifically in these constructs. If another value of
! @option{-O} or the negated form of a @option{-f}, @option{-m}, or
! @option{-W} switch is found later in the command line, the earlier
! switch value is ignored, except with @{@code{S}*@} where @code{S} is
! just one letter, which passes all matching options.
!
! The character @samp{|} at the beginning of the predicate text is used to
! indicate that a command should be piped to the following command, but
! only if @option{-pipe} is specified.
It is built into GCC which switches take arguments and which do not.
(You might think it would be useful to generalize this to allow each