The branch stable/14 has been updated by sjg:

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

commit 44ad87f77a847b1fcdc9bc0ee8d5532cc889b800
Author:     Simon J. Gerraty <[email protected]>
AuthorDate: 2025-07-19 17:37:32 +0000
Commit:     Simon J. Gerraty <[email protected]>
CommitDate: 2026-01-10 21:33:13 +0000

    Merge bmake-20250707
    
    Merge commit '3d772e596c1acf76f555c1f51fd8d834e56b0c35'
    
    (cherry picked from commit a8c56be47166295d37600ff81fc1857db87b3a9b)
---
 contrib/bmake/ChangeLog                            |  27 +++
 contrib/bmake/FILES                                |   8 +-
 contrib/bmake/VERSION                              |   2 +-
 contrib/bmake/arch.c                               |   6 +-
 contrib/bmake/bmake.1                              |  79 +++++++-
 contrib/bmake/bmake.cat1                           |  45 ++++-
 contrib/bmake/compat.c                             |  11 +-
 contrib/bmake/cond.c                               |  89 +++++----
 contrib/bmake/for.c                                |  12 +-
 contrib/bmake/job.c                                |  42 ++--
 contrib/bmake/job.h                                |   4 +-
 contrib/bmake/main.c                               |  54 ++---
 contrib/bmake/make.1                               |  79 +++++++-
 contrib/bmake/make.c                               |   6 +-
 contrib/bmake/make.h                               |   5 +-
 contrib/bmake/make_malloc.c                        |   7 +-
 contrib/bmake/mk/ChangeLog                         |   4 +
 contrib/bmake/mk/prog.mk                           |   8 +-
 contrib/bmake/parse.c                              |  19 +-
 contrib/bmake/str.c                                |   9 +-
 contrib/bmake/unit-tests/Makefile                  |   7 +-
 .../bmake/unit-tests/char-005c-reverse-solidus.exp |  13 ++
 .../bmake/unit-tests/char-005c-reverse-solidus.mk  | 131 ++++++++++++
 contrib/bmake/unit-tests/check-expect.lua          | 219 ++++++++++-----------
 contrib/bmake/unit-tests/cmd-errors-jobs.exp       |   4 +-
 contrib/bmake/unit-tests/cmd-errors-jobs.mk        |   6 +-
 contrib/bmake/unit-tests/cmd-errors-lint.exp       |   2 +-
 contrib/bmake/unit-tests/cmd-errors-lint.mk        |   4 +-
 contrib/bmake/unit-tests/cmd-errors.exp            |   2 +-
 contrib/bmake/unit-tests/cmd-errors.mk             |   4 +-
 contrib/bmake/unit-tests/cmdline-undefined.exp     |  20 +-
 contrib/bmake/unit-tests/cmdline-undefined.mk      |  26 +--
 contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp   |   4 +-
 contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk    |   6 +-
 contrib/bmake/unit-tests/cond-cmp-numeric.exp      |   8 +-
 contrib/bmake/unit-tests/cond-cmp-numeric.mk       |  10 +-
 contrib/bmake/unit-tests/cond-cmp-string.exp       |  16 +-
 contrib/bmake/unit-tests/cond-cmp-string.mk        |  18 +-
 contrib/bmake/unit-tests/cond-eof.exp              |   6 +-
 contrib/bmake/unit-tests/cond-eof.mk               |   8 +-
 contrib/bmake/unit-tests/cond-func-defined.exp     |   4 +-
 contrib/bmake/unit-tests/cond-func-defined.mk      |   6 +-
 contrib/bmake/unit-tests/cond-func-make.exp        |   2 +-
 contrib/bmake/unit-tests/cond-func-make.mk         |   4 +-
 contrib/bmake/unit-tests/cond-func.exp             |  12 +-
 contrib/bmake/unit-tests/cond-func.mk              |  14 +-
 contrib/bmake/unit-tests/cond-late.exp             |   2 +-
 contrib/bmake/unit-tests/cond-late.mk              |  16 +-
 contrib/bmake/unit-tests/cond-op-and-lint.exp      |   2 +-
 contrib/bmake/unit-tests/cond-op-and-lint.mk       |   4 +-
 contrib/bmake/unit-tests/cond-op-and.exp           |  10 +-
 contrib/bmake/unit-tests/cond-op-and.mk            |  12 +-
 contrib/bmake/unit-tests/cond-op-not.exp           |   2 +-
 contrib/bmake/unit-tests/cond-op-not.mk            |   4 +-
 contrib/bmake/unit-tests/cond-op-or-lint.exp       |   2 +-
 contrib/bmake/unit-tests/cond-op-or-lint.mk        |   4 +-
 contrib/bmake/unit-tests/cond-op-or.exp            |  10 +-
 contrib/bmake/unit-tests/cond-op-or.mk             |  12 +-
 contrib/bmake/unit-tests/cond-op-parentheses.exp   |   8 +-
 contrib/bmake/unit-tests/cond-op-parentheses.mk    |  10 +-
 contrib/bmake/unit-tests/cond-op.exp               |  14 +-
 contrib/bmake/unit-tests/cond-op.mk                |  16 +-
 contrib/bmake/unit-tests/cond-short.exp            |   2 +-
 contrib/bmake/unit-tests/cond-short.mk             |   4 +-
 contrib/bmake/unit-tests/cond-token-number.exp     |   8 +-
 contrib/bmake/unit-tests/cond-token-number.mk      |  10 +-
 contrib/bmake/unit-tests/cond-token-plain.exp      |  24 ++-
 contrib/bmake/unit-tests/cond-token-plain.mk       |  50 +++--
 contrib/bmake/unit-tests/cond-token-string.exp     |   2 +-
 contrib/bmake/unit-tests/cond-token-string.mk      |   4 +-
 contrib/bmake/unit-tests/cond-token-var.exp        |   6 +-
 contrib/bmake/unit-tests/cond-token-var.mk         |   8 +-
 contrib/bmake/unit-tests/dep-op-missing.exp        |   2 +-
 contrib/bmake/unit-tests/deptgt-begin.exp          |   2 +-
 contrib/bmake/unit-tests/deptgt-begin.mk           |   6 +-
 contrib/bmake/unit-tests/deptgt-path-suffix.exp    |   2 +-
 contrib/bmake/unit-tests/deptgt-path-suffix.mk     |   4 +-
 contrib/bmake/unit-tests/deptgt.exp                |   6 +-
 contrib/bmake/unit-tests/deptgt.mk                 |   8 +-
 contrib/bmake/unit-tests/directive-dinclude.exp    |   2 +-
 contrib/bmake/unit-tests/directive-dinclude.mk     |   4 +-
 .../bmake/unit-tests/directive-export-gmake.exp    |   2 +-
 contrib/bmake/unit-tests/directive-export-gmake.mk |   4 +-
 contrib/bmake/unit-tests/directive-for-errors.exp  |   6 +-
 contrib/bmake/unit-tests/directive-for-errors.mk   |   8 +-
 contrib/bmake/unit-tests/directive-for-escape.exp  |  10 +-
 contrib/bmake/unit-tests/directive-for-escape.mk   |  12 +-
 contrib/bmake/unit-tests/directive-for-lines.exp   |  12 +-
 contrib/bmake/unit-tests/directive-for-lines.mk    |  20 +-
 contrib/bmake/unit-tests/directive-for.exp         |  22 +--
 contrib/bmake/unit-tests/directive-for.mk          |  23 ++-
 .../bmake/unit-tests/directive-hyphen-include.exp  |   2 +-
 .../bmake/unit-tests/directive-hyphen-include.mk   |   4 +-
 contrib/bmake/unit-tests/directive-if.exp          |   2 +-
 contrib/bmake/unit-tests/directive-if.mk           |   4 +-
 contrib/bmake/unit-tests/directive-include.exp     |   2 +-
 contrib/bmake/unit-tests/directive-include.mk      |   4 +-
 .../bmake/unit-tests/directive-misspellings.exp    |   8 +-
 contrib/bmake/unit-tests/directive-misspellings.mk |  10 +-
 contrib/bmake/unit-tests/directive-sinclude.exp    |   2 +-
 contrib/bmake/unit-tests/directive-sinclude.mk     |   4 +-
 contrib/bmake/unit-tests/directive-unexport.exp    |   2 +-
 contrib/bmake/unit-tests/directive-unexport.mk     |   3 +-
 contrib/bmake/unit-tests/directive-warning.exp     |   6 +-
 contrib/bmake/unit-tests/directive-warning.mk      |   5 +-
 contrib/bmake/unit-tests/directive.exp             |   4 +-
 contrib/bmake/unit-tests/directive.mk              |   6 +-
 contrib/bmake/unit-tests/moderrs.exp               |  14 +-
 contrib/bmake/unit-tests/moderrs.mk                |  16 +-
 contrib/bmake/unit-tests/opt-debug-file.exp        |   6 +-
 contrib/bmake/unit-tests/opt-debug-file.mk         |  14 +-
 contrib/bmake/unit-tests/opt-debug-lint.exp        |   4 +-
 contrib/bmake/unit-tests/opt-debug-lint.mk         |   6 +-
 contrib/bmake/unit-tests/opt-jobs-internal.exp     |  18 +-
 contrib/bmake/unit-tests/parse.exp                 |   6 +-
 contrib/bmake/unit-tests/parse.mk                  |   8 +-
 contrib/bmake/unit-tests/var-op-assign.exp         |   2 +-
 contrib/bmake/unit-tests/var-op-assign.mk          |   4 +-
 contrib/bmake/unit-tests/var-op-expand.exp         |  14 +-
 contrib/bmake/unit-tests/var-op-expand.mk          |   8 +-
 contrib/bmake/unit-tests/varmisc.exp               |   2 +-
 contrib/bmake/unit-tests/varmisc.mk                |   4 +-
 contrib/bmake/unit-tests/varmod-edge.exp           |   4 +-
 contrib/bmake/unit-tests/varmod-edge.mk            |   6 +-
 contrib/bmake/unit-tests/varmod-ifelse.exp         |  43 ++--
 contrib/bmake/unit-tests/varmod-ifelse.mk          |  11 +-
 contrib/bmake/unit-tests/varmod-match-escape.exp   |  14 +-
 contrib/bmake/unit-tests/varmod-match-escape.mk    |  10 +-
 contrib/bmake/unit-tests/varmod-match.exp          |  20 +-
 contrib/bmake/unit-tests/varmod-match.mk           |  28 +--
 contrib/bmake/unit-tests/varmod-mtime.exp          |   6 +-
 contrib/bmake/unit-tests/varmod-mtime.mk           |   8 +-
 contrib/bmake/unit-tests/varmod-order.exp          |   6 +-
 contrib/bmake/unit-tests/varmod-order.mk           |   8 +-
 contrib/bmake/unit-tests/varmod-range.exp          |   2 +-
 contrib/bmake/unit-tests/varmod-range.mk           |   4 +-
 contrib/bmake/unit-tests/varmod.exp                |  49 +++--
 contrib/bmake/unit-tests/varmod.mk                 |  49 +++--
 contrib/bmake/unit-tests/varname-circumflex.exp    |   9 +
 contrib/bmake/unit-tests/varname-circumflex.mk     |  47 +++++
 contrib/bmake/unit-tests/varname-vpath.exp         |   8 +-
 contrib/bmake/unit-tests/varname.exp               |   4 +-
 contrib/bmake/unit-tests/varname.mk                |   6 +-
 contrib/bmake/unit-tests/varparse-errors.exp       |  28 +--
 contrib/bmake/unit-tests/varparse-errors.mk        |  30 +--
 contrib/bmake/var.c                                |  38 ++--
 usr.bin/bmake/Makefile.config                      |   2 +-
 usr.bin/bmake/unit-tests/Makefile                  |   7 +-
 148 files changed, 1300 insertions(+), 814 deletions(-)

diff --git a/contrib/bmake/ChangeLog b/contrib/bmake/ChangeLog
index 0a5eced2d439..5a1c30a95750 100644
--- a/contrib/bmake/ChangeLog
+++ b/contrib/bmake/ChangeLog
@@ -1,3 +1,30 @@
+2025-07-07  Simon J Gerraty  <[email protected]>
+
+       * VERSION (_MAKE_VERSION): 20250707
+       Merge with NetBSD make, pick up
+       o cond.c: improve debug log message for 'exists' function.
+       complain about unfinished escape sequences or string literals.
+
+2025-07-04  Simon J Gerraty  <[email protected]>
+
+       * VERSION (_MAKE_VERSION): 20250704
+       Merge with NetBSD make, pick up
+       o make.1: add a DIAGNOSTICS section for make to reference.
+       o main.c: simplify the warning for invalid -J by refering to
+       manual page.
+
+2025-06-30  Simon J Gerraty  <[email protected]>
+
+       * VERSION (_MAKE_VERSION): 20250630
+       Merge with NetBSD make, pick up
+       o consistently use double quotes in error messages
+       o cond.c: if a condition is erroneous, skip the whole .if/.endif
+       o make_malloc.c: in cleanup mode, initialize freshly allocated memory
+       o str.c: error out on an ":M" modifier whose pattern ends with
+       backslash
+       o var.c: fix parsing of modifier parts for :gmtime and :localtime
+       add POSIX $^ support
+
 2025-06-18  Simon J Gerraty  <[email protected]>
 
        * VERSION (_MAKE_VERSION): 20250618
diff --git a/contrib/bmake/FILES b/contrib/bmake/FILES
index 8bed07d546a3..1cec16b73ef4 100644
--- a/contrib/bmake/FILES
+++ b/contrib/bmake/FILES
@@ -76,6 +76,8 @@ unit-tests/archive-suffix.exp
 unit-tests/archive-suffix.mk
 unit-tests/archive.exp
 unit-tests/archive.mk
+unit-tests/char-005c-reverse-solidus.exp
+unit-tests/char-005c-reverse-solidus.mk
 unit-tests/check-expect.lua
 unit-tests/cmd-errors-jobs.exp
 unit-tests/cmd-errors-jobs.mk
@@ -602,8 +604,6 @@ unit-tests/shell-ksh.exp
 unit-tests/shell-ksh.mk
 unit-tests/shell-sh.exp
 unit-tests/shell-sh.mk
-unit-tests/suff.exp
-unit-tests/suff.mk
 unit-tests/suff-add-later.exp
 unit-tests/suff-add-later.mk
 unit-tests/suff-clear-regular.exp
@@ -634,6 +634,8 @@ unit-tests/suff-transform-select.exp
 unit-tests/suff-transform-select.mk
 unit-tests/suff-use.exp
 unit-tests/suff-use.mk
+unit-tests/suff.exp
+unit-tests/suff.mk
 unit-tests/sunshcmd.exp
 unit-tests/sunshcmd.mk
 unit-tests/ternary.exp
@@ -780,6 +782,8 @@ unit-tests/varmod-unique.exp
 unit-tests/varmod-unique.mk
 unit-tests/varmod.exp
 unit-tests/varmod.mk
+unit-tests/varname-circumflex.exp
+unit-tests/varname-circumflex.mk
 unit-tests/varname-dollar.exp
 unit-tests/varname-dollar.mk
 unit-tests/varname-dot-alltargets.exp
diff --git a/contrib/bmake/VERSION b/contrib/bmake/VERSION
index 1467403891f1..eef1ef4b8ba9 100644
--- a/contrib/bmake/VERSION
+++ b/contrib/bmake/VERSION
@@ -1,2 +1,2 @@
 # keep this compatible with sh and make
-_MAKE_VERSION=20250618
+_MAKE_VERSION=20250707
diff --git a/contrib/bmake/arch.c b/contrib/bmake/arch.c
index 77ac7f3c5707..87e2b128ae00 100644
--- a/contrib/bmake/arch.c
+++ b/contrib/bmake/arch.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: arch.c,v 1.222 2024/08/06 17:46:01 rillig Exp $        */
+/*     $NetBSD: arch.c,v 1.223 2025/06/28 22:39:27 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.222 2024/08/06 17:46:01 rillig Exp $");
+MAKE_RCSID("$NetBSD: arch.c,v 1.223 2025/06/28 22:39:27 rillig Exp $");
 
 typedef struct List ArchList;
 typedef struct ListNode ArchListNode;
@@ -314,7 +314,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
 
                if (*cp == '\0') {
                        Parse_Error(PARSE_FATAL,
-                           "Missing ')' in archive specification");
+                           "Missing \")\" in archive specification");
                        return false;
                }
 
diff --git a/contrib/bmake/bmake.1 b/contrib/bmake/bmake.1
index 92ed9e201ea5..01f173bc1a69 100644
--- a/contrib/bmake/bmake.1
+++ b/contrib/bmake/bmake.1
@@ -1,4 +1,4 @@
-.\"    $NetBSD: make.1,v 1.385 2025/06/13 03:51:18 rillig Exp $
+.\"    $NetBSD: make.1,v 1.387 2025/07/02 17:11:56 rillig 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 June 12, 2025
+.Dd July 2, 2025
 .Dt BMAKE 1
 .Os
 .Sh NAME
@@ -785,11 +785,13 @@ Is redundant with respect to global variables,
 which have already been expanded.
 .El
 .Pp
-The seven built-in local variables are:
+The built-in local variables are:
 .Bl -tag -width ".Va .ARCHIVE" -offset indent
 .It Va .ALLSRC
 The list of all sources for this target; also known as
-.Sq Va \&> .
+.Sq Va \&>
+or
+.Sq Va \&^ .
 .It Va .ARCHIVE
 The name of the archive file; also known as
 .Sq Va \&! .
@@ -823,6 +825,7 @@ in archive member rules.
 The shorter forms
 .Po
 .Sq Va \&> ,
+.Sq Va \&^ ,
 .Sq Va \&! ,
 .Sq Va \&< ,
 .Sq Va \&% ,
@@ -2714,6 +2717,8 @@ If the
 environment variable is set to
 .Dq yes ,
 any stack traces include the call chain of the parent processes.
+.\" .Sh EXIT STATUS
+.\" .Sh ENVIRONMENT
 .Sh FILES
 .Bl -tag -width /usr/share/mk -compact
 .It .depend
@@ -2727,6 +2732,68 @@ system makefile
 .It /usr/share/mk
 system makefile directory
 .El
+.\" .Sh EXAMPLES
+.Sh DIAGNOSTICS
+.Bl -tag
+.It Dv Invalid internal option \(dq-J\(dq in \(dq Ns Ar directory Ns Dv \(dq
+The internal
+.Fl J
+option coordinates the main
+.Nm
+process with the sub-make processes to limit
+the number of jobs that run in parallel.
+The option is passed to all child processes via the
+.Ev MAKEFLAGS
+environment variable.
+To become valid,
+this option requires that the target running the sub-make is marked with the
+.Dv .MAKE
+special source,
+or that one of the target's commands directly contains the word
+.Dq make
+or one of the expressions
+.Dq ${MAKE} ,
+.Dq ${.MAKE} ,
+.Dq $(MAKE) ,
+.Dq $(.MAKE) .
+If that's not the case,
+make issues the above warning and falls back to compat mode.
+.Pp
+To see the chain of sub-makes that leads to the invalid option, set the
+.Ev MAKE_STACK_TRACE
+environment variable to
+.Dq yes .
+.Pp
+To run the sub-make in parallel mode, even in dry-run mode (see the
+.Fl n
+option), add the
+.Dv .MAKE
+pseudo source to the target.
+This is appropriate when the sub-make runs the same target in a subdirectory.
+.Pp
+To run the sub-make in parallel mode but not in dry-mode,
+add a
+.Dq ${:D make}
+marker to one of the target's commands.
+This marker expands to an empty string
+and thus does not affect the executed commands.
+.\" The marker can even be added before any of the "@+-" modifiers,
+.\" so no need to mention this explicitly.
+.Pp
+To run the sub-make in compat mode, add the
+.Fl B
+option to its invocation.
+This is appropriate when the sub-make is only used to print a variable's
+value using the
+.Fl v
+or
+.Fl V
+options.
+.Pp
+To make the sub-make independent from the parent make, unset the
+.Ev MAKEFLAGS
+environment variable in the target's commands.
+.El
 .Sh COMPATIBILITY
 The basic make syntax is compatible between different make variants;
 however the special variables, variable modifiers and conditionals are not.
@@ -2813,6 +2880,7 @@ not trying to chain transformations together, etc.) is 
also reasonably
 portable.
 .Sh SEE ALSO
 .Xr mkdep 1
+.\" .Sh STANDARDS
 .Sh HISTORY
 .Nm
 is derived from NetBSD
@@ -2837,6 +2905,8 @@ has been used to FoRCe rebuilding (since the 
target/dependency
 does not exist ... unless someone creates an
 .Pa FRC
 file).
+.\" .Sh AUTHORS
+.\" .Sh CAVEATS
 .Sh BUGS
 The
 .Nm
@@ -2858,3 +2928,4 @@ using that token pool to abort the build and exit with 
error code 6.
 Sometimes the attempt to suppress a cascade of unnecessary errors,
 can result in a seemingly unexplained
 .Ql *** Error code 6
+.\" .Sh SECURITY CONSIDERATIONS
diff --git a/contrib/bmake/bmake.cat1 b/contrib/bmake/bmake.cat1
index 667c80898def..950437a8db9c 100644
--- a/contrib/bmake/bmake.cat1
+++ b/contrib/bmake/bmake.cat1
@@ -507,10 +507,10 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
            ::==      Is redundant with respect to global variables, which 
have
                    already been expanded.
 
-     The seven built-in local variables are:
+     The built-in local variables are:
 
            _._A_L_L_S_R_C   The list of all sources for this target; 
also known as
-                     `_>'.
+                     `_>' or `_^'.
 
            _._A_R_C_H_I_V_E  The name of the archive file; also known 
as `_!'.
 
@@ -531,9 +531,9 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
                      compatibility with other makes this is an alias for
                      _._A_R_C_H_I_V_E in archive member rules.
 
-     The shorter forms (`_>', `_!', `_<', `_%', `_?', `_*', and `_@') 
are permitted
-     for backward compatibility with historical makefiles and legacy POSIX
-     make and are not recommended.
+     The shorter forms (`_>', `_^', `_!', `_<', `_%', `_?', `_*', and 
`_@') are
+     permitted for backward compatibility with historical makefiles and legacy
+     POSIX make and are not recommended.
 
      Variants of these variables with the punctuation followed immediately by
      `D' or `F', e.g. `$(@D)', are legacy forms equivalent to using the `:H'
@@ -1748,6 +1748,39 @@ FFIILLEESS
      sys.mk         system makefile
      /usr/share/mk  system makefile directory
 
+DDIIAAGGNNOOSSTTIICCSS
+     Invalid internal option "-J" in "_d_i_r_e_c_t_o_r_y"
+             The internal --JJ option coordinates the main bbmmaakkee 
process with
+             the sub-make processes to limit the number of jobs that run in
+             parallel.  The option is passed to all child processes via the
+             MAKEFLAGS environment variable.  To become valid, this option
+             requires that the target running the sub-make is marked with the
+             .MAKE special source, or that one of the target's commands
+             directly contains the word "make" or one of the expressions
+             "${MAKE}", "${.MAKE}", "$(MAKE)", "$(.MAKE)".  If that's not the
+             case, make issues the above warning and falls back to compat
+             mode.
+
+             To see the chain of sub-makes that leads to the invalid option,
+             set the MAKE_STACK_TRACE environment variable to "yes".
+
+             To run the sub-make in parallel mode, even in dry-run mode (see
+             the --nn option), add the .MAKE pseudo source to the target.  
This
+             is appropriate when the sub-make runs the same target in a
+             subdirectory.
+
+             To run the sub-make in parallel mode but not in dry-mode, add a
+             "${:D make}" marker to one of the target's commands.  This marker
+             expands to an empty string and thus does not affect the executed
+             commands.
+
+             To run the sub-make in compat mode, add the --BB option to its
+             invocation.  This is appropriate when the sub-make is only used
+             to print a variable's value using the --vv or --VV options.
+
+             To make the sub-make independent from the parent make, unset the
+             MAKEFLAGS environment variable in the target's commands.
+
 CCOOMMPPAATTIIBBIILLIITTYY
      The basic make syntax is compatible between different make variants;
      however the special variables, variable modifiers and conditionals are
@@ -1831,4 +1864,4 @@ BBUUGGSS
      attempt to suppress a cascade of unnecessary errors, can result in a
      seemingly unexplained `*** Error code 6'
 
-FreeBSD 14.2-RELEASE-p1          June 12, 2025         FreeBSD 14.2-RELEASE-p1
+FreeBSD 14.2-RELEASE-p1          July 2, 2025          FreeBSD 14.2-RELEASE-p1
diff --git a/contrib/bmake/compat.c b/contrib/bmake/compat.c
index 7a51a99be4ba..f32213bf67e5 100644
--- a/contrib/bmake/compat.c
+++ b/contrib/bmake/compat.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: compat.c,v 1.267 2025/06/13 03:51:18 rillig Exp $      */
+/*     $NetBSD: compat.c,v 1.268 2025/07/06 07:11:31 rillig Exp $      */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -97,7 +97,7 @@
 #include "pathnames.h"
 
 /*     "@(#)compat.c   8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: compat.c,v 1.267 2025/06/13 03:51:18 rillig Exp $");
+MAKE_RCSID("$NetBSD: compat.c,v 1.268 2025/07/06 07:11:31 rillig Exp $");
 
 static GNode *curTarg;
 static pid_t compatChild;
@@ -334,11 +334,8 @@ Compat_RunCommand(const char *cmdp, GNode *gn, 
StringListNode *ln)
        if (useShell) {
                static const char *shargv[5];
 
-               if (Cmd_Argv(cmd, cmd_len, shargv, 5,
-                       cmd_file, sizeof(cmd_file),
-                       errCheck && shellErrFlag != NULL,
-                       DEBUG(SHELL)) < 0)
-                       Fatal("cannot run \"%s\"", cmd);
+               Cmd_Argv(cmd, cmd_len, shargv, cmd_file, sizeof(cmd_file),
+                   errCheck && shellErrFlag != NULL, DEBUG(SHELL));
                av = shargv;
                bp = NULL;
                mav = NULL;
diff --git a/contrib/bmake/cond.c b/contrib/bmake/cond.c
index f83163cbb50e..b3613bbadf5d 100644
--- a/contrib/bmake/cond.c
+++ b/contrib/bmake/cond.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: cond.c,v 1.373 2025/04/22 19:28:50 rillig Exp $        */
+/*     $NetBSD: cond.c,v 1.378 2025/07/06 07:56:16 rillig Exp $        */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -77,9 +77,8 @@
  *                     '.if <cond>', '.elifnmake <cond>', '.else', '.endif'.
  *
  *     Cond_EvalCondition
- *                     Evaluate the conditional, which is either the argument
- *                     of one of the .if directives or the condition in a
- *                     ':?then:else' variable modifier.
+ *                     Evaluate a condition, either from one of the .if
+ *                     directives, or from a ':?then:else' modifier.
  *
  *     Cond_EndFile    At the end of reading a makefile, ensure that the
  *                     conditional directives are well-balanced.
@@ -91,14 +90,14 @@
 #include "dir.h"
 
 /*     "@(#)cond.c     8.2 (Berkeley) 1/2/94"  */
-MAKE_RCSID("$NetBSD: cond.c,v 1.373 2025/04/22 19:28:50 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.378 2025/07/06 07:56:16 rillig Exp $");
 
 /*
  * Conditional expressions conform to this grammar:
  *     Or -> And ('||' And)*
  *     And -> Term ('&&' Term)*
  *     Term -> Function '(' Argument ')'
- *     Term -> Leaf Operator Leaf
+ *     Term -> Leaf ComparisonOp Leaf
  *     Term -> Leaf
  *     Term -> '(' Or ')'
  *     Term -> '!' Term
@@ -106,7 +105,7 @@ MAKE_RCSID("$NetBSD: cond.c,v 1.373 2025/04/22 19:28:50 
rillig Exp $");
  *     Leaf -> Number
  *     Leaf -> VariableExpression
  *     Leaf -> BareWord
- *     Operator -> '==' | '!=' | '>' | '<' | '>=' | '<='
+ *     ComparisonOp -> '==' | '!=' | '>' | '<' | '>=' | '<='
  *
  * BareWord is an unquoted string literal, its evaluation depends on the kind
  * of '.if' directive.
@@ -156,12 +155,12 @@ typedef struct CondParser {
         * been an expression or a plain word.
         *
         * In conditional directives like '.if', the left-hand side must
-        * either be an expression, a quoted string or a number.
+        * either be a defined expression, a quoted string or a number.
         */
        bool leftUnquotedOK;
 
        const char *p;          /* The remaining condition to parse */
