]> git.ipfire.org Git - thirdparty/make.git/commitdiff
* src/read.c (find_percent_cached): [SV 60798] Silence GCC11 warnings
authorJouke Witteveen <j.witteveen@gmail.com>
Sun, 19 Dec 2021 21:19:02 +0000 (16:19 -0500)
committerPaul Smith <psmith@gnu.org>
Sun, 19 Dec 2021 21:55:50 +0000 (16:55 -0500)
src/read.c

index ae1ddabc1725e18b6237d8a48bedb59651939c4c..65ad694fdfc98efe5f71096824cd3f7dccf2c5bd 100644 (file)
@@ -2488,84 +2488,65 @@ find_percent (char *pattern)
   return find_char_unquote (pattern, '%');
 }
 
-/* Search STRING for an unquoted % and handle quoting.  Returns a pointer to
-   the % or NULL if no % was found.
+/* Return a pointer to the first unescaped %, or NULL if there isn't one.
+   Compress any escape chars up to the first unescaped %, but not afterward.
    This version is used with strings in the string cache: if there's a need to
-   modify the string a new version will be added to the string cache and
-   *STRING will be set to that.  */
+   modify the string to handle escape chars a new version will be added to the
+   string cache and *STRING will be set to that.  */
 
 const char *
 find_percent_cached (const char **string)
 {
-  const char *p = *string;
-  char *new = 0;
-  size_t slen = 0;
+  const char *p = strchr (*string, '%');
+  char *new, *np;
+  size_t slen;
 
-  /* If the first char is a % return now.  This lets us avoid extra tests
-     inside the loop.  */
-  if (*p == '%')
+  /* If there is no % or there is but it's not escaped, reuse this string.  */
+  if (!p || p == *string || p[-1] != '\\')
     return p;
 
-  while (1)
+  /* We must create a new cached string with backslashes compressed.  */
+  slen = strlen (*string);
+  new = alloca (slen + 1);
+  memcpy (new, *string, slen + 1);
+  np = new + (p - *string);
+
+  do
     {
-      p = strchr(p, '%');
+      /* Remember where the percent is.  */
+      char *pp = np;
+      int i = -2;
 
-      if (!p)
-        break;
-
-      /* See if this % is escaped with a backslash; if not we're done.  */
-      if (p[-1] != '\\')
-        break;
+      /* This % is preceded by a backslash; search for more backslashes.  */
+      while (&np[i] >= new && np[i] == '\\')
+        --i;
+      ++i;
 
+      /* The number of backslashes is -I.  Copy the string over itself to
+         swallow half of them.  */
       {
-        /* Search for more backslashes.  */
-        char *pv;
-        int i = -2;
-
-        while (&p[i] >= *string && p[i] == '\\')
-          --i;
-        ++i;
-
-        /* At this point we know we'll need to allocate a new string.
-           Make a copy if we haven't yet done so.  */
-        if (! new)
-          {
-            slen = strlen (*string);
-            new = alloca (slen + 1);
-            memcpy (new, *string, slen + 1);
-            p = new + (p - *string);
-            *string = new;
-          }
+        /* Avoid arithmetic conversion of negative values to unsigned.  */
+        int hi = -(i/2);
+        memmove (&pp[i], &pp[i/2], (slen - (pp - new)) + hi + 1);
+      }
 
-        /* At this point *string, p, and new all point into the same string.
-           Get a non-const version of p so we can modify new.  */
-        pv = new + (p - *string);
+      /* Update SLEN and set NP to point after the %.  */
+      slen += i/2 + i%2;
+      np += i/2;
 
-        /* The number of backslashes is now -I.
-           Copy P over itself to swallow half of them.  */
-        {
-          /* Avoid arithmetic conversion of negative values to unsigned.  */
-          int hi = -(i/2);
-          memmove (&pv[i], &pv[i/2], (slen - (pv - new)) + hi + 1);
-          p += i/2;
-        }
+      /* If all backslashes quoted each other then % was unquoted.  */
+      if (i % 2 == 0)
+        break;
 
-        /* If the backslashes quoted each other; the % was unquoted.  */
-        if (i % 2 == 0)
-          break;
-      }
+      np = strchr (np, '%');
     }
+  while (np && np[-1] == '\\');
 
-  /* If we had to change STRING, add it to the strcache.  */
-  if (new)
-    {
-      *string = strcache_add (*string);
-      if (p)
-        p = *string + (p - new);
-    }
+  /* Add the new string to the strcache.  */
+  *string = strcache_add (new);
 
   /* If we didn't find a %, return NULL.  Otherwise return a ptr to it.  */
-  return p;
+  return np ? *string + (np - new) : NULL;
 }
 \f
 /* Find the next line of text in an eval buffer, combining continuation lines