The branch stable/14 has been updated by sjg:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ba508f1da16dd58684f03f06805b0f668e4c87b2

commit ba508f1da16dd58684f03f06805b0f668e4c87b2
Author:     Simon J. Gerraty <[email protected]>
AuthorDate: 2024-06-29 00:19:51 +0000
Commit:     Simon J. Gerraty <[email protected]>
CommitDate: 2026-01-10 21:33:12 +0000

    Merge bmake-20240625
    
    Merge commit 'dbb5be7f07456d02ce444484c683b130439acb45'
    
    (cherry picked from commit 8d5c8e21c690b35d0a9a604d6b886fba222cd2fe)
---
 contrib/bmake/ChangeLog                            |  49 ++++
 contrib/bmake/VERSION                              |   2 +-
 contrib/bmake/arch.c                               |  15 +-
 contrib/bmake/bmake.1                              |  33 ++-
 contrib/bmake/bmake.cat1                           |  26 +-
 contrib/bmake/compat.c                             |  57 ++--
 contrib/bmake/cond.c                               |  21 +-
 contrib/bmake/dir.c                                |  25 +-
 contrib/bmake/for.c                                |  34 +--
 contrib/bmake/hash.c                               |  31 +--
 contrib/bmake/hash.h                               |   4 +-
 contrib/bmake/job.c                                |  36 ++-
 contrib/bmake/main.c                               |  61 +++--
 contrib/bmake/make.1                               |  33 ++-
 contrib/bmake/make.c                               |  36 +--
 contrib/bmake/make.h                               |  41 +--
 contrib/bmake/meta.c                               |  25 +-
 contrib/bmake/mk/ChangeLog                         |  13 +
 contrib/bmake/mk/dirdeps.mk                        |  46 +++-
 contrib/bmake/mk/install-mk                        |   4 +-
 contrib/bmake/parse.c                              |  67 +++--
 contrib/bmake/suff.c                               |   9 +-
 contrib/bmake/targ.c                               |  20 +-
 contrib/bmake/unit-tests/Makefile                  |  13 +-
 contrib/bmake/unit-tests/cond-func-empty.mk        |  26 +-
 contrib/bmake/unit-tests/dep-duplicate.exp         |   2 +-
 contrib/bmake/unit-tests/dep-duplicate.mk          |   8 +-
 contrib/bmake/unit-tests/dep-var.exp               |   4 +-
 contrib/bmake/unit-tests/dep-var.mk                |   6 +-
 .../bmake/unit-tests/directive-export-literal.exp  |   3 +
 .../bmake/unit-tests/directive-export-literal.mk   |  25 +-
 contrib/bmake/unit-tests/directive-export.exp      |   7 +-
 contrib/bmake/unit-tests/directive-export.mk       |   8 +-
 contrib/bmake/unit-tests/directive-for-empty.exp   |   7 +-
 contrib/bmake/unit-tests/directive-for-empty.mk    |  26 +-
 contrib/bmake/unit-tests/directive-for-errors.mk   |   4 +-
 contrib/bmake/unit-tests/export-all.mk             |   4 +-
 contrib/bmake/unit-tests/opt-debug-hash.exp        |   2 +-
 contrib/bmake/unit-tests/opt-debug-hash.mk         |   7 +-
 contrib/bmake/unit-tests/parse-var.mk              |  10 +-
 contrib/bmake/unit-tests/recursive.mk              |   4 +-
 contrib/bmake/unit-tests/shell-csh.mk              |   4 +-
 contrib/bmake/unit-tests/suff-incomplete.exp       |   2 +-
 contrib/bmake/unit-tests/suff-main-several.exp     |   2 +-
 contrib/bmake/unit-tests/var-eval-short.exp        |  18 +-
 contrib/bmake/unit-tests/varmod-head.mk            |   8 +-
 contrib/bmake/unit-tests/varmod-ifelse.mk          |   4 +-
 contrib/bmake/unit-tests/varmod-loop.exp           |  10 +-
 contrib/bmake/unit-tests/varmod-loop.mk            |  16 +-
 contrib/bmake/unit-tests/varmod-match-escape.exp   |   4 +-
 contrib/bmake/unit-tests/varmod-match-escape.mk    |   6 +-
 contrib/bmake/unit-tests/varmod-match.exp          |  22 +-
 contrib/bmake/unit-tests/varmod-match.mk           |  27 +-
 contrib/bmake/unit-tests/varmod-sysv.exp           |   2 +
 contrib/bmake/unit-tests/varmod-sysv.mk            |  10 +-
 contrib/bmake/unit-tests/varmod-tail.mk            |  10 +-
 contrib/bmake/unit-tests/varmod-to-separator.exp   |  24 +-
 contrib/bmake/unit-tests/varmod-to-separator.mk    |  15 +-
 contrib/bmake/unit-tests/varmod-undefined.mk       |  51 +++-
 contrib/bmake/unit-tests/varmod.exp                |  25 ++
 contrib/bmake/unit-tests/varmod.mk                 | 125 ++++++++-
 .../bmake/unit-tests/varname-dot-make-level.exp    |   3 +
 contrib/bmake/unit-tests/varname-dot-make-level.mk |  24 +-
 contrib/bmake/unit-tests/varname-dot-newline.exp   |   5 +
 contrib/bmake/unit-tests/varname-dot-newline.mk    |  13 +-
 contrib/bmake/unit-tests/varname-dot-objdir.exp    |   1 +
 contrib/bmake/unit-tests/varname-dot-objdir.mk     |  11 +-
 contrib/bmake/unit-tests/varparse-errors.mk        |   4 +-
 contrib/bmake/var.c                                | 298 ++++++++++++---------
 usr.bin/bmake/Makefile.config                      |   2 +-
 usr.bin/bmake/unit-tests/Makefile                  |  13 +-
 71 files changed, 1029 insertions(+), 584 deletions(-)

