As a prerequisite for (a corner case in) fixing PR target/40411, we need the ability to escape special characters in specs. Case at hand: we want to match -std=iso9899:199409 which doesn't work right now. The option isn't an alias but the canonical form (though in theory one could introduce -std=c94 and make the above an alias for that), so we can only match it directly. The goal is to have this work:
#define STARTFILE_ARCH_SPEC \ "%{ansi|std=c90|std=iso9899\\:199409:values-Xc.o%s; :values-Xa.o%s} \ %{std=c90|std=gnu90:values-xpg4.o%s; :values-xpg6.o%s}" Jeff submitted a patch for this in the PR almost 8 years ago, and I've just updated it slightly so it applies to mainline, and copied the docs snippet to invoke.texi with the necessary markup. Bootstrapped (together with the current proposed patch to fix the PR above) on i386-pc-solaris2.12 and sparc-sun-solaris2.12. I'm unsure if the patch is large enough to need a copyright assignment (in which case it's almost certainly too late for GCC 7), and even if not if it's appropriate at this point in the release cycle. How should we deal with this? Thanks. Rainer -- ----------------------------------------------------------------------------- Rainer Orth, Center for Biotechnology, Bielefeld University 2017-01-10 Jeff Downs <heydo...@somuchpressure.net> Rainer Orth <r...@cebitec.uni-bielefeld.de> gcc: * gcc.c (handle_braces): Support escaping in switch matching text. * doc/invoke.texi (Spec Files): Document it.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -26391,6 +26391,13 @@ be as many clauses as you need. This ma @end table +The switch matching text @code{S} in a %@{@code{S}@}, +%@{@code{S}:@code{X}@} or similar construct can use a backslash to +ignore the special meaning of the character following it, thus allowing +literal matching of a character that is otherwise specially treated. +For example, %@{@code{std=iso9899\:1999}:@code{X}@} would substitute +@code{X} if the @option{-std=iso9899:1999} option were given. + 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. diff --git a/gcc/gcc.c b/gcc/gcc.c --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -583,6 +583,12 @@ or with constant text in a single argume %(Spec) processes a specification defined in a specs file as *Spec: +The switch matching text S in a %{S}, %{S:X}, or similar construct can use a +backslash to ignore the special meaning of the character following it, thus +allowing literal matching of a character that is otherwise specially treated. +For example, %{std=iso9899\:1999:X} would substitute X if the +-std=iso9899:1999 option were given. + 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 @@ -6228,6 +6234,8 @@ handle_braces (const char *p) { const char *atom, *end_atom; const char *d_atom = NULL, *d_end_atom = NULL; + char *esc_buf = NULL, *d_esc_buf = NULL; + int esc; const char *orig = p; bool a_is_suffix; @@ -6278,11 +6286,41 @@ handle_braces (const char *p) p++, a_is_spectype = true; atom = p; + esc = 0; while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '=' - || *p == ',' || *p == '.' || *p == '@') - p++; + || *p == ',' || *p == '.' || *p == '@' || *p == '\\') + { + if (*p == '\\') + { + p++; + if (!*p) + fatal_error (input_location, + "braced spec %qs ends in escape", orig); + esc++; + } + p++; + } end_atom = p; + if (esc) + { + const char *ap; + char *ep; + if (esc_buf && esc_buf != d_esc_buf) + free(esc_buf); + esc_buf = NULL; + ep = esc_buf = (char *)xmalloc (end_atom - atom - esc + 1); + for (ap = atom; ap != end_atom; ap++, ep++) + { + if (*ap == '\\') + ap++; + *ep = *ap; + } + *ep = '\0'; + atom = esc_buf; + end_atom = ep; + } + if (*p == '*') p++, a_is_starred = 1; } @@ -6349,6 +6387,7 @@ handle_braces (const char *p) disj_matched = true; d_atom = atom; d_end_atom = end_atom; + d_esc_buf = esc_buf; } } } @@ -6360,7 +6399,7 @@ handle_braces (const char *p) p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred, disj_matched && !n_way_matched); if (p == 0) - return 0; + goto done; /* If we have an N-way choice, reset state for the next disjunction. */ @@ -6381,6 +6420,12 @@ handle_braces (const char *p) } while (*p++ != '}'); + done: + if (d_esc_buf && d_esc_buf != esc_buf) + free(d_esc_buf); + if (esc_buf) + free(esc_buf); + return p; invalid: