From cf1c79c9a331896d5bc2e68a1ea8206105a53eaa Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Sun, 4 Mar 2012 16:53:50 +0000 Subject: Improve handling for escaped colons in prerequisite lists. Fixes Savannah bug #12126 and bug #16545 --- ChangeLog | 4 ++ read.c | 77 ++++++++++++++++++++++++++++++-------- tests/ChangeLog | 6 +++ tests/scripts/features/escape | 8 ++++ tests/scripts/features/se_explicit | 10 ++++- 5 files changed, 88 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index ff84a98..1bb2184 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-03-04 Paul Smith + * read.c (unescape_char): New function to remove escapes from a char. + (record_files): Call it on the dependency string to unescape ":". + Fixes Savannah bug #12126 and bug #16545. + * make.h (CSTRLEN): Determine the length of a constant string. * main.c: Use the new macro. * read.c: Ditto. diff --git a/read.c b/read.c index 51e345b..d7b357b 100644 --- a/read.c +++ b/read.c @@ -156,6 +156,7 @@ static enum make_word_type get_next_mword (char *buffer, char *delim, static void remove_comments (char *line); static char *find_char_unquote (char *string, int stop1, int stop2, int blank, int ignorevars); +static char *unescape_char (char *string, int c); /* Compare a word, both length and contents. @@ -1872,24 +1873,28 @@ record_files (struct nameseq *filenames, const char *pattern, expansion: if so, snap_deps() will do it. */ if (depstr == 0) deps = 0; - else if (second_expansion && strchr (depstr, '$')) - { - deps = alloc_dep (); - deps->name = depstr; - deps->need_2nd_expansion = 1; - deps->staticpattern = pattern != 0; - } else { - deps = split_prereqs (depstr); - free (depstr); - - /* We'll enter static pattern prereqs later when we have the stem. We - don't want to enter pattern rules at all so that we don't think that - they ought to exist (make manual "Implicit Rule Search Algorithm", - item 5c). */ - if (! pattern && ! implicit_percent) - deps = enter_prereqs (deps, NULL); + depstr = unescape_char (depstr, ':'); + if (second_expansion && strchr (depstr, '$')) + { + deps = alloc_dep (); + deps->name = depstr; + deps->need_2nd_expansion = 1; + deps->staticpattern = pattern != 0; + } + else + { + deps = split_prereqs (depstr); + free (depstr); + + /* We'll enter static pattern prereqs later when we have the stem. + We don't want to enter pattern rules at all so that we don't + think that they ought to exist (make manual "Implicit Rule Search + Algorithm", item 5c). */ + if (! pattern && ! implicit_percent) + deps = enter_prereqs (deps, NULL); + } } /* For implicit rules, _all_ the targets must have a pattern. That means we @@ -2211,6 +2216,46 @@ find_char_unquote (char *string, int stop1, int stop2, int blank, return 0; } +/* Unescape a character in a string. The string is compressed onto itself. */ + +static char * +unescape_char (char *string, int c) +{ + char *p = string; + char *s = string; + + while (*s != '\0') + { + if (*s == '\\') + { + char *e = s; + int l; + + /* We found a backslash. See if it's escaping our character. */ + while (*e == '\\') + ++e; + l = e - s; + + if (*e != c || l%2 == 0) + /* It's not; just take it all without unescaping. */ + memcpy (p, s, l); + else if (l > 1) + { + /* It is, and there's >1 backslash. Take half of them. */ + l /= 2; + memcpy (p, s, l); + p += l; + } + s = e; + } + + *(p++) = *(s++); + } + + *p = '\0'; + return string; +} + /* Search PATTERN for an unquoted % and handle quoting. */ char * diff --git a/tests/ChangeLog b/tests/ChangeLog index 9d98731..78bd4ca 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,5 +1,11 @@ 2012-03-04 Paul Smith + * scripts/features/se_explicit: Test $(x:%=%) format in secondary + expansion prerequisite lists. See Savannah bug #16545. + + * scripts/features/escape: Test escaped ":" in prerequisite lists. + See Savannah bug #12126. + * scripts/variables/private: Test appending private variables in pattern-specific target rules. See Savannah bug #35468. diff --git a/tests/scripts/features/escape b/tests/scripts/features/escape index 36bab18..0d4427e 100644 --- a/tests/scripts/features/escape +++ b/tests/scripts/features/escape @@ -54,5 +54,13 @@ run_make_test(undef, 'sharp', 'foo#bar.ext = (foo#bar.ext)'); +# Test escaped colons in prerequisites +# Quoting of backslashes in q!! is kind of messy. +run_make_test(q! +foo: foo\\:bar foo\\\\\\:bar foo\\\\\\\\\\:bar +foo foo\\:bar foo\\\\\\:bar foo\\\\\\\\\\:bar: ; @echo '$@' +!, + '', "foo:bar\nfoo\\:bar\nfoo\\\\:bar\nfoo\n"); + # This tells the test driver that the perl test script executed properly. 1; diff --git a/tests/scripts/features/se_explicit b/tests/scripts/features/se_explicit index f942a1c..c3cade4 100644 --- a/tests/scripts/features/se_explicit +++ b/tests/scripts/features/se_explicit @@ -152,5 +152,13 @@ a%l: q1x $$+ q2x ; @echo '$+' '', "q1x bar bar q2x bar bar\n"); -# This tells the test driver that the perl test script executed properly. +# Allow patsubst shorthand in second expansion context. +# Requires the colon to be quoted. Savannah bug #16545 +run_make_test(q! +.PHONY: foo.bar +.SECONDEXPANSION: +foo: $$(@\\:%=%.bar); @echo '$^' +!, + '', "foo.bar\n"); + 1; -- cgit v1.2.3