-       Token curr;             /* Single push-back token used in parsing */
+       Token curr;             /* The push-back token, or TOK_NONE */
 } CondParser;
 
 static CondResult CondParser_Or(CondParser *, bool);
@@ -255,7 +254,7 @@ ParseFuncArg(const char **pp, bool doEval, const char *func)
                        len++;
 
                Parse_Error(PARSE_FATAL,
-                   "Missing ')' after argument '%.*s' for '%.*s'",
+                   "Missing \")\" after argument \"%.*s\" for \"%.*s\"",
                    (int)(argEnd - argStart), argStart, len, func);
                free(res);
                return NULL;
@@ -284,7 +283,8 @@ FuncMake(const char *targetPattern)
                if (res.error != NULL && !warned) {
                        warned = true;
                        Parse_Error(PARSE_WARNING,
-                           "%s in pattern argument '%s' to function 'make'",
+                           "%s in pattern argument \"%s\" "
+                           "to function \"make\"",
                            res.error, targetPattern);
                }
                if (res.matched)
@@ -301,14 +301,16 @@ FuncExists(const char *file)
        char *path;
 
        path = Dir_FindFile(file, &dirSearchPath);
-       DEBUG2(COND, "exists(%s) result is \"%s\"\n",
-           file, path != NULL ? path : "");
        result = path != NULL;
+       if (result)
+               DEBUG2(COND, "\"%s\" exists in \"%s\"\n", file, path);
+       else
+               DEBUG1(COND, "\"%s\" does not exist\n", file);
        free(path);
        return result;
 }
 
-/* See if the given node exists and is an actual target. */
+/* See if the given node is an actual target. */
 static bool
 FuncTarget(const char *node)
 {
@@ -316,10 +318,7 @@ FuncTarget(const char *node)
        return gn != NULL && GNode_IsTarget(gn);
 }
 
-/*
- * See if the given node exists and is an actual target with commands
- * associated with it.
- */
+/* See if the given node is an actual target with commands. */
 static bool
 FuncCommands(const char *node)
 {
@@ -374,38 +373,37 @@ is_separator(char ch)
  *
  * Return whether to continue parsing the leaf.
  *
- * Example: .if x${CENTER}y == "${PREFIX}${SUFFIX}" || 0x${HEX}
+ * Examples: .if x${CENTER}y == "${PREFIX}${SUFFIX}" || 0x${HEX}
  */
 static bool
 CondParser_StringExpr(CondParser *par, const char *start,
                      bool doEval, bool quoted,
-                     Buffer *buf, FStr *inout_str)
+                     Buffer *buf, FStr *out_str)
 {
        VarEvalMode emode;
        const char *p;
-       bool atStart;           /* true means an expression outside quotes */
+       bool outsideQuotes;
 
        emode = doEval && quoted ? VARE_EVAL
            : doEval ? VARE_EVAL_DEFINED_LOUD
            : VARE_PARSE;
 
        p = par->p;
-       atStart = p == start;
-       *inout_str = Var_Parse(&p, SCOPE_CMDLINE, emode);
-       /* TODO: handle errors */
-       if (inout_str->str == var_Error) {
-               FStr_Done(inout_str);
-               *inout_str = FStr_InitRefer(NULL);
+       outsideQuotes = p == start;
+       *out_str = Var_Parse(&p, SCOPE_CMDLINE, emode);
+       if (out_str->str == var_Error) {
+               FStr_Done(out_str);
+               *out_str = FStr_InitRefer(NULL);
                return false;
        }
        par->p = p;
 
-       if (atStart && is_separator(par->p[0]))
+       if (outsideQuotes && is_separator(par->p[0]))
                return false;
 
-       Buf_AddStr(buf, inout_str->str);
-       FStr_Done(inout_str);
-       *inout_str = FStr_InitRefer(NULL);      /* not finished yet */
+       Buf_AddStr(buf, out_str->str);
+       FStr_Done(out_str);
+       *out_str = FStr_InitRefer(NULL);        /* not finished yet */
        return true;
 }
 
@@ -414,7 +412,7 @@ CondParser_StringExpr(CondParser *par, const char *start,
  * on the left-hand and right-hand sides of comparisons.
  *
  * Return the string without any enclosing quotes, or NULL on error.
- * Sets out_quoted if the leaf was a quoted string literal.
+ * Set out_quoted if the leaf was a quoted string literal.
  */
 static FStr
 CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK,
@@ -439,12 +437,14 @@ CondParser_Leaf(CondParser *par, bool doEval, bool 
unquotedOK,
                        if (par->p[0] != '\0') {
                                Buf_AddByte(&buf, par->p[0]);
                                par->p++;
-                       }
+                       } else
+                               Parse_Error(PARSE_FATAL,
+                                   "Unfinished backslash escape sequence");
                        continue;
                case '"':
                        par->p++;
                        if (quoted)
-                               goto return_buf;        /* skip the closing 
quote */
+                               goto return_buf;
                        Buf_AddByte(&buf, '"');
                        continue;
                case ')':       /* see is_separator */
@@ -475,6 +475,9 @@ CondParser_Leaf(CondParser *par, bool doEval, bool 
unquotedOK,
                        continue;
                }
        }
+       if (quoted)
+               Parse_Error(PARSE_FATAL,
+                   "Unfinished string literal \"%s\"", start);
 return_buf:
        str = FStr_InitOwn(buf.data);
        buf.data = NULL;
@@ -528,8 +531,8 @@ EvalCompareStr(const char *lhs, ComparisonOp op, const char 
*rhs)
 {
        if (op != EQ && op != NE) {
                Parse_Error(PARSE_FATAL,
-                   "Comparison with '%s' requires both operands "
-                   "'%s' and '%s' to be numeric",
+                   "Comparison with \"%s\" requires both operands "
+                   "\"%s\" and \"%s\" to be numeric",
                    opname[op], lhs, rhs);
                return TOK_ERROR;
        }
@@ -603,7 +606,7 @@ CondParser_Comparison(CondParser *par, bool doEval)
 
        if (par->p[0] == '\0') {
                Parse_Error(PARSE_FATAL,
-                   "Missing right-hand side of operator '%s'", opname[op]);
+                   "Missing right-hand side of operator \"%s\"", opname[op]);
                goto done_lhs;
        }
 
@@ -768,7 +771,7 @@ CondParser_Token(CondParser *par, bool doEval)
                if (par->p[0] == '|')
                        par->p++;
                else {
-                       Parse_Error(PARSE_FATAL, "Unknown operator '|'");
+                       Parse_Error(PARSE_FATAL, "Unknown operator \"|\"");
                        return TOK_ERROR;
                }
                return TOK_OR;
@@ -778,7 +781,7 @@ CondParser_Token(CondParser *par, bool doEval)
                if (par->p[0] == '&')
                        par->p++;
                else {
-                       Parse_Error(PARSE_FATAL, "Unknown operator '&'");
+                       Parse_Error(PARSE_FATAL, "Unknown operator \"&\"");
                        return TOK_ERROR;
                }
                return TOK_AND;
@@ -825,7 +828,7 @@ CondParser_Skip(CondParser *par, Token t)
 /*
  * Term -> '(' Or ')'
  * Term -> '!' Term
- * Term -> Leaf Operator Leaf
+ * Term -> Leaf ComparisonOp Leaf
  * Term -> Leaf
  */
 static CondResult
@@ -923,8 +926,10 @@ CondEvalExpression(const char *cond, bool plain,
        if (par.curr != TOK_EOF)
                rval = CR_ERROR;
 
-       if (rval == CR_ERROR && eprint && parseErrors == parseErrorsBefore)
-               Parse_Error(PARSE_FATAL, "Malformed conditional '%s'", cond);
+       if (parseErrors != parseErrorsBefore)
+               rval = CR_ERROR;
+       else if (rval == CR_ERROR && eprint)
+               Parse_Error(PARSE_FATAL, "Malformed conditional \"%s\"", cond);
 
        return rval;
 }
diff --git a/contrib/bmake/for.c b/contrib/bmake/for.c
index 438fb4e84de0..904853107db8 100644
--- a/contrib/bmake/for.c
+++ b/contrib/bmake/for.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: for.c,v 1.185 2025/04/22 19:28:50 rillig Exp $ */
+/*     $NetBSD: for.c,v 1.186 2025/06/28 22:39:27 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.185 2025/04/22 19:28:50 rillig Exp $");
+MAKE_RCSID("$NetBSD: for.c,v 1.186 2025/06/28 22:39:27 rillig Exp $");
 
 
 typedef struct ForLoop {
@@ -153,7 +153,8 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
        for (;;) {
                cpp_skip_whitespace(&p);
                if (*p == '\0') {
-                       Parse_Error(PARSE_FATAL, "missing `in' in for");
+                       Parse_Error(PARSE_FATAL,
+                           "Missing \"in\" in .for loop");
                        goto cleanup;
                }
 
@@ -168,7 +169,8 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
        }
 
        if (f->vars.len == 0) {
-               Parse_Error(PARSE_FATAL, "no iteration variables in for");
+               Parse_Error(PARSE_FATAL,
+                   "Missing iteration variables in .for loop");
                return;
        }
 
@@ -177,7 +179,7 @@ ForLoop_ParseVarnames(ForLoop *f, const char **pp)
 
 invalid_variable_name:
        Parse_Error(PARSE_FATAL,
-           "invalid character '%c' in .for loop variable name", *p);
+           "Invalid character \"%c\" in .for loop variable name", *p);
 cleanup:
        while (f->vars.len > 0)
                free(*(char **)Vector_Pop(&f->vars));
diff --git a/contrib/bmake/job.c b/contrib/bmake/job.c
index 582870088f2d..0c54e710afeb 100644
--- a/contrib/bmake/job.c
+++ b/contrib/bmake/job.c
@@ -1,4 +1,4 @@
-/*     $NetBSD: job.c,v 1.516 2025/06/13 06:13:19 rillig Exp $ */
+/*     $NetBSD: job.c,v 1.517 2025/07/06 07:11:31 rillig Exp $ */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -89,7 +89,7 @@
  *                     define the shell that is used for the creation
  *                     commands in jobs mode.
  *
- *     Job_Finish      Make the .END target. Must only be called when the
+ *     Job_MakeDotEnd  Make the .END target. Must only be called when the
  *                     job table is empty.
  *
  *     Job_AbortAll    Kill all currently running jobs, in an emergency.
@@ -137,7 +137,7 @@
 #include "trace.h"
 
 /*     "@(#)job.c      8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: job.c,v 1.516 2025/06/13 06:13:19 rillig Exp $");
+MAKE_RCSID("$NetBSD: job.c,v 1.517 2025/07/06 07:11:31 rillig Exp $");
 
 
 #ifdef USE_SELECT
@@ -599,7 +599,7 @@ Job_Pid(Job *job)
 }
 
 static void
-DumpJobs(const char *where)
+JobTable_Dump(const char *where)
 {
        const Job *job;
        char flags[4];
@@ -662,6 +662,13 @@ SetNonblocking(int fd)
                Punt("SetNonblocking.set: %s", strerror(errno));
 }
 
+static void
+SetCloseOnExec(int fd)
+{
+       if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
+               Punt("SetCloseOnExec: %s", strerror(errno));
+}
+
 static void
 JobCreatePipe(Job *job, int minfd)
 {
@@ -683,10 +690,8 @@ JobCreatePipe(Job *job, int minfd)
        job->inPipe = pipe_fds[0];
        job->outPipe = pipe_fds[1];
 
-       if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1)
-               Punt("SetCloseOnExec: %s", strerror(errno));
-       if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1)
-               Punt("SetCloseOnExec: %s", strerror(errno));
+       SetCloseOnExec(job->inPipe);
+       SetCloseOnExec(job->outPipe);
 
        /*
         * We mark the input side of the pipe non-blocking; we poll(2) the
@@ -822,7 +827,7 @@ JobFindPid(int pid, enum JobStatus status, bool isJobs)
                        return job;
        }
        if (DEBUG(JOB) && isJobs)
-               DumpJobs("no pid");
+               JobTable_Dump("no pid");
        return NULL;
 }
 
@@ -1624,7 +1629,7 @@ JobExec(Job *job, char **argv)
                debug_printf(
                    "JobExec: target %s, pid %d added to jobs table\n",
                    job->node->name, job->pid);
-               DumpJobs("job started");
+               JobTable_Dump("job started");
        }
        JobsTable_Unlock(&mask);
 }
@@ -2433,7 +2438,6 @@ static void
 JobInterrupt(bool runINTERRUPT, int signo)
 {
        Job *job;
-       GNode *interrupt;
        sigset_t mask;
 
        aborting = ABORT_INTERRUPT;
@@ -2460,10 +2464,10 @@ JobInterrupt(bool runINTERRUPT, int signo)
        JobsTable_Unlock(&mask);
 
        if (runINTERRUPT && !opts.touch) {
-               interrupt = Targ_FindNode(".INTERRUPT");
-               if (interrupt != NULL) {
+               GNode *dotInterrupt = Targ_FindNode(".INTERRUPT");
+               if (dotInterrupt != NULL) {
                        opts.ignoreErrors = false;
-                       JobRun(interrupt);
+                       JobRun(dotInterrupt);
                }
        }
        Trace_Log(MAKEINTR, NULL);
@@ -2472,15 +2476,15 @@ JobInterrupt(bool runINTERRUPT, int signo)
 
 /* Make the .END target, returning the number of job-related errors. */
 int
-Job_Finish(void)
+Job_MakeDotEnd(void)
 {
-       GNode *endNode = Targ_GetEndNode();
-       if (!Lst_IsEmpty(&endNode->commands) ||
-           !Lst_IsEmpty(&endNode->children)) {
+       GNode *dotEnd = Targ_GetEndNode();
+       if (!Lst_IsEmpty(&dotEnd->commands) ||
+           !Lst_IsEmpty(&dotEnd->children)) {
                if (job_errors != 0)
                        Error("Errors reported so .END ignored");
                else
-                       JobRun(endNode);
+                       JobRun(dotEnd);
        }
        return job_errors;
 }
diff --git a/contrib/bmake/job.h b/contrib/bmake/job.h
index 901be0eef1dd..2b4b5e59c37e 100644
--- a/contrib/bmake/job.h
+++ b/contrib/bmake/job.h
@@ -1,4 +1,4 @@
-/*     $NetBSD: job.h,v 1.84 2025/04/22 19:28:50 rillig Exp $  */
+/*     $NetBSD: job.h,v 1.85 2025/07/06 07:11:31 rillig Exp $  */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -101,7 +101,7 @@ void Job_CatchOutput(void);
 void Job_Make(GNode *);
 void Job_Init(void);
 bool Job_ParseShell(char *) MAKE_ATTR_USE;
-int Job_Finish(void);
+int Job_MakeDotEnd(void);
 #ifdef CLEANUP
 void Job_End(void);
 #endif
diff --git a/contrib/bmake/main.c b/contrib/bmake/main.c
index d020ba85f16b..a773b44f42c4 100644
--- a/contrib/bmake/main.c
+++ b/contrib/bmake/main.c
@@ -1,4 +1,4 @@
*** 4776 LINES SKIPPED ***

Reply via email to