diff --git a/contrib/bmake/ChangeLog b/contrib/bmake/ChangeLog
index 6d8a8228969d..8b6e0b2ea512 100644
--- a/contrib/bmake/ChangeLog
+++ b/contrib/bmake/ChangeLog
@@ -1,3 +1,52 @@
+2024-06-25  Simon J Gerraty  <[email protected]>
+
+       * VERSION (_MAKE_VERSION): 20240625
+       Merge with NetBSD make, pick up
+       o job.c: ensure shellPath is always duped, avoid upsetting free()
+
+2024-06-16  Simon J Gerraty  <[email protected]>
+
+       * VERSION (_MAKE_VERSION): 20240616
+       Merge with NetBSD make, pick up
+       o clean up collection of context information for error messages
+       o in warnings, move the word "warning" to the front
+       o var.c: throw an error on attempt to override an internal
+       read-only variable
+
+2024-06-10  Simon J Gerraty  <[email protected]>
+
+       * VERSION (_MAKE_VERSION): 20240610
+       Merge with NetBSD make, pick up
+       o for.c: remove redundant shortcut for building the .for loop body
+
+2024-06-02  Simon J Gerraty  <[email protected]>
+
+       * VERSION (_MAKE_VERSION): 20240602
+       Merge with NetBSD make, pick up
+       o rename some VarEvalMode constants to better match debug names.
+       o var.c: avoid out-of-bounds read when parsing indirect modifiers.
+
+2024-06-01  Simon J Gerraty  <[email protected]>
+
+       * VERSION (_MAKE_VERSION): 20240601
+       Merge with NetBSD make, pick up
+       o add .export-all rather than allow .export with no argument
+       which can happen accidentally.
+       o if lua is available, run check-expect.lua after unit-tests
+       o main.c: use snprintf rather than strncpy
+       fix memory leak when purging realpath cache.
+
+2024-05-28  Simon J Gerraty  <[email protected]>
+
+       * VERSION (_MAKE_VERSION): 20240528
+       Merge with NetBSD make, pick up
+       o fix a number of memory leaks
+       o replace magic numbers with POSIX FILENO constants
+       o hash.c: remove dead code from HashTable_DeleteEntry
+       o main.c: when complaining about unusable .OBJDIR
+       call PrintOnError if MAKE_DEBUG_OBJDIR_CHECK_WRITABLE is true.
+       o parse.c: use fewer technical terms in debug message for dependency
+
 2024-05-20  Simon J Gerraty  <[email protected]>
 
        * VERSION (_MAKE_VERSION):
diff --git a/contrib/bmake/VERSION b/contrib/bmake/VERSION
index 4af36cf84624..81837cc6765f 100644
--- a/contrib/bmake/VERSION
+++ b/contrib/bmake/VERSION
@@ -1,2 +1,2 @@
 # keep this compatible with sh and make
-_MAKE_VERSION=20240520
+_MAKE_VERSION=20240625
diff --git a/contrib/bmake/arch.c b/contrib/bmake/arch.c
index 4e52532c780a..d8b467e02874 100644
--- a/contrib/bmake/arch.c
+++ b/contrib/bmake/arch.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: arch.c,v 1.217 2024/04/27 20:41:32 rillig Exp $        */
+/*     $NetBSD: arch.c,v 1.219 2024/06/02 15:31:25 rillig Exp $        */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -147,7 +147,7 @@ struct ar_hdr {
 #include "dir.h"
 
 /*     "@(#)arch.c     8.2 (Berkeley) 1/2/94"  */
-MAKE_RCSID("$NetBSD: arch.c,v 1.217 2024/04/27 20:41:32 rillig Exp $");
+MAKE_RCSID("$NetBSD: arch.c,v 1.219 2024/06/02 15:31:25 rillig Exp $");
 
 typedef struct List ArchList;
 typedef struct ListNode ArchListNode;
@@ -204,7 +204,7 @@ ArchFree(Arch *a)
        HashIter hi;
 
        HashIter_Init(&hi, &a->members);
-       while (HashIter_Next(&hi) != NULL)
+       while (HashIter_Next(&hi))
                free(hi.entry->value);
 
        free(a->name);
@@ -257,7 +257,8 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
                        bool isError;
 
                        /* XXX: is expanded twice: once here and once below */
-                       result = Var_Parse(&nested_p, scope, VARE_UNDEFERR);
+                       result = Var_Parse(&nested_p, scope,
+                           VARE_EVAL_DEFINED);
                        /* TODO: handle errors */
                        isError = result.str == var_Error;
                        FStr_Done(&result);
@@ -272,7 +273,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
 
        spec[cp++ - spec] = '\0';
        if (expandLib)
-               Var_Expand(&lib, scope, VARE_UNDEFERR);
+               Var_Expand(&lib, scope, VARE_EVAL_DEFINED);
 
        for (;;) {
                /*
@@ -296,7 +297,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
                                const char *nested_p = cp;
 
                                result = Var_Parse(&nested_p, scope,
-                                   VARE_UNDEFERR);
+                                   VARE_EVAL_DEFINED);
                                /* TODO: handle errors */
                                isError = result.str == var_Error;
                                FStr_Done(&result);
@@ -341,7 +342,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
                        char *p;
                        const char *unexpandedMem = mem.str;
 
-                       Var_Expand(&mem, scope, VARE_UNDEFERR);
+                       Var_Expand(&mem, scope, VARE_EVAL_DEFINED);
 
                        /*
                         * Now form an archive spec and recurse to deal with
diff --git a/contrib/bmake/bmake.1 b/contrib/bmake/bmake.1
index d4e937424286..eb30d2173098 100644
--- a/contrib/bmake/bmake.1
+++ b/contrib/bmake/bmake.1
@@ -1,4 +1,4 @@
-.\"    $NetBSD: make.1,v 1.375 2024/03/10 02:53:37 sjg Exp $
+.\"    $NetBSD: make.1,v 1.377 2024/06/01 06:26:36 sjg Exp $
 .\"
 .\" Copyright (c) 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\"    from: @(#)make.1        8.4 (Berkeley) 3/19/94
 .\"
-.Dd March 9, 2024
+.Dd June 1, 2024
 .Dt BMAKE 1
 .Os
 .Sh NAME
@@ -1143,9 +1143,19 @@ This mode can be used to detect undeclared dependencies 
between files.
 Used to create files in a separate directory, see
 .Va .OBJDIR .
 .It Va MAKE_OBJDIR_CHECK_WRITABLE
-Used to force a separate directory for the created files,
-even if that directory is not writable, see
-.Va .OBJDIR .
+When true,
+.Nm
+will check that
+.Va .OBJDIR
+is writable, and issue a warning if not.
+.It Va MAKE_DEBUG_OBJDIR_CHECK_WRITABLE
+When true and
+.Nm
+is warning about an unwritable
+.Va .OBJDIR ,
+report the variables listed in
+.Va MAKE_PRINT_VAR_ON_ERROR
+to help debug.
 .It Va MAKEOBJDIRPREFIX
 Used to create files in a separate directory, see
 .Va .OBJDIR .
@@ -1951,12 +1961,7 @@ The directives for exporting and unexporting variables 
are:
 .Bl -tag -width Ds
 .It Ic .export Ar variable No ...
 Export the specified global variable.
-If no variable list is provided, all globals are exported
-except for internal variables (those that start with
-.Ql \&. ) .
-This is not affected by the
-.Fl X
-flag, so should be used with caution.
+.Pp
 For compatibility with other make programs,
 .Cm export Ar variable\| Ns Cm \&= Ns Ar value
 (without leading dot) is also accepted.
@@ -1964,6 +1969,12 @@ For compatibility with other make programs,
 Appending a variable name to
 .Va .MAKE.EXPORTED
 is equivalent to exporting a variable.
+.It Ic .export-all
+Export all globals except for internal variables (those that start with
+.Ql \&. ) .
+This is not affected by the
+.Fl X
+flag, so should be used with caution.
 .It Ic .export-env Ar variable No ...
 The same as
 .Ql .export ,
diff --git a/contrib/bmake/bmake.cat1 b/contrib/bmake/bmake.cat1
index f2b05878e7e2..456885bc634c 100644
--- a/contrib/bmake/bmake.cat1
+++ b/contrib/bmake/bmake.cat1
@@ -756,8 +756,13 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
              Used to create files in a separate directory, see 
_._O_B_J_D_I_R.
 
      
_M_A_K_E___O_B_J_D_I_R___C_H_E_C_K___W_R_I_T_A_B_L_E
-             Used to force a separate directory for the created files, even if
-             that directory is not writable, see _._O_B_J_D_I_R.
+             When true, bbmmaakkee will check that _._O_B_J_D_I_R 
is writable, and issue a
+             warning if not.
+
+     
_M_A_K_E___D_E_B_U_G___O_B_J_D_I_R___C_H_E_C_K___W_R_I_T_A_B_L_E
+             When true and bbmmaakkee is warning about an unwritable 
_._O_B_J_D_I_R,
+             report the variables listed in 
_M_A_K_E___P_R_I_N_T___V_A_R___O_N___E_R_R_O_R to help
+             debug.
 
      _M_A_K_E_O_B_J_D_I_R_P_R_E_F_I_X
              Used to create files in a separate directory, see 
_._O_B_J_D_I_R.
@@ -1230,16 +1235,19 @@ DDIIRREECCTTIIVVEESS
      The directives for exporting and unexporting variables are:
 
      ..eexxppoorrtt _v_a_r_i_a_b_l_e ...
-             Export the specified global variable.  If no variable list is
-             provided, all globals are exported except for internal variables
-             (those that start with `.').  This is not affected by the --XX
-             flag, so should be used with caution.  For compatibility with
-             other make programs, eexxppoorrtt 
_v_a_r_i_a_b_l_e==_v_a_l_u_e (without leading dot)
-             is also accepted.
+             Export the specified global variable.
+
+             For compatibility with other make programs, eexxppoorrtt 
_v_a_r_i_a_b_l_e==_v_a_l_u_e
+             (without leading dot) is also accepted.
 
              Appending a variable name to 
_._M_A_K_E_._E_X_P_O_R_T_E_D is equivalent to
              exporting a variable.
 
+     ..eexxppoorrtt--aallll
+             Export all globals except for internal variables (those that
+             start with `.').  This is not affected by the --XX flag, so 
should
+             be used with caution.
+
      ..eexxppoorrtt--eennvv _v_a_r_i_a_b_l_e ...
              The same as `.export', except that the variable is not appended
              to _._M_A_K_E_._E_X_P_O_R_T_E_D.  This allows 
exporting a value to the
@@ -1780,4 +1788,4 @@ BBUUGGSS
      attempt to suppress a cascade of unnecessary errors, can result in a
      seemingly unexplained `*** Error code 6'
 
-FreeBSD 13.2-RELEASE-p10         March 9, 2024        FreeBSD 13.2-RELEASE-p10
+FreeBSD 13.2-RELEASE-p11         June 1, 2024         FreeBSD 13.2-RELEASE-p11
diff --git a/contrib/bmake/compat.c b/contrib/bmake/compat.c
index 3a8b1c4b2640..5d1b3ab52344 100644
--- a/contrib/bmake/compat.c
+++ b/contrib/bmake/compat.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: compat.c,v 1.255 2024/04/20 10:18:55 rillig Exp $      */
+/*     $NetBSD: compat.c,v 1.259 2024/06/15 20:02:45 rillig Exp $      */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -94,7 +94,7 @@
 #include "pathnames.h"
 
 /*     "@(#)compat.c   8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: compat.c,v 1.255 2024/04/20 10:18:55 rillig Exp $");
+MAKE_RCSID("$NetBSD: compat.c,v 1.259 2024/06/15 20:02:45 rillig Exp $");
 
 static GNode *curTarg = NULL;
 static pid_t compatChild;
@@ -203,6 +203,24 @@ UseShell(const char *cmd MAKE_ATTR_UNUSED)
 #endif
 }
 
+static int
+Compat_Spawn(const char **av)
+{
+       int pid = vfork();
+       if (pid < 0)
+               Fatal("Could not fork");
+
+       if (pid == 0) {
+#ifdef USE_META
+               if (useMeta)
+                       meta_compat_child();
+#endif
+               (void)execvp(av[0], (char *const *)UNCONST(av));
+               execDie("exec", av[0]);
+       }
+       return pid;
+}
+
 /*
  * Execute the next command for a target. If the command returns an error,
  * the node's made field is set to ERROR and creation stops.
@@ -225,21 +243,18 @@ Compat_RunCommand(const char *cmdp, GNode *gn, 
StringListNode *ln)
        volatile bool errCheck; /* Check errors */
        WAIT_T reason;          /* Reason for child's death */
        WAIT_T status;          /* Description of child's death */
-       pid_t cpid;             /* Child actually found */
        pid_t retstat;          /* Result of wait */
-       const char **volatile av; /* Argument vector for thing to exec */
+       const char **av;        /* Arguments for the child process */
        char **volatile mav;    /* Copy of the argument vector for freeing */
        bool useShell;          /* True if command should be executed using a
                                 * shell */
-       const char *volatile cmd = cmdp;
+       const char *cmd = cmdp;
 
        silent = (gn->type & OP_SILENT) != OP_NONE;
        errCheck = !(gn->type & OP_IGNORE);
        doIt = false;
 
-       EvalStack_Push(gn->name, NULL, NULL);
-       cmdStart = Var_Subst(cmd, gn, VARE_WANTRES);
-       EvalStack_Pop();
+       cmdStart = Var_SubstInTarget(cmd, gn);
        /* TODO: handle errors */
 
        if (cmdStart[0] == '\0') {
@@ -264,11 +279,13 @@ Compat_RunCommand(const char *cmdp, GNode *gn, 
StringListNode *ln)
                         * usual '$$'.
                         */
                        Lst_Append(&endNode->commands, cmdStart);
-                       return true;
+                       goto register_command;
                }
        }
        if (strcmp(cmdStart, "...") == 0) {
                gn->type |= OP_SAVE_CMDS;
+       register_command:
+               Parse_RegisterCommand(cmdStart);
                return true;
        }
 
@@ -288,7 +305,7 @@ Compat_RunCommand(const char *cmdp, GNode *gn, 
StringListNode *ln)
        while (ch_isspace(*cmd))
                cmd++;
        if (cmd[0] == '\0')
-               return true;
+               goto register_command;
 
        useShell = UseShell(cmd);
 
@@ -298,7 +315,7 @@ Compat_RunCommand(const char *cmdp, GNode *gn, 
StringListNode *ln)
        }
 
        if (!doIt && !GNode_ShouldExecute(gn))
-               return true;
+               goto register_command;
 
        DEBUG1(JOB, "Execute: '%s'\n", cmd);
 
@@ -333,19 +350,7 @@ Compat_RunCommand(const char *cmdp, GNode *gn, 
StringListNode *ln)
 
        Var_ReexportVars(gn);
 
-       compatChild = cpid = vfork();
-       if (cpid < 0)
-               Fatal("Could not fork");
-
-       if (cpid == 0) {
-#ifdef USE_META
-               if (useMeta)
-                       meta_compat_child();
-#endif
-               (void)execvp(av[0], (char *const *)UNCONST(av));
-               execDie("exec", av[0]);
-       }
-
+       compatChild = Compat_Spawn(av);
        free(mav);
        free(bp);
 
@@ -355,11 +360,11 @@ Compat_RunCommand(const char *cmdp, GNode *gn, 
StringListNode *ln)
 
 #ifdef USE_META
        if (useMeta)
-               meta_compat_parent(cpid);
+               meta_compat_parent(compatChild);
 #endif
 
        /* The child is off and running. Now all we can do is wait... */
-       while ((retstat = wait(&reason)) != cpid) {
+       while ((retstat = wait(&reason)) != compatChild) {
                if (retstat > 0)
                        JobReapChild(retstat, reason, false); /* not ours? */
                if (retstat == -1 && errno != EINTR)
diff --git a/contrib/bmake/cond.c b/contrib/bmake/cond.c
index 5001677303e2..a6a73fe337dd 100644
--- a/contrib/bmake/cond.c
+++ b/contrib/bmake/cond.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: cond.c,v 1.363 2024/04/23 22:51:28 rillig Exp $        */
+/*     $NetBSD: cond.c,v 1.365 2024/06/02 15:31:25 rillig Exp $        */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -91,7 +91,7 @@
 #include "dir.h"
 
 /*     "@(#)cond.c     8.2 (Berkeley) 1/2/94"  */
-MAKE_RCSID("$NetBSD: cond.c,v 1.363 2024/04/23 22:51:28 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.365 2024/06/02 15:31:25 rillig Exp $");
 
 /*
  * Conditional expressions conform to this grammar:
@@ -222,8 +222,8 @@ ParseWord(const char **pp, bool doEval)
                        break;
                if (ch == '$') {
                        VarEvalMode emode = doEval
-                           ? VARE_UNDEFERR
-                           : VARE_PARSE_ONLY;
+                           ? VARE_EVAL_DEFINED
+                           : VARE_PARSE;
                        /*
                         * TODO: make Var_Parse complain about undefined
                         * variables.
@@ -396,9 +396,9 @@ CondParser_StringExpr(CondParser *par, const char *start,
        const char *p;
        bool atStart;           /* true means an expression outside quotes */
 
-       emode = doEval && quoted ? VARE_WANTRES
-           : doEval ? VARE_UNDEFERR
-           : VARE_PARSE_ONLY;
+       emode = doEval && quoted ? VARE_EVAL
+           : doEval ? VARE_EVAL_DEFINED
+           : VARE_PARSE;
 
        p = par->p;
        atStart = p == start;
@@ -651,8 +651,7 @@ CondParser_FuncCallEmpty(CondParser *par, bool doEval, 
Token *out_token)
                return false;
 
        p--;                    /* Make p[1] point to the '('. */
-       val = Var_Parse(&p, SCOPE_CMDLINE,
-           doEval ? VARE_WANTRES : VARE_PARSE_ONLY);
+       val = Var_Parse(&p, SCOPE_CMDLINE, doEval ? VARE_EVAL : VARE_PARSE);
        /* TODO: handle errors */
 
        if (val.str == var_Error)
@@ -736,8 +735,10 @@ CondParser_ComparisonOrLeaf(CondParser *par, bool doEval)
        arg = ParseWord(&p, doEval);
        assert(arg[0] != '\0');
 
-       if (*p == '=' || *p == '!' || *p == '<' || *p == '>')
+       if (*p == '=' || *p == '!' || *p == '<' || *p == '>') {
+               free(arg);
                return CondParser_Comparison(par, doEval);
+       }
        par->p = p;
 
        /*
diff --git a/contrib/bmake/dir.c b/contrib/bmake/dir.c
index de50b2faf511..860697120db0 100644
--- a/contrib/bmake/dir.c
+++ b/contrib/bmake/dir.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: dir.c,v 1.290 2024/05/20 19:14:12 sjg Exp $    */
+/*     $NetBSD: dir.c,v 1.294 2024/05/31 05:50:11 rillig Exp $ */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -132,7 +132,7 @@
 #include "job.h"
 
 /*     "@(#)dir.c      8.2 (Berkeley) 1/2/94"  */
-MAKE_RCSID("$NetBSD: dir.c,v 1.290 2024/05/20 19:14:12 sjg Exp $");
+MAKE_RCSID("$NetBSD: dir.c,v 1.294 2024/05/31 05:50:11 rillig Exp $");
 
 /*
  * A search path is a list of CachedDir structures. A CachedDir has in it the
@@ -501,6 +501,18 @@ Dir_InitDot(void)
        Dir_SetPATH();          /* initialize */
 }
 
+#ifdef CLEANUP
+static void
+FreeCachedTable(HashTable *tbl)
+{
+       HashIter hi;
+       HashIter_Init(&hi, tbl);
+       while (HashIter_Next(&hi))
+               free(hi.entry->value);
+       HashTable_Done(tbl);
+}
+#endif
+
 /* Clean up the directories module. */
 void
 Dir_End(void)
@@ -511,8 +523,8 @@ Dir_End(void)
        CachedDir_Assign(&dotLast, NULL);
        SearchPath_Clear(&dirSearchPath);
        OpenDirs_Done(&openDirs);
-       HashTable_Done(&mtimes);
-       HashTable_Done(&lmtimes);
+       FreeCachedTable(&mtimes);
+       FreeCachedTable(&lmtimes);
 #endif
 }
 
@@ -568,7 +580,7 @@ Dir_SetSYSPATH(void)
        CachedDirListNode *ln;
        SearchPath *path = Lst_IsEmpty(&sysIncPath->dirs)
                ? defSysIncPath : sysIncPath;
-       
+
        Var_ReadOnly(".SYSPATH", false);
        Global_Delete(".SYSPATH");
        for (ln = path->dirs.first; ln != NULL; ln = ln->next) {
@@ -644,7 +656,7 @@ DirMatchFiles(const char *pattern, CachedDir *dir, 
StringList *expansions)
         */
 
        HashIter_InitSet(&hi, &dir->files);
-       while (HashIter_Next(&hi) != NULL) {
+       while (HashIter_Next(&hi)) {
                const char *base = hi.entry->key;
                StrMatchResult res = Str_Match(base, pattern);
                /* TODO: handle errors from res.error */
@@ -864,6 +876,7 @@ SearchPath_ExpandMiddle(SearchPath *path, const char 
*pattern,
        (void)SearchPath_Add(partPath, dirpath);
        DirExpandPath(wildcardComponent + 1, partPath, expansions);
        SearchPath_Free(partPath);
+       free(dirpath);
 }
 
 /*
diff --git a/contrib/bmake/for.c b/contrib/bmake/for.c
index 91d9b8e13ce6..1563c2313963 100644
--- a/contrib/bmake/for.c
+++ b/contrib/bmake/for.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: for.c,v 1.179 2024/04/01 12:33:27 rillig Exp $ */
+/*     $NetBSD: for.c,v 1.182 2024/06/07 18:57:30 rillig Exp $ */
 
 /*
  * Copyright (c) 1992, The Regents of the University of California.
@@ -58,7 +58,7 @@
 #include "make.h"
 
 /*     "@(#)for.c      8.1 (Berkeley) 6/6/93"  */
-MAKE_RCSID("$NetBSD: for.c,v 1.179 2024/04/01 12:33:27 rillig Exp $");
+MAKE_RCSID("$NetBSD: for.c,v 1.182 2024/06/07 18:57:30 rillig Exp $");
 
 
 typedef struct ForLoop {
@@ -156,7 +156,8 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
                cpp_skip_whitespace(&p);
                if (*p == '\0') {
                        Parse_Error(PARSE_FATAL, "missing `in' in for");
-                       f->vars.len = 0;
+                       while (f->vars.len > 0)
+                               free(*(char **)Vector_Pop(&f->vars));
                        return;
                }
 
@@ -166,7 +167,8 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
                                    "invalid character '%c' "
                                    "in .for loop variable name",
                                    p[len]);
-                               f->vars.len = 0;
+                               while (f->vars.len > 0)
+                                       free(*(char **)Vector_Pop(&f->vars));
                                return;
                        }
                }
@@ -195,7 +197,7 @@ ForLoop_ParseItems(ForLoop *f, const char *p)
 
        cpp_skip_whitespace(&p);
 
-       items = Var_Subst(p, SCOPE_GLOBAL, VARE_WANTRES);
+       items = Var_Subst(p, SCOPE_GLOBAL, VARE_EVAL);
        /* TODO: handle errors */
 
        f->items = Substring_Words(items, false);
@@ -329,23 +331,6 @@ ExprLen(const char *s, const char *e)
        return 0;
 }
 
-/*
- * The .for loop substitutes the items as ${:U<value>...}, which means
- * that characters that break this syntax must be backslash-escaped.
- */
-static bool
-NeedsEscapes(Substring value, char endc)
-{
-       const char *p;
-
-       for (p = value.start; p != value.end; p++) {
-               if (*p == ':' || *p == '$' || *p == '\\' || *p == endc ||
-                   *p == '\n')
-                       return true;
-       }
-       return false;
-}
-
 /*
  * While expanding the body of a .for loop, write the item as a ${:U...}
  * expression, escaping characters as needed.  The result is later unescaped
@@ -357,11 +342,6 @@ AddEscaped(Buffer *cmds, Substring item, char endc)
        const char *p;
        char ch;
 
-       if (!NeedsEscapes(item, endc)) {
-               Buf_AddRange(cmds, item.start, item.end);
-               return;
-       }
-
        for (p = item.start; p != item.end;) {
                ch = *p;
                if (ch == '$') {
diff --git a/contrib/bmake/hash.c b/contrib/bmake/hash.c
index 88d41c2c0f6f..bc7279d7a994 100644
--- a/contrib/bmake/hash.c
+++ b/contrib/bmake/hash.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: hash.c,v 1.74 2023/12/19 19:33:39 rillig Exp $ */
+/*     $NetBSD: hash.c,v 1.78 2024/06/05 22:06:53 rillig Exp $ */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -74,7 +74,7 @@
 #include "make.h"
 
 /*     "@(#)hash.c     8.1 (Berkeley) 6/6/93"  */
-MAKE_RCSID("$NetBSD: hash.c,v 1.74 2023/12/19 19:33:39 rillig Exp $");
+MAKE_RCSID("$NetBSD: hash.c,v 1.78 2024/06/05 22:06:53 rillig Exp $");
 
 /*
  * The ratio of # entries to # buckets at which we rebuild the table to
@@ -288,24 +288,19 @@ void
 HashTable_DeleteEntry(HashTable *t, HashEntry *he)
 {
        HashEntry **ref = &t->buckets[he->hash & t->bucketsMask];
-       HashEntry *p;
-
-       for (; (p = *ref) != NULL; ref = &p->next) {
-               if (p == he) {
-                       *ref = p->next;
-                       free(p);
-                       t->numEntries--;
-                       return;
-               }
-       }
-       abort();
+
+       for (; *ref != he; ref = &(*ref)->next)
+               continue;
+       *ref = he->next;
+       free(he);
+       t->numEntries--;
 }
 
 /*
- * Return the next entry in the hash table, or NULL if the end of the table
- * is reached.
+ * Place the next entry from the hash table in hi->entry, or return false if
+ * the end of the table is reached.
  */
