/* 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
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"
/* 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,
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;
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;
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:
r->targets = targets;
r->suffixes = target_percents;
r->lens = xmalloc (n * sizeof (unsigned int));
+ r->_defn = NULL;
for (i = 0; i < n; ++i)
{
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);