This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]