-HashEntry *
+bool
 HashIter_Next(HashIter *hi)
 {
        HashTable *t = hi->table;
@@ -318,11 +313,11 @@ HashIter_Next(HashIter *hi)
 
        while (he == NULL) {    /* find the next nonempty chain */
                if (hi->nextBucket >= bucketsSize)
-                       return NULL;
+                       return false;
                he = buckets[hi->nextBucket++];
        }
        hi->entry = he;
-       return he;
+       return true;
 }
 
 void
diff --git a/contrib/bmake/hash.h b/contrib/bmake/hash.h
index 2bee685b7ebb..9201c65025c7 100644
--- a/contrib/bmake/hash.h
+++ b/contrib/bmake/hash.h
@@ -1,4 +1,4 @@
-/*     $NetBSD: hash.h,v 1.48 2023/12/19 19:33:39 rillig Exp $ */
+/*     $NetBSD: hash.h,v 1.50 2024/06/01 10:10:50 rillig Exp $ */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -140,7 +140,7 @@ void HashTable_Set(HashTable *, const char *, void *);
 void HashTable_DeleteEntry(HashTable *, HashEntry *);
 void HashTable_DebugStats(HashTable *, const char *);
 
-HashEntry *HashIter_Next(HashIter *);
+bool HashIter_Next(HashIter *) MAKE_ATTR_USE;
 
 MAKE_INLINE void
 HashSet_Init(HashSet *set)
diff --git a/contrib/bmake/job.c b/contrib/bmake/job.c
index 541a61294766..a5c3d704e4a1 100644
--- a/contrib/bmake/job.c
+++ b/contrib/bmake/job.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: job.c,v 1.471 2024/05/07 18:26:22 sjg Exp $    */
+/*     $NetBSD: job.c,v 1.477 2024/06/25 05:18:38 rillig Exp $ */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -154,7 +154,7 @@
 #include "trace.h"
 
 /*     "@(#)job.c      8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: job.c,v 1.471 2024/05/07 18:26:22 sjg Exp $");
+MAKE_RCSID("$NetBSD: job.c,v 1.477 2024/06/25 05:18:38 rillig Exp $");
 
 /*
  * A shell defines how the commands are run.  All commands for a target are
@@ -930,9 +930,7 @@ JobWriteCommand(Job *job, ShellWriter *wr, StringListNode 
*ln, const char *ucmd)
 
        run = GNode_ShouldExecute(job->node);
 
-       EvalStack_Push(job->node->name, NULL, NULL);
-       xcmd = Var_Subst(ucmd, job->node, VARE_WANTRES);
-       EvalStack_Pop();
+       xcmd = Var_SubstInTarget(ucmd, job->node);
        /* TODO: handle errors */
        xcmdStart = xcmd;
 
@@ -1059,11 +1057,10 @@ JobSaveCommands(Job *job)
                 * variables such as .TARGET, .IMPSRC.  It is not intended to
                 * expand the other variables as well; see deptgt-end.mk.
                 */
-               EvalStack_Push(job->node->name, NULL, NULL);
-               expanded_cmd = Var_Subst(cmd, job->node, VARE_WANTRES);
-               EvalStack_Pop();
+               expanded_cmd = Var_SubstInTarget(cmd, job->node);
                /* TODO: handle errors */
                Lst_Append(&Targ_GetEndNode()->commands, expanded_cmd);
+               Parse_RegisterCommand(expanded_cmd);
        }
 }
 
@@ -1098,7 +1095,7 @@ DebugFailedJob(const Job *job)
                debug_printf("\t%s\n", cmd);
 
                if (strchr(cmd, '$') != NULL) {
-                       char *xcmd = Var_Subst(cmd, job->node, VARE_WANTRES);
+                       char *xcmd = Var_Subst(cmd, job->node, VARE_EVAL);
                        debug_printf("\t=> %s\n", xcmd);
                        free(xcmd);
                }
@@ -1484,11 +1481,11 @@ JobExec(Job *job, char **argv)
                 * was marked close-on-exec, we must clear that bit in the
                 * new input.
                 */
-               if (dup2(fileno(job->cmdFILE), 0) == -1)
+               if (dup2(fileno(job->cmdFILE), STDIN_FILENO) == -1)
                        execDie("dup2", "job->cmdFILE");
-               if (fcntl(0, F_SETFD, 0) == -1)
+               if (fcntl(STDIN_FILENO, F_SETFD, 0) == -1)
                        execDie("fcntl clear close-on-exec", "stdin");
