aboutsummaryrefslogtreecommitdiff
path: root/gcc/gcc.c
diff options
context:
space:
mode:
authorJeff Downs <heydowns@somuchpressure.net>2017-05-03 15:22:51 +0000
committerRainer Orth <ro@gcc.gnu.org>2017-05-03 15:22:51 +0000
commit31c830503b480498449db3eb61daff50c2732da5 (patch)
tree7cfa04c0b21f8701559d66a4b492b1c0003253f2 /gcc/gcc.c
parent4d0e904fbf9c50e15e8c9f66ab41eaf58c2a309c (diff)
downloadgcc-31c830503b480498449db3eb61daff50c2732da5.zip
gcc-31c830503b480498449db3eb61daff50c2732da5.tar.gz
gcc-31c830503b480498449db3eb61daff50c2732da5.tar.bz2
Support escaping special characters in specs
2017-05-03 Jeff Downs <heydowns@somuchpressure.net> Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> * gcc.c (handle_braces): Support escaping in switch matching text. * doc/invoke.texi (Spec Files): Document it. Remove superfluous @code markup in items. Co-Authored-By: Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> From-SVN: r247552
Diffstat (limited to 'gcc/gcc.c')
-rw-r--r--gcc/gcc.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 826b012..120c5c0 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -584,6 +584,12 @@ or with constant text in a single argument.
%(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} substitutes X if the
+-std=iso9899:1999 option is 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
@@ -6237,6 +6243,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;
@@ -6287,11 +6295,42 @@ 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;
}
@@ -6358,6 +6397,7 @@ handle_braces (const char *p)
disj_matched = true;
d_atom = atom;
d_end_atom = end_atom;
+ d_esc_buf = esc_buf;
}
}
}
@@ -6369,7 +6409,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. */
@@ -6390,6 +6430,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: