Imported Upstream version 4.4
[platform/upstream/make.git] / src / rule.c
index 7efca58..0fc64bc 100644 (file)
@@ -1,5 +1,5 @@
 /* Pattern and suffix rule internals for GNU Make.
-Copyright (C) 1988-2020 Free Software Foundation, Inc.
+Copyright (C) 1988-2022 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
 GNU Make is free software; you can redistribute it and/or modify it under the
@@ -12,7 +12,7 @@ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License along with
-this program.  If not, see <http://www.gnu.org/licenses/>.  */
+this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
 #include "makeint.h"
 
@@ -59,6 +59,63 @@ struct file *suffix_file;
 /* Maximum length of a suffix.  */
 
 static size_t maxsuffix;
+
+/* Return the rule definition: space separated rule targets, followed by
+   either a colon or two colons in the case of a terminal rule, followed by
+   space separated rule prerequisites, followed by a pipe, followed by
+   order-only prerequisites, if present.  */
+
+const char *
+get_rule_defn (struct rule *r)
+{
+  if (r->_defn == NULL)
+    {
+      size_t len = 8; /* Reserve for ":: ", " | ", and nul.  */
+      unsigned int k;
+      char *p;
+      const char *sep = "";
+      const struct dep *dep, *ood = 0;
+
+      for (k = 0; k < r->num; ++k)
+        len += r->lens[k] + 1;
+
+      for (dep = r->deps; dep; dep = dep->next)
+        len += strlen (dep_name (dep)) + (dep->wait_here ? CSTRLEN (" .WAIT") : 0) + 1;
+
+      p = r->_defn = xmalloc (len);
+      for (k = 0; k < r->num; ++k, sep = " ")
+        p = mempcpy (mempcpy (p, sep, strlen (sep)), r->targets[k], r->lens[k]);
+      *p++ = ':';
+      if (r->terminal)
+        *p++ = ':';
+
+      /* Copy all normal dependencies; note any order-only deps.  */
+      for (dep = r->deps; dep; dep = dep->next)
+        if (dep->ignore_mtime == 0)
+          {
+            if (dep->wait_here)
+              p = mempcpy (p, " .WAIT", CSTRLEN (" .WAIT"));
+            p = mempcpy (mempcpy (p, " ", 1), dep_name (dep),
+                         strlen (dep_name (dep)));
+          }
+        else if (ood == 0)
+          ood = dep;
+
+      /* Copy order-only deps, if we have any.  */
+      for (sep = " | "; ood; ood = ood->next, sep = " ")
+        if (ood->ignore_mtime)
+          {
+            p = mempcpy (p, sep, strlen (sep));
+            if (ood->wait_here)
+              p = mempcpy (p, ".WAIT ", CSTRLEN (".WAIT "));
+            p = mempcpy (p, dep_name (ood), strlen (dep_name (ood)));
+          }
+      *p = '\0';
+    }
+
+  return r->_defn;
+}
+
 \f
 /* Compute the maximum dependency length and maximum number of dependencies of
    all implicit rules.  Also sets the subdir flag for a rule when appropriate,
@@ -80,7 +137,18 @@ snap_implicit_rules (void)
 
   for (dep = prereqs; dep; dep = dep->next)
     {
-      size_t l = strlen (dep_name (dep));
+      const char *d = dep_name (dep);
+      size_t l = strlen (d);
+
+      if (dep->need_2nd_expansion)
+        /* When pattern_search allocates a buffer, allow 5 bytes per each % to
+           substitute each % with $(*F) while avoiding realloc.  */
+        while ((d = strchr (d, '%')) != 0)
+          {
+            l += 4;
+            ++d;
+          }
+
       if (l > max_pattern_dep_length)
         max_pattern_dep_length = l;
       ++pre_deps;
@@ -398,6 +466,7 @@ install_pattern_rule (struct pspec *p, int terminal)
   r->targets = xmalloc (sizeof (const char *));
   r->suffixes = xmalloc (sizeof (const char *));
   r->lens = xmalloc (sizeof (unsigned int));
+  r->_defn = NULL;
 
   r->lens[0] = (unsigned int) strlen (p->target);
   r->targets[0] = p->target;
@@ -439,6 +508,7 @@ freerule (struct rule *rule, struct rule *lastrule)
   free ((void *)rule->targets);
   free ((void *)rule->suffixes);
   free (rule->lens);
+  free ((void *) rule->_defn);
 
   /* We can't free the storage for the commands because there
      are ways that they could be in more than one place:
@@ -488,6 +558,7 @@ create_pattern_rule (const char **targets, const char **target_percents,
   r->targets = targets;
   r->suffixes = target_percents;
   r->lens = xmalloc (n * sizeof (unsigned int));
+  r->_defn = NULL;
 
   for (i = 0; i < n; ++i)
     {
@@ -505,17 +576,8 @@ create_pattern_rule (const char **targets, const char **target_percents,
 static void                     /* Useful to call from gdb.  */
 print_rule (struct rule *r)
 {
-  unsigned int i;
-
-  for (i = 0; i < r->num; ++i)
-    {
-      fputs (r->targets[i], stdout);
-      putchar ((i + 1 == r->num) ? ':' : ' ');
-    }
-  if (r->terminal)
-    putchar (':');
-
-  print_prereqs (r->deps);
+  fputs (get_rule_defn (r), stdout);
+  putchar ('\n');
 
   if (r->cmds != 0)
     print_commands (r->cmds);