Improve handling for escaped colons in prerequisite lists.
authorPaul Smith <psmith@gnu.org>
Sun, 4 Mar 2012 16:53:50 +0000 (16:53 +0000)
committerPaul Smith <psmith@gnu.org>
Sun, 4 Mar 2012 16:53:50 +0000 (16:53 +0000)
Fixes Savannah bug #12126 and bug #16545

ChangeLog
read.c
tests/ChangeLog
tests/scripts/features/escape
tests/scripts/features/se_explicit

index ff84a98..1bb2184 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2012-03-04  Paul Smith  <psmith@gnu.org>
 
+       * 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 (file)
--- 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 *
index 9d98731..78bd4ca 100644 (file)
@@ -1,5 +1,11 @@
 2012-03-04  Paul Smith  <psmith@gnu.org>
 
+       * 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.
 
index 36bab18..0d4427e 100644 (file)
@@ -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;
index f942a1c..c3cade4 100644 (file)
@@ -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;