-               if (lseek(0, 0, SEEK_SET) == -1)
+               if (lseek(STDIN_FILENO, 0, SEEK_SET) == -1)
                        execDie("lseek to 0", "stdin");
 
                if (Always_pass_job_queue ||
@@ -1506,18 +1503,18 @@ JobExec(Job *job, char **argv)
                 * Set up the child's output to be routed through the pipe
                 * we've created for it.
                 */
-               if (dup2(job->outPipe, 1) == -1)
+               if (dup2(job->outPipe, STDOUT_FILENO) == -1)
                        execDie("dup2", "job->outPipe");
 
                /*
                 * The output channels are marked close on exec. This bit
-                * was duplicated by the dup2(on some systems), so we have
+                * was duplicated by dup2 (on some systems), so we have
                 * to clear it before routing the shell's error output to
                 * the same place as its standard output.
                 */
-               if (fcntl(1, F_SETFD, 0) == -1)
+               if (fcntl(STDOUT_FILENO, F_SETFD, 0) == -1)
                        execDie("clear close-on-exec", "stdout");
-               if (dup2(1, 2) == -1)
+               if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
                        execDie("dup2", "1, 2");
 
                /*
@@ -2172,7 +2169,7 @@ InitShellNameAndPath(void)
 
 #ifdef DEFSHELL_CUSTOM
        if (shellName[0] == '/') {
-               shellPath = shellName;
+               shellPath = bmake_strdup(shellName);
                shellName = str_basename(shellPath);
                return;
        }
@@ -2229,7 +2226,7 @@ Job_SetPrefix(void)
                Global_Set(".MAKE.JOB.PREFIX", "---");
 
        targPrefix = Var_Subst("${.MAKE.JOB.PREFIX}",
-           SCOPE_GLOBAL, VARE_WANTRES);
+           SCOPE_GLOBAL, VARE_EVAL);
        /* TODO: handle errors */
 }
 
@@ -2525,7 +2522,8 @@ Job_ParseShell(char *line)
                        }
                }
        } else {
-               shellPath = path;
+               free(UNCONST(shellPath));
+               shellPath = bmake_strdup(path);
                shellName = newShell.name != NULL ? newShell.name
                    : str_basename(path);
                if (!fullSpec) {
diff --git a/contrib/bmake/main.c b/contrib/bmake/main.c
index 6c97d648e5a2..de2f486c15d9 100644
--- a/contrib/bmake/main.c
+++ b/contrib/bmake/main.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: main.c,v 1.616 2024/05/19 17:55:54 sjg Exp $   */
+/*     $NetBSD: main.c,v 1.624 2024/06/02 15:31:26 rillig Exp $        */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -111,7 +111,7 @@
 #include "trace.h"
 
 /*     "@(#)main.c     8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: main.c,v 1.616 2024/05/19 17:55:54 sjg Exp $");
+MAKE_RCSID("$NetBSD: main.c,v 1.624 2024/06/02 15:31:26 rillig Exp $");
 #if defined(MAKE_NATIVE)
 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
            "The Regents of the University of California.  "
@@ -372,7 +372,7 @@ MainParseArgChdir(const char *argvalue)
            stat(curdir, &sb) != -1 &&
            sa.st_ino == sb.st_ino &&
            sa.st_dev == sb.st_dev)
-               strncpy(curdir, argvalue, MAXPATHLEN);
+               snprintf(curdir, MAXPATHLEN, "%s", argvalue);
        ignorePWD = true;
 }
 
@@ -743,6 +743,10 @@ Main_SetObjdir(bool writable, const char *fmt, ...)
        if ((writable && access(path, W_OK) != 0) || chdir(path) != 0) {
                (void)fprintf(stderr, "%s: warning: %s: %s.\n",
                    progname, path, strerror(errno));
+               /* Allow debugging how we got here - not always obvious */
+               if (GetBooleanExpr("${MAKE_DEBUG_OBJDIR_CHECK_WRITABLE}",
+                       false))
+                       PrintOnError(NULL, "");
                return false;
        }
 
@@ -766,7 +770,7 @@ SetVarObjdir(bool writable, const char *var, const char 
*suffix)
                return false;
        }
 
-       Var_Expand(&path, SCOPE_GLOBAL, VARE_WANTRES);
+       Var_Expand(&path, SCOPE_GLOBAL, VARE_EVAL);
 
        (void)Main_SetObjdir(writable, "%s%s", path.str, suffix);
 
@@ -808,8 +812,7 @@ siginfo(int signo MAKE_ATTR_UNUSED)
 static void
 MakeMode(void)
 {
-       char *mode = Var_Subst("${.MAKE.MODE:tl}",
-           SCOPE_GLOBAL, VARE_WANTRES);
+       char *mode = Var_Subst("${.MAKE.MODE:tl}", SCOPE_GLOBAL, VARE_EVAL);
        /* TODO: handle errors */
 
        if (mode[0] != '\0') {
@@ -832,14 +835,14 @@ static void
 PrintVar(const char *varname, bool expandVars)
 {
        if (strchr(varname, '$') != NULL) {
-               char *evalue = Var_Subst(varname, SCOPE_GLOBAL, VARE_WANTRES);
+               char *evalue = Var_Subst(varname, SCOPE_GLOBAL, VARE_EVAL);
                /* TODO: handle errors */
                printf("%s\n", evalue);
                free(evalue);
 
        } else if (expandVars) {
                char *expr = str_concat3("${", varname, "}");
-               char *evalue = Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES);
+               char *evalue = Var_Subst(expr, SCOPE_GLOBAL, VARE_EVAL);
                /* TODO: handle errors */
                free(expr);
                printf("%s\n", evalue);
@@ -865,7 +868,7 @@ GetBooleanExpr(const char *expr, bool fallback)
        char *value;
        bool res;
 
-       value = Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES);
+       value = Var_Subst(expr, SCOPE_GLOBAL, VARE_EVAL);
*** 3147 LINES SKIPPED ***

Reply via email to