aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/bmake/ChangeLog27
-rw-r--r--contrib/bmake/FILES8
-rw-r--r--contrib/bmake/VERSION2
-rw-r--r--contrib/bmake/arch.c6
-rw-r--r--contrib/bmake/bmake.179
-rw-r--r--contrib/bmake/bmake.cat145
-rw-r--r--contrib/bmake/compat.c11
-rw-r--r--contrib/bmake/cond.c89
-rw-r--r--contrib/bmake/for.c12
-rw-r--r--contrib/bmake/job.c42
-rw-r--r--contrib/bmake/job.h4
-rw-r--r--contrib/bmake/main.c54
-rw-r--r--contrib/bmake/make.179
-rw-r--r--contrib/bmake/make.c6
-rw-r--r--contrib/bmake/make.h5
-rw-r--r--contrib/bmake/make_malloc.c7
-rw-r--r--contrib/bmake/mk/ChangeLog4
-rw-r--r--contrib/bmake/mk/prog.mk8
-rw-r--r--contrib/bmake/parse.c19
-rw-r--r--contrib/bmake/str.c9
-rw-r--r--contrib/bmake/unit-tests/Makefile7
-rw-r--r--contrib/bmake/unit-tests/char-005c-reverse-solidus.exp13
-rw-r--r--contrib/bmake/unit-tests/char-005c-reverse-solidus.mk131
-rw-r--r--contrib/bmake/unit-tests/check-expect.lua219
-rw-r--r--contrib/bmake/unit-tests/cmd-errors-jobs.exp4
-rw-r--r--contrib/bmake/unit-tests/cmd-errors-jobs.mk6
-rw-r--r--contrib/bmake/unit-tests/cmd-errors-lint.exp2
-rw-r--r--contrib/bmake/unit-tests/cmd-errors-lint.mk4
-rw-r--r--contrib/bmake/unit-tests/cmd-errors.exp2
-rw-r--r--contrib/bmake/unit-tests/cmd-errors.mk4
-rw-r--r--contrib/bmake/unit-tests/cmdline-undefined.exp20
-rw-r--r--contrib/bmake/unit-tests/cmdline-undefined.mk26
-rw-r--r--contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp4
-rwxr-xr-xcontrib/bmake/unit-tests/cond-cmp-numeric-eq.mk6
-rw-r--r--contrib/bmake/unit-tests/cond-cmp-numeric.exp8
-rw-r--r--contrib/bmake/unit-tests/cond-cmp-numeric.mk10
-rw-r--r--contrib/bmake/unit-tests/cond-cmp-string.exp16
-rw-r--r--contrib/bmake/unit-tests/cond-cmp-string.mk18
-rw-r--r--contrib/bmake/unit-tests/cond-eof.exp6
-rw-r--r--contrib/bmake/unit-tests/cond-eof.mk8
-rw-r--r--contrib/bmake/unit-tests/cond-func-defined.exp4
-rw-r--r--contrib/bmake/unit-tests/cond-func-defined.mk6
-rw-r--r--contrib/bmake/unit-tests/cond-func-make.exp2
-rw-r--r--contrib/bmake/unit-tests/cond-func-make.mk4
-rw-r--r--contrib/bmake/unit-tests/cond-func.exp12
-rw-r--r--contrib/bmake/unit-tests/cond-func.mk14
-rw-r--r--contrib/bmake/unit-tests/cond-late.exp2
-rw-r--r--contrib/bmake/unit-tests/cond-late.mk16
-rw-r--r--contrib/bmake/unit-tests/cond-op-and-lint.exp2
-rw-r--r--contrib/bmake/unit-tests/cond-op-and-lint.mk4
-rw-r--r--contrib/bmake/unit-tests/cond-op-and.exp10
-rw-r--r--contrib/bmake/unit-tests/cond-op-and.mk12
-rw-r--r--contrib/bmake/unit-tests/cond-op-not.exp2
-rw-r--r--contrib/bmake/unit-tests/cond-op-not.mk4
-rw-r--r--contrib/bmake/unit-tests/cond-op-or-lint.exp2
-rw-r--r--contrib/bmake/unit-tests/cond-op-or-lint.mk4
-rw-r--r--contrib/bmake/unit-tests/cond-op-or.exp10
-rw-r--r--contrib/bmake/unit-tests/cond-op-or.mk12
-rw-r--r--contrib/bmake/unit-tests/cond-op-parentheses.exp8
-rw-r--r--contrib/bmake/unit-tests/cond-op-parentheses.mk10
-rw-r--r--contrib/bmake/unit-tests/cond-op.exp14
-rw-r--r--contrib/bmake/unit-tests/cond-op.mk16
-rw-r--r--contrib/bmake/unit-tests/cond-short.exp2
-rw-r--r--contrib/bmake/unit-tests/cond-short.mk4
-rw-r--r--contrib/bmake/unit-tests/cond-token-number.exp8
-rw-r--r--contrib/bmake/unit-tests/cond-token-number.mk10
-rw-r--r--contrib/bmake/unit-tests/cond-token-plain.exp24
-rw-r--r--contrib/bmake/unit-tests/cond-token-plain.mk50
-rw-r--r--contrib/bmake/unit-tests/cond-token-string.exp2
-rw-r--r--contrib/bmake/unit-tests/cond-token-string.mk4
-rw-r--r--contrib/bmake/unit-tests/cond-token-var.exp6
-rw-r--r--contrib/bmake/unit-tests/cond-token-var.mk8
-rw-r--r--contrib/bmake/unit-tests/dep-op-missing.exp2
-rw-r--r--contrib/bmake/unit-tests/deptgt-begin.exp2
-rw-r--r--contrib/bmake/unit-tests/deptgt-begin.mk6
-rw-r--r--contrib/bmake/unit-tests/deptgt-path-suffix.exp2
-rw-r--r--contrib/bmake/unit-tests/deptgt-path-suffix.mk4
-rw-r--r--contrib/bmake/unit-tests/deptgt.exp6
-rw-r--r--contrib/bmake/unit-tests/deptgt.mk8
-rwxr-xr-xcontrib/bmake/unit-tests/directive-dinclude.exp2
-rwxr-xr-xcontrib/bmake/unit-tests/directive-dinclude.mk4
-rw-r--r--contrib/bmake/unit-tests/directive-export-gmake.exp2
-rw-r--r--contrib/bmake/unit-tests/directive-export-gmake.mk4
-rw-r--r--contrib/bmake/unit-tests/directive-for-errors.exp6
-rw-r--r--contrib/bmake/unit-tests/directive-for-errors.mk8
-rw-r--r--contrib/bmake/unit-tests/directive-for-escape.exp10
-rw-r--r--contrib/bmake/unit-tests/directive-for-escape.mk12
-rw-r--r--contrib/bmake/unit-tests/directive-for-lines.exp12
-rw-r--r--contrib/bmake/unit-tests/directive-for-lines.mk20
-rwxr-xr-xcontrib/bmake/unit-tests/directive-for.exp22
-rwxr-xr-xcontrib/bmake/unit-tests/directive-for.mk23
-rwxr-xr-xcontrib/bmake/unit-tests/directive-hyphen-include.exp2
-rwxr-xr-xcontrib/bmake/unit-tests/directive-hyphen-include.mk4
-rw-r--r--contrib/bmake/unit-tests/directive-if.exp2
-rw-r--r--contrib/bmake/unit-tests/directive-if.mk4
-rwxr-xr-xcontrib/bmake/unit-tests/directive-include.exp2
-rwxr-xr-xcontrib/bmake/unit-tests/directive-include.mk4
-rw-r--r--contrib/bmake/unit-tests/directive-misspellings.exp8
-rw-r--r--contrib/bmake/unit-tests/directive-misspellings.mk10
-rwxr-xr-xcontrib/bmake/unit-tests/directive-sinclude.exp2
-rwxr-xr-xcontrib/bmake/unit-tests/directive-sinclude.mk4
-rw-r--r--contrib/bmake/unit-tests/directive-unexport.exp2
-rw-r--r--contrib/bmake/unit-tests/directive-unexport.mk3
-rw-r--r--contrib/bmake/unit-tests/directive-warning.exp6
-rw-r--r--contrib/bmake/unit-tests/directive-warning.mk5
-rw-r--r--contrib/bmake/unit-tests/directive.exp4
-rw-r--r--contrib/bmake/unit-tests/directive.mk6
-rw-r--r--contrib/bmake/unit-tests/moderrs.exp14
-rw-r--r--contrib/bmake/unit-tests/moderrs.mk16
-rw-r--r--contrib/bmake/unit-tests/opt-debug-file.exp6
-rw-r--r--contrib/bmake/unit-tests/opt-debug-file.mk14
-rw-r--r--contrib/bmake/unit-tests/opt-debug-lint.exp4
-rw-r--r--contrib/bmake/unit-tests/opt-debug-lint.mk6
-rw-r--r--contrib/bmake/unit-tests/opt-jobs-internal.exp18
-rw-r--r--contrib/bmake/unit-tests/parse.exp6
-rw-r--r--contrib/bmake/unit-tests/parse.mk8
-rw-r--r--contrib/bmake/unit-tests/var-op-assign.exp2
-rw-r--r--contrib/bmake/unit-tests/var-op-assign.mk4
-rw-r--r--contrib/bmake/unit-tests/var-op-expand.exp14
-rw-r--r--contrib/bmake/unit-tests/var-op-expand.mk8
-rw-r--r--contrib/bmake/unit-tests/varmisc.exp2
-rw-r--r--contrib/bmake/unit-tests/varmisc.mk4
-rw-r--r--contrib/bmake/unit-tests/varmod-edge.exp4
-rw-r--r--contrib/bmake/unit-tests/varmod-edge.mk6
-rw-r--r--contrib/bmake/unit-tests/varmod-ifelse.exp43
-rw-r--r--contrib/bmake/unit-tests/varmod-ifelse.mk11
-rwxr-xr-xcontrib/bmake/unit-tests/varmod-match-escape.exp14
-rwxr-xr-xcontrib/bmake/unit-tests/varmod-match-escape.mk10
-rw-r--r--contrib/bmake/unit-tests/varmod-match.exp20
-rw-r--r--contrib/bmake/unit-tests/varmod-match.mk28
-rw-r--r--contrib/bmake/unit-tests/varmod-mtime.exp6
-rw-r--r--contrib/bmake/unit-tests/varmod-mtime.mk8
-rw-r--r--contrib/bmake/unit-tests/varmod-order.exp6
-rw-r--r--contrib/bmake/unit-tests/varmod-order.mk8
-rw-r--r--contrib/bmake/unit-tests/varmod-range.exp2
-rw-r--r--contrib/bmake/unit-tests/varmod-range.mk4
-rw-r--r--contrib/bmake/unit-tests/varmod.exp49
-rw-r--r--contrib/bmake/unit-tests/varmod.mk49
-rw-r--r--contrib/bmake/unit-tests/varname-circumflex.exp9
-rw-r--r--contrib/bmake/unit-tests/varname-circumflex.mk47
-rw-r--r--contrib/bmake/unit-tests/varname-vpath.exp8
-rw-r--r--contrib/bmake/unit-tests/varname.exp4
-rw-r--r--contrib/bmake/unit-tests/varname.mk6
-rw-r--r--contrib/bmake/unit-tests/varparse-errors.exp28
-rw-r--r--contrib/bmake/unit-tests/varparse-errors.mk30
-rw-r--r--contrib/bmake/var.c38
-rw-r--r--contrib/bsnmp/lib/snmpclient.c12
-rw-r--r--contrib/bsnmp/lib/snmpclient.h1
-rw-r--r--contrib/bsnmp/lib/snmppriv.h1
-rw-r--r--contrib/bsnmp/snmpd/main.c17
-rw-r--r--contrib/bsnmp/snmpd/trans_lsock.c2
-rw-r--r--contrib/elftoolchain/libelf/elf_open.35
-rw-r--r--contrib/elftoolchain/libelf/gelf_xlatetof.311
-rw-r--r--contrib/less/NEWS10
-rw-r--r--contrib/less/decode.c2
-rw-r--r--contrib/less/help.c2
-rw-r--r--contrib/less/less.h9
-rw-r--r--contrib/less/less.nro2
-rw-r--r--contrib/less/lessecho.nro2
-rw-r--r--contrib/less/lesskey.nro2
-rw-r--r--contrib/less/os.c6
-rw-r--r--contrib/less/version.c4
-rw-r--r--contrib/libbegemot/rpoll.c22
-rw-r--r--contrib/llvm-project/clang/include/clang/Sema/Sema.h9
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp23
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp10
-rw-r--r--contrib/tzcode/localtime.c34
167 files changed, 1392 insertions, 899 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 <sjg@beast.crufty.net>
+
+ * 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 <sjg@beast.crufty.net>
+
+ * 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 <sjg@beast.crufty.net>
+
+ * 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 <sjg@beast.crufty.net>
* 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];
@@ -663,6 +663,13 @@ SetNonblocking(int fd)
}
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)
{
int i;
@@ -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 @@
-/* $NetBSD: main.c,v 1.659 2025/06/13 05:41:36 rillig Exp $ */
+/* $NetBSD: main.c,v 1.661 2025/07/06 07:11:31 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.659 2025/06/13 05:41:36 rillig Exp $");
+MAKE_RCSID("$NetBSD: main.c,v 1.661 2025/07/06 07:11:31 rillig Exp $");
#if defined(MAKE_NATIVE)
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
"The Regents of the University of California. "
@@ -1221,23 +1221,8 @@ InitMaxJobs(void)
if (bogusJflag && !opts.compatMake) {
opts.compatMake = true;
Parse_Error(PARSE_WARNING,
- "internal option \"-J\" in \"%s\" "
- "refers to unopened file descriptors; "
- "falling back to compat mode.\n"
- "\t"
- "To run the target even in -n mode, "
- "add the .MAKE pseudo-source to the target.\n"
- "\t"
- "To run the target in default mode only, "
- "add a ${:D make} marker to a target's command. "
- "(This marker expression expands to an empty string.)\n"
- "\t"
- "To make the sub-make run in compat mode, add -B to "
- "its invocation.\n"
- "\t"
- "To make the sub-make independent from the parent make, "
- "unset the MAKEFLAGS environment variable in the "
- "target's commands.",
+ "Invalid internal option \"-J\" in \"%s\"; "
+ "see the manual page",
curdir);
PrintStackTrace(true);
return;
@@ -1734,11 +1719,10 @@ found:
}
/* populate av for Cmd_Exec and Compat_RunCommand */
-int
-Cmd_Argv(const char *cmd, size_t cmd_len, const char **av, size_t avsz,
+void
+Cmd_Argv(const char *cmd, size_t cmd_len, const char *av[5],
char *cmd_file, size_t cmd_filesz, bool eflag, bool xflag)
{
- int ac = 0;
int cmd_fd = -1;
if (shellPath == NULL)
@@ -1764,23 +1748,19 @@ Cmd_Argv(const char *cmd, size_t cmd_len, const char **av, size_t avsz,
cmd_file[0] = '\0';
}
- if (avsz < 4 || (eflag && avsz < 5))
- return -1;
-
/* The following works for any of the builtin shell specs. */
- av[ac++] = shellPath;
+ *av++ = shellPath;
if (eflag)
- av[ac++] = shellErrFlag;
+ *av++ = shellErrFlag;
if (cmd_fd >= 0) {
if (xflag)
- av[ac++] = "-x";
- av[ac++] = cmd_file;
+ *av++ = "-x";
+ *av++ = cmd_file;
} else {
- av[ac++] = xflag ? "-xc" : "-c";
- av[ac++] = cmd;
+ *av++ = xflag ? "-xc" : "-c";
+ *av++ = cmd;
}
- av[ac] = NULL;
- return ac;
+ *av = NULL;
}
/*
@@ -1790,7 +1770,7 @@ Cmd_Argv(const char *cmd, size_t cmd_len, const char **av, size_t avsz,
char *
Cmd_Exec(const char *cmd, char **error)
{
- const char *args[4]; /* Arguments for invoking the shell */
+ const char *args[5]; /* Arguments for invoking the shell */
int pipefds[2];
int cpid; /* Child PID */
int pid; /* PID from wait() */
@@ -1804,8 +1784,8 @@ Cmd_Exec(const char *cmd, char **error)
DEBUG1(VAR, "Capturing the output of command \"%s\"\n", cmd);
- if (Cmd_Argv(cmd, 0, args, 4, cmd_file, sizeof(cmd_file), false, false) < 0
- || pipe(pipefds) == -1) {
+ Cmd_Argv(cmd, 0, args, cmd_file, sizeof(cmd_file), false, false);
+ if (pipe(pipefds) == -1) {
*error = str_concat3(
"Couldn't create pipe for \"", cmd, "\"");
return bmake_strdup("");
@@ -2083,7 +2063,7 @@ shouldDieQuietly(GNode *gn, int bf)
else if (bf >= 0)
quietly = bf;
else
- quietly = (gn != NULL && (gn->type & OP_MAKE)) ? 1 : 0;
+ quietly = gn != NULL && gn->type & OP_MAKE ? 1 : 0;
}
return quietly != 0;
}
diff --git a/contrib/bmake/make.1 b/contrib/bmake/make.1
index f05653af7e31..de67759290c4 100644
--- a/contrib/bmake/make.1
+++ b/contrib/bmake/make.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 MAKE 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 \&% ,
@@ -2725,6 +2728,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
@@ -2738,6 +2743,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.
@@ -2825,6 +2892,7 @@ portable.
.Sh SEE ALSO
.Xr mkdep 1 ,
.Xr style.Makefile 5
+.\" .Sh STANDARDS
.Sh HISTORY
A
.Nm
@@ -2844,6 +2912,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
@@ -2865,3 +2935,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/make.c b/contrib/bmake/make.c
index 3826c4d4e6a1..811f6e0849c4 100644
--- a/contrib/bmake/make.c
+++ b/contrib/bmake/make.c
@@ -1,4 +1,4 @@
-/* $NetBSD: make.c,v 1.272 2025/05/18 07:02:00 rillig Exp $ */
+/* $NetBSD: make.c,v 1.273 2025/07/06 07:11:31 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -107,7 +107,7 @@
#endif
/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */
-MAKE_RCSID("$NetBSD: make.c,v 1.272 2025/05/18 07:02:00 rillig Exp $");
+MAKE_RCSID("$NetBSD: make.c,v 1.273 2025/07/06 07:11:31 rillig Exp $");
/* Sequence # to detect recursion. */
static unsigned checked_seqno = 1;
@@ -1404,7 +1404,7 @@ Make_MakeParallel(GNodeList *targets)
(void)MakeStartJobs();
}
- errors = Job_Finish();
+ errors = Job_MakeDotEnd();
DEBUG1(MAKE, "done: errors %d\n", errors);
if (errors == 0) {
diff --git a/contrib/bmake/make.h b/contrib/bmake/make.h
index 405f03144b69..6b2b215592dd 100644
--- a/contrib/bmake/make.h
+++ b/contrib/bmake/make.h
@@ -1,4 +1,4 @@
-/* $NetBSD: make.h,v 1.360 2025/06/13 18:31:08 rillig Exp $ */
+/* $NetBSD: make.h,v 1.361 2025/07/06 07:11:31 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -884,7 +884,8 @@ void JobReapChild(pid_t, int, bool);
#endif
/* main.c */
void Main_ParseArgLine(const char *);
-int Cmd_Argv(const char *, size_t, const char **, size_t, char *, size_t, bool, bool);
+void Cmd_Argv(const char *, size_t, const char *[5], char *, size_t,
+ bool, bool);
char *Cmd_Exec(const char *, char **) MAKE_ATTR_USE;
void Var_ExportStackTrace(const char *, const char *);
void Error(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
diff --git a/contrib/bmake/make_malloc.c b/contrib/bmake/make_malloc.c
index d7a735b8b08e..86e339de5dd2 100644
--- a/contrib/bmake/make_malloc.c
+++ b/contrib/bmake/make_malloc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: make_malloc.c,v 1.27 2025/06/12 18:51:05 rillig Exp $ */
+/* $NetBSD: make_malloc.c,v 1.28 2025/06/29 09:37:58 rillig Exp $ */
/*
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
#include "make.h"
-MAKE_RCSID("$NetBSD: make_malloc.c,v 1.27 2025/06/12 18:51:05 rillig Exp $");
+MAKE_RCSID("$NetBSD: make_malloc.c,v 1.28 2025/06/29 09:37:58 rillig Exp $");
#ifndef USE_EMALLOC
@@ -50,6 +50,9 @@ bmake_malloc(size_t len)
if ((p = malloc(len)) == NULL)
enomem();
+#ifdef CLEANUP
+ memset(p, 'Z', len);
+#endif
return p;
}
diff --git a/contrib/bmake/mk/ChangeLog b/contrib/bmake/mk/ChangeLog
index 1822f917a138..db524d2343b6 100644
--- a/contrib/bmake/mk/ChangeLog
+++ b/contrib/bmake/mk/ChangeLog
@@ -1,3 +1,7 @@
+2025-07-04 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * prog.mk: .MADE is a special source not a target!
+
2025-05-28 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20250528
diff --git a/contrib/bmake/mk/prog.mk b/contrib/bmake/mk/prog.mk
index 119645c49859..a7ced7b15d31 100644
--- a/contrib/bmake/mk/prog.mk
+++ b/contrib/bmake/mk/prog.mk
@@ -1,4 +1,4 @@
-# $Id: prog.mk,v 1.45 2024/12/12 19:56:36 sjg Exp $
+# $Id: prog.mk,v 1.46 2025/07/05 16:43:03 sjg Exp $
# should be set properly in sys.mk
_this ?= ${.PARSEFILE:S,bsd.,,}
@@ -27,11 +27,11 @@ CFLAGS+= -mcmodel=medlow
.if ${OBJECT_FMT} == "ELF"
.ifndef LIBCRTBEGIN
LIBCRTBEGIN= ${DESTDIR}/usr/lib/crtbegin.o
-.MADE: ${LIBCRTBEGIN}
+${LIBCRTBEGIN}: .MADE
.endif
.ifndef LIBCRTEND
LIBCRTEND= ${DESTDIR}/usr/lib/crtend.o
-.MADE: ${LIBCRTEND}
+${LIBCRTEND}: .MADE
.endif
_SHLINKER= ${SHLINKDIR}/ld.elf_so
.else
@@ -42,7 +42,7 @@ _SHLINKER= ${SHLINKDIR}/ld.so
.ifndef LIBCRT0
LIBCRT0= ${DESTDIR}/usr/lib/crt0.o
-.MADE: ${LIBCRT0}
+${LIBCRT0}: .MADE
.endif
.endif # NetBSD
diff --git a/contrib/bmake/parse.c b/contrib/bmake/parse.c
index 844d4db207ca..ecc77366d2d7 100644
--- a/contrib/bmake/parse.c
+++ b/contrib/bmake/parse.c
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.752 2025/06/16 18:20:00 rillig Exp $ */
+/* $NetBSD: parse.c,v 1.753 2025/06/28 22:39:27 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -110,7 +110,7 @@
#include "pathnames.h"
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: parse.c,v 1.752 2025/06/16 18:20:00 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.753 2025/06/28 22:39:27 rillig Exp $");
/* Detects a multiple-inclusion guard in a makefile. */
typedef enum {
@@ -954,10 +954,10 @@ InvalidLineType(const char *line, const char *unexpanded_line)
Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"",
(int)(dirend - dirstart), dirstart);
} else if (strcmp(line, unexpanded_line) == 0)
- Parse_Error(PARSE_FATAL, "Invalid line '%s'", line);
+ Parse_Error(PARSE_FATAL, "Invalid line \"%s\"", line);
else
Parse_Error(PARSE_FATAL,
- "Invalid line '%s', expanded to '%s'",
+ "Invalid line \"%s\", expanded to \"%s\"",
unexpanded_line, line);
}
@@ -1063,7 +1063,7 @@ HandleDependencyTargetPath(const char *suffixName,
path = Suff_GetPath(suffixName);
if (path == NULL) {
Parse_Error(PARSE_FATAL,
- "Suffix '%s' not defined (yet)", suffixName);
+ "Suffix \"%s\" not defined (yet)", suffixName);
return false;
}
@@ -1159,7 +1159,7 @@ SkipExtraTargets(char **pp, const char *lstart)
if (warning) {
const char *start = *pp;
cpp_skip_whitespace(&start);
- Parse_Error(PARSE_WARNING, "Extra target '%.*s' ignored",
+ Parse_Error(PARSE_WARNING, "Extra target \"%.*s\" ignored",
(int)(p - start), start);
}
@@ -1446,7 +1446,8 @@ ApplyDependencyTarget(char *name, char *nameEnd, ParseSpecial *inout_special,
if (*inout_special == SP_NOT && *name != '\0')
HandleDependencyTargetMundane(name);
else if (*inout_special == SP_PATH && *name != '.' && *name != '\0')
- Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", name);
+ Parse_Error(PARSE_WARNING, "Extra target \"%s\" ignored",
+ name);
*nameEnd = savedNameEnd;
return true;
@@ -2066,7 +2067,7 @@ ParseInclude(char *directive)
if (*p != '"' && *p != '<') {
Parse_Error(PARSE_FATAL,
- ".include filename must be delimited by '\"' or '<'");
+ ".include filename must be delimited by \"\" or <>");
return;
}
@@ -2078,7 +2079,7 @@ ParseInclude(char *directive)
if (*p != endc) {
Parse_Error(PARSE_FATAL,
- "Unclosed .include filename. '%c' expected", endc);
+ "Unclosed .include filename, \"%c\" expected", endc);
return;
}
diff --git a/contrib/bmake/str.c b/contrib/bmake/str.c
index f705b0deb874..e66cdbc8682e 100644
--- a/contrib/bmake/str.c
+++ b/contrib/bmake/str.c
@@ -1,4 +1,4 @@
-/* $NetBSD: str.c,v 1.105 2024/07/07 07:50:57 rillig Exp $ */
+/* $NetBSD: str.c,v 1.106 2025/06/28 21:09:43 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -71,7 +71,7 @@
#include "make.h"
/* "@(#)str.c 5.8 (Berkeley) 6/1/90" */
-MAKE_RCSID("$NetBSD: str.c,v 1.105 2024/07/07 07:50:57 rillig Exp $");
+MAKE_RCSID("$NetBSD: str.c,v 1.106 2025/06/28 21:09:43 rillig Exp $");
static HashTable interned_strings;
@@ -363,8 +363,11 @@ match_fixed_length:
continue;
}
- if (*pat == '\\') /* match the next character exactly */
+ if (*pat == '\\') { /* match the next character exactly */
pat++;
+ if (*pat == '\0')
+ res.error = "Unfinished backslash at the end";
+ }
if (*pat != *str) {
if (asterisk && str == fixed_str) {
while (*str != '\0' && *str != *pat)
diff --git a/contrib/bmake/unit-tests/Makefile b/contrib/bmake/unit-tests/Makefile
index 618a5959e304..4e639056815a 100644
--- a/contrib/bmake/unit-tests/Makefile
+++ b/contrib/bmake/unit-tests/Makefile
@@ -1,6 +1,6 @@
-# $Id: Makefile,v 1.239 2025/06/15 21:32:16 sjg Exp $
+# $Id: Makefile,v 1.240 2025/06/30 18:40:54 sjg Exp $
#
-# $NetBSD: Makefile,v 1.367 2025/06/13 20:23:16 rillig Exp $
+# $NetBSD: Makefile,v 1.369 2025/06/29 09:40:13 rillig Exp $
#
# Unit tests for make(1)
#
@@ -58,6 +58,7 @@ rm-tmpdir: .NOMETA
# src/tests/usr.bin/make/t_make.sh as well.
#TESTS+= archive
#TESTS+= archive-suffix
+TESTS+= char-005c-reverse-solidus
TESTS+= cmd-errors
TESTS+= cmd-errors-jobs
TESTS+= cmd-errors-lint
@@ -413,6 +414,7 @@ TESTS+= varmod-to-upper
TESTS+= varmod-undefined
TESTS+= varmod-unique
TESTS+= varname
+TESTS+= varname-circumflex
TESTS+= varname-dollar
TESTS+= varname-dot-alltargets
TESTS+= varname-dot-curdir
@@ -541,7 +543,6 @@ TESTS:= ${TESTS:${BROKEN_TESTS:S,^,N,:ts:}}
# Ideas for more tests:
# char-0020-space.mk
-# char-005C-backslash.mk
# escape-cond-str.mk
# escape-cond-func-arg.mk
# escape-varmod.mk
diff --git a/contrib/bmake/unit-tests/char-005c-reverse-solidus.exp b/contrib/bmake/unit-tests/char-005c-reverse-solidus.exp
new file mode 100644
index 000000000000..351ef95040e5
--- /dev/null
+++ b/contrib/bmake/unit-tests/char-005c-reverse-solidus.exp
@@ -0,0 +1,13 @@
+make: char-005c-reverse-solidus.mk:57: Unclosed expression, expecting "}" for modifier "Mx\}"
+ while evaluating variable "BACKSLASH" with value ""
+make: char-005c-reverse-solidus.mk:64: Unclosed expression, expecting "}" for modifier "Mx\\}"
+ while evaluating variable "BACKSLASH" with value ""
+make: char-005c-reverse-solidus.mk:71: Unclosed expression, expecting "}" for modifier "Mx\\\\\\\\}"
+ while evaluating variable "BACKSLASH" with value ""
+make: char-005c-reverse-solidus.mk:100: Unfinished backslash at the end in pattern "\" of modifier ":M"
+ while evaluating variable "BACKSLASH" with value "\"
+make: char-005c-reverse-solidus.mk:111: Unclosed expression, expecting "}" for modifier "M${:U\\\\}} != "\\""
+ while evaluating variable "BACKSLASH" with value ""
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
+exit status 1
diff --git a/contrib/bmake/unit-tests/char-005c-reverse-solidus.mk b/contrib/bmake/unit-tests/char-005c-reverse-solidus.mk
new file mode 100644
index 000000000000..7a151ac46322
--- /dev/null
+++ b/contrib/bmake/unit-tests/char-005c-reverse-solidus.mk
@@ -0,0 +1,131 @@
+# $NetBSD: char-005c-reverse-solidus.mk,v 1.2 2025/06/29 11:27:21 rillig Exp $
+#
+# Tests for the character U+005C "REVERSE SOLIDUS".
+#
+# See also:
+# TODO
+# TODO
+# TODO
+
+# TODO: Where is this character used normally?
+# TODO: What are the edge cases?
+
+# TODO: escape '#' in lines
+# TODO: escape '#' in comments
+# TODO: escape ':' in modifiers
+# TODO: escape any character in condition strings
+
+# begin https://gnats.netbsd.org/46139
+
+# Too see the details of parsing, uncomment the following line.
+#.MAKEFLAGS: -dcpv
+
+# This backslash is treated as a line continuation.
+# It does not end up in the variable value.
+LINE_CONTINUATION=foo\
+# This line is still part of the variable assignment
+.if ${LINE_CONTINUATION:C,[^a-z],<>,gW} != "foo"
+. error
+.endif
+
+# The variable value contains two backslashes.
+TWO_BACKSLASHES_AT_EOL=foo\\
+.if ${TWO_BACKSLASHES_AT_EOL:C,[^a-z],<>,gW} != "foo<><>"
+. error
+.endif
+
+TRAILING_WHITESPACE=foo\ # trailing space
+.if ${TRAILING_WHITESPACE:C,[^a-z],<>,gW} != "foo<><>"
+. error
+.endif
+
+# The simplest was to produce a single backslash is the :U modifier.
+BACKSLASH= ${:U\\}
+.if ${BACKSLASH} != "\\"
+. error
+.endif
+BACKSLASH_C= ${:U1:C,.,\\,}
+.if ${BACKSLASH_C} != "\\"
+. error
+.endif
+
+# expect+5: Unclosed expression, expecting "}" for modifier "Mx\}"
+# At the point where the unclosed expression is detected, the ":M" modifier
+# has been applied to the expression. Its pattern is "x}", which doesn't
+# match the single backslash.
+# expect: while evaluating variable "BACKSLASH" with value ""
+.if ${BACKSLASH:Mx\}
+. error
+.else
+. error
+.endif
+
+# expect+1: Unclosed expression, expecting "}" for modifier "Mx\\}"
+.if ${BACKSLASH:Mx\\}
+. error
+.else
+. error
+.endif
+
+# expect+1: Unclosed expression, expecting "}" for modifier "Mx\\\\\\\\}"
+.if ${BACKSLASH:Mx\\\\\\\\}
+. error
+.else
+. error
+.endif
+
+# Adding more text after the backslash adds to the pattern, as the backslash
+# serves to escape the ":" that is otherwise used to separate the modifiers.
+# The result is a single ":M" modifier with the pattern "x:Nzzz".
+.if ${BACKSLASH:Mx\:Nzzz} != ""
+. error
+.endif
+
+# The pattern ends up as "x\:Nzzz". Only the sequence "\:" is unescaped, all
+# others, including "\\", are left as-is.
+.if ${BACKSLASH:Mx\\:Nzzz} != ""
+. error
+.endif
+
+# The pattern for the ":M" modifier ends up as "x\\\\\\\:Nzzz". Only the
+# sequence "\:" is unescaped, all others, including "\\", are left as-is.
+.if ${BACKSLASH:Mx\\\\\\\\:Nzzz} != ""
+. error
+.endif
+
+# The ":M" modifier is parsed differently than the other modifiers. To
+# circumvent the peculiarities of that parser, the pattern can be passed via
+# an expression. There, the usual escaping rules for modifiers apply.
+# expect+1: Unfinished backslash at the end in pattern "\" of modifier ":M"
+.if ${BACKSLASH:M${BACKSLASH}} != "\\"
+. error
+.else
+. error
+.endif
+
+# Trying to bypass the parser by using a direct expression doesn't work, as
+# the parser for the ":M" modifier does not parse the subexpression like in
+# all other places, but instead counts the braces and tries to decode the
+# escaping, which fails in this case.
+# expect+1: Unclosed expression, expecting "}" for modifier "M${:U\\\\}} != "\\""
+.if ${BACKSLASH:M${:U\\\\}} != "\\"
+. error
+.else
+. error
+.endif
+
+# Matching a backslash with the pattern matching characters works.
+.if ${BACKSLASH:M?} != "\\"
+. error
+.endif
+.if ${BACKSLASH:M*} != "\\"
+. error
+.endif
+.if ${BACKSLASH:M[Z-a]} != "\\"
+. error
+.endif
+.if ${BACKSLASH:M[\\]} != "\\"
+. error
+.endif
+
+# end https://gnats.netbsd.org/46139
diff --git a/contrib/bmake/unit-tests/check-expect.lua b/contrib/bmake/unit-tests/check-expect.lua
index 218056fbc021..2f3adf49baa6 100644
--- a/contrib/bmake/unit-tests/check-expect.lua
+++ b/contrib/bmake/unit-tests/check-expect.lua
@@ -1,5 +1,5 @@
#! /usr/bin/lua
--- $NetBSD: check-expect.lua,v 1.13 2025/04/13 09:29:32 rillig Exp $
+-- $NetBSD: check-expect.lua,v 1.17 2025/07/01 05:03:18 rillig Exp $
--[[
@@ -9,29 +9,32 @@ Check that the various 'expect' comments in the .mk files produce the
expected text in the corresponding .exp file.
# expect: <line>
- All of these lines must occur in the .exp file, in the same order as
- in the .mk file.
-
-# expect-reset
- Search the following 'expect:' comments from the top of the .exp
- file again.
+ Each <line> must occur in the .exp file.
+ The order in the .mk file must be the same as in the .exp file.
# expect[+-]offset: <message>
- Each message must occur in the .exp file and refer back to the
+ Each <message> must occur in the .exp file and refer back to the
source line in the .mk file.
+ Each such line in the .exp file must have a corresponding expect line
+ in the .mk file.
+ The order in the .mk file must be the same as in the .exp file.
+
+# expect-reset
+ Search the following "expect:" and "expect[+-]offset:" comments
+ from the top of the .exp file again.
# expect-not: <substring>
- The substring must not occur as part of any line of the .exp file.
+ The <substring> must not occur as part of any line in the .exp file.
# expect-not-matches: <pattern>
- The pattern (see https://lua.org/manual/5.4/manual.html#6.4.1)
- must not occur as part of any line of the .exp file.
+ The <pattern> (see https://lua.org/manual/5.4/manual.html#6.4.1)
+ must not occur as part of any line in the .exp file.
]]
local had_errors = false
---@param fmt string
-function print_error(fmt, ...)
+local function print_error(fmt, ...)
print(fmt:format(...))
had_errors = true
end
@@ -42,7 +45,9 @@ local function load_lines(fname)
local lines = {}
local f = io.open(fname, "r")
- if f == nil then return nil end
+ if f == nil then
+ return nil
+ end
for line in f:lines() do
table.insert(lines, line)
@@ -53,135 +58,129 @@ local function load_lines(fname)
end
----@param exp_lines string[]
-local function collect_lineno_diagnostics(exp_lines)
- ---@type table<string, string[]>
- local by_location = {}
+--- @shape ExpLine
+--- @field filename string | nil
+--- @field lineno number | nil
+--- @field text string
- for _, line in ipairs(exp_lines) do
- ---@type string | nil, string, string
- local l_fname, l_lineno, l_msg =
- line:match('^make: ([^:]+):(%d+): (.*)')
- if l_fname ~= nil then
- local location = ("%s:%d"):format(l_fname, l_lineno)
- if by_location[location] == nil then
- by_location[location] = {}
- end
- table.insert(by_location[location], l_msg)
+
+--- @param lines string[]
+--- @return ExpLine[]
+local function parse_exp(lines)
+ local exp_lines = {}
+ for _, line in ipairs(lines) do
+ local l_filename, l_lineno, l_text =
+ line:match('^make: ([^:]+%.mk):(%d+):%s+(.*)')
+ if not l_filename then
+ l_text = line
end
+ l_text = l_text:gsub("^%s+", ""):gsub("%s+$", "")
+ table.insert(exp_lines, {
+ filename = l_filename,
+ lineno = tonumber(l_lineno),
+ text = l_text,
+ })
end
-
- return by_location
+ return exp_lines
end
-
-local function missing(by_location)
- ---@type {filename: string, lineno: number, location: string, message: string}[]
- local missing_expectations = {}
-
- for location, messages in pairs(by_location) do
- for _, message in ipairs(messages) do
- if message ~= "" and location:find(".mk:") then
- local filename, lineno = location:match("^(%S+):(%d+)$")
- table.insert(missing_expectations, {
- filename = filename,
- lineno = tonumber(lineno),
- location = location,
- message = message
- })
- end
+---@param exp_lines ExpLine[]
+local function detect_missing_expect_lines(exp_fname, exp_lines, s, e)
+ for i = s, e do
+ local exp_line = exp_lines[i]
+ if exp_line.filename then
+ print_error("error: %s:%d requires in %s:%d: # expect+1: %s",
+ exp_fname, i, exp_line.filename, exp_line.lineno, exp_line.text)
end
end
- table.sort(missing_expectations, function(a, b)
- if a.filename ~= b.filename then
- return a.filename < b.filename
- end
- return a.lineno < b.lineno
- end)
- return missing_expectations
end
-
local function check_mk(mk_fname)
local exp_fname = mk_fname:gsub("%.mk$", ".exp")
local mk_lines = load_lines(mk_fname)
- local exp_lines = load_lines(exp_fname)
- if exp_lines == nil then return end
- local by_location = collect_lineno_diagnostics(exp_lines)
- local prev_expect_line = 0
+ local exp_raw_lines = load_lines(exp_fname)
+ if exp_raw_lines == nil then
+ return
+ end
+ local exp_lines = parse_exp(exp_raw_lines)
+
+ local exp_it = 1
for mk_lineno, mk_line in ipairs(mk_lines) do
- for text in mk_line:gmatch("#%s*expect%-not:%s*(.*)") do
- local i = 1
- while i <= #exp_lines and not exp_lines[i]:find(text, 1, true) do
- i = i + 1
- end
- if i <= #exp_lines then
- print_error("error: %s:%d: %s must not contain '%s'",
- mk_fname, mk_lineno, exp_fname, text)
+ local function match(pattern, action)
+ local _, n = mk_line:gsub(pattern, action)
+ if n > 0 then
+ match = function() end
end
end
- for text in mk_line:gmatch("#%s*expect%-not%-matches:%s*(.*)") do
- local i = 1
- while i <= #exp_lines and not exp_lines[i]:find(text) do
- i = i + 1
+ match("^#%s+expect%-not:%s*(.*)", function(text)
+ for exp_lineno, exp_line in ipairs(exp_lines) do
+ if exp_line.text:find(text, 1, true) then
+ print_error("error: %s:%d: %s:%d must not contain '%s'",
+ mk_fname, mk_lineno, exp_fname, exp_lineno, text)
+ end
end
- if i <= #exp_lines then
- print_error("error: %s:%d: %s must not match '%s'",
- mk_fname, mk_lineno, exp_fname, text)
+ end)
+
+ match("^#%s+expect%-not%-matches:%s*(.*)", function(pattern)
+ for exp_lineno, exp_line in ipairs(exp_lines) do
+ if exp_line.text:find(pattern) then
+ print_error("error: %s:%d: %s:%d must not match '%s'",
+ mk_fname, mk_lineno, exp_fname, exp_lineno, pattern)
+ end
end
- end
+ end)
- for text in mk_line:gmatch("#%s*expect:%s*(.*)") do
- local i = prev_expect_line
- -- As of 2022-04-15, some lines in the .exp files contain trailing
- -- whitespace. If possible, this should be avoided by rewriting the
- -- debug logging. When done, the trailing gsub can be removed.
- -- See deptgt-phony.exp lines 14 and 15.
- while i < #exp_lines and text ~= exp_lines[i + 1]:gsub("^%s*", ""):gsub("%s*$", "") do
+ match("^#%s+expect:%s*(.*)", function(text)
+ local i = exp_it
+ while i <= #exp_lines and text ~= exp_lines[i].text do
i = i + 1
end
- if i < #exp_lines then
- prev_expect_line = i + 1
+ if i <= #exp_lines then
+ detect_missing_expect_lines(exp_fname, exp_lines, exp_it, i - 1)
+ exp_lines[i].text = ""
+ exp_it = i + 1
else
print_error("error: %s:%d: '%s:%d+' must contain '%s'",
- mk_fname, mk_lineno, exp_fname, prev_expect_line + 1, text)
+ mk_fname, mk_lineno, exp_fname, exp_it, text)
end
- end
- if mk_line:match("^#%s*expect%-reset$") then
- prev_expect_line = 0
- end
+ end)
- ---@param text string
- for offset, text in mk_line:gmatch("#%s*expect([+%-]%d+):%s*(.*)") do
- local location = ("%s:%d"):format(mk_fname, mk_lineno + tonumber(offset))
-
- local found = false
- if by_location[location] ~= nil then
- for i, message in ipairs(by_location[location]) do
- if message == text then
- by_location[location][i] = ""
- found = true
- break
- elseif message ~= "" then
- print_error("error: %s:%d: out-of-order '%s'",
- mk_fname, mk_lineno, message)
- end
- end
+ match("^#%s+expect%-reset$", function()
+ exp_it = 1
+ end)
+
+ match("^#%s+expect([+%-]%d+):%s*(.*)", function(offset, text)
+ local msg_lineno = mk_lineno + tonumber(offset)
+
+ local i = exp_it
+ while i <= #exp_lines and text ~= exp_lines[i].text do
+ i = i + 1
end
- if not found then
- print_error("error: %s:%d: %s must contain '%s'",
- mk_fname, mk_lineno, exp_fname, text)
+ if i <= #exp_lines and exp_lines[i].lineno == msg_lineno then
+ detect_missing_expect_lines(exp_fname, exp_lines, exp_it, i - 1)
+ exp_lines[i].text = ""
+ exp_it = i + 1
+ elseif i <= #exp_lines then
+ print_error("error: %s:%d: expect%+d must be expect%+d",
+ mk_fname, mk_lineno, tonumber(offset),
+ exp_lines[i].lineno - mk_lineno)
+ else
+ print_error("error: %s:%d: %s:%d+ must contain '%s'",
+ mk_fname, mk_lineno, exp_fname, exp_it, text)
end
- end
- end
+ end)
+
+ match("^#%s+expect[+%-:]", function()
+ print_error("error: %s:%d: invalid \"expect\" line: %s",
+ mk_fname, mk_lineno, mk_line)
+ end)
- for _, m in ipairs(missing(by_location)) do
- print_error("missing: %s: # expect+1: %s", m.location, m.message)
end
+ detect_missing_expect_lines(exp_fname, exp_lines, exp_it, #exp_lines)
end
for _, fname in ipairs(arg) do
diff --git a/contrib/bmake/unit-tests/cmd-errors-jobs.exp b/contrib/bmake/unit-tests/cmd-errors-jobs.exp
index bd3ae1e51332..3be1bb9b0773 100644
--- a/contrib/bmake/unit-tests/cmd-errors-jobs.exp
+++ b/contrib/bmake/unit-tests/cmd-errors-jobs.exp
@@ -11,7 +11,7 @@ make: Unclosed variable "UNCLOSED"
in command ": unexpected $@-${UNCLOSED"
in target "parse-error-unclosed-expression"
in make[1] in directory "<curdir>"
-make: Unclosed expression, expecting '}'
+make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": unexpected $@-${UNCLOSED:"
in target "parse-error-unclosed-modifier"
@@ -28,7 +28,7 @@ make: Unclosed variable "UNCLOSED"
in command ": unexpected $@-${UNCLOSED"
in target "parse-error-unclosed-expression"
in make[1] in directory "<curdir>"
-make: Unclosed expression, expecting '}'
+make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": unexpected $@-${UNCLOSED:"
in target "parse-error-unclosed-modifier"
diff --git a/contrib/bmake/unit-tests/cmd-errors-jobs.mk b/contrib/bmake/unit-tests/cmd-errors-jobs.mk
index a29883fc6676..f6261d6ad1a8 100644
--- a/contrib/bmake/unit-tests/cmd-errors-jobs.mk
+++ b/contrib/bmake/unit-tests/cmd-errors-jobs.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cmd-errors-jobs.mk,v 1.15 2025/03/29 19:08:52 rillig Exp $
+# $NetBSD: cmd-errors-jobs.mk,v 1.16 2025/06/28 22:39:28 rillig Exp $
#
# Demonstrate how errors in expressions affect whether the commands
# are actually executed in jobs mode.
@@ -50,11 +50,11 @@ parse-error-unknown-modifier:
# expect-not-matches: ^: unexpected
# expect: make: Unclosed variable "UNCLOSED"
# expect: in command ": unexpected $@-${UNCLOSED"
-# expect: make: Unclosed expression, expecting '}'
+# expect: make: Unclosed expression, expecting "}"
# expect: make: Unknown modifier ":Z"
# expect: end parse-error-direct with status 2
# expect: make: Unclosed variable "UNCLOSED"
-# expect: make: Unclosed expression, expecting '}'
+# expect: make: Unclosed expression, expecting "}"
# expect: make: Unknown modifier ":Z"
# expect: end parse-error-indirect with status 2
diff --git a/contrib/bmake/unit-tests/cmd-errors-lint.exp b/contrib/bmake/unit-tests/cmd-errors-lint.exp
index ec7336f618b8..b08a65ff96dc 100644
--- a/contrib/bmake/unit-tests/cmd-errors-lint.exp
+++ b/contrib/bmake/unit-tests/cmd-errors-lint.exp
@@ -2,7 +2,7 @@
make: Unclosed variable "UNCLOSED"
in command ": $@ ${UNCLOSED"
in target "unclosed-expression"
-make: Unclosed expression, expecting '}'
+make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": $@ ${UNCLOSED:"
in target "unclosed-modifier"
diff --git a/contrib/bmake/unit-tests/cmd-errors-lint.mk b/contrib/bmake/unit-tests/cmd-errors-lint.mk
index eb2ec1171545..455ef2c0cfe7 100644
--- a/contrib/bmake/unit-tests/cmd-errors-lint.mk
+++ b/contrib/bmake/unit-tests/cmd-errors-lint.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cmd-errors-lint.mk,v 1.7 2025/03/29 19:08:52 rillig Exp $
+# $NetBSD: cmd-errors-lint.mk,v 1.8 2025/06/28 22:39:28 rillig Exp $
#
# Demonstrate how errors in expressions affect whether the commands
# are actually executed.
@@ -19,7 +19,7 @@ unclosed-expression:
: $@ ${UNCLOSED
unclosed-modifier:
-# expect: make: Unclosed expression, expecting '}'
+# expect: make: Unclosed expression, expecting "}"
# expect-not: : unclosed-modifier
: $@ ${UNCLOSED:
diff --git a/contrib/bmake/unit-tests/cmd-errors.exp b/contrib/bmake/unit-tests/cmd-errors.exp
index 62da47ff42c5..2916d423029e 100644
--- a/contrib/bmake/unit-tests/cmd-errors.exp
+++ b/contrib/bmake/unit-tests/cmd-errors.exp
@@ -2,7 +2,7 @@
make: Unclosed variable "UNCLOSED"
in command ": $@-${UNCLOSED"
in target "unclosed-expression"
-make: Unclosed expression, expecting '}'
+make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": $@-${UNCLOSED:"
in target "unclosed-modifier"
diff --git a/contrib/bmake/unit-tests/cmd-errors.mk b/contrib/bmake/unit-tests/cmd-errors.mk
index 8766b6a856c7..52e314c5bd38 100644
--- a/contrib/bmake/unit-tests/cmd-errors.mk
+++ b/contrib/bmake/unit-tests/cmd-errors.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cmd-errors.mk,v 1.12 2025/03/29 19:08:52 rillig Exp $
+# $NetBSD: cmd-errors.mk,v 1.13 2025/06/28 22:39:28 rillig Exp $
#
# Demonstrate how errors in expressions affect whether the commands
# are actually executed in compat mode.
@@ -17,7 +17,7 @@ unclosed-expression:
: $@-${UNCLOSED
unclosed-modifier:
-# expect: make: Unclosed expression, expecting '}'
+# expect: make: Unclosed expression, expecting "}"
# expect-not: : unclosed-modifier-
: $@-${UNCLOSED:
diff --git a/contrib/bmake/unit-tests/cmdline-undefined.exp b/contrib/bmake/unit-tests/cmdline-undefined.exp
index 12fc45e50822..ae0b35dac420 100644
--- a/contrib/bmake/unit-tests/cmdline-undefined.exp
+++ b/contrib/bmake/unit-tests/cmdline-undefined.exp
@@ -1,17 +1,17 @@
The = assignment operator
-make: cmdline-undefined.mk:31: From the command line: Undefined is .
-make: cmdline-undefined.mk:34: From .MAKEFLAGS '=': Undefined is .
-make: cmdline-undefined.mk:37: From .MAKEFLAGS ':=': Undefined is .
-make: cmdline-undefined.mk:43: From the command line: Undefined is now defined.
-make: cmdline-undefined.mk:46: From .MAKEFLAGS '=': Undefined is now defined.
+make: cmdline-undefined.mk:41: From the command line: Undefined is .
+make: cmdline-undefined.mk:42: From .MAKEFLAGS '=': Undefined is .
+make: cmdline-undefined.mk:43: From .MAKEFLAGS ':=': Undefined is .
+make: cmdline-undefined.mk:47: From the command line: Undefined is now defined.
+make: cmdline-undefined.mk:48: From .MAKEFLAGS '=': Undefined is now defined.
make: cmdline-undefined.mk:49: From .MAKEFLAGS ':=': Undefined is now defined.
The := assignment operator
-make: cmdline-undefined.mk:31: From the command line: Undefined is .
-make: cmdline-undefined.mk:34: From .MAKEFLAGS '=': Undefined is .
-make: cmdline-undefined.mk:37: From .MAKEFLAGS ':=': Undefined is .
-make: cmdline-undefined.mk:43: From the command line: Undefined is now defined.
-make: cmdline-undefined.mk:46: From .MAKEFLAGS '=': Undefined is now defined.
+make: cmdline-undefined.mk:41: From the command line: Undefined is .
+make: cmdline-undefined.mk:42: From .MAKEFLAGS '=': Undefined is .
+make: cmdline-undefined.mk:43: From .MAKEFLAGS ':=': Undefined is .
+make: cmdline-undefined.mk:47: From the command line: Undefined is now defined.
+make: cmdline-undefined.mk:48: From .MAKEFLAGS '=': Undefined is now defined.
make: cmdline-undefined.mk:49: From .MAKEFLAGS ':=': Undefined is now defined.
exit status 0
diff --git a/contrib/bmake/unit-tests/cmdline-undefined.mk b/contrib/bmake/unit-tests/cmdline-undefined.mk
index e7c0400ad1e1..2deb944b1fab 100644
--- a/contrib/bmake/unit-tests/cmdline-undefined.mk
+++ b/contrib/bmake/unit-tests/cmdline-undefined.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cmdline-undefined.mk,v 1.5 2024/04/23 22:51:28 rillig Exp $
+# $NetBSD: cmdline-undefined.mk,v 1.6 2025/06/30 21:44:39 rillig Exp $
#
# Tests for undefined variables in expressions in the command line.
@@ -8,6 +8,12 @@ all:
# (which probably occurs rarely in practice, if at all), but their
# variable value is not expanded, as usual.
#
+# expect+30: From the command line: Undefined is .
+# expect+30: From .MAKEFLAGS '=': Undefined is .
+# expect+30: From .MAKEFLAGS ':=': Undefined is .
+# expect+33: From the command line: Undefined is now defined.
+# expect+33: From .MAKEFLAGS '=': Undefined is now defined.
+# expect+33: From .MAKEFLAGS ':=': Undefined is now defined.
@echo 'The = assignment operator'
@${.MAKE} -f ${MAKEFILE} print-undefined \
CMDLINE='Undefined is $${UNDEFINED}.'
@@ -16,6 +22,12 @@ all:
# The interesting case is using the ':=' assignment operator, which
# expands its right-hand side. But only those variables that are
# defined.
+# expect+16: From the command line: Undefined is .
+# expect+16: From .MAKEFLAGS '=': Undefined is .
+# expect+16: From .MAKEFLAGS ':=': Undefined is .
+# expect+19: From the command line: Undefined is now defined.
+# expect+19: From .MAKEFLAGS '=': Undefined is now defined.
+# expect+19: From .MAKEFLAGS ':=': Undefined is now defined.
@echo 'The := assignment operator'
@${.MAKE} -f ${MAKEFILE} print-undefined \
CMDLINE:='Undefined is $${UNDEFINED}.'
@@ -26,26 +38,14 @@ all:
.MAKEFLAGS: MAKEFLAGS_ASSIGN='Undefined is $${UNDEFINED}.'
.MAKEFLAGS: MAKEFLAGS_SUBST:='Undefined is $${UNDEFINED}.'
-# expect+2: From the command line: Undefined is .
-# expect+1: From the command line: Undefined is .
.info From the command line: ${CMDLINE}
-# expect+2: From .MAKEFLAGS '=': Undefined is .
-# expect+1: From .MAKEFLAGS '=': Undefined is .
.info From .MAKEFLAGS '=': ${MAKEFLAGS_ASSIGN}
-# expect+2: From .MAKEFLAGS ':=': Undefined is .
-# expect+1: From .MAKEFLAGS ':=': Undefined is .
.info From .MAKEFLAGS ':=': ${MAKEFLAGS_SUBST}
UNDEFINED?= now defined
-# expect+2: From the command line: Undefined is now defined.
-# expect+1: From the command line: Undefined is now defined.
.info From the command line: ${CMDLINE}
-# expect+2: From .MAKEFLAGS '=': Undefined is now defined.
-# expect+1: From .MAKEFLAGS '=': Undefined is now defined.
.info From .MAKEFLAGS '=': ${MAKEFLAGS_ASSIGN}
-# expect+2: From .MAKEFLAGS ':=': Undefined is now defined.
-# expect+1: From .MAKEFLAGS ':=': Undefined is now defined.
.info From .MAKEFLAGS ':=': ${MAKEFLAGS_SUBST}
print-undefined:
diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp
index 1a386d53dbef..81c73d887c18 100644
--- a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp
+++ b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp
@@ -1,5 +1,5 @@
-make: cond-cmp-numeric-eq.mk:68: Malformed conditional '!(12345 = 12345)'
-make: cond-cmp-numeric-eq.mk:76: Malformed conditional '!(12345 === 12345)'
+make: cond-cmp-numeric-eq.mk:68: Malformed conditional "!(12345 = 12345)"
+make: cond-cmp-numeric-eq.mk:76: Malformed conditional "!(12345 === 12345)"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk
index a8630cb37f1f..ea60f6f7b18d 100755
--- a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk
+++ b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-cmp-numeric-eq.mk,v 1.8 2024/08/06 18:00:16 rillig Exp $
+# $NetBSD: cond-cmp-numeric-eq.mk,v 1.9 2025/06/28 22:39:28 rillig Exp $
#
# Tests for numeric comparisons with the == operator in .if conditions.
@@ -64,7 +64,7 @@
.endif
# There is no = operator for numbers.
-# expect+1: Malformed conditional '!(12345 = 12345)'
+# expect+1: Malformed conditional "!(12345 = 12345)"
.if !(12345 = 12345)
. error
.else
@@ -72,7 +72,7 @@
.endif
# There is no === operator for numbers either.
-# expect+1: Malformed conditional '!(12345 === 12345)'
+# expect+1: Malformed conditional "!(12345 === 12345)"
.if !(12345 === 12345)
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric.exp b/contrib/bmake/unit-tests/cond-cmp-numeric.exp
index 0945bef72300..2959ad99716c 100644
--- a/contrib/bmake/unit-tests/cond-cmp-numeric.exp
+++ b/contrib/bmake/unit-tests/cond-cmp-numeric.exp
@@ -1,15 +1,15 @@
CondParser_Eval: !(${:UINF} > 1e100)
-make: cond-cmp-numeric.mk:15: Comparison with '>' requires both operands 'INF' and '1e100' to be numeric
+make: cond-cmp-numeric.mk:15: Comparison with ">" requires both operands "INF" and "1e100" to be numeric
CondParser_Eval: ${:UNaN} > NaN
-make: cond-cmp-numeric.mk:21: Comparison with '>' requires both operands 'NaN' and 'NaN' to be numeric
+make: cond-cmp-numeric.mk:21: Comparison with ">" requires both operands "NaN" and "NaN" to be numeric
CondParser_Eval: !(${:UNaN} == NaN)
Comparing "NaN" == "NaN"
CondParser_Eval: 123 ! 123
-make: cond-cmp-numeric.mk:38: Malformed conditional '123 ! 123'
+make: cond-cmp-numeric.mk:38: Malformed conditional "123 ! 123"
CondParser_Eval: ${:U 123} < 124
Comparing 123.000000 < 124.000000
CondParser_Eval: ${:U123 } < 124
-make: cond-cmp-numeric.mk:54: Comparison with '<' requires both operands '123 ' and '124' to be numeric
+make: cond-cmp-numeric.mk:54: Comparison with "<" requires both operands "123 " and "124" to be numeric
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric.mk b/contrib/bmake/unit-tests/cond-cmp-numeric.mk
index 63a3bff8d560..abe5cc4cce9c 100644
--- a/contrib/bmake/unit-tests/cond-cmp-numeric.mk
+++ b/contrib/bmake/unit-tests/cond-cmp-numeric.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-cmp-numeric.mk,v 1.8 2024/08/06 18:00:16 rillig Exp $
+# $NetBSD: cond-cmp-numeric.mk,v 1.9 2025/06/28 22:39:28 rillig Exp $
#
# Tests for numeric comparisons in .if conditions.
#
@@ -11,13 +11,13 @@
# Even if strtod(3) parses "INF" as +Infinity, make does not accept this
# since it is not really a number; see TryParseNumber.
-# expect+1: Comparison with '>' requires both operands 'INF' and '1e100' to be numeric
+# expect+1: Comparison with ">" requires both operands "INF" and "1e100" to be numeric
.if !(${:UINF} > 1e100)
. error
.endif
# Neither is NaN a number; see TryParseNumber.
-# expect+1: Comparison with '>' requires both operands 'NaN' and 'NaN' to be numeric
+# expect+1: Comparison with ">" requires both operands "NaN" and "NaN" to be numeric
.if ${:UNaN} > NaN
. error
.endif
@@ -34,7 +34,7 @@
# whether the operator is valid, leaving the rest of the work to the
# evaluation functions EvalCompareNum and EvalCompareStr. Ensure that this
# parse error is properly reported.
-# expect+1: Malformed conditional '123 ! 123'
+# expect+1: Malformed conditional "123 ! 123"
.if 123 ! 123
. error
.else
@@ -50,7 +50,7 @@
# Trailing spaces are NOT allowed for numbers.
# See EvalCompare and TryParseNumber.
-# expect+1: Comparison with '<' requires both operands '123 ' and '124' to be numeric
+# expect+1: Comparison with "<" requires both operands "123 " and "124" to be numeric
.if ${:U123 } < 124
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-cmp-string.exp b/contrib/bmake/unit-tests/cond-cmp-string.exp
index b55f30182442..8291d5300c3b 100644
--- a/contrib/bmake/unit-tests/cond-cmp-string.exp
+++ b/contrib/bmake/unit-tests/cond-cmp-string.exp
@@ -1,11 +1,11 @@
-make: cond-cmp-string.mk:19: Malformed conditional 'str != str'
-make: cond-cmp-string.mk:44: Malformed conditional '"string" != "str""ing"'
-make: cond-cmp-string.mk:52: Malformed conditional '!("value" = "value")'
-make: cond-cmp-string.mk:60: Malformed conditional '!("value" === "value")'
-make: cond-cmp-string.mk:118: Comparison with '<' requires both operands 'string' and 'string' to be numeric
-make: cond-cmp-string.mk:126: Comparison with '<=' requires both operands 'string' and 'string' to be numeric
-make: cond-cmp-string.mk:134: Comparison with '>' requires both operands 'string' and 'string' to be numeric
-make: cond-cmp-string.mk:142: Comparison with '>=' requires both operands 'string' and 'string' to be numeric
+make: cond-cmp-string.mk:19: Malformed conditional "str != str"
+make: cond-cmp-string.mk:44: Malformed conditional ""string" != "str""ing""
+make: cond-cmp-string.mk:52: Malformed conditional "!("value" = "value")"
+make: cond-cmp-string.mk:60: Malformed conditional "!("value" === "value")"
+make: cond-cmp-string.mk:118: Comparison with "<" requires both operands "string" and "string" to be numeric
+make: cond-cmp-string.mk:126: Comparison with "<=" requires both operands "string" and "string" to be numeric
+make: cond-cmp-string.mk:134: Comparison with ">" requires both operands "string" and "string" to be numeric
+make: cond-cmp-string.mk:142: Comparison with ">=" requires both operands "string" and "string" to be numeric
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-cmp-string.mk b/contrib/bmake/unit-tests/cond-cmp-string.mk
index a913750a017f..56427bda11d0 100644
--- a/contrib/bmake/unit-tests/cond-cmp-string.mk
+++ b/contrib/bmake/unit-tests/cond-cmp-string.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-cmp-string.mk,v 1.20 2024/08/06 18:00:16 rillig Exp $
+# $NetBSD: cond-cmp-string.mk,v 1.21 2025/06/28 22:39:28 rillig Exp $
#
# Tests for string comparisons in .if conditions.
@@ -15,7 +15,7 @@
# The left-hand side of the comparison must be enclosed in quotes.
# This one is not enclosed in quotes and thus generates an error message.
-# expect+1: Malformed conditional 'str != str'
+# expect+1: Malformed conditional "str != str"
.if str != str
. error
.endif
@@ -40,7 +40,7 @@
# It is not possible to concatenate two string literals to form a single
# string. In C, Python and the shell this is possible, but not in make.
-# expect+1: Malformed conditional '"string" != "str""ing"'
+# expect+1: Malformed conditional ""string" != "str""ing""
.if "string" != "str""ing"
. error
.else
@@ -48,7 +48,7 @@
.endif
# There is no = operator for strings.
-# expect+1: Malformed conditional '!("value" = "value")'
+# expect+1: Malformed conditional "!("value" = "value")"
.if !("value" = "value")
. error
.else
@@ -56,7 +56,7 @@
.endif
# There is no === operator for strings either.
-# expect+1: Malformed conditional '!("value" === "value")'
+# expect+1: Malformed conditional "!("value" === "value")"
.if !("value" === "value")
. error
.else
@@ -114,7 +114,7 @@
.endif
# Strings cannot be compared relationally, only for equality.
-# expect+1: Comparison with '<' requires both operands 'string' and 'string' to be numeric
+# expect+1: Comparison with "<" requires both operands "string" and "string" to be numeric
.if "string" < "string"
. error
.else
@@ -122,7 +122,7 @@
.endif
# Strings cannot be compared relationally, only for equality.
-# expect+1: Comparison with '<=' requires both operands 'string' and 'string' to be numeric
+# expect+1: Comparison with "<=" requires both operands "string" and "string" to be numeric
.if "string" <= "string"
. error
.else
@@ -130,7 +130,7 @@
.endif
# Strings cannot be compared relationally, only for equality.
-# expect+1: Comparison with '>' requires both operands 'string' and 'string' to be numeric
+# expect+1: Comparison with ">" requires both operands "string" and "string" to be numeric
.if "string" > "string"
. error
.else
@@ -138,7 +138,7 @@
.endif
# Strings cannot be compared relationally, only for equality.
-# expect+1: Comparison with '>=' requires both operands 'string' and 'string' to be numeric
+# expect+1: Comparison with ">=" requires both operands "string" and "string" to be numeric
.if "string" >= "string"
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-eof.exp b/contrib/bmake/unit-tests/cond-eof.exp
index 44e481745a24..fb23e248178e 100644
--- a/contrib/bmake/unit-tests/cond-eof.exp
+++ b/contrib/bmake/unit-tests/cond-eof.exp
@@ -1,6 +1,6 @@
-make: cond-eof.mk:17: Malformed conditional '0 ${SIDE_EFFECT} ${SIDE_EFFECT2}'
-make: cond-eof.mk:20: Malformed conditional '1 ${SIDE_EFFECT} ${SIDE_EFFECT2}'
-make: cond-eof.mk:23: Malformed conditional '(0) ${SIDE_EFFECT} ${SIDE_EFFECT2}'
+make: cond-eof.mk:17: Malformed conditional "0 ${SIDE_EFFECT} ${SIDE_EFFECT2}"
+make: cond-eof.mk:20: Malformed conditional "1 ${SIDE_EFFECT} ${SIDE_EFFECT2}"
+make: cond-eof.mk:23: Malformed conditional "(0) ${SIDE_EFFECT} ${SIDE_EFFECT2}"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-eof.mk b/contrib/bmake/unit-tests/cond-eof.mk
index 706a7deebd1a..04d79d0783ad 100644
--- a/contrib/bmake/unit-tests/cond-eof.mk
+++ b/contrib/bmake/unit-tests/cond-eof.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-eof.mk,v 1.7 2024/08/06 18:00:16 rillig Exp $
+# $NetBSD: cond-eof.mk,v 1.8 2025/06/28 22:39:28 rillig Exp $
#
# Tests for parsing the end of '.if' conditions, which are represented as the
# token TOK_EOF.
@@ -13,12 +13,12 @@ SIDE_EFFECT2= ${:!echo 'side effect 2' 1>&2!}
# These syntax errors are an edge case that does not occur during normal
# operation. Still, it is easy to avoid evaluating these expressions, just in
# case they have side effects.
-# expect+1: Malformed conditional '0 ${SIDE_EFFECT} ${SIDE_EFFECT2}'
+# expect+1: Malformed conditional "0 ${SIDE_EFFECT} ${SIDE_EFFECT2}"
.if 0 ${SIDE_EFFECT} ${SIDE_EFFECT2}
.endif
-# expect+1: Malformed conditional '1 ${SIDE_EFFECT} ${SIDE_EFFECT2}'
+# expect+1: Malformed conditional "1 ${SIDE_EFFECT} ${SIDE_EFFECT2}"
.if 1 ${SIDE_EFFECT} ${SIDE_EFFECT2}
.endif
-# expect+1: Malformed conditional '(0) ${SIDE_EFFECT} ${SIDE_EFFECT2}'
+# expect+1: Malformed conditional "(0) ${SIDE_EFFECT} ${SIDE_EFFECT2}"
.if (0) ${SIDE_EFFECT} ${SIDE_EFFECT2}
.endif
diff --git a/contrib/bmake/unit-tests/cond-func-defined.exp b/contrib/bmake/unit-tests/cond-func-defined.exp
index ea3ced9398e8..04b57061f803 100644
--- a/contrib/bmake/unit-tests/cond-func-defined.exp
+++ b/contrib/bmake/unit-tests/cond-func-defined.exp
@@ -1,5 +1,5 @@
-make: cond-func-defined.mk:24: Missing ')' after argument 'A' for 'defined'
-make: cond-func-defined.mk:34: Missing ')' after argument 'DEF' for 'defined'
+make: cond-func-defined.mk:24: Missing ")" after argument "A" for "defined"
+make: cond-func-defined.mk:34: Missing ")" after argument "DEF" for "defined"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-func-defined.mk b/contrib/bmake/unit-tests/cond-func-defined.mk
index 66f95f3380c1..52eeaec8ccfc 100644
--- a/contrib/bmake/unit-tests/cond-func-defined.mk
+++ b/contrib/bmake/unit-tests/cond-func-defined.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-defined.mk,v 1.14 2025/01/10 23:00:38 rillig Exp $
+# $NetBSD: cond-func-defined.mk,v 1.15 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the defined() function in .if conditions.
@@ -20,7 +20,7 @@ ${:UA B}= variable name with spaces
.endif
# The argument of a function must not directly contain whitespace.
-# expect+1: Missing ')' after argument 'A' for 'defined'
+# expect+1: Missing ")" after argument "A" for "defined"
.if !defined(A B)
. error
.endif
@@ -30,7 +30,7 @@ ${:UA B}= variable name with spaces
. error
.endif
-# expect+1: Missing ')' after argument 'DEF' for 'defined'
+# expect+1: Missing ")" after argument "DEF" for "defined"
.if defined(DEF
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-func-make.exp b/contrib/bmake/unit-tests/cond-func-make.exp
index 4d493b3c3ccb..ab25dfc5b553 100644
--- a/contrib/bmake/unit-tests/cond-func-make.exp
+++ b/contrib/bmake/unit-tests/cond-func-make.exp
@@ -1,4 +1,4 @@
-make: cond-func-make.mk:24: warning: Unfinished character list in pattern argument '[' to function 'make'
+make: cond-func-make.mk:24: warning: Unfinished character list in pattern argument "[" to function "make"
: via-cmdline
: via-dot-makeflags
exit status 0
diff --git a/contrib/bmake/unit-tests/cond-func-make.mk b/contrib/bmake/unit-tests/cond-func-make.mk
index 1a14fd320a3c..8903f9c0e723 100644
--- a/contrib/bmake/unit-tests/cond-func-make.mk
+++ b/contrib/bmake/unit-tests/cond-func-make.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-make.mk,v 1.6 2025/01/10 23:00:38 rillig Exp $
+# $NetBSD: cond-func-make.mk,v 1.7 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the make() function in .if conditions, which tests whether
# the argument has been passed as a target via the command line or later
@@ -20,7 +20,7 @@
. error
.endif
-# expect+1: warning: Unfinished character list in pattern argument '[' to function 'make'
+# expect+1: warning: Unfinished character list in pattern argument "[" to function "make"
.if make([)
. error
.endif
diff --git a/contrib/bmake/unit-tests/cond-func.exp b/contrib/bmake/unit-tests/cond-func.exp
index c80f95f39c0b..77f65e77d46c 100644
--- a/contrib/bmake/unit-tests/cond-func.exp
+++ b/contrib/bmake/unit-tests/cond-func.exp
@@ -1,13 +1,13 @@
-make: cond-func.mk:37: Missing ')' after argument 'A' for 'defined'
-make: cond-func.mk:53: Missing ')' after argument 'A' for 'defined'
-make: cond-func.mk:57: Missing ')' after argument 'A' for 'defined'
-make: cond-func.mk:91: Unknown operator '&'
+make: cond-func.mk:37: Missing ")" after argument "A" for "defined"
+make: cond-func.mk:53: Missing ")" after argument "A" for "defined"
+make: cond-func.mk:57: Missing ")" after argument "A" for "defined"
+make: cond-func.mk:91: Unknown operator "&"
make: cond-func.mk:107: A plain function name is parsed as defined(...).
make: cond-func.mk:115: A plain function name is parsed as defined(...).
make: cond-func.mk:126: Symbols may start with a function name.
make: cond-func.mk:132: Symbols may start with a function name.
-make: cond-func.mk:138: Missing ')' after argument '' for 'defined'
-make: cond-func.mk:145: Missing ')' after argument '${:UVARNAME}.param' for 'defined'
+make: cond-func.mk:138: Missing ")" after argument "" for "defined"
+make: cond-func.mk:145: Missing ")" after argument "${:UVARNAME}.param" for "defined"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-func.mk b/contrib/bmake/unit-tests/cond-func.mk
index 3e4f8a9f151f..50b3f83cd4cb 100644
--- a/contrib/bmake/unit-tests/cond-func.mk
+++ b/contrib/bmake/unit-tests/cond-func.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func.mk,v 1.18 2024/08/07 05:48:45 rillig Exp $
+# $NetBSD: cond-func.mk,v 1.19 2025/06/28 22:39:28 rillig Exp $
#
# Tests for those parts of the functions in .if conditions that are common
# among several functions.
@@ -33,7 +33,7 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces
.endif
# The argument of a function must not directly contain whitespace.
-# expect+1: Missing ')' after argument 'A' for 'defined'
+# expect+1: Missing ")" after argument "A" for "defined"
.if !defined(A B)
. error
.endif
@@ -49,11 +49,11 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces
#
# It's not entirely clear why these characters are forbidden.
# The most plausible reason seems to be typo detection.
-# expect+1: Missing ')' after argument 'A' for 'defined'
+# expect+1: Missing ")" after argument "A" for "defined"
.if !defined(A&B)
. error
.endif
-# expect+1: Missing ')' after argument 'A' for 'defined'
+# expect+1: Missing ")" after argument "A" for "defined"
.if !defined(A|B)
. error
.endif
@@ -87,7 +87,7 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces
# interpreted as defined(A) && defined(B). Each kind of .if directive has a
# default function that is called when a bare word is parsed. For the plain
# .if directive, this function is 'defined'; see "struct If ifs" in cond.c.
-# expect+1: Unknown operator '&'
+# expect+1: Unknown operator "&"
.if A&B
. error
.endif
@@ -134,14 +134,14 @@ defined-var= # defined but empty
. error
.endif
-# expect+1: Missing ')' after argument '' for 'defined'
+# expect+1: Missing ")" after argument "" for "defined"
.if defined(
. error
.else
. error
.endif
-# expect+1: Missing ')' after argument '${:UVARNAME}.param' for 'defined'
+# expect+1: Missing ")" after argument "${:UVARNAME}.param" for "defined"
.if defined(${:UVARNAME}.param extra)
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-late.exp b/contrib/bmake/unit-tests/cond-late.exp
index 13846e8c822a..e4b3fdac85f4 100644
--- a/contrib/bmake/unit-tests/cond-late.exp
+++ b/contrib/bmake/unit-tests/cond-late.exp
@@ -1,4 +1,4 @@
-make: cond-late.mk:38: Bad condition
+make: cond-late.mk:29: Bad condition
while evaluating condition " != "no""
while evaluating variable "VAR" with value "${${UNDEF} != "no":?:}"
in make[1] in directory "<curdir>"
diff --git a/contrib/bmake/unit-tests/cond-late.mk b/contrib/bmake/unit-tests/cond-late.mk
index a8f381590a6e..154617f4f2b2 100644
--- a/contrib/bmake/unit-tests/cond-late.mk
+++ b/contrib/bmake/unit-tests/cond-late.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-late.mk,v 1.9 2024/08/29 20:20:35 rillig Exp $
+# $NetBSD: cond-late.mk,v 1.10 2025/06/30 21:44:39 rillig Exp $
#
# Using the :? modifier, expressions can contain conditional
# expressions that are evaluated late, at expansion time.
@@ -23,6 +23,13 @@ parse-time: .PHONY
COND.true= "yes" == "yes"
COND.false= "yes" != "yes"
+.if make(do-parse-time)
+VAR= ${${UNDEF} != "no":?:}
+# expect+1: Bad condition
+. if empty(VAR:Mpattern)
+. endif
+.endif
+
# If the order of evaluation were to change to first parse the condition
# and then expand the variables, the output would change from the
# current "yes no" to "yes yes", since both variables are non-empty.
@@ -31,10 +38,3 @@ COND.false= "yes" != "yes"
cond-literal:
@echo ${ ${COND.true} :?yes:no}
@echo ${ ${COND.false} :?yes:no}
-
-.if make(do-parse-time)
-VAR= ${${UNDEF} != "no":?:}
-# expect+1: Bad condition
-. if empty(VAR:Mpattern)
-. endif
-.endif
diff --git a/contrib/bmake/unit-tests/cond-op-and-lint.exp b/contrib/bmake/unit-tests/cond-op-and-lint.exp
index 8896fea5c9b6..74ac32e205e6 100644
--- a/contrib/bmake/unit-tests/cond-op-and-lint.exp
+++ b/contrib/bmake/unit-tests/cond-op-and-lint.exp
@@ -1,4 +1,4 @@
-make: cond-op-and-lint.mk:10: Unknown operator '&'
+make: cond-op-and-lint.mk:10: Unknown operator "&"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-op-and-lint.mk b/contrib/bmake/unit-tests/cond-op-and-lint.mk
index bac4566314b0..0daa3a728f86 100644
--- a/contrib/bmake/unit-tests/cond-op-and-lint.mk
+++ b/contrib/bmake/unit-tests/cond-op-and-lint.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op-and-lint.mk,v 1.2 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: cond-op-and-lint.mk,v 1.3 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the && operator in .if conditions, in lint mode.
@@ -6,7 +6,7 @@
# The '&' operator is not allowed in lint mode.
# It is not used in practice anyway.
-# expect+1: Unknown operator '&'
+# expect+1: Unknown operator "&"
.if 0 & 0
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-op-and.exp b/contrib/bmake/unit-tests/cond-op-and.exp
index 1ada96a00bdd..b3e45ea1767e 100644
--- a/contrib/bmake/unit-tests/cond-op-and.exp
+++ b/contrib/bmake/unit-tests/cond-op-and.exp
@@ -1,11 +1,11 @@
make: cond-op-and.mk:36: Variable "UNDEF" is undefined
make: cond-op-and.mk:41: Variable "UNDEF" is undefined
make: cond-op-and.mk:44: Variable "UNDEF" is undefined
-make: cond-op-and.mk:60: Unknown operator '&'
-make: cond-op-and.mk:66: Unknown operator '&'
-make: cond-op-and.mk:72: Unknown operator '&'
-make: cond-op-and.mk:78: Unknown operator '&'
-make: cond-op-and.mk:87: Unknown operator '&'
+make: cond-op-and.mk:60: Unknown operator "&"
+make: cond-op-and.mk:66: Unknown operator "&"
+make: cond-op-and.mk:72: Unknown operator "&"
+make: cond-op-and.mk:78: Unknown operator "&"
+make: cond-op-and.mk:87: Unknown operator "&"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-op-and.mk b/contrib/bmake/unit-tests/cond-op-and.mk
index 5d7f8a06800a..cb84e39e9217 100644
--- a/contrib/bmake/unit-tests/cond-op-and.mk
+++ b/contrib/bmake/unit-tests/cond-op-and.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op-and.mk,v 1.12 2025/01/11 21:21:33 rillig Exp $
+# $NetBSD: cond-op-and.mk,v 1.13 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the && operator in .if conditions.
@@ -56,25 +56,25 @@ DEF= defined
# The && operator may be abbreviated as &. This is not widely known though
# and is also not documented in the manual page.
-# expect+1: Unknown operator '&'
+# expect+1: Unknown operator "&"
.if 0 & 0
. error
.else
. error
.endif
-# expect+1: Unknown operator '&'
+# expect+1: Unknown operator "&"
.if 1 & 0
. error
.else
. error
.endif
-# expect+1: Unknown operator '&'
+# expect+1: Unknown operator "&"
.if 0 & 1
. error
.else
. error
.endif
-# expect+1: Unknown operator '&'
+# expect+1: Unknown operator "&"
.if !(1 & 1)
. error
.else
@@ -83,7 +83,7 @@ DEF= defined
# There is no operator '&&&'. The first two '&&' form an operator, the third
# '&' forms the next (incomplete) token.
-# expect+1: Unknown operator '&'
+# expect+1: Unknown operator "&"
.if 0 &&& 0
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-op-not.exp b/contrib/bmake/unit-tests/cond-op-not.exp
index 63aa928eabc3..f0dfb3b757b1 100644
--- a/contrib/bmake/unit-tests/cond-op-not.exp
+++ b/contrib/bmake/unit-tests/cond-op-not.exp
@@ -3,7 +3,7 @@ make: cond-op-not.mk:39: Not space evaluates to false.
make: cond-op-not.mk:44: Not 0 evaluates to true.
make: cond-op-not.mk:53: Not 1 evaluates to false.
make: cond-op-not.mk:60: Not word evaluates to false.
-make: cond-op-not.mk:65: Malformed conditional '!'
+make: cond-op-not.mk:65: Malformed conditional "!"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-op-not.mk b/contrib/bmake/unit-tests/cond-op-not.mk
index 4565b60b115d..393d68675fca 100644
--- a/contrib/bmake/unit-tests/cond-op-not.mk
+++ b/contrib/bmake/unit-tests/cond-op-not.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op-not.mk,v 1.9 2024/08/06 18:00:17 rillig Exp $
+# $NetBSD: cond-op-not.mk,v 1.10 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the ! operator in .if conditions, which negates its argument.
@@ -61,7 +61,7 @@
.endif
# A single exclamation mark is a parse error.
-# expect+1: Malformed conditional '!'
+# expect+1: Malformed conditional "!"
.if !
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-op-or-lint.exp b/contrib/bmake/unit-tests/cond-op-or-lint.exp
index 1c5837a9aca6..32d39dead9a1 100644
--- a/contrib/bmake/unit-tests/cond-op-or-lint.exp
+++ b/contrib/bmake/unit-tests/cond-op-or-lint.exp
@@ -1,4 +1,4 @@
-make: cond-op-or-lint.mk:10: Unknown operator '|'
+make: cond-op-or-lint.mk:10: Unknown operator "|"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-op-or-lint.mk b/contrib/bmake/unit-tests/cond-op-or-lint.mk
index 9ece9d5c9af6..1efc5d94cbf2 100644
--- a/contrib/bmake/unit-tests/cond-op-or-lint.mk
+++ b/contrib/bmake/unit-tests/cond-op-or-lint.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op-or-lint.mk,v 1.2 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: cond-op-or-lint.mk,v 1.3 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the || operator in .if conditions, in lint mode.
@@ -6,7 +6,7 @@
# The '|' operator is not allowed in lint mode.
# It is not used in practice anyway.
-# expect+1: Unknown operator '|'
+# expect+1: Unknown operator "|"
.if 0 | 0
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-op-or.exp b/contrib/bmake/unit-tests/cond-op-or.exp
index 6213759c24f7..fe42ffd6b310 100644
--- a/contrib/bmake/unit-tests/cond-op-or.exp
+++ b/contrib/bmake/unit-tests/cond-op-or.exp
@@ -1,11 +1,11 @@
make: cond-op-or.mk:36: Variable "UNDEF" is undefined
make: cond-op-or.mk:41: Variable "UNDEF" is undefined
make: cond-op-or.mk:44: Variable "UNDEF" is undefined
-make: cond-op-or.mk:60: Unknown operator '|'
-make: cond-op-or.mk:66: Unknown operator '|'
-make: cond-op-or.mk:72: Unknown operator '|'
-make: cond-op-or.mk:78: Unknown operator '|'
-make: cond-op-or.mk:87: Unknown operator '|'
+make: cond-op-or.mk:60: Unknown operator "|"
+make: cond-op-or.mk:66: Unknown operator "|"
+make: cond-op-or.mk:72: Unknown operator "|"
+make: cond-op-or.mk:78: Unknown operator "|"
+make: cond-op-or.mk:87: Unknown operator "|"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-op-or.mk b/contrib/bmake/unit-tests/cond-op-or.mk
index 381516499093..1c6e081dcac1 100644
--- a/contrib/bmake/unit-tests/cond-op-or.mk
+++ b/contrib/bmake/unit-tests/cond-op-or.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op-or.mk,v 1.14 2025/01/11 21:21:33 rillig Exp $
+# $NetBSD: cond-op-or.mk,v 1.15 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the || operator in .if conditions.
@@ -56,25 +56,25 @@ DEF= defined
# The || operator may be abbreviated as |. This is not widely known though
# and is also not documented in the manual page.
-# expect+1: Unknown operator '|'
+# expect+1: Unknown operator "|"
.if 0 | 0
. error
.else
. error
.endif
-# expect+1: Unknown operator '|'
+# expect+1: Unknown operator "|"
.if !(1 | 0)
. error
.else
. error
.endif
-# expect+1: Unknown operator '|'
+# expect+1: Unknown operator "|"
.if !(0 | 1)
. error
.else
. error
.endif
-# expect+1: Unknown operator '|'
+# expect+1: Unknown operator "|"
.if !(1 | 1)
. error
.else
@@ -83,7 +83,7 @@ DEF= defined
# There is no operator '|||'. The first two '||' form an operator, the third
# '|' forms the next (incomplete) token.
-# expect+1: Unknown operator '|'
+# expect+1: Unknown operator "|"
.if 0 ||| 0
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-op-parentheses.exp b/contrib/bmake/unit-tests/cond-op-parentheses.exp
index a4091226ec34..f8f9efc00772 100644
--- a/contrib/bmake/unit-tests/cond-op-parentheses.exp
+++ b/contrib/bmake/unit-tests/cond-op-parentheses.exp
@@ -1,7 +1,7 @@
-make: cond-op-parentheses.mk:22: Comparison with '>' requires both operands '3' and '(2' to be numeric
-make: cond-op-parentheses.mk:25: Malformed conditional '(3) > 2'
-make: cond-op-parentheses.mk:44: Malformed conditional '('
-make: cond-op-parentheses.mk:58: Malformed conditional ')'
+make: cond-op-parentheses.mk:22: Comparison with ">" requires both operands "3" and "(2" to be numeric
+make: cond-op-parentheses.mk:25: Malformed conditional "(3) > 2"
+make: cond-op-parentheses.mk:44: Malformed conditional "("
+make: cond-op-parentheses.mk:58: Malformed conditional ")"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-op-parentheses.mk b/contrib/bmake/unit-tests/cond-op-parentheses.mk
index 17d5d767cd41..17d6504ede9e 100644
--- a/contrib/bmake/unit-tests/cond-op-parentheses.mk
+++ b/contrib/bmake/unit-tests/cond-op-parentheses.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op-parentheses.mk,v 1.8 2024/08/06 18:00:17 rillig Exp $
+# $NetBSD: cond-op-parentheses.mk,v 1.9 2025/06/28 22:39:28 rillig Exp $
#
# Tests for parentheses in .if conditions, which group expressions to override
# the precedence of the operators '!', '&&' and '||'. Parentheses cannot be
@@ -18,10 +18,10 @@
#
# XXX: It's inconsistent that the right operand has unbalanced parentheses.
#
-# expect+1: Comparison with '>' requires both operands '3' and '(2' to be numeric
+# expect+1: Comparison with ">" requires both operands "3" and "(2" to be numeric
.if 3 > (2)
.endif
-# expect+1: Malformed conditional '(3) > 2'
+# expect+1: Malformed conditional "(3) > 2"
.if (3) > 2
.endif
@@ -40,7 +40,7 @@
.endif
# An unbalanced opening parenthesis is a parse error.
-# expect+1: Malformed conditional '('
+# expect+1: Malformed conditional "("
.if (
. error
.else
@@ -54,7 +54,7 @@
# TOK_TRUE, TOK_FALSE or TOK_ERROR. In cond.c 1.241, the return type of that
# function was changed to a properly restricted enum type, to prevent this bug
# from occurring again.
-# expect+1: Malformed conditional ')'
+# expect+1: Malformed conditional ")"
.if )
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-op.exp b/contrib/bmake/unit-tests/cond-op.exp
index 1125a35fa3b3..692698b91a96 100644
--- a/contrib/bmake/unit-tests/cond-op.exp
+++ b/contrib/bmake/unit-tests/cond-op.exp
@@ -1,7 +1,7 @@
-make: cond-op.mk:51: Malformed conditional '"!word" == !word'
-make: cond-op.mk:72: Malformed conditional '0 ${ERR::=evaluated}'
+make: cond-op.mk:51: Malformed conditional ""!word" == !word"
+make: cond-op.mk:72: Malformed conditional "0 ${ERR::=evaluated}"
make: cond-op.mk:77: A misplaced expression after 0 is not evaluated.
-make: cond-op.mk:82: Malformed conditional '1 ${ERR::=evaluated}'
+make: cond-op.mk:82: Malformed conditional "1 ${ERR::=evaluated}"
make: cond-op.mk:87: A misplaced expression after 1 is not evaluated.
make: cond-op.mk:93: A B C => (A || B) && C A || B && C A || (B && C)
make: cond-op.mk:108: 0 0 0 => 0 0 0
@@ -12,10 +12,10 @@ make: cond-op.mk:108: 1 0 0 => 0 1 1
make: cond-op.mk:108: 1 0 1 => 1 1 1
make: cond-op.mk:108: 1 1 0 => 0 1 1
make: cond-op.mk:108: 1 1 1 => 1 1 1
-make: cond-op.mk:120: Malformed conditional '1 &&'
-make: cond-op.mk:129: Malformed conditional '0 &&'
-make: cond-op.mk:138: Malformed conditional '1 ||'
-make: cond-op.mk:148: Malformed conditional '0 ||'
+make: cond-op.mk:120: Malformed conditional "1 &&"
+make: cond-op.mk:129: Malformed conditional "0 &&"
+make: cond-op.mk:138: Malformed conditional "1 ||"
+make: cond-op.mk:148: Malformed conditional "0 ||"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-op.mk b/contrib/bmake/unit-tests/cond-op.mk
index 6493d887c806..974cb938065c 100644
--- a/contrib/bmake/unit-tests/cond-op.mk
+++ b/contrib/bmake/unit-tests/cond-op.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op.mk,v 1.17 2024/08/06 18:00:17 rillig Exp $
+# $NetBSD: cond-op.mk,v 1.18 2025/06/28 22:39:28 rillig Exp $
#
# Tests for operators like &&, ||, ! in .if conditions.
#
@@ -47,7 +47,7 @@
# appear unquoted. If any, it must be enclosed in quotes.
# In any case, it is not interpreted as a negation of an unquoted string.
# See CondParser_String.
-# expect+1: Malformed conditional '"!word" == !word'
+# expect+1: Malformed conditional ""!word" == !word"
.if "!word" == !word
. error
.endif
@@ -68,7 +68,7 @@
# next token, even though in this position of the condition, only comparison
# operators, TOK_AND, TOK_OR or TOK_RPAREN are allowed.
.undef ERR
-# expect+1: Malformed conditional '0 ${ERR::=evaluated}'
+# expect+1: Malformed conditional "0 ${ERR::=evaluated}"
.if 0 ${ERR::=evaluated}
. error
.endif
@@ -78,7 +78,7 @@
.endif
.undef ERR
-# expect+1: Malformed conditional '1 ${ERR::=evaluated}'
+# expect+1: Malformed conditional "1 ${ERR::=evaluated}"
.if 1 ${ERR::=evaluated}
. error
.endif
@@ -116,7 +116,7 @@
# This condition is obviously malformed. It is properly detected and also
# was properly detected before 2021-01-19, but only because the left hand
# side of the '&&' evaluated to true.
-# expect+1: Malformed conditional '1 &&'
+# expect+1: Malformed conditional "1 &&"
.if 1 &&
. error
.else
@@ -125,7 +125,7 @@
# This obviously malformed condition was not detected as such before cond.c
# 1.238 from 2021-01-19.
-# expect+1: Malformed conditional '0 &&'
+# expect+1: Malformed conditional "0 &&"
.if 0 &&
. error
.else
@@ -134,7 +134,7 @@
# This obviously malformed condition was not detected as such before cond.c
# 1.238 from 2021-01-19.
-# expect+1: Malformed conditional '1 ||'
+# expect+1: Malformed conditional "1 ||"
.if 1 ||
. error
.else
@@ -144,7 +144,7 @@
# This condition is obviously malformed. It is properly detected and also
# was properly detected before 2021-01-19, but only because the left hand
# side of the '||' evaluated to false.
-# expect+1: Malformed conditional '0 ||'
+# expect+1: Malformed conditional "0 ||"
.if 0 ||
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-short.exp b/contrib/bmake/unit-tests/cond-short.exp
index 19c7ef3d0b89..4100e6e5ef2b 100644
--- a/contrib/bmake/unit-tests/cond-short.exp
+++ b/contrib/bmake/unit-tests/cond-short.exp
@@ -7,7 +7,7 @@ expected M pattern
expected or
expected or exists
expected or empty
-make: cond-short.mk:231: Comparison with '<' requires both operands '' and '42' to be numeric
+make: cond-short.mk:231: Comparison with "<" requires both operands "" and "42" to be numeric
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-short.mk b/contrib/bmake/unit-tests/cond-short.mk
index bcdf372ca6e6..8c4c4140596e 100644
--- a/contrib/bmake/unit-tests/cond-short.mk
+++ b/contrib/bmake/unit-tests/cond-short.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-short.mk,v 1.23 2023/11/19 22:32:44 rillig Exp $
+# $NetBSD: cond-short.mk,v 1.24 2025/06/28 22:39:28 rillig Exp $
#
# Demonstrates that in conditions, the right-hand side of an && or ||
# is only evaluated if it can actually influence the result.
@@ -227,7 +227,7 @@ VAR= ${VAR${:U1}}
# Due to the quotes around the left-hand side of the '<', the operand is
# marked as a string, thus preventing a numerical comparison.
#
-# expect+1: Comparison with '<' requires both operands '' and '42' to be numeric
+# expect+1: Comparison with "<" requires both operands "" and "42" to be numeric
.if "${INDIR_UNDEF}" < ${NUMBER}
. info yes
.else
diff --git a/contrib/bmake/unit-tests/cond-token-number.exp b/contrib/bmake/unit-tests/cond-token-number.exp
index 401f8a2364b7..a3b53c2dcd44 100644
--- a/contrib/bmake/unit-tests/cond-token-number.exp
+++ b/contrib/bmake/unit-tests/cond-token-number.exp
@@ -1,7 +1,7 @@
-make: cond-token-number.mk:16: Malformed conditional '-0'
-make: cond-token-number.mk:27: Malformed conditional '+0'
-make: cond-token-number.mk:38: Malformed conditional '!-1'
-make: cond-token-number.mk:49: Malformed conditional '!+1'
+make: cond-token-number.mk:16: Malformed conditional "-0"
+make: cond-token-number.mk:27: Malformed conditional "+0"
+make: cond-token-number.mk:38: Malformed conditional "!-1"
+make: cond-token-number.mk:49: Malformed conditional "!+1"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-token-number.mk b/contrib/bmake/unit-tests/cond-token-number.mk
index 329a51d73b2a..1d0f8d20287e 100644
--- a/contrib/bmake/unit-tests/cond-token-number.mk
+++ b/contrib/bmake/unit-tests/cond-token-number.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-number.mk,v 1.11 2024/08/06 18:00:17 rillig Exp $
+# $NetBSD: cond-token-number.mk,v 1.12 2025/06/28 22:39:28 rillig Exp $
#
# Tests for number tokens in .if conditions.
#
@@ -12,7 +12,7 @@
# accepted by the condition parser.
#
# See the ch_isdigit call in CondParser_String.
-# expect+1: Malformed conditional '-0'
+# expect+1: Malformed conditional "-0"
.if -0
. error
.else
@@ -23,7 +23,7 @@
# accepted by the condition parser.
#
# See the ch_isdigit call in CondParser_String.
-# expect+1: Malformed conditional '+0'
+# expect+1: Malformed conditional "+0"
.if +0
. error
.else
@@ -34,7 +34,7 @@
# accepted by the condition parser.
#
# See the ch_isdigit call in CondParser_String.
-# expect+1: Malformed conditional '!-1'
+# expect+1: Malformed conditional "!-1"
.if !-1
. error
.else
@@ -45,7 +45,7 @@
# accepted by the condition parser.
#
# See the ch_isdigit call in CondParser_String.
-# expect+1: Malformed conditional '!+1'
+# expect+1: Malformed conditional "!+1"
.if !+1
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-token-plain.exp b/contrib/bmake/unit-tests/cond-token-plain.exp
index 52d7e6fcddaa..0b430eba7d39 100644
--- a/contrib/bmake/unit-tests/cond-token-plain.exp
+++ b/contrib/bmake/unit-tests/cond-token-plain.exp
@@ -1,10 +1,12 @@
CondParser_Eval: ${:Uvalue} != value
Comparing "value" != "value"
CondParser_Eval: ${:U} != "
+make: cond-token-plain.mk:19: Unfinished string literal """
Comparing "" != ""
CondParser_Eval: ${:U#hash} != "#hash"
Comparing "#hash" != "#hash"
CondParser_Eval: ${:U\\} != "\\
+make: cond-token-plain.mk:43: Unfinished string literal ""\\"
Comparing "\" != "\"
CondParser_Eval: ${:U#hash} != #hash
Comparing "#hash" != "#hash"
@@ -39,9 +41,9 @@ make: cond-token-plain.mk:139: Numbers can be composed from literals and express
CondParser_Eval: 0${:Ux01}
make: cond-token-plain.mk:144: Numbers can be composed from literals and expressions.
CondParser_Eval: "" ==
-make: cond-token-plain.mk:151: Missing right-hand side of operator '=='
+make: cond-token-plain.mk:151: Missing right-hand side of operator "=="
CondParser_Eval: == ""
-make: cond-token-plain.mk:160: Malformed conditional '== ""'
+make: cond-token-plain.mk:160: Malformed conditional "== """
CondParser_Eval: \\
make: cond-token-plain.mk:176: The variable '\\' is not defined.
CondParser_Eval: \\
@@ -49,15 +51,23 @@ make: cond-token-plain.mk:182: Now the variable '\\' is defined.
CondParser_Eval: "unquoted\"quoted" != unquoted"quoted
Comparing "unquoted"quoted" != "unquoted"quoted"
CondParser_Eval: $$$$$$$$ != ""
-make: cond-token-plain.mk:197: Malformed conditional '$$$$$$$$ != ""'
+make: cond-token-plain.mk:197: Malformed conditional "$$$$$$$$ != """
CondParser_Eval: left == right
-make: cond-token-plain.mk:206: Malformed conditional 'left == right'
+make: cond-token-plain.mk:206: Malformed conditional "left == right"
CondParser_Eval: ${0:?:} || left == right
CondParser_Eval: 0
-make: cond-token-plain.mk:212: Malformed conditional '${0:?:} || left == right'
+make: cond-token-plain.mk:212: Malformed conditional "${0:?:} || left == right"
CondParser_Eval: left == right || ${0:?:}
-make: cond-token-plain.mk:217: Malformed conditional 'left == right || ${0:?:}'
-make: cond-token-plain.mk:236: Malformed conditional 'VAR.${IF_COUNT::+=1} != ""'
+make: cond-token-plain.mk:217: Malformed conditional "left == right || ${0:?:}"
+make: cond-token-plain.mk:236: Malformed conditional "VAR.${IF_COUNT::+=1} != """
+make: cond-token-plain.mk:272: Unfinished backslash escape sequence
+ while evaluating condition " str == str\"
+make: cond-token-plain.mk:282: Unfinished backslash escape sequence
+ while evaluating condition " str == "str\"
+make: cond-token-plain.mk:282: Unfinished string literal ""str\"
+ while evaluating condition " str == "str\"
+make: cond-token-plain.mk:289: Unfinished string literal ""str"
+ while evaluating condition " str == "str"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/cond-token-plain.mk b/contrib/bmake/unit-tests/cond-token-plain.mk
index 4509c1feca80..400af22f92d7 100644
--- a/contrib/bmake/unit-tests/cond-token-plain.mk
+++ b/contrib/bmake/unit-tests/cond-token-plain.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-plain.mk,v 1.20 2024/08/06 18:00:17 rillig Exp $
+# $NetBSD: cond-token-plain.mk,v 1.23 2025/07/06 07:56:16 rillig Exp $
#
# Tests for plain tokens (that is, string literals without quotes)
# in .if conditions. These are also called bare words.
@@ -14,8 +14,8 @@
# condition since comment parsing is done in an early phase and removes the
# '#' and everything after it long before the condition parser gets to see it.
#
-# XXX: The error message is missing for this malformed condition.
-# The right-hand side of the comparison is just a '"', before unescaping.
+#
+# expect+1: Unfinished string literal """
.if ${:U} != "#hash"
. error
.endif
@@ -38,8 +38,8 @@
# comments are stripped in an earlier phase. See "case '#'" in
# CondParser_Token.
#
-# XXX: Missing error message for the malformed condition. The right-hand
-# side before unescaping is double-quotes, backslash, backslash.
+#
+# expect+1: Unfinished string literal ""\\"
.if ${:U\\} != "\\#hash"
. error
.endif
@@ -147,7 +147,7 @@ VAR= defined
.endif
# If the right-hand side is missing, it's a parse error.
-# expect+1: Missing right-hand side of operator '=='
+# expect+1: Missing right-hand side of operator "=="
.if "" ==
. error
.else
@@ -156,7 +156,7 @@ VAR= defined
# If the left-hand side is missing, it's a parse error as well, but without
# a specific error message.
-# expect+1: Malformed conditional '== ""'
+# expect+1: Malformed conditional "== """
.if == ""
. error
.else
@@ -193,7 +193,7 @@ ${:U\\\\}= backslash
# FIXME: In CondParser_String, Var_Parse returns var_Error without a
# corresponding error message.
-# expect+1: Malformed conditional '$$$$$$$$ != ""'
+# expect+1: Malformed conditional "$$$$$$$$ != """
.if $$$$$$$$ != ""
. error
.else
@@ -202,18 +202,18 @@ ${:U\\\\}= backslash
# In a condition in an .if directive, the left-hand side must not be an
# unquoted string literal.
-# expect+1: Malformed conditional 'left == right'
+# expect+1: Malformed conditional "left == right"
.if left == right
.endif
# Before cond.c 1.276 from 2021-09-21, an expression containing the
# modifier ':?:' allowed unquoted string literals for the rest of the
# condition. This was an unintended implementation mistake.
-# expect+1: Malformed conditional '${0:?:} || left == right'
+# expect+1: Malformed conditional "${0:?:} || left == right"
.if ${0:?:} || left == right
.endif
# This affected only the comparisons after the expression, so the following
# was still a syntax error.
-# expect+1: Malformed conditional 'left == right || ${0:?:}'
+# expect+1: Malformed conditional "left == right || ${0:?:}"
.if left == right || ${0:?:}
.endif
@@ -232,7 +232,7 @@ ${:U\\\\}= backslash
# for the second time. The right-hand side of a comparison may be a bare
# word, but that side has no risk of being parsed more than once.
#
-# expect+1: Malformed conditional 'VAR.${IF_COUNT::+=1} != ""'
+# expect+1: Malformed conditional "VAR.${IF_COUNT::+=1} != """
.if VAR.${IF_COUNT::+=1} != ""
. error
.else
@@ -265,3 +265,29 @@ COND= VAR.$${MOD_COUNT::+=1}
. error
.endif
#.MAKEFLAGS: -d0
+
+
+# A trailing backslash in a bare word does not escape anything.
+# expect+1: Unfinished backslash escape sequence
+.if ${${:U str == str\\}:?yes:no}
+. error
+.else
+. error
+.endif
+
+# A trailing backslash in an unfinished string literal word does not escape
+# anything.
+# expect+2: Unfinished backslash escape sequence
+# expect+1: Unfinished string literal ""str\"
+.if ${${:U str == "str\\}:?yes:no}
+. error
+.else
+. error
+.endif
+
+# expect+1: Unfinished string literal ""str"
+.if ${${:U str == "str}:?yes:no}
+. error
+.else
+. error
+.endif
diff --git a/contrib/bmake/unit-tests/cond-token-string.exp b/contrib/bmake/unit-tests/cond-token-string.exp
index d0a5a25f2aa4..d31c0abda17d 100644
--- a/contrib/bmake/unit-tests/cond-token-string.exp
+++ b/contrib/bmake/unit-tests/cond-token-string.exp
@@ -1,7 +1,7 @@
make: cond-token-string.mk:14: Unknown modifier ":Z"
while evaluating "${:Uvalue:Z}"" with value "value"
make: cond-token-string.mk:24: xvalue is not defined.
-make: cond-token-string.mk:31: Malformed conditional 'x${:Uvalue} == ""'
+make: cond-token-string.mk:31: Malformed conditional "x${:Uvalue} == """
make: cond-token-string.mk:41: Expected.
CondParser_Eval: "UNDEF"
make: cond-token-string.mk:51: The string literal "UNDEF" is not empty.
diff --git a/contrib/bmake/unit-tests/cond-token-string.mk b/contrib/bmake/unit-tests/cond-token-string.mk
index fb069f830582..9afe64dca821 100644
--- a/contrib/bmake/unit-tests/cond-token-string.mk
+++ b/contrib/bmake/unit-tests/cond-token-string.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-string.mk,v 1.16 2025/03/29 19:08:52 rillig Exp $
+# $NetBSD: cond-token-string.mk,v 1.17 2025/06/28 22:39:28 rillig Exp $
#
# Tests for quoted string literals in .if conditions.
#
@@ -27,7 +27,7 @@
# The 'x' produces a "Malformed conditional" since the left-hand side of a
# comparison in an .if directive must be either an expression, a
# quoted string literal or a number that starts with a digit.
-# expect+1: Malformed conditional 'x${:Uvalue} == ""'
+# expect+1: Malformed conditional "x${:Uvalue} == """
.if x${:Uvalue} == ""
. error
.else
diff --git a/contrib/bmake/unit-tests/cond-token-var.exp b/contrib/bmake/unit-tests/cond-token-var.exp
index 1bf61e79ca61..b63d606c7e5a 100644
--- a/contrib/bmake/unit-tests/cond-token-var.exp
+++ b/contrib/bmake/unit-tests/cond-token-var.exp
@@ -6,11 +6,11 @@ make: cond-token-var.mk:64: Variable "U" is undefined
make: cond-token-var.mk:69: Variable "U" is undefined
make: cond-token-var.mk:78: Variable "U" is undefined
Var_Parse: ${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3} (eval)
-make: cond-token-var.mk:106: Malformed conditional 'x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}'
+make: cond-token-var.mk:106: Malformed conditional "x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}"
Var_Parse: ${DEF}y == "${UNDEF2}" || 0x${UNDEF3} (eval)
-make: cond-token-var.mk:111: Malformed conditional 'x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}'
+make: cond-token-var.mk:111: Malformed conditional "x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}"
Var_Parse: ${DEF}y == "${DEF}" || 0x${UNDEF3} (eval)
-make: cond-token-var.mk:116: Malformed conditional 'x${DEF}y == "${DEF}" || 0x${UNDEF3}'
+make: cond-token-var.mk:116: Malformed conditional "x${DEF}y == "${DEF}" || 0x${UNDEF3}"
Global: VAR.param = value of VAR.param
Var_Parse: ${VAR.param$U} (eval-defined-loud)
Var_Parse: $U} (eval)
diff --git a/contrib/bmake/unit-tests/cond-token-var.mk b/contrib/bmake/unit-tests/cond-token-var.mk
index 8da8a2436390..842ca4d2cb12 100644
--- a/contrib/bmake/unit-tests/cond-token-var.mk
+++ b/contrib/bmake/unit-tests/cond-token-var.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-var.mk,v 1.13 2025/04/04 18:57:01 rillig Exp $
+# $NetBSD: cond-token-var.mk,v 1.14 2025/06/28 22:39:28 rillig Exp $
#
# Tests for expressions in .if conditions.
#
@@ -102,17 +102,17 @@ DEF= defined
.MAKEFLAGS: -dv
# The left-hand side of a comparison must not be an unquoted word.
-# expect+1: Malformed conditional 'x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}'
+# expect+1: Malformed conditional "x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}"
.if x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}
.endif
# The left-hand side of a comparison must not be an unquoted word.
-# expect+1: Malformed conditional 'x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}'
+# expect+1: Malformed conditional "x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}"
.if x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}
.endif
# The left-hand side of a comparison must not be an unquoted word.
-# expect+1: Malformed conditional 'x${DEF}y == "${DEF}" || 0x${UNDEF3}'
+# expect+1: Malformed conditional "x${DEF}y == "${DEF}" || 0x${UNDEF3}"
.if x${DEF}y == "${DEF}" || 0x${UNDEF3}
.endif
diff --git a/contrib/bmake/unit-tests/dep-op-missing.exp b/contrib/bmake/unit-tests/dep-op-missing.exp
index 8521dbf79792..7c03092e09be 100644
--- a/contrib/bmake/unit-tests/dep-op-missing.exp
+++ b/contrib/bmake/unit-tests/dep-op-missing.exp
@@ -1,4 +1,4 @@
-make: dep-op-missing.tmp:1: Invalid line 'target'
+make: dep-op-missing.tmp:1: Invalid line "target"
in make[1] in directory "<curdir>"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
diff --git a/contrib/bmake/unit-tests/deptgt-begin.exp b/contrib/bmake/unit-tests/deptgt-begin.exp
index bf6f61a51e72..5aa673e33d30 100644
--- a/contrib/bmake/unit-tests/deptgt-begin.exp
+++ b/contrib/bmake/unit-tests/deptgt-begin.exp
@@ -1,5 +1,5 @@
make: deptgt-begin.mk:19: warning: duplicate script for target ".BEGIN" ignored
-make: deptgt-begin.mk:9: warning: using previous script for ".BEGIN" defined here
+make: deptgt-begin.mk:8: warning: using previous script for ".BEGIN" defined here
: parse time
: Making before-begin before .BEGIN.
: .BEGIN
diff --git a/contrib/bmake/unit-tests/deptgt-begin.mk b/contrib/bmake/unit-tests/deptgt-begin.mk
index 8b9842641a2d..a29155cb5fc2 100644
--- a/contrib/bmake/unit-tests/deptgt-begin.mk
+++ b/contrib/bmake/unit-tests/deptgt-begin.mk
@@ -1,10 +1,9 @@
-# $NetBSD: deptgt-begin.mk,v 1.7 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: deptgt-begin.mk,v 1.8 2025/06/30 21:44:39 rillig Exp $
#
# Tests for the special target .BEGIN in dependency declarations,
# which is a container for commands that are run before any other
# commands from the shell lines.
-# expect+2: warning: using previous script for ".BEGIN" defined here
.BEGIN:
: $@
@@ -14,7 +13,8 @@
# add its commands after this.
#
# There are several ways to resolve this situation, which are detailed below.
-# expect+2: warning: duplicate script for target ".BEGIN" ignored
+# expect+3: warning: duplicate script for target ".BEGIN" ignored
+# expect-9: warning: using previous script for ".BEGIN" defined here
.BEGIN:
: Making another $@.
diff --git a/contrib/bmake/unit-tests/deptgt-path-suffix.exp b/contrib/bmake/unit-tests/deptgt-path-suffix.exp
index 6294d8a39dc0..e1c67daa8787 100644
--- a/contrib/bmake/unit-tests/deptgt-path-suffix.exp
+++ b/contrib/bmake/unit-tests/deptgt-path-suffix.exp
@@ -1,4 +1,4 @@
-make: deptgt-path-suffix.mk:8: Suffix '.c' not defined (yet)
+make: deptgt-path-suffix.mk:8: Suffix ".c" not defined (yet)
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/deptgt-path-suffix.mk b/contrib/bmake/unit-tests/deptgt-path-suffix.mk
index 494a076a5520..68bb27036b68 100644
--- a/contrib/bmake/unit-tests/deptgt-path-suffix.mk
+++ b/contrib/bmake/unit-tests/deptgt-path-suffix.mk
@@ -1,10 +1,10 @@
-# $NetBSD: deptgt-path-suffix.mk,v 1.3 2021/12/13 23:38:54 rillig Exp $
+# $NetBSD: deptgt-path-suffix.mk,v 1.4 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the special target .PATH.suffix in dependency declarations.
# TODO: Implementation
-# expect+1: Suffix '.c' not defined (yet)
+# expect+1: Suffix ".c" not defined (yet)
.PATH.c: ..
.SUFFIXES: .c
diff --git a/contrib/bmake/unit-tests/deptgt.exp b/contrib/bmake/unit-tests/deptgt.exp
index 4c7cb4e50ddc..230fa497fcbd 100644
--- a/contrib/bmake/unit-tests/deptgt.exp
+++ b/contrib/bmake/unit-tests/deptgt.exp
@@ -1,4 +1,4 @@
-make: deptgt.mk:11: warning: Extra target '.PHONY' ignored
+make: deptgt.mk:11: warning: Extra target ".PHONY" ignored
make: deptgt.mk:30: Unassociated shell command ": command3 # parse error, since targets == NULL"
Parsing deptgt.mk:36: ${:U}: empty-source
ParseDependency(: empty-source)
@@ -18,8 +18,8 @@ make: deptgt.mk:51: Unknown modifier ":Z"
while evaluating "${:U:Z}:" with value ""
make: deptgt.mk:55: Unknown modifier ":Z"
while parsing "${:U:Z}:"
-make: deptgt.mk:58: warning: Extra target 'ordinary' ignored
-make: deptgt.mk:61: warning: Extra target (ordinary) ignored
+make: deptgt.mk:58: warning: Extra target "ordinary" ignored
+make: deptgt.mk:61: warning: Extra target "ordinary" ignored
make: deptgt.mk:64: warning: Special and mundane targets don't mix. Mundane ones ignored
make: Fatal errors encountered -- cannot continue
make: stopped making "target1" in unit-tests
diff --git a/contrib/bmake/unit-tests/deptgt.mk b/contrib/bmake/unit-tests/deptgt.mk
index 779a1faf7115..fd7a716e3ebc 100644
--- a/contrib/bmake/unit-tests/deptgt.mk
+++ b/contrib/bmake/unit-tests/deptgt.mk
@@ -1,4 +1,4 @@
-# $NetBSD: deptgt.mk,v 1.23 2025/03/29 19:08:52 rillig Exp $
+# $NetBSD: deptgt.mk,v 1.24 2025/06/28 22:39:28 rillig Exp $
#
# Tests for special targets like .BEGIN or .SUFFIXES in dependency
# declarations.
@@ -7,7 +7,7 @@
# Just in case anyone tries to compile several special targets in a single
# dependency line: That doesn't work, and make immediately rejects it.
-# expect+1: warning: Extra target '.PHONY' ignored
+# expect+1: warning: Extra target ".PHONY" ignored
.SUFFIXES .PHONY: .c.o
# The following lines demonstrate how 'targets' is set and reset during
@@ -54,10 +54,10 @@ ${:U:Z}:
# expect+1: Unknown modifier ":Z"
$${:U:Z}:
-# expect+1: warning: Extra target 'ordinary' ignored
+# expect+1: warning: Extra target "ordinary" ignored
.END ordinary:
-# expect+1: warning: Extra target (ordinary) ignored
+# expect+1: warning: Extra target "ordinary" ignored
.PATH ordinary:
# expect+1: warning: Special and mundane targets don't mix. Mundane ones ignored
diff --git a/contrib/bmake/unit-tests/directive-dinclude.exp b/contrib/bmake/unit-tests/directive-dinclude.exp
index 5f5fec4d403e..55f1f77fbfde 100755
--- a/contrib/bmake/unit-tests/directive-dinclude.exp
+++ b/contrib/bmake/unit-tests/directive-dinclude.exp
@@ -1,4 +1,4 @@
-make: directive-dinclude-error.inc:1: Invalid line 'syntax error'
+make: directive-dinclude-error.inc:1: Invalid line "syntax error"
in directive-dinclude.mk:21
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
diff --git a/contrib/bmake/unit-tests/directive-dinclude.mk b/contrib/bmake/unit-tests/directive-dinclude.mk
index c363209579ad..da063083235f 100755
--- a/contrib/bmake/unit-tests/directive-dinclude.mk
+++ b/contrib/bmake/unit-tests/directive-dinclude.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-dinclude.mk,v 1.4 2025/03/30 09:51:50 rillig Exp $
+# $NetBSD: directive-dinclude.mk,v 1.5 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the .dinclude directive, which includes another file,
# silently skipping it if it cannot be opened. This is primarily used for
@@ -16,7 +16,7 @@
.dinclude "${MAKEFILE}/subdir"
# Errors that are not related to opening the file are still reported.
-# expect: make: directive-dinclude-error.inc:1: Invalid line 'syntax error'
+# expect: make: directive-dinclude-error.inc:1: Invalid line "syntax error"
_!= echo 'syntax error' > directive-dinclude-error.inc
.dinclude "${.CURDIR}/directive-dinclude-error.inc"
_!= rm directive-dinclude-error.inc
diff --git a/contrib/bmake/unit-tests/directive-export-gmake.exp b/contrib/bmake/unit-tests/directive-export-gmake.exp
index f7bb07ab9da2..2c2875d669d2 100644
--- a/contrib/bmake/unit-tests/directive-export-gmake.exp
+++ b/contrib/bmake/unit-tests/directive-export-gmake.exp
@@ -1,4 +1,4 @@
-make: directive-export-gmake.mk:71: Invalid line 'export VAR=${:U1}', expanded to 'export VAR=1'
+make: directive-export-gmake.mk:71: Invalid line "export VAR=${:U1}", expanded to "export VAR=1"
in .for loop from directive-export-gmake.mk:67 with value = 1
make: directive-export-gmake.mk:85: 16:00:00
make: directive-export-gmake.mk:92: Variable/Value missing from "export"
diff --git a/contrib/bmake/unit-tests/directive-export-gmake.mk b/contrib/bmake/unit-tests/directive-export-gmake.mk
index de79470bf305..6e1d57c6a62d 100644
--- a/contrib/bmake/unit-tests/directive-export-gmake.mk
+++ b/contrib/bmake/unit-tests/directive-export-gmake.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-export-gmake.mk,v 1.9 2023/12/17 09:44:00 rillig Exp $
+# $NetBSD: directive-export-gmake.mk,v 1.10 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the export directive (without leading dot), as in GNU make.
@@ -67,7 +67,7 @@ export VAR=an ${UNDEF} variable
.for value in 1
# XXX: The ':' in this line is inside an expression and should thus not be
# interpreted as a dependency operator.
-# expect+1: Invalid line 'export VAR=${:U1}', expanded to 'export VAR=1'
+# expect+1: Invalid line "export VAR=${:U1}", expanded to "export VAR=1"
export VAR=${value}
.endfor
diff --git a/contrib/bmake/unit-tests/directive-for-errors.exp b/contrib/bmake/unit-tests/directive-for-errors.exp
index 39929864314d..1bae631b967a 100644
--- a/contrib/bmake/unit-tests/directive-for-errors.exp
+++ b/contrib/bmake/unit-tests/directive-for-errors.exp
@@ -4,10 +4,10 @@ make: directive-for-errors.mk:13: for-less endfor
make: directive-for-errors.mk:25: Unknown directive "for"
make: directive-for-errors.mk:27: warning: <>
make: directive-for-errors.mk:29: for-less endfor
-make: directive-for-errors.mk:44: invalid character '$' in .for loop variable name
-make: directive-for-errors.mk:52: no iteration variables in for
+make: directive-for-errors.mk:44: Invalid character "$" in .for loop variable name
+make: directive-for-errors.mk:52: Missing iteration variables in .for loop
make: directive-for-errors.mk:64: Wrong number of words (5) in .for substitution list with 3 variables
-make: directive-for-errors.mk:78: missing `in' in for
+make: directive-for-errors.mk:78: Missing "in" in .for loop
make: directive-for-errors.mk:85: Unknown modifier ":Z"
while evaluating "${:U3:Z} 4" with value "3"
make: Fatal errors encountered -- cannot continue
diff --git a/contrib/bmake/unit-tests/directive-for-errors.mk b/contrib/bmake/unit-tests/directive-for-errors.mk
index a58b8294289b..2571b600bf38 100644
--- a/contrib/bmake/unit-tests/directive-for-errors.mk
+++ b/contrib/bmake/unit-tests/directive-for-errors.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for-errors.mk,v 1.17 2025/05/03 08:18:33 rillig Exp $
+# $NetBSD: directive-for-errors.mk,v 1.18 2025/06/28 22:39:28 rillig Exp $
#
# Tests for error handling in .for loops.
@@ -40,7 +40,7 @@
# error everywhere outside a .for loop.
${:U\$}= dollar # see whether the "variable" '$' is local
${:U\\}= backslash # see whether the "variable" '\' is local
-# expect+1: invalid character '$' in .for loop variable name
+# expect+1: Invalid character "$" in .for loop variable name
.for a b $ \ in 1 2 3 4
. info Dollar $$ ${$} $($) and backslash $\ ${\} $(\).
.endfor
@@ -48,7 +48,7 @@ ${:U\\}= backslash # see whether the "variable" '\' is local
# If there are no variables, there is no point in expanding the .for loop
# since this would end up in an endless loop, consuming 0 of the 3 values in
# each iteration.
-# expect+1: no iteration variables in for
+# expect+1: Missing iteration variables in .for loop
.for in 1 2 3
# XXX: This should not be reached. It should be skipped, as already done
# when the number of values is not a multiple of the number of variables,
@@ -74,7 +74,7 @@ ${:U\\}= backslash # see whether the "variable" '\' is local
# A missing 'in' parses the .for loop but skips the body.
-# expect+1: missing `in' in for
+# expect+1: Missing "in" in .for loop
.for i over k
. error
.endfor
diff --git a/contrib/bmake/unit-tests/directive-for-escape.exp b/contrib/bmake/unit-tests/directive-for-escape.exp
index 6ab8a333a10f..78cc57a738a2 100644
--- a/contrib/bmake/unit-tests/directive-for-escape.exp
+++ b/contrib/bmake/unit-tests/directive-for-escape.exp
@@ -1,14 +1,14 @@
For: end for 1
For: loop body with chars = !"#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~:
. info ${:U!"#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
-make: directive-for-escape.mk:21: Unclosed expression, expecting '}' for modifier "U!""
+make: directive-for-escape.mk:21: Unclosed expression, expecting "}" for modifier "U!""
while evaluating "${:U!"" with value "!""
in .for loop from directive-for-escape.mk:20 with chars = !"#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
make: directive-for-escape.mk:21: !"
For: end for 1
For: loop body with chars = !"\\#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~:
. info ${:U!"\\\\#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
-make: directive-for-escape.mk:33: Unclosed expression, expecting '}' for modifier "U!"\\\\"
+make: directive-for-escape.mk:33: Unclosed expression, expecting "}" for modifier "U!"\\\\"
while evaluating "${:U!"\\\\" with value "!"\\"
in .for loop from directive-for-escape.mk:32 with chars = !"\\#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
make: directive-for-escape.mk:33: !"\\
@@ -69,9 +69,9 @@ For: end for 1
For: loop body with i = $:
. info ${:U\$}
make: directive-for-escape.mk:147: $
-make: directive-for-escape.mk:155: invalid character ':' in .for loop variable name
+make: directive-for-escape.mk:155: Invalid character ":" in .for loop variable name
For: end for 1
-make: directive-for-escape.mk:165: invalid character '}' in .for loop variable name
+make: directive-for-escape.mk:165: Invalid character "}" in .for loop variable name
For: end for 1
For: end for 1
For: loop body with i = inner:
@@ -89,7 +89,7 @@ For: end for 1
For: loop body with i = inner:
. info ${i2} ${i,} ${:Uinner}${:Uinner}${:Uinner:M*}${:Uinner}
make: directive-for-escape.mk:187: two comma innerinnerinnerinner
-make: directive-for-escape.mk:196: invalid character '$' in .for loop variable name
+make: directive-for-escape.mk:196: Invalid character "$" in .for loop variable name
For: end for 1
make: directive-for-escape.mk:208: eight and no cents.
For: end for 1
diff --git a/contrib/bmake/unit-tests/directive-for-escape.mk b/contrib/bmake/unit-tests/directive-for-escape.mk
index e688ce98f258..913d61831c46 100644
--- a/contrib/bmake/unit-tests/directive-for-escape.mk
+++ b/contrib/bmake/unit-tests/directive-for-escape.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for-escape.mk,v 1.29 2024/08/29 20:20:36 rillig Exp $
+# $NetBSD: directive-for-escape.mk,v 1.30 2025/06/28 22:39:28 rillig Exp $
#
# Test escaping of special characters in the iteration values of a .for loop.
# These values get expanded later using the :U variable modifier, and this
@@ -15,7 +15,7 @@ ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
# XXX: As of 2020-12-31, the '#' is not preserved in the expanded body of
# the loop. Not only would it need the escaping for the variable modifier
# ':U' but also the escaping for the line-end comment.
-# expect+3: Unclosed expression, expecting '}' for modifier "U!""
+# expect+3: Unclosed expression, expecting "}" for modifier "U!""
# expect+2: !"
.for chars in ${ASCII}
. info ${chars}
@@ -27,7 +27,7 @@ ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
# This means that a '#' sign cannot be passed in the value of a .for loop
# at all.
ASCII.2020-12-31= !"\\\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
-# expect+3: Unclosed expression, expecting '}' for modifier "U!"\\\\"
+# expect+3: Unclosed expression, expecting "}" for modifier "U!"\\\\"
# expect+2: !"\\
.for chars in ${ASCII.2020-12-31}
. info ${chars}
@@ -151,7 +151,7 @@ VALUES= begin<$${UNDEF:Ufallback:N{{{}}}}>end
# could contain colons, which affected expressions having this exact
# modifier. This possibility was neither intended nor documented.
NUMBERS= one two three
-# expect+1: invalid character ':' in .for loop variable name
+# expect+1: Invalid character ":" in .for loop variable name
.for NUMBERS:M*e in replaced
. info ${NUMBERS} ${NUMBERS:M*e}
.endfor
@@ -161,7 +161,7 @@ NUMBERS= one two three
# expressions. This possibility was neither intended nor documented.
BASENAME= one
EXT= .c
-# expect+1: invalid character '}' in .for loop variable name
+# expect+1: Invalid character "}" in .for loop variable name
.for BASENAME}${EXT in replaced
. info ${BASENAME}${EXT}
.endfor
@@ -192,7 +192,7 @@ i,= comma
# skipped "stupid" variable names though, but ForLoop_SubstVarLong naively
# parsed the body of the loop, substituting each '${$}' with an actual
# '${:Udollar}'.
-# expect+1: invalid character '$' in .for loop variable name
+# expect+1: Invalid character "$" in .for loop variable name
.for $ in dollar
. info eight $$$$$$$$ and no cents.
. info eight ${$}${$}${$}${$} and no cents.
diff --git a/contrib/bmake/unit-tests/directive-for-lines.exp b/contrib/bmake/unit-tests/directive-for-lines.exp
index bf5b2b8b1209..23227122ffd3 100644
--- a/contrib/bmake/unit-tests/directive-for-lines.exp
+++ b/contrib/bmake/unit-tests/directive-for-lines.exp
@@ -1,9 +1,9 @@
-make: directive-for-lines.mk:27: expect 23
-make: directive-for-lines.mk:27: expect 23
-make: directive-for-lines.mk:36: expect 30
-make: directive-for-lines.mk:27: expect 23
-make: directive-for-lines.mk:27: expect 23
-make: directive-for-lines.mk:36: expect 30
+make: directive-for-lines.mk:31: This is line 31.
+make: directive-for-lines.mk:31: This is line 31.
+make: directive-for-lines.mk:38: This is line 38.
+make: directive-for-lines.mk:31: This is line 31.
+make: directive-for-lines.mk:31: This is line 31.
+make: directive-for-lines.mk:38: This is line 38.
make: no target to make.
make: stopped in unit-tests
diff --git a/contrib/bmake/unit-tests/directive-for-lines.mk b/contrib/bmake/unit-tests/directive-for-lines.mk
index cae4e0a38897..898a1960e76a 100644
--- a/contrib/bmake/unit-tests/directive-for-lines.mk
+++ b/contrib/bmake/unit-tests/directive-for-lines.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for-lines.mk,v 1.5 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: directive-for-lines.mk,v 1.6 2025/06/30 21:44:39 rillig Exp $
#
# Tests for the line numbers that are reported in .for loops.
#
@@ -7,6 +7,14 @@
# messages inside .for loops had been wrong since ParseGetLine skipped empty
# lines, even when collecting the lines for the .for loop body.
+# expect+21: This is line 31.
+# expect+20: This is line 31.
+# expect+26: This is line 38.
+
+# expect+17: This is line 31.
+# expect+16: This is line 31.
+# expect+22: This is line 38.
+
.for outer in a b
# comment \
@@ -20,19 +28,13 @@
VAR= \
multi-line
-# expect+4: expect 23
-# expect+3: expect 23
-# expect+2: expect 23
-# expect+1: expect 23
-.info expect 23
+.info This is line 31.
.endfor
# comment \
# continued comment
-# expect+2: expect 30
-# expect+1: expect 30
-.info expect 30
+.info This is line 38.
.endfor
diff --git a/contrib/bmake/unit-tests/directive-for.exp b/contrib/bmake/unit-tests/directive-for.exp
index cf87e6ea8569..d1c1064f0ef5 100755
--- a/contrib/bmake/unit-tests/directive-for.exp
+++ b/contrib/bmake/unit-tests/directive-for.exp
@@ -14,16 +14,16 @@ make: directive-for.mk:158: {{}} {{}} {{}}
make: directive-for.mk:158: )( )( )(
make: directive-for.mk:158: ][ ][ ][
make: directive-for.mk:158: }{ }{ }{
-make: directive-for.mk:166: invalid character ':' in .for loop variable name
-make: directive-for.mk:173: invalid character '$' in .for loop variable name
-make: directive-for.mk:185: invalid character '$' in .for loop variable name
-make: directive-for.mk:207: no iteration variables in for
-make: directive-for.mk:233: 1 open conditional
- in .for loop from directive-for.mk:231 with var = value
-make: directive-for.mk:249: for-less endfor
-make: directive-for.mk:250: if-less endif
-make: directive-for.mk:258: if-less endif
- in .for loop from directive-for.mk:257 with var = value
+make: directive-for.mk:166: Invalid character ":" in .for loop variable name
+make: directive-for.mk:173: Invalid character "$" in .for loop variable name
+make: directive-for.mk:185: Invalid character "$" in .for loop variable name
+make: directive-for.mk:208: Missing iteration variables in .for loop
+make: directive-for.mk:234: 1 open conditional
+ in .for loop from directive-for.mk:232 with var = value
+make: directive-for.mk:252: for-less endfor
+make: directive-for.mk:254: if-less endif
+make: directive-for.mk:263: if-less endif
+ in .for loop from directive-for.mk:261 with var = value
For: new loop 2
For: end for 2
For: end for 1
@@ -34,7 +34,7 @@ For: loop body with outer = o:
endfor
For: end for 1
For: loop body with inner = i:
-make: directive-for.mk:307: newline-item=(a)
+make: directive-for.mk:312: newline-item=(a)
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/directive-for.mk b/contrib/bmake/unit-tests/directive-for.mk
index 2f989f54f228..72ffaa142ad6 100755
--- a/contrib/bmake/unit-tests/directive-for.mk
+++ b/contrib/bmake/unit-tests/directive-for.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for.mk,v 1.30 2025/03/30 16:43:10 rillig Exp $
+# $NetBSD: directive-for.mk,v 1.32 2025/07/01 04:24:20 rillig Exp $
#
# Tests for the .for directive.
#
@@ -162,14 +162,14 @@ EXPANSION${plus}= value
# except for whitespace, allowing for creative side effects, as usual for
# arbitrary code injection.
var= outer
-# expect+1: invalid character ':' in .for loop variable name
+# expect+1: Invalid character ":" in .for loop variable name
.for var:Q in value "quoted"
. info <${var}> <${var:Q}> <${var:Q:Q}>
.endfor
# Before 2023-05-09, when variable names could contain '$', the short
# expression '$$' was preserved, the long expressions were substituted.
-# expect+1: invalid character '$' in .for loop variable name
+# expect+1: Invalid character "$" in .for loop variable name
.for $ in value
. info <$$> <${$}> <$($)>
.endfor
@@ -181,7 +181,7 @@ var= outer
# possibility, therefore the variable names are restricted to using harmless
# characters only.
INDIRECT= direct
-# expect+1: invalid character '$' in .for loop variable name
+# expect+1: Invalid character "$" in .for loop variable name
.for $(INDIRECT) in value
# If the variable name could be chosen dynamically, the iteration variable
# might have been 'direct', thereby expanding the expression '${direct}'.
@@ -204,7 +204,8 @@ INDIRECT= ${DIRECT}
# An empty list of variables to the left of the 'in' is a parse error.
-.for in value # expect+0: no iteration variables in for
+# expect+1: Missing iteration variables in .for loop
+.for in value
. error
.endfor
@@ -230,7 +231,8 @@ INDIRECT= ${DIRECT}
# is processed.
.for var in value
. if 0
-.endfor # expect+0: 1 open conditional
+.endfor
+# expect-1: 1 open conditional
# If there are no iteration values, the loop body is not processed, and the
# check for mismatched conditionals is not performed.
@@ -246,8 +248,10 @@ INDIRECT= ${DIRECT}
.if 0
. for var in value # does not need a corresponding .endfor
.endif
-.endfor # expect+0: for-less endfor
-.endif # expect+0: if-less endif
+# expect+1: for-less endfor
+.endfor
+# expect+1: if-less endif
+.endif
# When a .for without the corresponding .endfor occurs in an active branch of
@@ -255,7 +259,8 @@ INDIRECT= ${DIRECT}
# without looking at any other directives.
.if 1
. for var in value
-. endif # expect+0: if-less endif
+# expect+1: if-less endif
+. endif
. endfor # no 'for-less endfor'
.endif # no 'if-less endif'
diff --git a/contrib/bmake/unit-tests/directive-hyphen-include.exp b/contrib/bmake/unit-tests/directive-hyphen-include.exp
index 3f17f0c41f0b..d1d37e783ca9 100755
--- a/contrib/bmake/unit-tests/directive-hyphen-include.exp
+++ b/contrib/bmake/unit-tests/directive-hyphen-include.exp
@@ -1,4 +1,4 @@
-make: directive-hyphen-include-error.inc:1: Invalid line 'syntax error'
+make: directive-hyphen-include-error.inc:1: Invalid line "syntax error"
in directive-hyphen-include.mk:20
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
diff --git a/contrib/bmake/unit-tests/directive-hyphen-include.mk b/contrib/bmake/unit-tests/directive-hyphen-include.mk
index ad596f4c47db..de438dfaffac 100755
--- a/contrib/bmake/unit-tests/directive-hyphen-include.mk
+++ b/contrib/bmake/unit-tests/directive-hyphen-include.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-hyphen-include.mk,v 1.4 2025/03/30 09:51:50 rillig Exp $
+# $NetBSD: directive-hyphen-include.mk,v 1.5 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the .-include directive, which includes another file,
# silently skipping it if it cannot be opened.
@@ -15,7 +15,7 @@
.-include "${MAKEFILE}/subdir"
# Errors that are not related to opening the file are still reported.
-# expect: make: directive-hyphen-include-error.inc:1: Invalid line 'syntax error'
+# expect: make: directive-hyphen-include-error.inc:1: Invalid line "syntax error"
_!= echo 'syntax error' > directive-hyphen-include-error.inc
.-include "${.CURDIR}/directive-hyphen-include-error.inc"
_!= rm directive-hyphen-include-error.inc
diff --git a/contrib/bmake/unit-tests/directive-if.exp b/contrib/bmake/unit-tests/directive-if.exp
index 0d4a7ea16d34..634c9ee6b1df 100644
--- a/contrib/bmake/unit-tests/directive-if.exp
+++ b/contrib/bmake/unit-tests/directive-if.exp
@@ -5,7 +5,7 @@ make: directive-if.mk:45: This is not conditional.
make: directive-if.mk:47: if-less else
make: directive-if.mk:49: This is not conditional.
make: directive-if.mk:51: if-less endif
-make: directive-if.mk:55: Malformed conditional ''
+make: directive-if.mk:55: Malformed conditional ""
make: directive-if.mk:66: Quotes in plain words are probably a mistake.
make: directive-if.mk:76: Don't do this, always put a space after a directive.
make: directive-if.mk:81: Don't do this, always put a space after a directive.
diff --git a/contrib/bmake/unit-tests/directive-if.mk b/contrib/bmake/unit-tests/directive-if.mk
index 7ff04da0755b..5d1232d245a9 100644
--- a/contrib/bmake/unit-tests/directive-if.mk
+++ b/contrib/bmake/unit-tests/directive-if.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-if.mk,v 1.13 2024/08/06 18:00:17 rillig Exp $
+# $NetBSD: directive-if.mk,v 1.14 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the .if directive.
#
@@ -51,7 +51,7 @@
.endif
# Missing condition.
-# expect+1: Malformed conditional ''
+# expect+1: Malformed conditional ""
.if
. error
.else
diff --git a/contrib/bmake/unit-tests/directive-include.exp b/contrib/bmake/unit-tests/directive-include.exp
index 71f39c57e807..361389cf1cad 100755
--- a/contrib/bmake/unit-tests/directive-include.exp
+++ b/contrib/bmake/unit-tests/directive-include.exp
@@ -8,7 +8,7 @@ make: directive-include.mk:56: Unknown modifier ":Z"
while evaluating "${:U123:Z}.mk" with value "123"
make: directive-include.mk:56: Could not find nonexistent.mk
make: directive-include.mk:61: Cannot open /nonexistent
-make: directive-include.mk:66: Invalid line 'include'
+make: directive-include.mk:66: Invalid line "include"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/directive-include.mk b/contrib/bmake/unit-tests/directive-include.mk
index 42cdd97c43c7..ad6936ab2f3c 100755
--- a/contrib/bmake/unit-tests/directive-include.mk
+++ b/contrib/bmake/unit-tests/directive-include.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-include.mk,v 1.19 2025/03/30 09:51:50 rillig Exp $
+# $NetBSD: directive-include.mk,v 1.20 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the .include directive, which includes another file.
@@ -62,7 +62,7 @@ include /nonexistent # comment
sinclude /nonexistent # comment
include ${:U/dev/null} # comment
include /dev/null /dev/null
-# expect+1: Invalid line 'include'
+# expect+1: Invalid line "include"
include
# XXX: trailing whitespace in diagnostic, missing quotes around filename
diff --git a/contrib/bmake/unit-tests/directive-misspellings.exp b/contrib/bmake/unit-tests/directive-misspellings.exp
index b918d05a2683..c551d73d5f98 100644
--- a/contrib/bmake/unit-tests/directive-misspellings.exp
+++ b/contrib/bmake/unit-tests/directive-misspellings.exp
@@ -1,6 +1,6 @@
make: directive-misspellings.mk:13: Unknown directive "dinclud"
make: directive-misspellings.mk:16: Unknown directive "dincludx"
-make: directive-misspellings.mk:18: .include filename must be delimited by '"' or '<'
+make: directive-misspellings.mk:18: .include filename must be delimited by "" or <>
make: directive-misspellings.mk:21: Unknown directive "erro"
make: directive-misspellings.mk:23: Unknown directive "errox"
make: directive-misspellings.mk:28: Unknown directive "expor"
@@ -13,18 +13,18 @@ make: directive-misspellings.mk:46: Unknown directive "export-literax"
make: directive-misspellings.mk:48: Unknown directive "export-literally"
make: directive-misspellings.mk:51: Unknown directive "-includ"
make: directive-misspellings.mk:54: Unknown directive "-includx"
-make: directive-misspellings.mk:56: .include filename must be delimited by '"' or '<'
+make: directive-misspellings.mk:56: .include filename must be delimited by "" or <>
make: directive-misspellings.mk:59: Unknown directive "includ"
make: directive-misspellings.mk:61: Could not find file
make: directive-misspellings.mk:63: Unknown directive "includx"
-make: directive-misspellings.mk:65: .include filename must be delimited by '"' or '<'
+make: directive-misspellings.mk:65: .include filename must be delimited by "" or <>
make: directive-misspellings.mk:68: Unknown directive "inf"
make: directive-misspellings.mk:70: msg
make: directive-misspellings.mk:72: Unknown directive "infx"
make: directive-misspellings.mk:74: Unknown directive "infos"
make: directive-misspellings.mk:77: Unknown directive "sinclud"
make: directive-misspellings.mk:80: Unknown directive "sincludx"
-make: directive-misspellings.mk:82: .include filename must be delimited by '"' or '<'
+make: directive-misspellings.mk:82: .include filename must be delimited by "" or <>
make: directive-misspellings.mk:85: Unknown directive "unde"
make: directive-misspellings.mk:88: Unknown directive "undex"
make: directive-misspellings.mk:90: Unknown directive "undefs"
diff --git a/contrib/bmake/unit-tests/directive-misspellings.mk b/contrib/bmake/unit-tests/directive-misspellings.mk
index 0014076d041f..cd6222b378f5 100644
--- a/contrib/bmake/unit-tests/directive-misspellings.mk
+++ b/contrib/bmake/unit-tests/directive-misspellings.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-misspellings.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: directive-misspellings.mk,v 1.5 2025/06/28 22:39:28 rillig Exp $
#
# Tests for misspelled directives.
#
@@ -14,7 +14,7 @@
.dinclude "file"
# expect+1: Unknown directive "dincludx"
.dincludx "file"
-# expect+1: .include filename must be delimited by '"' or '<'
+# expect+1: .include filename must be delimited by "" or <>
.dincludes "file" # XXX: the 's' is not meant to be a filename
# expect+1: Unknown directive "erro"
@@ -52,7 +52,7 @@
.-include "file"
# expect+1: Unknown directive "-includx"
.-includx "file"
-# expect+1: .include filename must be delimited by '"' or '<'
+# expect+1: .include filename must be delimited by "" or <>
.-includes "file" # XXX: the 's' is not meant to be a filename
# expect+1: Unknown directive "includ"
@@ -61,7 +61,7 @@
.include "file"
# expect+1: Unknown directive "includx"
.includx "file"
-# expect+1: .include filename must be delimited by '"' or '<'
+# expect+1: .include filename must be delimited by "" or <>
.includex "file" # XXX: the 's' is not meant to be a filename
# expect+1: Unknown directive "inf"
@@ -78,7 +78,7 @@
.sinclude "file"
# expect+1: Unknown directive "sincludx"
.sincludx "file"
-# expect+1: .include filename must be delimited by '"' or '<'
+# expect+1: .include filename must be delimited by "" or <>
.sincludes "file" # XXX: the 's' is not meant to be a filename
# expect+1: Unknown directive "unde"
diff --git a/contrib/bmake/unit-tests/directive-sinclude.exp b/contrib/bmake/unit-tests/directive-sinclude.exp
index b7503e18c9b5..74db51227f07 100755
--- a/contrib/bmake/unit-tests/directive-sinclude.exp
+++ b/contrib/bmake/unit-tests/directive-sinclude.exp
@@ -1,4 +1,4 @@
-make: directive-include-error.inc:1: Invalid line 'syntax error'
+make: directive-include-error.inc:1: Invalid line "syntax error"
in directive-sinclude.mk:20
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
diff --git a/contrib/bmake/unit-tests/directive-sinclude.mk b/contrib/bmake/unit-tests/directive-sinclude.mk
index d40915fa86d5..4c856d22be4f 100755
--- a/contrib/bmake/unit-tests/directive-sinclude.mk
+++ b/contrib/bmake/unit-tests/directive-sinclude.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-sinclude.mk,v 1.6 2025/03/30 09:51:50 rillig Exp $
+# $NetBSD: directive-sinclude.mk,v 1.7 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the .sinclude directive, which includes another file,
# silently skipping it if it cannot be opened.
@@ -15,7 +15,7 @@
.sinclude "${MAKEFILE}/subdir"
# Errors that are not related to opening the file are still reported.
-# expect: make: directive-include-error.inc:1: Invalid line 'syntax error'
+# expect: make: directive-include-error.inc:1: Invalid line "syntax error"
_!= echo 'syntax error' > directive-include-error.inc
.sinclude "${.CURDIR}/directive-include-error.inc"
_!= rm directive-include-error.inc
diff --git a/contrib/bmake/unit-tests/directive-unexport.exp b/contrib/bmake/unit-tests/directive-unexport.exp
index 1be4b03e3874..25bab7d7fd35 100644
--- a/contrib/bmake/unit-tests/directive-unexport.exp
+++ b/contrib/bmake/unit-tests/directive-unexport.exp
@@ -1,5 +1,5 @@
make: directive-unexport.mk:19: UT_A=a UT_B=b UT_C=c
make: directive-unexport.mk:21: UT_A UT_B UT_C
make: directive-unexport.mk:30: UT_A=a UT_B=b UT_C=c
-make: directive-unexport.mk:31:
+make: directive-unexport.mk:32:
exit status 0
diff --git a/contrib/bmake/unit-tests/directive-unexport.mk b/contrib/bmake/unit-tests/directive-unexport.mk
index e759fe3e35f2..3c10ffa07d6a 100644
--- a/contrib/bmake/unit-tests/directive-unexport.mk
+++ b/contrib/bmake/unit-tests/directive-unexport.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-unexport.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: directive-unexport.mk,v 1.9 2025/06/30 21:44:39 rillig Exp $
#
# Tests for the .unexport directive.
#
@@ -28,6 +28,7 @@ UT_C= c
# expect+1: UT_A=a UT_B=b UT_C=c
.info ${:!env|sort|grep '^UT_'!}
+# expect+1:
.info ${.MAKE.EXPORTED}
.unexport # oops: missing argument
diff --git a/contrib/bmake/unit-tests/directive-warning.exp b/contrib/bmake/unit-tests/directive-warning.exp
index 2dd4e8ceb7f9..250e32583847 100644
--- a/contrib/bmake/unit-tests/directive-warning.exp
+++ b/contrib/bmake/unit-tests/directive-warning.exp
@@ -3,9 +3,9 @@ make: directive-warning.mk:12: Unknown directive "warn"
make: directive-warning.mk:14: Unknown directive "warnin"
make: directive-warning.mk:16: Unknown directive "warnin"
make: directive-warning.mk:18: Missing argument for ".warning"
-make: directive-warning.mk:19: warning: message
-make: directive-warning.mk:21: Unknown directive "warnings"
-make: directive-warning.mk:23: Unknown directive "warnings"
+make: directive-warning.mk:20: warning: message
+make: directive-warning.mk:22: Unknown directive "warnings"
+make: directive-warning.mk:24: Unknown directive "warnings"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/directive-warning.mk b/contrib/bmake/unit-tests/directive-warning.mk
index bf0683f8911f..50666487c13f 100644
--- a/contrib/bmake/unit-tests/directive-warning.mk
+++ b/contrib/bmake/unit-tests/directive-warning.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-warning.mk,v 1.9 2023/12/17 09:44:00 rillig Exp $
+# $NetBSD: directive-warning.mk,v 1.10 2025/07/01 04:24:20 rillig Exp $
#
# Tests for the .warning directive.
#
@@ -16,7 +16,8 @@
.warnin message # misspelled
# expect+1: Missing argument for ".warning"
.warning # "Missing argument"
-.warning message # expect+0: warning: message
+# expect+1: warning: message
+.warning message
# expect+1: Unknown directive "warnings"
.warnings # misspelled
# expect+1: Unknown directive "warnings"
diff --git a/contrib/bmake/unit-tests/directive.exp b/contrib/bmake/unit-tests/directive.exp
index 2f1da18cdbb5..dce759abfe52 100644
--- a/contrib/bmake/unit-tests/directive.exp
+++ b/contrib/bmake/unit-tests/directive.exp
@@ -7,8 +7,8 @@ Global: .info = value
make: directive.mk:31: := value
Global: .MAKEFLAGS = -r -k -d v -d
Global: .MAKEFLAGS = -r -k -d v -d 0
-make: directive.mk:40: Invalid line 'target-without-colon'
-make: directive.mk:43: Invalid line 'target-without-colon another-target'
+make: directive.mk:40: Invalid line "target-without-colon"
+make: directive.mk:43: Invalid line "target-without-colon another-target"
make: Fatal errors encountered -- cannot continue
make: stopped making ".target" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/directive.mk b/contrib/bmake/unit-tests/directive.mk
index 61938360dfc7..5f5be5aa0fab 100644
--- a/contrib/bmake/unit-tests/directive.mk
+++ b/contrib/bmake/unit-tests/directive.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive.mk,v 1.9 2023/11/19 22:32:44 rillig Exp $
+# $NetBSD: directive.mk,v 1.10 2025/06/28 22:39:28 rillig Exp $
#
# Tests for the preprocessing directives, such as .if or .info.
@@ -36,8 +36,8 @@
# Not even the space after the '.info' can change anything about this.
.${:Uinfo} : source
-# expect+1: Invalid line 'target-without-colon'
+# expect+1: Invalid line "target-without-colon"
target-without-colon
-# expect+1: Invalid line 'target-without-colon another-target'
+# expect+1: Invalid line "target-without-colon another-target"
target-without-colon another-target
diff --git a/contrib/bmake/unit-tests/moderrs.exp b/contrib/bmake/unit-tests/moderrs.exp
index 08aa2582f6be..4758294f0993 100644
--- a/contrib/bmake/unit-tests/moderrs.exp
+++ b/contrib/bmake/unit-tests/moderrs.exp
@@ -7,11 +7,11 @@ make: Unknown modifier ":Z"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 'VAR:${MOD_UNKN}=before-${VAR:${MOD_UNKN}:inner}-after'"
in target "mod-unknown-indirect"
-make: Unclosed expression, expecting '}' for modifier "S,V,v,"
+make: Unclosed expression, expecting "}" for modifier "S,V,v,"
while evaluating variable "VAR" with value "Thevariable"
in command "@echo VAR:S,V,v,=${VAR:S,V,v,"
in target "unclosed-direct"
-make: Unclosed expression after indirect modifier, expecting '}'
+make: Unclosed expression after indirect modifier, expecting "}"
while evaluating variable "VAR" with value "Thevariable"
in command "@echo VAR:${MOD_TERM},=${VAR:${MOD_S}"
in target "unclosed-indirect"
@@ -29,7 +29,7 @@ make: Unfinished modifier after "...}", expecting "@"
in command "@echo ${UNDEF:U1 2 3:@var@...}"
in target "unfinished-loop-2"
1 2 3
-make: Unclosed expression, expecting '}' for modifier "@var@${var}}...@"
+make: Unclosed expression, expecting "}" for modifier "@var@${var}}...@"
while evaluating variable "UNDEF" with value "1}... 2}... 3}..."
in command "@echo ${UNDEF:U1 2 3:@var@${var}}...@"
in target "loop-close-1"
@@ -55,7 +55,7 @@ make: Unfinished modifier after "=exclam}", expecting "!"
while evaluating variable "!" with value "!"
in command "@echo ${!:L:!=exclam}"
in target "exclam-2"
-make: Missing delimiter for modifier ':S'
+make: Missing delimiter for modifier ":S"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 1: ${VAR:S"
in target "mod-subst-delimiter-1"
@@ -75,12 +75,12 @@ make: Unfinished modifier after "to", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 5: ${VAR:S,from,to"
in target "mod-subst-delimiter-5"
-make: Unclosed expression, expecting '}' for modifier "S,from,to,"
+make: Unclosed expression, expecting "}" for modifier "S,from,to,"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 6: ${VAR:S,from,to,"
in target "mod-subst-delimiter-6"
7: TheVariable
-make: Missing delimiter for modifier ':C'
+make: Missing delimiter for modifier ":C"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 1: ${VAR:C"
in target "mod-regex-delimiter-1"
@@ -100,7 +100,7 @@ make: Unfinished modifier after "to", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 5: ${VAR:C,from,to"
in target "mod-regex-delimiter-5"
-make: Unclosed expression, expecting '}' for modifier "C,from,to,"
+make: Unclosed expression, expecting "}" for modifier "C,from,to,"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 6: ${VAR:C,from,to,"
in target "mod-regex-delimiter-6"
diff --git a/contrib/bmake/unit-tests/moderrs.mk b/contrib/bmake/unit-tests/moderrs.mk
index ca5cc082e6b8..c2ee320e2df2 100644
--- a/contrib/bmake/unit-tests/moderrs.mk
+++ b/contrib/bmake/unit-tests/moderrs.mk
@@ -1,4 +1,4 @@
-# $NetBSD: moderrs.mk,v 1.46 2025/03/30 00:35:52 rillig Exp $
+# $NetBSD: moderrs.mk,v 1.47 2025/06/28 22:39:29 rillig Exp $
#
# various modifier error tests
@@ -33,11 +33,11 @@ mod-unknown-indirect:
@echo 'VAR:${MOD_UNKN}=before-${VAR:${MOD_UNKN}:inner}-after'
unclosed-direct:
-# expect: make: Unclosed expression, expecting '}' for modifier "S,V,v,"
+# expect: make: Unclosed expression, expecting "}" for modifier "S,V,v,"
@echo VAR:S,V,v,=${VAR:S,V,v,
unclosed-indirect:
-# expect: make: Unclosed expression after indirect modifier, expecting '}'
+# expect: make: Unclosed expression after indirect modifier, expecting "}"
@echo VAR:${MOD_TERM},=${VAR:${MOD_S}
unfinished-indirect:
@@ -60,7 +60,7 @@ unfinished-loop-3:
# This is also contrary to the SysV modifier, where only the actually
# used delimiter (either braces or parentheses) must be balanced.
loop-close-1:
-# expect: make: Unclosed expression, expecting '}' for modifier "@var@${var}}...@"
+# expect: make: Unclosed expression, expecting "}" for modifier "@var@${var}}...@"
@echo ${UNDEF:U1 2 3:@var@${var}}...@
loop-close-2:
@echo ${UNDEF:U1 2 3:@var@${var}}...@}
@@ -107,7 +107,7 @@ exclam-2:
@echo ${!:L:!=exclam}
mod-subst-delimiter-1:
-# expect: make: Missing delimiter for modifier ':S'
+# expect: make: Missing delimiter for modifier ":S"
@echo 1: ${VAR:S
mod-subst-delimiter-2:
# expect: make: Unfinished modifier after "", expecting ","
@@ -122,13 +122,13 @@ mod-subst-delimiter-5:
# expect: make: Unfinished modifier after "to", expecting ","
@echo 5: ${VAR:S,from,to
mod-subst-delimiter-6:
-# expect: make: Unclosed expression, expecting '}' for modifier "S,from,to,"
+# expect: make: Unclosed expression, expecting "}" for modifier "S,from,to,"
@echo 6: ${VAR:S,from,to,
mod-subst-delimiter-7:
@echo 7: ${VAR:S,from,to,}
mod-regex-delimiter-1:
-# expect: make: Missing delimiter for modifier ':C'
+# expect: make: Missing delimiter for modifier ":C"
@echo 1: ${VAR:C
mod-regex-delimiter-2:
# expect: make: Unfinished modifier after "", expecting ","
@@ -143,7 +143,7 @@ mod-regex-delimiter-5:
# expect: make: Unfinished modifier after "to", expecting ","
@echo 5: ${VAR:C,from,to
mod-regex-delimiter-6:
-# expect: make: Unclosed expression, expecting '}' for modifier "C,from,to,"
+# expect: make: Unclosed expression, expecting "}" for modifier "C,from,to,"
@echo 6: ${VAR:C,from,to,
mod-regex-delimiter-7:
@echo 7: ${VAR:C,from,to,}
diff --git a/contrib/bmake/unit-tests/opt-debug-file.exp b/contrib/bmake/unit-tests/opt-debug-file.exp
index 1059351188e4..4a497f3011d9 100644
--- a/contrib/bmake/unit-tests/opt-debug-file.exp
+++ b/contrib/bmake/unit-tests/opt-debug-file.exp
@@ -1,6 +1,6 @@
-make: opt-debug-file.mk:44: This goes to stderr only, once.
-make: opt-debug-file.mk:47: This goes to stderr only, once.
-make: opt-debug-file.mk:50: This goes to stderr, and in addition to the debug log.
+make: opt-debug-file.mk:54: This goes to stderr only, once.
+make: opt-debug-file.mk:57: This goes to stderr only, once.
+make: opt-debug-file.mk:60: This goes to stderr, and in addition to the debug log.
CondParser_Eval: ${:!cat opt-debug-file.debuglog!:Maddition:[#]} != 1
Comparing 1.000000 != 1.000000
make: Unterminated quoted string [make 'This goes to stdout only, once.]
diff --git a/contrib/bmake/unit-tests/opt-debug-file.mk b/contrib/bmake/unit-tests/opt-debug-file.mk
index 33a35e0a458a..d107f177dae3 100644
--- a/contrib/bmake/unit-tests/opt-debug-file.mk
+++ b/contrib/bmake/unit-tests/opt-debug-file.mk
@@ -1,4 +1,4 @@
-# $NetBSD: opt-debug-file.mk,v 1.11 2024/06/30 15:21:24 rillig Exp $
+# $NetBSD: opt-debug-file.mk,v 1.12 2025/07/06 08:48:34 rillig Exp $
#
# Tests for the -dF command line option, which redirects the debug log
# to a file instead of writing it to stderr.
@@ -27,7 +27,9 @@ DEBUG_OUTPUT:= ${:!cat opt-debug-file.debuglog!}
.endif
# To get the unexpanded text that was actually written to the debug log
-# file, the content of that log file must not be stored in a variable.
+# file, the content of that log file must not be stored in a variable
+# directly. Instead, it can be processed in a single expression by a chain
+# of modifiers.
#
# XXX: In the :M modifier, a dollar is escaped using '$$', not '\$'. This
# escaping scheme unnecessarily differs from all other modifiers.
@@ -35,6 +37,14 @@ DEBUG_OUTPUT:= ${:!cat opt-debug-file.debuglog!}
. error
.endif
+# To get the unexpanded text that was actually written to the debug log
+# file, the content of that log file must not be stored in a variable
+# directly. Instead, each dollar sign must be escaped first.
+DEBUG_OUTPUT:= ${:!cat opt-debug-file.debuglog!:S,\$,\$\$,g}
+.if ${DEBUG_OUTPUT:M*Uexpanded*} != "\${:Uexpanded}"
+. error
+.endif
+
.MAKEFLAGS: -d0
diff --git a/contrib/bmake/unit-tests/opt-debug-lint.exp b/contrib/bmake/unit-tests/opt-debug-lint.exp
index 8e7339fcd2e9..7173ec476ec5 100644
--- a/contrib/bmake/unit-tests/opt-debug-lint.exp
+++ b/contrib/bmake/unit-tests/opt-debug-lint.exp
@@ -1,8 +1,8 @@
make: opt-debug-lint.mk:20: Variable "X" is undefined
make: opt-debug-lint.mk:43: Variable "UNDEF" is undefined
-make: opt-debug-lint.mk:65: Missing delimiter ':' after modifier "L"
+make: opt-debug-lint.mk:65: Missing delimiter ":" after modifier "L"
while evaluating variable "value" with value "value"
-make: opt-debug-lint.mk:65: Missing delimiter ':' after modifier "P"
+make: opt-debug-lint.mk:65: Missing delimiter ":" after modifier "P"
while evaluating variable "value" with value "value"
make: opt-debug-lint.mk:74: Unknown modifier ":${"
while evaluating variable "value" with value ""
diff --git a/contrib/bmake/unit-tests/opt-debug-lint.mk b/contrib/bmake/unit-tests/opt-debug-lint.mk
index 59cd36fb05e9..2f73c9bf645c 100644
--- a/contrib/bmake/unit-tests/opt-debug-lint.mk
+++ b/contrib/bmake/unit-tests/opt-debug-lint.mk
@@ -1,4 +1,4 @@
-# $NetBSD: opt-debug-lint.mk,v 1.24 2025/04/04 18:57:01 rillig Exp $
+# $NetBSD: opt-debug-lint.mk,v 1.25 2025/06/28 22:39:29 rillig Exp $
#
# Tests for the -dL command line option, which runs additional checks
# to catch common mistakes, such as unclosed expressions.
@@ -60,8 +60,8 @@ ${UNDEF}: ${UNDEF}
# Since 2020-10-03, in lint mode the variable modifier must be separated
# by colons. See varparse-mod.mk.
-# expect+2: Missing delimiter ':' after modifier "L"
-# expect+1: Missing delimiter ':' after modifier "P"
+# expect+2: Missing delimiter ":" after modifier "L"
+# expect+1: Missing delimiter ":" after modifier "P"
.if ${value:LPL} != "value"
. error
.endif
diff --git a/contrib/bmake/unit-tests/opt-jobs-internal.exp b/contrib/bmake/unit-tests/opt-jobs-internal.exp
index e3e8ee498224..61c96256a2e4 100644
--- a/contrib/bmake/unit-tests/opt-jobs-internal.exp
+++ b/contrib/bmake/unit-tests/opt-jobs-internal.exp
@@ -1,25 +1,13 @@
direct: mode=parallel
make: error: invalid internal option "-J garbage" in "<curdir>"
-make: warning: internal option "-J" in "<curdir>" refers to unopened file descriptors; falling back to compat mode.
- To run the target even in -n mode, add the .MAKE pseudo-source to the target.
- To run the target in default mode only, add a ${:D make} marker to a target's command. (This marker expression expands to an empty string.)
- To make the sub-make run in compat mode, add -B to its invocation.
- To make the sub-make independent from the parent make, unset the MAKEFLAGS environment variable in the target's commands.
+make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
in make[2] in directory "<curdir>"
direct-open: mode=compat
-make: warning: internal option "-J" in "<curdir>" refers to unopened file descriptors; falling back to compat mode.
- To run the target even in -n mode, add the .MAKE pseudo-source to the target.
- To run the target in default mode only, add a ${:D make} marker to a target's command. (This marker expression expands to an empty string.)
- To make the sub-make run in compat mode, add -B to its invocation.
- To make the sub-make independent from the parent make, unset the MAKEFLAGS environment variable in the target's commands.
+make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
in make[2] in directory "<curdir>"
indirect-open: mode=compat
indirect-expr: mode=parallel
-make: warning: internal option "-J" in "<curdir>" refers to unopened file descriptors; falling back to compat mode.
- To run the target even in -n mode, add the .MAKE pseudo-source to the target.
- To run the target in default mode only, add a ${:D make} marker to a target's command. (This marker expression expands to an empty string.)
- To make the sub-make run in compat mode, add -B to its invocation.
- To make the sub-make independent from the parent make, unset the MAKEFLAGS environment variable in the target's commands.
+make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
in make[2] in directory "<curdir>"
indirect-comment: mode=compat
indirect-silent-comment: mode=parallel
diff --git a/contrib/bmake/unit-tests/parse.exp b/contrib/bmake/unit-tests/parse.exp
index 86d12effb5c7..4f97a9350550 100644
--- a/contrib/bmake/unit-tests/parse.exp
+++ b/contrib/bmake/unit-tests/parse.exp
@@ -1,6 +1,6 @@
-make: parse.mk:7: Invalid line '<<<<<< old'
-make: parse.mk:14: Invalid line '>>>>>> new'
-make: parse.mk:25: Invalid line 'one-target ${:U }', expanded to 'one-target '
+make: parse.mk:7: Invalid line "<<<<<< old"
+make: parse.mk:14: Invalid line ">>>>>> new"
+make: parse.mk:25: Invalid line "one-target ${:U }", expanded to "one-target "
make: Fatal errors encountered -- cannot continue
make: stopped making "Try_to_crash_FreeBSD.xxxxxxxxxxxxxxxxxx" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/parse.mk b/contrib/bmake/unit-tests/parse.mk
index 80a51f2de11e..fb959a4a5e1b 100644
--- a/contrib/bmake/unit-tests/parse.mk
+++ b/contrib/bmake/unit-tests/parse.mk
@@ -1,16 +1,16 @@
-# $NetBSD: parse.mk,v 1.7 2023/08/19 11:09:02 rillig Exp $
+# $NetBSD: parse.mk,v 1.8 2025/06/28 22:39:29 rillig Exp $
#
# Test those parts of the parsing that do not belong in any of the other
# categories.
-# expect+1: Invalid line '<<<<<< old'
+# expect+1: Invalid line "<<<<<< old"
<<<<<< old
# No diagnostic since the following line is parsed as a variable assignment,
# even though the variable name is empty. See also varname-empty.mk.
====== middle
-# expect+1: Invalid line '>>>>>> new'
+# expect+1: Invalid line ">>>>>> new"
>>>>>> new
@@ -21,7 +21,7 @@
# the expanded line's terminating '\0'.
#
# https://bugs.freebsd.org/265119
-# expect+1: Invalid line 'one-target ${:U }', expanded to 'one-target '
+# expect+1: Invalid line "one-target ${:U }", expanded to "one-target "
one-target ${:U }
diff --git a/contrib/bmake/unit-tests/var-op-assign.exp b/contrib/bmake/unit-tests/var-op-assign.exp
index 4e287e518eb7..83459de4184d 100644
--- a/contrib/bmake/unit-tests/var-op-assign.exp
+++ b/contrib/bmake/unit-tests/var-op-assign.exp
@@ -1,5 +1,5 @@
this will be evaluated later
-make: var-op-assign.mk:60: Invalid line 'VARIABLE NAME= variable value'
+make: var-op-assign.mk:60: Invalid line "VARIABLE NAME= variable value"
make: var-op-assign.mk:95: Parsing still continues until here.
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
diff --git a/contrib/bmake/unit-tests/var-op-assign.mk b/contrib/bmake/unit-tests/var-op-assign.mk
index a900c28a918d..a218dbfdac0a 100644
--- a/contrib/bmake/unit-tests/var-op-assign.mk
+++ b/contrib/bmake/unit-tests/var-op-assign.mk
@@ -1,4 +1,4 @@
-# $NetBSD: var-op-assign.mk,v 1.11 2023/11/19 21:47:52 rillig Exp $
+# $NetBSD: var-op-assign.mk,v 1.12 2025/06/28 22:39:29 rillig Exp $
#
# Tests for the = variable assignment operator, which overwrites an existing
# variable or creates it.
@@ -56,7 +56,7 @@ VAR= ${:! echo 'this will be evaluated later' 1>&2 !}
# In a variable assignment, the variable name must consist of a single word.
# The following line therefore generates a parse error.
-# expect+1: Invalid line 'VARIABLE NAME= variable value'
+# expect+1: Invalid line "VARIABLE NAME= variable value"
VARIABLE NAME= variable value
# But if the whitespace appears inside parentheses or braces, everything is
diff --git a/contrib/bmake/unit-tests/var-op-expand.exp b/contrib/bmake/unit-tests/var-op-expand.exp
index 105d2f50acc8..5e2c3d1936d7 100644
--- a/contrib/bmake/unit-tests/var-op-expand.exp
+++ b/contrib/bmake/unit-tests/var-op-expand.exp
@@ -1,22 +1,20 @@
make: var-op-expand.mk:274: Unknown modifier ":s,value,replaced,"
while evaluating variable "later" with value ""
while evaluating variable "indirect" with value "${later:s,value,replaced,} ok ${later:value=sysv}"
-make: var-op-expand.mk:278: warning: XXX Neither branch should be taken.
-make: var-op-expand.mk:283: Unknown modifier ":s,value,replaced,"
+make: var-op-expand.mk:282: Unknown modifier ":s,value,replaced,"
while evaluating variable "later" with value "lowercase-value"
while evaluating variable "indirect" with value "${later:s,value,replaced,} ok ${later:value=sysv}"
-make: var-op-expand.mk:285: warning: XXX Neither branch should be taken.
-make: var-op-expand.mk:297: Bad condition
+make: var-op-expand.mk:295: Bad condition
while evaluating condition " < 0 "
-make: var-op-expand.mk:297: Unknown modifier ":Z1"
+make: var-op-expand.mk:295: Unknown modifier ":Z1"
while parsing "${:Z1}:${:Z2}}"
while evaluating then-branch of condition " < 0 "
-make: var-op-expand.mk:297: Unknown modifier ":Z2"
+make: var-op-expand.mk:295: Unknown modifier ":Z2"
while parsing "${:Z2}}"
while evaluating else-branch of condition " < 0 "
-make: var-op-expand.mk:297: Unknown modifier ":Z1"
+make: var-op-expand.mk:295: Unknown modifier ":Z1"
while evaluating "${:Z1}:${:Z2}}" with value ""
-make: var-op-expand.mk:297: Unknown modifier ":Z2"
+make: var-op-expand.mk:295: Unknown modifier ":Z2"
while evaluating "${:Z2}}" with value ""
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
diff --git a/contrib/bmake/unit-tests/var-op-expand.mk b/contrib/bmake/unit-tests/var-op-expand.mk
index 6a49648f0618..fb9e1713438b 100644
--- a/contrib/bmake/unit-tests/var-op-expand.mk
+++ b/contrib/bmake/unit-tests/var-op-expand.mk
@@ -1,4 +1,4 @@
-# $NetBSD: var-op-expand.mk,v 1.24 2025/04/30 06:01:07 rillig Exp $
+# $NetBSD: var-op-expand.mk,v 1.25 2025/06/29 11:27:21 rillig Exp $
#
# Tests for the := variable assignment operator, which expands its
# right-hand side.
@@ -274,15 +274,13 @@ indirect:= ${INDIRECT:tl}
.if ${indirect} != " ok "
. error
.else
-# expect+1: warning: XXX Neither branch should be taken.
-. warning XXX Neither branch should be taken.
+. error
.endif
LATER= uppercase-value
later= lowercase-value
# expect+1: Unknown modifier ":s,value,replaced,"
.if ${indirect} != "uppercase-replaced ok uppercase-sysv"
-# expect+1: warning: XXX Neither branch should be taken.
-. warning XXX Neither branch should be taken.
+. error
.else
. error
.endif
diff --git a/contrib/bmake/unit-tests/varmisc.exp b/contrib/bmake/unit-tests/varmisc.exp
index 509dbcc5e689..44b3c8e759cb 100644
--- a/contrib/bmake/unit-tests/varmisc.exp
+++ b/contrib/bmake/unit-tests/varmisc.exp
@@ -57,7 +57,7 @@ make: Unclosed variable "PATTERN"
while evaluating variable "UNCLOSED" with value ""
in command "@echo ${UNCLOSED:M${PATTERN"
in target "varerror-unclosed-5"
-make: Unclosed expression, expecting '}' for modifier "M${PATTERN"
+make: Unclosed expression, expecting "}" for modifier "M${PATTERN"
while evaluating variable "UNCLOSED" with value ""
in command "@echo ${UNCLOSED:M${PATTERN"
in target "varerror-unclosed-5"
diff --git a/contrib/bmake/unit-tests/varmisc.mk b/contrib/bmake/unit-tests/varmisc.mk
index b067742e9ac4..e36396633dc2 100644
--- a/contrib/bmake/unit-tests/varmisc.mk
+++ b/contrib/bmake/unit-tests/varmisc.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmisc.mk,v 1.37 2024/08/29 20:20:36 rillig Exp $
+# $NetBSD: varmisc.mk,v 1.38 2025/06/28 22:39:29 rillig Exp $
#
# Miscellaneous variable tests.
@@ -200,7 +200,7 @@ varerror-unclosed-4:
# expect: make: Unclosed variable "UNCLOSED"
@echo ${UNCLOSED
varerror-unclosed-5:
-# expect: make: Unclosed expression, expecting '}' for modifier "M${PATTERN"
+# expect: make: Unclosed expression, expecting "}" for modifier "M${PATTERN"
@echo ${UNCLOSED:M${PATTERN
varerror-unclosed-6:
# expect: make: Unclosed variable "param"
diff --git a/contrib/bmake/unit-tests/varmod-edge.exp b/contrib/bmake/unit-tests/varmod-edge.exp
index 2b41623bb66c..b80380fb702c 100644
--- a/contrib/bmake/unit-tests/varmod-edge.exp
+++ b/contrib/bmake/unit-tests/varmod-edge.exp
@@ -1,8 +1,8 @@
-make: varmod-edge.mk:60: Unclosed expression, expecting '}' for modifier "U*)"
+make: varmod-edge.mk:60: Unclosed expression, expecting "}" for modifier "U*)"
while evaluating "${:U*)" with value "*)"
while evaluating variable "INP" with value "(parentheses)"
while evaluating variable "MOD" with value "${INP:M${:U*)}}"
-make: varmod-edge.mk:88: Unfinished character list in pattern '[[' of modifier ':M'
+make: varmod-edge.mk:88: Unfinished character list in pattern "[[" of modifier ":M"
while evaluating variable "INP" with value "[ [[ [[["
while evaluating variable "MOD" with value "${INP:M${:U[[}}"
make: varmod-edge.mk:178: Unfinished modifier after "a\=b}", expecting "="
diff --git a/contrib/bmake/unit-tests/varmod-edge.mk b/contrib/bmake/unit-tests/varmod-edge.mk
index 473c7ad171e5..b5f879372afd 100644
--- a/contrib/bmake/unit-tests/varmod-edge.mk
+++ b/contrib/bmake/unit-tests/varmod-edge.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-edge.mk,v 1.36 2025/03/29 19:08:52 rillig Exp $
+# $NetBSD: varmod-edge.mk,v 1.37 2025/06/28 22:39:29 rillig Exp $
#
# Tests for edge cases in variable modifiers.
#
@@ -56,7 +56,7 @@ EXP= \(\{}\):
INP= (parentheses)
MOD= ${INP:M${:U*)}}
EXP= (parentheses)}
-# expect+1: Unclosed expression, expecting '}' for modifier "U*)"
+# expect+1: Unclosed expression, expecting "}" for modifier "U*)"
.if ${MOD} != ${EXP}
. warning expected "${EXP}", got "${MOD}"
.endif
@@ -84,7 +84,7 @@ EXP= [
INP= [ [[ [[[
MOD= ${INP:M${:U[[}}
EXP= [
-# expect+1: Unfinished character list in pattern '[[' of modifier ':M'
+# expect+1: Unfinished character list in pattern "[[" of modifier ":M"
.if ${MOD} != ${EXP}
. warning expected "${EXP}", got "${MOD}"
.endif
diff --git a/contrib/bmake/unit-tests/varmod-ifelse.exp b/contrib/bmake/unit-tests/varmod-ifelse.exp
index 039f0fd0b9a7..bf642c86fc8c 100644
--- a/contrib/bmake/unit-tests/varmod-ifelse.exp
+++ b/contrib/bmake/unit-tests/varmod-ifelse.exp
@@ -12,26 +12,25 @@ Comparing 1.000000 == 0.000000
make: varmod-ifelse.mk:94: Bad condition
while evaluating condition "1 == == 2"
Comparing "" != ""
-make: varmod-ifelse.mk:98: warning: Oops, the parse error should have been propagated.
CondParser_Eval: ${ ${:U\$}{VAR} == value:?ok:bad} != "ok"
CondParser_Eval: ${VAR} == value
Comparing "value" == "value"
Comparing "ok" != "ok"
-make: varmod-ifelse.mk:160: no.
-make: varmod-ifelse.mk:163: Comparison with '>=' requires both operands 'no' and '10' to be numeric
+make: varmod-ifelse.mk:159: no.
+make: varmod-ifelse.mk:162: Comparison with ">=" requires both operands "no" and "10" to be numeric
while evaluating condition "string == "literal" || no >= 10"
-make: varmod-ifelse.mk:163: .
-make: varmod-ifelse.mk:170: Bad condition
+make: varmod-ifelse.mk:162: .
+make: varmod-ifelse.mk:169: Bad condition
while evaluating condition "string == "literal" && >= 10"
-make: varmod-ifelse.mk:170: .
-make: varmod-ifelse.mk:173: Bad condition
+make: varmod-ifelse.mk:169: .
+make: varmod-ifelse.mk:172: Bad condition
while evaluating condition "string == "literal" || >= 10"
-make: varmod-ifelse.mk:173: .
-make: varmod-ifelse.mk:181: <true>
-make: varmod-ifelse.mk:184: <false>
-make: varmod-ifelse.mk:188: Bad condition
+make: varmod-ifelse.mk:172: .
+make: varmod-ifelse.mk:180: <true>
+make: varmod-ifelse.mk:183: <false>
+make: varmod-ifelse.mk:187: Bad condition
while evaluating condition " "
-make: varmod-ifelse.mk:188: <>
+make: varmod-ifelse.mk:187: <>
CondParser_Eval: 0 && ${1:?${:Uthen0:S,}},,}:${:Uelse0:S,}},,}} != "not evaluated"
CondParser_Eval: 1 && ${0:?${:Uthen1:S,}},,}:${:Uelse1:S,}},,}} != "else1"
CondParser_Eval: 0
@@ -41,31 +40,31 @@ CondParser_Eval: 1
Comparing "then2" != "then2"
CondParser_Eval: ${DELAYED} == "one"
Comparing "two" == "one"
-make: varmod-ifelse.mk:284: no
+make: varmod-ifelse.mk:283: no
CondParser_Eval: ${DELAYED} == "two"
Comparing "two" == "two"
-make: varmod-ifelse.mk:286: yes
+make: varmod-ifelse.mk:285: yes
CondParser_Eval: ${DELAYED} == "one"
Comparing "two" == "one"
-make: varmod-ifelse.mk:289: no
+make: varmod-ifelse.mk:288: no
CondParser_Eval: ${DELAYED} == "two"
Comparing "two" == "two"
-make: varmod-ifelse.mk:292: yes
-make: varmod-ifelse.mk:314: Unknown modifier ":X-then"
+make: varmod-ifelse.mk:291: yes
+make: varmod-ifelse.mk:313: Unknown modifier ":X-then"
while evaluating "${:X-then}:${:X-else}}" with value ""
while evaluating then-branch of condition "1"
-make: varmod-ifelse.mk:314: Unknown modifier ":X-else"
+make: varmod-ifelse.mk:313: Unknown modifier ":X-else"
while parsing "${:X-else}}"
while evaluating else-branch of condition "1"
-make: varmod-ifelse.mk:322: Bad condition
+make: varmod-ifelse.mk:321: Bad condition
while evaluating condition " < 0 "
-make: varmod-ifelse.mk:322: Unknown modifier ":Z1"
+make: varmod-ifelse.mk:321: Unknown modifier ":Z1"
while parsing "${:Z1}:${:Z2}}>"
while evaluating then-branch of condition " < 0 "
-make: varmod-ifelse.mk:322: Unknown modifier ":Z2"
+make: varmod-ifelse.mk:321: Unknown modifier ":Z2"
while parsing "${:Z2}}>"
while evaluating else-branch of condition " < 0 "
-make: varmod-ifelse.mk:322: <>
+make: varmod-ifelse.mk:321: <>
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/varmod-ifelse.mk b/contrib/bmake/unit-tests/varmod-ifelse.mk
index 986524330a97..fcd483d0c497 100644
--- a/contrib/bmake/unit-tests/varmod-ifelse.mk
+++ b/contrib/bmake/unit-tests/varmod-ifelse.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-ifelse.mk,v 1.39 2025/04/30 06:01:07 rillig Exp $
+# $NetBSD: varmod-ifelse.mk,v 1.41 2025/06/29 11:27:21 rillig Exp $
#
# Tests for the ${cond:?then:else} variable modifier, which evaluates either
# the then-expression or the else-expression, depending on the condition.
@@ -73,9 +73,9 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign}
. error
.endif
-# If the "Bad conditional expression" appears in a quoted string literal, the
+# If the "Bad condition" appears in a quoted string literal, the
# error message "Malformed conditional" is not printed, leaving only the "Bad
-# conditional expression".
+# condition".
#
# XXX: The left-hand side is enclosed in quotes. This results in Var_Parse
# being called without VARE_EVAL_DEFINED. When ApplyModifier_IfElse
@@ -94,8 +94,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign}
.if "${1 == == 2:?yes:no}" != ""
. error
.else
-# expect+1: warning: Oops, the parse error should have been propagated.
-. warning Oops, the parse error should have been propagated.
+. error
.endif
.MAKEFLAGS: -d0
@@ -158,7 +157,7 @@ STRING= string
NUMBER= no # not really a number
# expect+1: no.
.info ${${STRING} == "literal" && ${NUMBER} >= 10:?yes:no}.
-# expect+2: Comparison with '>=' requires both operands 'no' and '10' to be numeric
+# expect+2: Comparison with ">=" requires both operands "no" and "10" to be numeric
# expect+1: .
.info ${${STRING} == "literal" || ${NUMBER} >= 10:?yes:no}.
diff --git a/contrib/bmake/unit-tests/varmod-match-escape.exp b/contrib/bmake/unit-tests/varmod-match-escape.exp
index 25d78226345c..42e470310d4c 100755
--- a/contrib/bmake/unit-tests/varmod-match-escape.exp
+++ b/contrib/bmake/unit-tests/varmod-match-escape.exp
@@ -33,14 +33,18 @@ Comparing ":" != "::"
make: varmod-match-escape.mk:43: warning: XXX: Oops
Global: .MAKEFLAGS = -r -k -d cv -d
Global: .MAKEFLAGS = -r -k -d cv -d 0
-make: varmod-match-escape.mk:69: Dollar followed by nothing
+make: varmod-match-escape.mk:63: Unfinished backslash at the end in pattern "\" of modifier ":M"
while evaluating "${:U\$:M\$} != """ with value "$"
-make: varmod-match-escape.mk:110: Unfinished character list in pattern '[A-]' of modifier ':M'
+make: varmod-match-escape.mk:71: Dollar followed by nothing
+ while evaluating "${:U\$:M\$} != """ with value "$"
+make: varmod-match-escape.mk:71: Unfinished backslash at the end in pattern "\" of modifier ":M"
+ while evaluating "${:U\$:M\$} != """ with value "$"
+make: varmod-match-escape.mk:112: Unfinished character list in pattern "[A-]" of modifier ":M"
while evaluating variable "WORDS" with value "A A] A]] B B] B]] ] ]] ]]] a a] a]]"
- in .for loop from varmod-match-escape.mk:107 with pattern = [A-]
-make: varmod-match-escape.mk:110: Unfinished character list in pattern '[^A-]' of modifier ':M'
+ in .for loop from varmod-match-escape.mk:109 with pattern = [A-]
+make: varmod-match-escape.mk:112: Unfinished character list in pattern "[^A-]" of modifier ":M"
while evaluating variable "WORDS" with value "A A] A]] B B] B]] ] ]] ]]] a a] a]]"
- in .for loop from varmod-match-escape.mk:107 with pattern = [^A-]
+ in .for loop from varmod-match-escape.mk:109 with pattern = [^A-]
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/varmod-match-escape.mk b/contrib/bmake/unit-tests/varmod-match-escape.mk
index d9e2009f9b60..5c492d9d1f72 100755
--- a/contrib/bmake/unit-tests/varmod-match-escape.mk
+++ b/contrib/bmake/unit-tests/varmod-match-escape.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-match-escape.mk,v 1.18 2024/08/29 20:20:36 rillig Exp $
+# $NetBSD: varmod-match-escape.mk,v 1.20 2025/06/28 22:39:29 rillig Exp $
#
# As of 2020-08-01, the :M and :N modifiers interpret backslashes differently,
# depending on whether there was an expression somewhere before the
@@ -59,13 +59,15 @@ VALUES= : :: :\:
# '\{' nor '\}'. But the text is expanded, and a lonely '$' at the end
# is silently discarded. The resulting expanded pattern is thus '\', that
# is a single backslash.
+# expect+1: Unfinished backslash at the end in pattern "\" of modifier ":M"
.if ${:U\$:M\$} != ""
. error
.endif
# In lint mode, the case of a lonely '$' is covered with an error message.
.MAKEFLAGS: -dL
-# expect+1: Dollar followed by nothing
+# expect+2: Dollar followed by nothing
+# expect+1: Unfinished backslash at the end in pattern "\" of modifier ":M"
.if ${:U\$:M\$} != ""
. error
.endif
@@ -105,8 +107,8 @@ EXP.[^A-]]= a
EXP.[^A-]]]= a]
.for pattern in [A-] [A-]] [A-]]] [^A-] [^A-]] [^A-]]]
-# expect+2: Unfinished character list in pattern '[A-]' of modifier ':M'
-# expect+1: Unfinished character list in pattern '[^A-]' of modifier ':M'
+# expect+2: Unfinished character list in pattern "[A-]" of modifier ":M"
+# expect+1: Unfinished character list in pattern "[^A-]" of modifier ":M"
. if ${WORDS:M${pattern}} != ${EXP.${pattern}}
. warning ${pattern}: ${WORDS:M${pattern}} != ${EXP.${pattern}}
. endif
diff --git a/contrib/bmake/unit-tests/varmod-match.exp b/contrib/bmake/unit-tests/varmod-match.exp
index 14eb7862d815..7bccc4283e32 100644
--- a/contrib/bmake/unit-tests/varmod-match.exp
+++ b/contrib/bmake/unit-tests/varmod-match.exp
@@ -1,22 +1,22 @@
-make: varmod-match.mk:289: Unfinished character list in pattern 'a[' of modifier ':M'
+make: varmod-match.mk:293: Unfinished character list in pattern "a[" of modifier ":M"
while evaluating variable "WORDS" with value "a a["
-make: varmod-match.mk:297: Unfinished character list in pattern 'a[^' of modifier ':M'
+make: varmod-match.mk:301: Unfinished character list in pattern "a[^" of modifier ":M"
while evaluating variable "WORDS" with value "a a[ aX"
-make: varmod-match.mk:305: Unfinished character list in pattern '[-x1-3' of modifier ':M'
+make: varmod-match.mk:309: Unfinished character list in pattern "[-x1-3" of modifier ":M"
while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 [x1-3"
-make: varmod-match.mk:313: Unfinished character list in pattern '*[-x1-3' of modifier ':M'
+make: varmod-match.mk:317: Unfinished character list in pattern "*[-x1-3" of modifier ":M"
while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3"
-make: varmod-match.mk:322: Unfinished character list in pattern '[^-x1-3' of modifier ':M'
+make: varmod-match.mk:326: Unfinished character list in pattern "[^-x1-3" of modifier ":M"
while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 [x1-3"
-make: varmod-match.mk:336: Unfinished character list in pattern '?[\' of modifier ':M'
+make: varmod-match.mk:340: Unfinished character list in pattern "?[\" of modifier ":M"
while evaluating variable "WORDS" with value "\\ \a x\"
-make: varmod-match.mk:344: Unfinished character range in pattern '[x-' of modifier ':M'
+make: varmod-match.mk:348: Unfinished character range in pattern "[x-" of modifier ":M"
while evaluating variable "WORDS" with value "[x- x x- y"
-make: varmod-match.mk:356: Unfinished character range in pattern '[^x-' of modifier ':M'
+make: varmod-match.mk:360: Unfinished character range in pattern "[^x-" of modifier ":M"
while evaluating variable "WORDS" with value "[x- x x- y yyyyy"
-make: varmod-match.mk:363: Unfinished character list in pattern '[' of modifier ':M'
+make: varmod-match.mk:367: Unfinished character list in pattern "[" of modifier ":M"
while evaluating variable " : :: " with value " : :: "
-make: varmod-match.mk:363: Unknown modifier ":]"
+make: varmod-match.mk:367: Unknown modifier ":]"
while evaluating variable " : :: " with value ""
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
diff --git a/contrib/bmake/unit-tests/varmod-match.mk b/contrib/bmake/unit-tests/varmod-match.mk
index 99184989fb83..5894196c9cd5 100644
--- a/contrib/bmake/unit-tests/varmod-match.mk
+++ b/contrib/bmake/unit-tests/varmod-match.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-match.mk,v 1.30 2025/03/29 19:08:52 rillig Exp $
+# $NetBSD: varmod-match.mk,v 1.32 2025/06/29 09:40:13 rillig Exp $
#
# Tests for the ':M' modifier, which keeps only those words that match the
# given pattern.
@@ -13,8 +13,12 @@
# 6. Error handling
# 7. Historical bugs
#
-# See ApplyModifier_Match, ParseModifier_Match, ModifyWord_Match and
-# Str_Match.
+# See also:
+# char-005c-reverse-solidus.mk
+# ApplyModifier_Match
+# ParseModifier_Match
+# ModifyWord_Match
+# Str_Match
# 1. Pattern characters '*', '?' and '\'
@@ -285,7 +289,7 @@ ${:U*}= asterisk
# [ Incomplete empty character list, never matches.
WORDS= a a[
-# expect+1: Unfinished character list in pattern 'a[' of modifier ':M'
+# expect+1: Unfinished character list in pattern "a[" of modifier ":M"
.if ${WORDS:Ma[} != ""
. error
.endif
@@ -293,7 +297,7 @@ WORDS= a a[
# [^ Incomplete negated empty character list, matches any single
# character.
WORDS= a a[ aX
-# expect+1: Unfinished character list in pattern 'a[^' of modifier ':M'
+# expect+1: Unfinished character list in pattern "a[^" of modifier ":M"
.if ${WORDS:Ma[^} != "a[ aX"
. error
.endif
@@ -301,7 +305,7 @@ WORDS= a a[ aX
# [-x1-3 Incomplete character list, matches those elements that can be
# parsed without lookahead.
WORDS= - + x xx 0 1 2 3 4 [x1-3
-# expect+1: Unfinished character list in pattern '[-x1-3' of modifier ':M'
+# expect+1: Unfinished character list in pattern "[-x1-3" of modifier ":M"
.if ${WORDS:M[-x1-3} != "- x 1 2 3"
. error
.endif
@@ -309,7 +313,7 @@ WORDS= - + x xx 0 1 2 3 4 [x1-3
# *[-x1-3 Incomplete character list after a wildcard, matches those
# words that end with one of the characters from the list.
WORDS= - + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3
-# expect+1: Unfinished character list in pattern '*[-x1-3' of modifier ':M'
+# expect+1: Unfinished character list in pattern "*[-x1-3" of modifier ":M"
.if ${WORDS:M*[-x1-3} != "- x xx 1 2 3 01 11 001 011 101 111 [x1-3"
. warning ${WORDS:M*[-x1-3}
.endif
@@ -318,7 +322,7 @@ WORDS= - + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3
# Incomplete negated character list, matches any character
# except those elements that can be parsed without lookahead.
WORDS= - + x xx 0 1 2 3 4 [x1-3
-# expect+1: Unfinished character list in pattern '[^-x1-3' of modifier ':M'
+# expect+1: Unfinished character list in pattern "[^-x1-3" of modifier ":M"
.if ${WORDS:M[^-x1-3} != "+ 0 4"
. error
.endif
@@ -332,7 +336,7 @@ WORDS= - + x xx 0 1 2 3 4 [x1-3
# '\', as there is no following space that could be escaped.
WORDS= \\ \a ${:Ux\\}
PATTERN= ${:U?[\\}
-# expect+1: Unfinished character list in pattern '?[\' of modifier ':M'
+# expect+1: Unfinished character list in pattern "?[\" of modifier ":M"
.if ${WORDS:M${PATTERN}} != "\\\\ x\\"
. error
.endif
@@ -340,7 +344,7 @@ PATTERN= ${:U?[\\}
# [x- Incomplete character list containing an incomplete character
# range, matches only the 'x'.
WORDS= [x- x x- y
-# expect+1: Unfinished character range in pattern '[x-' of modifier ':M'
+# expect+1: Unfinished character range in pattern "[x-" of modifier ":M"
.if ${WORDS:M[x-} != "x"
. error
.endif
@@ -352,13 +356,13 @@ WORDS= [x- x x- y
# XXX: Even matches strings that are longer than a single
# character.
WORDS= [x- x x- y yyyyy
-# expect+1: Unfinished character range in pattern '[^x-' of modifier ':M'
+# expect+1: Unfinished character range in pattern "[^x-" of modifier ":M"
.if ${WORDS:M[^x-} != "[x- y yyyyy"
. error
.endif
# [:] matches never since the ':' starts the next modifier
-# expect+2: Unfinished character list in pattern '[' of modifier ':M'
+# expect+2: Unfinished character list in pattern "[" of modifier ":M"
# expect+1: Unknown modifier ":]"
.if ${ ${:U\:} ${:U\:\:} :L:M[:]} != ":"
. error
diff --git a/contrib/bmake/unit-tests/varmod-mtime.exp b/contrib/bmake/unit-tests/varmod-mtime.exp
index 9960dd877768..53b86b99b867 100644
--- a/contrib/bmake/unit-tests/varmod-mtime.exp
+++ b/contrib/bmake/unit-tests/varmod-mtime.exp
@@ -1,12 +1,12 @@
-make: varmod-mtime.mk:46: Invalid argument '123x' for modifier ':mtime'
+make: varmod-mtime.mk:46: Invalid argument "123x" for modifier ":mtime"
while evaluating variable "no/such/file" with value "no/such/file"
make: varmod-mtime.mk:68: Cannot determine mtime for "no/such/file1": <ENOENT>
while evaluating variable "no/such/file1 no/such/file2" with value "no/such/file1 no/such/file2"
make: varmod-mtime.mk:68: Cannot determine mtime for "no/such/file2": <ENOENT>
while evaluating variable "no/such/file1 no/such/file2" with value "no/such/file1 no/such/file2"
-make: varmod-mtime.mk:78: Invalid argument 'errorhandler-no' for modifier ':mtime'
+make: varmod-mtime.mk:78: Invalid argument "errorhandler-no" for modifier ":mtime"
while evaluating variable "MAKEFILE" with value "varmod-mtime.mk"
-make: varmod-mtime.mk:86: Invalid argument 'warn' for modifier ':mtime'
+make: varmod-mtime.mk:86: Invalid argument "warn" for modifier ":mtime"
while evaluating variable "MAKEFILE" with value "varmod-mtime.mk"
make: varmod-mtime.mk:110: Unknown modifier ":mtim"
while evaluating variable "anything" with value "anything"
diff --git a/contrib/bmake/unit-tests/varmod-mtime.mk b/contrib/bmake/unit-tests/varmod-mtime.mk
index ec33cd698b41..aed7024efd6b 100644
--- a/contrib/bmake/unit-tests/varmod-mtime.mk
+++ b/contrib/bmake/unit-tests/varmod-mtime.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-mtime.mk,v 1.16 2025/06/12 18:51:05 rillig Exp $
+# $NetBSD: varmod-mtime.mk,v 1.17 2025/06/28 22:39:29 rillig Exp $
#
# Tests for the ':mtime' variable modifier, which maps each word of the
# expression to that file's modification time.
@@ -42,7 +42,7 @@ not_found_mtime:= ${no/such/file:L:mtime}
# The fallback timestamp must only be an integer, without trailing characters.
-# expect+1: Invalid argument '123x' for modifier ':mtime'
+# expect+1: Invalid argument "123x" for modifier ":mtime"
.if ${no/such/file:L:mtime=123x}
. error
.else
@@ -74,7 +74,7 @@ _!= rm -f ${COOKIE}
# Only the word 'error' is a special argument to the ':mtime' modifier, all
# other words result in a parse error.
-# expect+1: Invalid argument 'errorhandler-no' for modifier ':mtime'
+# expect+1: Invalid argument "errorhandler-no" for modifier ":mtime"
.if ${MAKEFILE:mtime=errorhandler-no} > 0
.else
. error
@@ -82,7 +82,7 @@ _!= rm -f ${COOKIE}
# Only the word 'error' can be used as a fallback argument to the modifier.
-# expect+1: Invalid argument 'warn' for modifier ':mtime'
+# expect+1: Invalid argument "warn" for modifier ":mtime"
.if ${MAKEFILE:mtime=warn} > 0
. error
.else
diff --git a/contrib/bmake/unit-tests/varmod-order.exp b/contrib/bmake/unit-tests/varmod-order.exp
index f48256c6ae0e..fd18f0e11ee1 100644
--- a/contrib/bmake/unit-tests/varmod-order.exp
+++ b/contrib/bmake/unit-tests/varmod-order.exp
@@ -2,11 +2,11 @@ make: varmod-order.mk:14: Unknown modifier ":OX"
while evaluating variable "WORDS" with value "one two three four five six seven eight nine ten"
make: varmod-order.mk:17: Unknown modifier ":OxXX"
while evaluating variable "WORDS" with value "one two three four five six seven eight nine ten"
-make: varmod-order.mk:20: Unclosed expression, expecting '}' for modifier "O"
+make: varmod-order.mk:20: Unclosed expression, expecting "}" for modifier "O"
while evaluating variable "WORDS" with value "eight five four nine one seven six ten three two"
-make: varmod-order.mk:22: Unclosed expression, expecting '}' for modifier "On"
+make: varmod-order.mk:22: Unclosed expression, expecting "}" for modifier "On"
while evaluating variable "NUMBERS" with value "1 2 3 4 5 6 7 8 9 10"
-make: varmod-order.mk:24: Unclosed expression, expecting '}' for modifier "Onr"
+make: varmod-order.mk:24: Unclosed expression, expecting "}" for modifier "Onr"
while evaluating variable "NUMBERS" with value "10 9 8 7 6 5 4 3 2 1"
make: varmod-order.mk:30: Unknown modifier ":Oxn"
while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2"
diff --git a/contrib/bmake/unit-tests/varmod-order.mk b/contrib/bmake/unit-tests/varmod-order.mk
index c8386ef951dc..f4fa5d10cdf8 100644
--- a/contrib/bmake/unit-tests/varmod-order.mk
+++ b/contrib/bmake/unit-tests/varmod-order.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-order.mk,v 1.19 2025/03/29 23:50:07 rillig Exp $
+# $NetBSD: varmod-order.mk,v 1.20 2025/06/28 22:39:29 rillig Exp $
#
# Tests for the :O variable modifier and its variants, which either sort the
# words of the value or shuffle them.
@@ -16,11 +16,11 @@ _:= ${WORDS:OX}
# expect+1: Unknown modifier ":OxXX"
_:= ${WORDS:OxXX}
-# expect+1: Unclosed expression, expecting '}' for modifier "O"
+# expect+1: Unclosed expression, expecting "}" for modifier "O"
_:= ${WORDS:O
-# expect+1: Unclosed expression, expecting '}' for modifier "On"
+# expect+1: Unclosed expression, expecting "}" for modifier "On"
_:= ${NUMBERS:On
-# expect+1: Unclosed expression, expecting '}' for modifier "Onr"
+# expect+1: Unclosed expression, expecting "}" for modifier "Onr"
_:= ${NUMBERS:Onr
# Shuffling numerically doesn't make sense, so don't allow 'x' and 'n' to be
diff --git a/contrib/bmake/unit-tests/varmod-range.exp b/contrib/bmake/unit-tests/varmod-range.exp
index 768ba9ac2f2d..b98865a4084a 100644
--- a/contrib/bmake/unit-tests/varmod-range.exp
+++ b/contrib/bmake/unit-tests/varmod-range.exp
@@ -1,6 +1,6 @@
make: varmod-range.mk:43: Variable "" is undefined
while evaluating "${:range=5} != """ with value "1 2 3 4 5"
-make: varmod-range.mk:66: Invalid number "x}Rest" != "Rest"" for ':range' modifier
+make: varmod-range.mk:66: Invalid number "x}Rest" != "Rest"" for modifier ":range"
while evaluating "${:U:range=x}Rest" != "Rest"" with value ""
make: varmod-range.mk:76: Unknown modifier ":x0"
while evaluating "${:U:range=0x0}Rest" != "Rest"" with value "1"
diff --git a/contrib/bmake/unit-tests/varmod-range.mk b/contrib/bmake/unit-tests/varmod-range.mk
index 7a60bcc23d86..69dcf6ad1a7d 100644
--- a/contrib/bmake/unit-tests/varmod-range.mk
+++ b/contrib/bmake/unit-tests/varmod-range.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-range.mk,v 1.18 2025/04/04 18:57:01 rillig Exp $
+# $NetBSD: varmod-range.mk,v 1.19 2025/06/28 22:39:29 rillig Exp $
#
# Tests for the :range variable modifier, which generates sequences
# of integers from the given range.
@@ -62,7 +62,7 @@
#
# Since 2020-11-01, the parser issues a more precise "Invalid number" error
# instead.
-# expect+1: Invalid number "x}Rest" != "Rest"" for ':range' modifier
+# expect+1: Invalid number "x}Rest" != "Rest"" for modifier ":range"
.if "${:U:range=x}Rest" != "Rest"
. error
.else
diff --git a/contrib/bmake/unit-tests/varmod.exp b/contrib/bmake/unit-tests/varmod.exp
index 09c922aa16bd..022181d05cf1 100644
--- a/contrib/bmake/unit-tests/varmod.exp
+++ b/contrib/bmake/unit-tests/varmod.exp
@@ -1,47 +1,54 @@
make: varmod.mk:111: To escape a dollar, use \$, not $$, at "$$:L} != """
-make: varmod.mk:111: Invalid variable name ':', at "$:L} != """
+make: varmod.mk:111: Invalid variable name ":", at "$:L} != """
make: varmod.mk:117: Dollar followed by nothing
while evaluating "${:Uword:@word@${word}$@} != "word"" with value "word"
-make: varmod.mk:127: Missing delimiter ':' after modifier "P"
+make: varmod.mk:125: Missing delimiter ":" after modifier "P"
while evaluating variable "VAR" with value "VAR"
-make: varmod.mk:129: Missing argument for ".error"
-make: varmod.mk:135: Invalid modifier ":[99333000222000111000]"
+make: varmod.mk:134: Invalid modifier ":[99333000222000111000]"
while evaluating variable "word" with value "word"
-make: varmod.mk:138: Invalid modifier ":[2147483648]"
+make: varmod.mk:137: Invalid modifier ":[2147483648]"
while evaluating variable "word" with value "word"
-make: varmod.mk:144: Invalid number "99333000222000111000}" for ':range' modifier
+make: varmod.mk:143: Invalid number "99333000222000111000}" for modifier ":range"
while evaluating variable "word" with value "word"
-make: varmod.mk:151: Invalid time value "\"
+make: varmod.mk:150: Invalid time value "\"
while evaluating indirect modifiers "gmtime=\"
while evaluating "${:${:Ugmtime=\\}}" with value ""
-make: varmod.mk:166: Dollar followed by nothing
+make: varmod.mk:165: Dollar followed by nothing
while evaluating variable "VAR" with value "value$"
-make: varmod.mk:172: Dollar followed by nothing
+make: varmod.mk:171: Dollar followed by nothing
while evaluating variable "VAR" with value "value$"
-make: varmod.mk:172: Dollar followed by nothing
+make: varmod.mk:171: Dollar followed by nothing
while evaluating variable "VAR" with value "value$ appended$"
-make: varmod.mk:182: Dollar followed by nothing
+make: varmod.mk:181: Dollar followed by nothing
while evaluating variable "word" with value "word"
-make: varmod.mk:186: Invalid modifier ":[$]"
+make: varmod.mk:185: Invalid modifier ":[$]"
while evaluating variable "word" with value ""
-make: varmod.mk:203: Dollar followed by nothing
+make: varmod.mk:202: Dollar followed by nothing
while evaluating variable "VAR" with value "value$ appended$"
-make: varmod.mk:203: Invalid variable name '}', at "$} != "set""
+make: varmod.mk:202: Invalid variable name "}", at "$} != "set""
while evaluating variable "VAR" with value "value<space>appended"
-make: varmod.mk:207: Invalid variable name '}', at "$} != "fallback""
+make: varmod.mk:206: Invalid variable name "}", at "$} != "fallback""
while evaluating "${:Ufallback$} != "fallback"" with value ""
-make: varmod.mk:211: Invalid time value "1000$"
+make: varmod.mk:210: Invalid time value "1000$"
while evaluating variable "%y" with value "%y"
-make: varmod.mk:217: Invalid time value "1000$"
+make: varmod.mk:216: Invalid time value "1000$"
while evaluating variable "%y" with value "%y"
-make: varmod.mk:223: Dollar followed by nothing
+make: varmod.mk:222: Dollar followed by nothing
while evaluating variable "word" with value "word"
-make: varmod.mk:227: Dollar followed by nothing
+make: varmod.mk:226: Dollar followed by nothing
while evaluating variable "word" with value "word"
-make: varmod.mk:231: Invalid argument 'fallback$' for modifier ':mtime'
+make: varmod.mk:230: Invalid argument "fallback$" for modifier ":mtime"
while evaluating variable "." with value "."
-make: varmod.mk:245: Missing delimiter ':' after modifier "L"
+make: varmod.mk:244: Missing delimiter ":" after modifier "L"
while evaluating variable "VAR" with value "VAR"
+make: varmod.mk:256: Invalid time value " : } \ $ ) \) ( "
+ while evaluating variable "%Y" with value "%Y"
+make: varmod.mk:263: Invalid time value " : \) \ $ "
+ while evaluating variable "%Y" with value "%Y"
+make: varmod.mk:268: Invalid time value " : } \ $ ) \) ( "
+ while evaluating variable "%Y" with value "%Y"
+make: varmod.mk:273: Invalid time value " : \) \ $ "
+ while evaluating variable "%Y" with value "%Y"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/contrib/bmake/unit-tests/varmod.mk b/contrib/bmake/unit-tests/varmod.mk
index cc7b08c447e9..af976f9d0086 100644
--- a/contrib/bmake/unit-tests/varmod.mk
+++ b/contrib/bmake/unit-tests/varmod.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod.mk,v 1.26 2025/03/30 01:27:13 rillig Exp $
+# $NetBSD: varmod.mk,v 1.30 2025/06/29 11:27:21 rillig Exp $
#
# Tests for variable modifiers, such as :Q, :S,from,to or :Ufallback.
#
@@ -107,7 +107,7 @@ DOLLAR2= ${:U\$}
# Should it?
.MAKEFLAGS: -dL
# expect+2: To escape a dollar, use \$, not $$, at "$$:L} != """
-# expect+1: Invalid variable name ':', at "$:L} != """
+# expect+1: Invalid variable name ":", at "$:L} != """
.if ${$$:L} != ""
. error
.endif
@@ -118,14 +118,13 @@ DOLLAR2= ${:U\$}
. error
.endif
-# The variable modifier :P does not fall back to the SysV modifier.
+# The modifier :P does not fall back to the SysV modifier.
# Therefore the modifier :P=RE generates a parse error.
-# XXX: The .error should not be reached since the expression is
-# malformed, and this error should be propagated up to Cond_EvalLine.
VAR= STOP
-# expect+1: Missing delimiter ':' after modifier "P"
+# expect+1: Missing delimiter ":" after modifier "P"
.if ${VAR:P=RE} != "STORE"
-# expect+1: Missing argument for ".error"
+. error
+.else
. error
.endif
@@ -140,7 +139,7 @@ VAR= STOP
# Test the range generation modifier ':range=n' with a very large number that
# is larger than SIZE_MAX for any supported platform.
-# expect+1: Invalid number "99333000222000111000}" for ':range' modifier
+# expect+1: Invalid number "99333000222000111000}" for modifier ":range"
.if ${word:L:range=99333000222000111000}
.endif
@@ -199,11 +198,11 @@ VAR_DOLLAR= VAR$$
. error
.endif
# expect+2: Dollar followed by nothing
-# expect+1: Invalid variable name '}', at "$} != "set""
+# expect+1: Invalid variable name "}", at "$} != "set""
.if ${VAR:Dset$} != "set"
. error
.endif
-# expect+1: Invalid variable name '}', at "$} != "fallback""
+# expect+1: Invalid variable name "}", at "$} != "fallback""
.if ${:Ufallback$} != "fallback"
. error
.endif
@@ -227,7 +226,7 @@ VAR_DOLLAR= VAR$$
.if ${word:L:NX*$} != "word"
. error
.endif
-# expect+1: Invalid argument 'fallback$' for modifier ':mtime'
+# expect+1: Invalid argument "fallback$" for modifier ":mtime"
.if ${.:L:mtime=fallback$}
. error
.else
@@ -241,10 +240,36 @@ VAR_DOLLAR= VAR$$
.endif
.undef VAR
-# expect+1: Missing delimiter ':' after modifier "L"
+# expect+1: Missing delimiter ":" after modifier "L"
.if ${VAR:LAR=ALUE} != "VALUE"
. error
.endif
.if ${VAR:L:AR=ALUE} != "VALUE"
. error
.endif
+
+
+# When an expression has the usual form ${...} with braces,
+# in the part of a modifier, ":}\$" can be escaped using a backslash.
+# All other characters are passed through unmodified.
+# expect+1: Invalid time value " : } \ $ ) \) ( "
+.if ${%Y:L:localtime= \: \} \\ \$ ) \) ( :M*} != ": } \\ \$ ) \\) ("
+. error
+.endif
+# When an expression has the unusual form $(...) with parentheses,
+# in the part of a modifier, ":)\$" can be escaped using a backslash.
+# All other characters are passed through unmodified.
+# expect+1: Invalid time value " : \) \ $ "
+.if ${%Y:L:localtime= \: \) \\ \$ } \} { :M*} != ": ) \\ \$ } \\} {"
+. error
+.endif
+# Same when the modifier is the last modifier in an expression.
+# expect+1: Invalid time value " : } \ $ ) \) ( "
+.if ${%Y:L:localtime= \: \} \\ \$ ) \) ( } != " : } \\ \$ ) \\) ( "
+. error
+.endif
+# Same when the modifier is the last modifier in an expression.
+# expect+1: Invalid time value " : \) \ $ "
+.if ${%Y:L:localtime= \: \) \\ \$ } \} { } != " : ) \\ \$ } \\} { "
+. error
+.endif
diff --git a/contrib/bmake/unit-tests/varname-circumflex.exp b/contrib/bmake/unit-tests/varname-circumflex.exp
new file mode 100644
index 000000000000..184b021fd5e5
--- /dev/null
+++ b/contrib/bmake/unit-tests/varname-circumflex.exp
@@ -0,0 +1,9 @@
+no_prerequisites:
+prerequisite: file1.o
+unique: file1.o file2.o file3.o
+duplicate: file1.o file2.o file3.o
+dir_part: /usr/include /usr/include .
+file_part: stdio.h unistd.h foo.h
+implicit.tout: implicit.tin
+wait: file1.o .WAIT_1 file2.o
+exit status 0
diff --git a/contrib/bmake/unit-tests/varname-circumflex.mk b/contrib/bmake/unit-tests/varname-circumflex.mk
new file mode 100644
index 000000000000..270f7123781b
--- /dev/null
+++ b/contrib/bmake/unit-tests/varname-circumflex.mk
@@ -0,0 +1,47 @@
+# $NetBSD: varname-circumflex.mk,v 1.1 2025/06/27 20:20:56 rillig Exp $
+#
+# Tests for the target-local variable "^", which is required by POSIX 2024
+# and provided by GNU make.
+
+# TODO: Support $^.
+
+all: .PHONY
+all: no_prerequisites prerequisite
+all: unique duplicate
+all: dir_part file_part
+all: implicit.tout
+all: wait
+
+.if defined(^)
+. error
+.endif
+
+no_prerequisites:
+ @echo $@: $^
+
+prerequisite: file1.o
+ @echo $@: $^
+
+unique: file1.o file2.o file3.o
+ @echo $@: $^
+
+duplicate: file1.o file2.o file3.o file3.o
+ @echo $@: $^
+
+dir_part: /usr/include/stdio.h /usr/include/unistd.h foo.h
+ @echo $@: $(^D)
+
+file_part: /usr/include/stdio.h /usr/include/unistd.h foo.h
+ @echo $@: ${^F}
+
+wait: file1.o .WAIT file2.o
+ @echo $@: $^
+
+.SUFFIXES:
+.SUFFIXES: .tin .tout
+
+.tin.tout:
+ @echo $@: $^
+
+file1.o file2.o file3.o:
+/usr/include/stdio.h /usr/include/unistd.h foo.h implicit.tin:
diff --git a/contrib/bmake/unit-tests/varname-vpath.exp b/contrib/bmake/unit-tests/varname-vpath.exp
index bf7a3036e99d..a750957b92ac 100644
--- a/contrib/bmake/unit-tests/varname-vpath.exp
+++ b/contrib/bmake/unit-tests/varname-vpath.exp
@@ -1,12 +1,12 @@
CondParser_Eval: !defined(TEST_MAIN)
CondParser_Eval: exists(file-in-subdirectory)
-exists(file-in-subdirectory) result is ""
+"file-in-subdirectory" does not exist
CondParser_Eval: exists(file2-in-subdirectory)
-exists(file2-in-subdirectory) result is ""
+"file2-in-subdirectory" does not exist
CondParser_Eval: exists(file-in-subdirectory)
-exists(file-in-subdirectory) result is "varname-vpath.dir/file-in-subdirectory"
+"file-in-subdirectory" exists in "varname-vpath.dir/file-in-subdirectory"
: yes 1
CondParser_Eval: exists(file2-in-subdirectory)
-exists(file2-in-subdirectory) result is "varname-vpath.dir2/file2-in-subdirectory"
+"file2-in-subdirectory" exists in "varname-vpath.dir2/file2-in-subdirectory"
: yes 2
exit status 0
diff --git a/contrib/bmake/unit-tests/varname.exp b/contrib/bmake/unit-tests/varname.exp
index d173d2025e9f..454e40cdf9cf 100644
--- a/contrib/bmake/unit-tests/varname.exp
+++ b/contrib/bmake/unit-tests/varname.exp
@@ -5,13 +5,13 @@ Var_Parse: ${VARNAME} (eval)
Global: VAR((( = 3 open parentheses
Var_Parse: ${VAR(((}}}}" != "3 open parentheses}}}" (eval)
Global: .ALLTARGETS = VAR(((=)
-make: varname.mk:31: Missing ')' in archive specification
+make: varname.mk:31: Missing ")" in archive specification
make: varname.mk:31: Error in archive specification: "VAR"
Var_Parse: ${:UVAR\(\(\(}= try2 (eval)
Evaluating modifier ${:U...} on value "" (eval, undefined)
Result of ${:UVAR\(\(\(} is "VAR\(\(\(" (eval, defined)
Global: .ALLTARGETS = VAR(((=) VAR\(\(\(=
-make: varname.mk:37: Invalid line '${:UVAR\(\(\(}= try2', expanded to 'VAR\(\(\(= try2'
+make: varname.mk:37: Invalid line "${:UVAR\(\(\(}= try2", expanded to "VAR\(\(\(= try2"
Var_Parse: ${VARNAME} (eval)
Global: VAR((( = try3
Global: .MAKEFLAGS = -r -k -d v -d
diff --git a/contrib/bmake/unit-tests/varname.mk b/contrib/bmake/unit-tests/varname.mk
index ae18819aa19e..17f29da7ef4c 100644
--- a/contrib/bmake/unit-tests/varname.mk
+++ b/contrib/bmake/unit-tests/varname.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varname.mk,v 1.17 2025/06/12 04:33:00 rillig Exp $
+# $NetBSD: varname.mk,v 1.18 2025/06/28 22:39:29 rillig Exp $
#
# Tests for variable names.
@@ -26,14 +26,14 @@ ${VARNAME}= 3 open parentheses
# This is not a variable assignment since the parentheses and braces are not
# balanced. At the end of the line, there are still 3 levels open, which
# means the variable name is not finished.
-# expect+2: Missing ')' in archive specification
+# expect+2: Missing ")" in archive specification
# expect+1: Error in archive specification: "VAR"
${:UVAR(((}= try1
# On the left-hand side of a variable assignments, the backslash is not parsed
# as an escape character, therefore the parentheses still count to the nesting
# level, which at the end of the line is still 3. Therefore this is not a
# variable assignment as well.
-# expect+1: Invalid line '${:UVAR\(\(\(}= try2', expanded to 'VAR\(\(\(= try2'
+# expect+1: Invalid line "${:UVAR\(\(\(}= try2", expanded to "VAR\(\(\(= try2"
${:UVAR\(\(\(}= try2
# To assign to a variable with an arbitrary name, the variable name has to
# come from an external source, not the text that is parsed in the assignment
diff --git a/contrib/bmake/unit-tests/varparse-errors.exp b/contrib/bmake/unit-tests/varparse-errors.exp
index d4d01c96627e..2a9be069075f 100644
--- a/contrib/bmake/unit-tests/varparse-errors.exp
+++ b/contrib/bmake/unit-tests/varparse-errors.exp
@@ -12,33 +12,33 @@ make: varparse-errors.mk:73: Unknown modifier ":OX"
make: varparse-errors.mk:73: Unknown modifier ":OX"
while evaluating "${:OX}" with value ""
while evaluating variable "IND" with value "${:OX}"
-make: varparse-errors.mk:81: Unclosed expression, expecting '}' for modifier "Q"
+make: varparse-errors.mk:81: Unclosed expression, expecting "}" for modifier "Q"
while evaluating "${:U:Q" with value ""
-make: varparse-errors.mk:83: Unclosed expression, expecting '}' for modifier "sh"
+make: varparse-errors.mk:83: Unclosed expression, expecting "}" for modifier "sh"
while evaluating "${:U:sh" with value ""
-make: varparse-errors.mk:85: Unclosed expression, expecting '}' for modifier "tA"
+make: varparse-errors.mk:85: Unclosed expression, expecting "}" for modifier "tA"
while evaluating "${:U:tA" with value ""
-make: varparse-errors.mk:87: Unclosed expression, expecting '}' for modifier "tsX"
+make: varparse-errors.mk:87: Unclosed expression, expecting "}" for modifier "tsX"
while evaluating "${:U:tsX" with value ""
-make: varparse-errors.mk:89: Unclosed expression, expecting '}' for modifier "ts"
+make: varparse-errors.mk:89: Unclosed expression, expecting "}" for modifier "ts"
while evaluating "${:U:ts" with value ""
-make: varparse-errors.mk:91: Unclosed expression, expecting '}' for modifier "ts\040"
+make: varparse-errors.mk:91: Unclosed expression, expecting "}" for modifier "ts\040"
while evaluating "${:U:ts\040" with value ""
-make: varparse-errors.mk:93: Unclosed expression, expecting '}' for modifier "u"
+make: varparse-errors.mk:93: Unclosed expression, expecting "}" for modifier "u"
while evaluating "${:U:u" with value ""
-make: varparse-errors.mk:95: Unclosed expression, expecting '}' for modifier "H"
+make: varparse-errors.mk:95: Unclosed expression, expecting "}" for modifier "H"
while evaluating "${:U:H" with value "."
-make: varparse-errors.mk:97: Unclosed expression, expecting '}' for modifier "[1]"
+make: varparse-errors.mk:97: Unclosed expression, expecting "}" for modifier "[1]"
while evaluating "${:U:[1]" with value ""
-make: varparse-errors.mk:99: Unclosed expression, expecting '}' for modifier "hash"
+make: varparse-errors.mk:99: Unclosed expression, expecting "}" for modifier "hash"
while evaluating "${:U:hash" with value "b2af338b"
-make: varparse-errors.mk:101: Unclosed expression, expecting '}' for modifier "range"
+make: varparse-errors.mk:101: Unclosed expression, expecting "}" for modifier "range"
while evaluating "${:U:range" with value "1"
-make: varparse-errors.mk:103: Unclosed expression, expecting '}' for modifier "_"
+make: varparse-errors.mk:103: Unclosed expression, expecting "}" for modifier "_"
while evaluating "${:U:_" with value ""
-make: varparse-errors.mk:105: Unclosed expression, expecting '}' for modifier "gmtime"
+make: varparse-errors.mk:105: Unclosed expression, expecting "}" for modifier "gmtime"
while evaluating "${:U:gmtime" with value "<timestamp>"
-make: varparse-errors.mk:107: Unclosed expression, expecting '}' for modifier "localtime"
+make: varparse-errors.mk:107: Unclosed expression, expecting "}" for modifier "localtime"
while evaluating "${:U:localtime" with value "<timestamp>"
make: varparse-errors.tmp:1: Unknown modifier ":Z"
while evaluating "${:Z}" with value ""
diff --git a/contrib/bmake/unit-tests/varparse-errors.mk b/contrib/bmake/unit-tests/varparse-errors.mk
index 2d1142fbb65c..bd74c442e789 100644
--- a/contrib/bmake/unit-tests/varparse-errors.mk
+++ b/contrib/bmake/unit-tests/varparse-errors.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varparse-errors.mk,v 1.25 2025/05/03 08:18:33 rillig Exp $
+# $NetBSD: varparse-errors.mk,v 1.26 2025/06/28 22:39:29 rillig Exp $
# Tests for parsing and evaluating all kinds of expressions.
#
@@ -77,33 +77,33 @@ _:= ${:U:OX:U${IND}} ${:U:OX:U${IND}}
# Before var.c 1.032 from 2022-08-24, make complained about 'Unknown modifier'
# or 'Bad modifier' when in fact the modifier was entirely correct, it was
# just not delimited by either ':' or '}' but instead by '\0'.
-# expect+1: Unclosed expression, expecting '}' for modifier "Q"
+# expect+1: Unclosed expression, expecting "}" for modifier "Q"
UNCLOSED:= ${:U:Q
-# expect+1: Unclosed expression, expecting '}' for modifier "sh"
+# expect+1: Unclosed expression, expecting "}" for modifier "sh"
UNCLOSED:= ${:U:sh
-# expect+1: Unclosed expression, expecting '}' for modifier "tA"
+# expect+1: Unclosed expression, expecting "}" for modifier "tA"
UNCLOSED:= ${:U:tA
-# expect+1: Unclosed expression, expecting '}' for modifier "tsX"
+# expect+1: Unclosed expression, expecting "}" for modifier "tsX"
UNCLOSED:= ${:U:tsX
-# expect+1: Unclosed expression, expecting '}' for modifier "ts"
+# expect+1: Unclosed expression, expecting "}" for modifier "ts"
UNCLOSED:= ${:U:ts
-# expect+1: Unclosed expression, expecting '}' for modifier "ts\040"
+# expect+1: Unclosed expression, expecting "}" for modifier "ts\040"
UNCLOSED:= ${:U:ts\040
-# expect+1: Unclosed expression, expecting '}' for modifier "u"
+# expect+1: Unclosed expression, expecting "}" for modifier "u"
UNCLOSED:= ${:U:u
-# expect+1: Unclosed expression, expecting '}' for modifier "H"
+# expect+1: Unclosed expression, expecting "}" for modifier "H"
UNCLOSED:= ${:U:H
-# expect+1: Unclosed expression, expecting '}' for modifier "[1]"
+# expect+1: Unclosed expression, expecting "}" for modifier "[1]"
UNCLOSED:= ${:U:[1]
-# expect+1: Unclosed expression, expecting '}' for modifier "hash"
+# expect+1: Unclosed expression, expecting "}" for modifier "hash"
UNCLOSED:= ${:U:hash
-# expect+1: Unclosed expression, expecting '}' for modifier "range"
+# expect+1: Unclosed expression, expecting "}" for modifier "range"
UNCLOSED:= ${:U:range
-# expect+1: Unclosed expression, expecting '}' for modifier "_"
+# expect+1: Unclosed expression, expecting "}" for modifier "_"
UNCLOSED:= ${:U:_
-# expect+1: Unclosed expression, expecting '}' for modifier "gmtime"
+# expect+1: Unclosed expression, expecting "}" for modifier "gmtime"
UNCLOSED:= ${:U:gmtime
-# expect+1: Unclosed expression, expecting '}' for modifier "localtime"
+# expect+1: Unclosed expression, expecting "}" for modifier "localtime"
UNCLOSED:= ${:U:localtime
diff --git a/contrib/bmake/var.c b/contrib/bmake/var.c
index 55d20bd324ac..66b18f769371 100644
--- a/contrib/bmake/var.c
+++ b/contrib/bmake/var.c
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.1168 2025/06/13 18:31:08 rillig Exp $ */
+/* $NetBSD: var.c,v 1.1171 2025/06/29 11:02:17 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -143,7 +143,7 @@
#endif
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.1168 2025/06/13 18:31:08 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.1171 2025/06/29 11:02:17 rillig Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -452,6 +452,8 @@ VarNew(FStr name, const char *value,
static Substring
CanonicalVarname(Substring name)
{
+ if (Substring_Equals(name, "^"))
+ return Substring_InitStr(ALLSRC);
if (!(Substring_Length(name) > 0 && name.start[0] == '.'))
return name;
@@ -471,8 +473,6 @@ CanonicalVarname(Substring name)
if (Substring_Equals(name, ".TARGET"))
return Substring_InitStr(TARGET);
- /* GNU make has an additional alias $^ == ${.ALLSRC}. */
-
if (Substring_Equals(name, ".SHELL") && shellPath == NULL)
Shell_Init();
@@ -2134,16 +2134,16 @@ typedef enum ApplyModifierResult {
} ApplyModifierResult;
/*
- * Allow backslashes to escape the delimiter, $, and \, but don't touch other
+ * Allow backslashes to escape the delimiters, $, and \, but don't touch other
* backslashes.
*/
static bool
-IsEscapedModifierPart(const char *p, char delim,
+IsEscapedModifierPart(const char *p, char end1, char end2,
struct ModifyWord_SubstArgs *subst)
{
if (p[0] != '\\' || p[1] == '\0')
return false;
- if (p[1] == delim || p[1] == '\\' || p[1] == '$')
+ if (p[1] == end1 || p[1] == end2 || p[1] == '\\' || p[1] == '$')
return true;
return p[1] == '&' && subst != NULL;
}
@@ -2236,7 +2236,7 @@ ParseModifierPart(
LazyBuf_Init(part, p);
while (*p != '\0' && *p != end1 && *p != end2) {
- if (IsEscapedModifierPart(p, end2, subst)) {
+ if (IsEscapedModifierPart(p, end1, end2, subst)) {
LazyBuf_Add(part, p[1]);
p += 2;
} else if (*p != '$') { /* Unescaped, simple text */
@@ -2703,7 +2703,7 @@ ApplyModifier_Range(const char **pp, ModChain *ch)
const char *p = mod + 6;
if (!TryParseSize(&p, &n)) {
Parse_Error(PARSE_FATAL,
- "Invalid number \"%s\" for ':range' modifier",
+ "Invalid number \"%s\" for modifier \":range\"",
mod + 6);
return AMR_CLEANUP;
}
@@ -2834,7 +2834,7 @@ ModifyWord_Match(Substring word, SepBuf *buf, void *data)
if (res.error != NULL && !args->error_reported) {
args->error_reported = true;
Parse_Error(PARSE_FATAL,
- "%s in pattern '%s' of modifier '%s'",
+ "%s in pattern \"%s\" of modifier \"%s\"",
res.error, args->pattern, args->neg ? ":N" : ":M");
}
if (res.matched != args->neg)
@@ -2927,7 +2927,7 @@ ApplyModifier_Mtime(const char **pp, ModChain *ch)
invalid_argument:
Parse_Error(PARSE_FATAL,
- "Invalid argument '%.*s' for modifier ':mtime'",
+ "Invalid argument \"%.*s\" for modifier \":mtime\"",
(int)strcspn(*pp + 1, ":{}()"), *pp + 1);
return AMR_CLEANUP;
}
@@ -2965,7 +2965,7 @@ ApplyModifier_Subst(const char **pp, ModChain *ch)
char delim = (*pp)[1];
if (delim == '\0') {
Parse_Error(PARSE_FATAL,
- "Missing delimiter for modifier ':S'");
+ "Missing delimiter for modifier \":S\"");
(*pp)++;
return AMR_CLEANUP;
}
@@ -3017,7 +3017,7 @@ ApplyModifier_Regex(const char **pp, ModChain *ch)
char delim = (*pp)[1];
if (delim == '\0') {
Parse_Error(PARSE_FATAL,
- "Missing delimiter for modifier ':C'");
+ "Missing delimiter for modifier \":C\"");
(*pp)++;
return AMR_CLEANUP;
}
@@ -3995,7 +3995,7 @@ ApplyModifiersIndirect(ModChain *ch, const char **pp)
else if (*p == '\0' && ch->endc != '\0') {
Parse_Error(PARSE_FATAL,
"Unclosed expression after indirect modifier, "
- "expecting '%c'",
+ "expecting \"%c\"",
ch->endc);
*pp = p;
return AMIR_OUT;
@@ -4051,14 +4051,14 @@ ApplySingleModifier(const char **pp, ModChain *ch)
if (*p == '\0' && ch->endc != '\0') {
Parse_Error(PARSE_FATAL,
- "Unclosed expression, expecting '%c' for "
+ "Unclosed expression, expecting \"%c\" for "
"modifier \"%.*s\"",
ch->endc, (int)(p - mod), mod);
} else if (*p == ':') {
p++;
} else if (opts.strict && *p != '\0' && *p != ch->endc) {
Parse_Error(PARSE_FATAL,
- "Missing delimiter ':' after modifier \"%.*s\"",
+ "Missing delimiter \":\" after modifier \"%.*s\"",
(int)(p - mod), mod);
/*
* TODO: propagate parse error to the enclosing
@@ -4106,7 +4106,7 @@ ApplyModifiers(
if (*p == '\0' && endc != '\0') {
Parse_Error(PARSE_FATAL,
- "Unclosed expression, expecting '%c'", ch.endc);
+ "Unclosed expression, expecting \"%c\"", ch.endc);
goto cleanup;
}
@@ -4263,7 +4263,7 @@ IsShortVarnameValid(char varname, const char *start)
Parse_Error(PARSE_FATAL, "Dollar followed by nothing");
else if (save_dollars)
Parse_Error(PARSE_FATAL,
- "Invalid variable name '%c', at \"%s\"", varname, start);
+ "Invalid variable name \"%c\", at \"%s\"", varname, start);
return false;
}
@@ -4330,7 +4330,7 @@ FindLocalLegacyVar(Substring varname, GNode *scope,
return NULL;
if (varname.start[1] != 'F' && varname.start[1] != 'D')
return NULL;
- if (strchr("@%?*!<>", varname.start[0]) == NULL)
+ if (strchr("@%?*!<>^", varname.start[0]) == NULL)
return NULL;
v = VarFindSubstring(Substring_Init(varname.start, varname.start + 1),
diff --git a/contrib/bsnmp/lib/snmpclient.c b/contrib/bsnmp/lib/snmpclient.c
index b312a37ed3ed..d5d4af998a0c 100644
--- a/contrib/bsnmp/lib/snmpclient.c
+++ b/contrib/bsnmp/lib/snmpclient.c
@@ -981,14 +981,8 @@ open_client_local(const char *path)
char *ptr;
int stype;
- if (snmp_client.chost == NULL) {
- if ((snmp_client.chost = malloc(1 + sizeof(DEFAULT_LOCAL)))
- == NULL) {
- seterr(&snmp_client, "%s", strerror(errno));
- return (-1);
- }
- strcpy(snmp_client.chost, DEFAULT_LOCAL);
- }
+ if (snmp_client.chost == NULL && path == NULL)
+ path = SNMP_DEFAULT_LOCAL;
if (path != NULL) {
if ((ptr = malloc(1 + strlen(path))) == NULL) {
seterr(&snmp_client, "%s", strerror(errno));
@@ -1012,7 +1006,7 @@ open_client_local(const char *path)
snprintf(snmp_client.local_path, sizeof(snmp_client.local_path),
"%s", SNMP_LOCAL_PATH);
- if (mkstemp(snmp_client.local_path) == -1) {
+ if (mktemp(snmp_client.local_path) == NULL) {
seterr(&snmp_client, "%s", strerror(errno));
(void)close(snmp_client.fd);
snmp_client.fd = -1;
diff --git a/contrib/bsnmp/lib/snmpclient.h b/contrib/bsnmp/lib/snmpclient.h
index a19bdb2ea653..662dc7c4a204 100644
--- a/contrib/bsnmp/lib/snmpclient.h
+++ b/contrib/bsnmp/lib/snmpclient.h
@@ -40,6 +40,7 @@
#define SNMP_STRERROR_LEN 200
+#define SNMP_DEFAULT_LOCAL "/var/run/snmpd.sock"
#define SNMP_LOCAL_PATH "/tmp/snmpXXXXXXXXXXXXXX"
diff --git a/contrib/bsnmp/lib/snmppriv.h b/contrib/bsnmp/lib/snmppriv.h
index 5b66992ca985..6ed51cf39369 100644
--- a/contrib/bsnmp/lib/snmppriv.h
+++ b/contrib/bsnmp/lib/snmppriv.h
@@ -44,4 +44,3 @@ enum snmp_code snmp_pdu_decrypt(const struct snmp_pdu *);
#define DEFAULT_HOST "localhost"
#define DEFAULT_PORT "snmp"
-#define DEFAULT_LOCAL "/var/run/snmp.sock"
diff --git a/contrib/bsnmp/snmpd/main.c b/contrib/bsnmp/snmpd/main.c
index 928b84121f82..c77572934d24 100644
--- a/contrib/bsnmp/snmpd/main.c
+++ b/contrib/bsnmp/snmpd/main.c
@@ -42,6 +42,7 @@
#include <sys/un.h>
#include <sys/ucred.h>
#include <sys/uio.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
@@ -1509,7 +1510,7 @@ main(int argc, char *argv[])
{
int opt;
FILE *fp;
- int background = 1;
+ bool background = true;
struct tport *p;
const char *prefix = "snmpd";
struct lmodule *m;
@@ -1526,11 +1527,6 @@ main(int argc, char *argv[])
NULL
};
- snmp_printf = snmp_printf_func;
- snmp_error = snmp_error_func;
- snmp_debug = snmp_debug_func;
- asn_error = asn_error_func;
-
while ((opt = getopt(argc, argv, "c:dD:e:hI:l:m:p:")) != EOF)
switch (opt) {
@@ -1539,7 +1535,7 @@ main(int argc, char *argv[])
break;
case 'd':
- background = 0;
+ background = false;
break;
case 'D':
@@ -1601,6 +1597,13 @@ main(int argc, char *argv[])
break;
}
+ if (background) {
+ snmp_printf = snmp_printf_func;
+ snmp_error = snmp_error_func;
+ snmp_debug = snmp_debug_func;
+ asn_error = asn_error_func;
+ }
+
openlog(prefix, LOG_PID | (background ? 0 : LOG_PERROR), LOG_USER);
setlogmask(LOG_UPTO(debug.logpri - 1));
diff --git a/contrib/bsnmp/snmpd/trans_lsock.c b/contrib/bsnmp/snmpd/trans_lsock.c
index fa3bd34d14f0..ca2311be7cc3 100644
--- a/contrib/bsnmp/snmpd/trans_lsock.c
+++ b/contrib/bsnmp/snmpd/trans_lsock.c
@@ -417,7 +417,7 @@ lsock_send(struct tport *tp, const u_char *buf, size_t len,
}
}
- return (sendto(peer->input.fd, buf, len, 0, addr, addrlen));
+ return (sendto(peer->input.fd, buf, len, MSG_NOSIGNAL, addr, addrlen));
}
static void
diff --git a/contrib/elftoolchain/libelf/elf_open.3 b/contrib/elftoolchain/libelf/elf_open.3
index 054036a24935..896bf8455ae5 100644
--- a/contrib/elftoolchain/libelf/elf_open.3
+++ b/contrib/elftoolchain/libelf/elf_open.3
@@ -23,11 +23,12 @@
.\"
.\" $Id: elf_open.3 3743 2019-06-12 19:36:30Z jkoshy $
.\"
-.Dd June 12, 2019
+.Dd July 15, 2025
.Dt ELF_OPEN 3
.Os
.Sh NAME
-.Nm elf_open
+.Nm elf_open ,
+.Nm elf_openmemory
.Nd open ELF objects and ar(1) archives
.Sh LIBRARY
.Lb libelf
diff --git a/contrib/elftoolchain/libelf/gelf_xlatetof.3 b/contrib/elftoolchain/libelf/gelf_xlatetof.3
index 2e5ee0fe15e0..4a7b25c99b5a 100644
--- a/contrib/elftoolchain/libelf/gelf_xlatetof.3
+++ b/contrib/elftoolchain/libelf/gelf_xlatetof.3
@@ -23,13 +23,16 @@
.\"
.\" $Id: gelf_xlatetof.3 3639 2018-10-14 14:07:02Z jkoshy $
.\"
-.Dd October 11, 2018
+.Dd July 15, 2025
.Dt GELF_XLATETOF 3
.Os
.Sh NAME
-.Nm elf32_xlate ,
-.Nm elf64_xlate ,
-.Nm gelf_xlate
+.Nm elf32_xlatetof ,
+.Nm elf32_xlatetom ,
+.Nm elf64_xlatetof ,
+.Nm elf64_xlatetom ,
+.Nm gelf_xlatetof ,
+.Nm gelf_xlatetom
.Nd translate data between files and memory
.Sh LIBRARY
.Lb libelf
diff --git a/contrib/less/NEWS b/contrib/less/NEWS
index 5767ded21a00..cdc8196a5f16 100644
--- a/contrib/less/NEWS
+++ b/contrib/less/NEWS
@@ -11,6 +11,16 @@
======================================================================
+ Major changes between "less" versions 678 and 679
+
+* Fix bad parsing of lesskey file an env var is a prefix of another
+ env var (github #626).
+
+* Fix unexpected exit using -K if a key press is received while reading
+ the input file (github #628).
+
+======================================================================
+
Major changes between "less" versions 668 and 678
* Treat -r in LESS environment variable as -R.
diff --git a/contrib/less/decode.c b/contrib/less/decode.c
index 2942a30863cb..8e451d1810c9 100644
--- a/contrib/less/decode.c
+++ b/contrib/less/decode.c
@@ -750,7 +750,7 @@ static int cmd_search(constant char *cmd, constant unsigned char *table, constan
{
action = taction;
*extra = textra;
- } else if (match > 0) /* cmd is a prefix of this table entry */
+ } else if (match > 0 && action == A_INVALID) /* cmd is a prefix of this table entry */
{
action = A_PREFIX;
}
diff --git a/contrib/less/help.c b/contrib/less/help.c
index 81e0943fe4e2..5d8ba9a1b0fe 100644
--- a/contrib/less/help.c
+++ b/contrib/less/help.c
@@ -1,4 +1,4 @@
-/* This file was generated by mkhelp.pl from less.hlp at 20:41 on 2025/5/1 */
+/* This file was generated by mkhelp.pl from less.hlp at 19:46 on 2025/5/28 */
#include "less.h"
constant char helpdata[] = {
'\n',
diff --git a/contrib/less/less.h b/contrib/less/less.h
index 94a3e2235906..7b2d2c25bfc6 100644
--- a/contrib/less/less.h
+++ b/contrib/less/less.h
@@ -575,10 +575,11 @@ typedef enum {
#endif
#endif
-#define S_INTERRUPT 01
-#define S_STOP 02
-#define S_WINCH 04
-#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP))
+#define S_INTERRUPT (1<<0)
+#define S_SWINTERRUPT (1<<1)
+#define S_STOP (1<<2)
+#define S_WINCH (1<<3)
+#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_SWINTERRUPT|S_STOP))
#ifdef EXIT_SUCCESS
#define QUIT_OK EXIT_SUCCESS
diff --git a/contrib/less/less.nro b/contrib/less/less.nro
index 6b74ec5f161b..25a9869a9c59 100644
--- a/contrib/less/less.nro
+++ b/contrib/less/less.nro
@@ -1,5 +1,5 @@
'\" t
-.TH LESS 1 "Version 678: 01 May 2025"
+.TH LESS 1 "Version 679: 28 May 2025"
.SH NAME
less \- display the contents of a file in a terminal
.SH SYNOPSIS
diff --git a/contrib/less/lessecho.nro b/contrib/less/lessecho.nro
index 696fcb13b214..f0cccc4de6da 100644
--- a/contrib/less/lessecho.nro
+++ b/contrib/less/lessecho.nro
@@ -1,4 +1,4 @@
-.TH LESSECHO 1 "Version 678: 01 May 2025"
+.TH LESSECHO 1 "Version 679: 28 May 2025"
.SH NAME
lessecho \- expand metacharacters
.SH SYNOPSIS
diff --git a/contrib/less/lesskey.nro b/contrib/less/lesskey.nro
index 61ba056b04c6..0a17c9deff71 100644
--- a/contrib/less/lesskey.nro
+++ b/contrib/less/lesskey.nro
@@ -1,5 +1,5 @@
'\" t
-.TH LESSKEY 1 "Version 678: 01 May 2025"
+.TH LESSKEY 1 "Version 679: 28 May 2025"
.SH NAME
lesskey \- customize key bindings for less
.SH "SYNOPSIS (deprecated)"
diff --git a/contrib/less/os.c b/contrib/less/os.c
index 98a7ecf70c3c..357cbb356a16 100644
--- a/contrib/less/os.c
+++ b/contrib/less/os.c
@@ -275,7 +275,7 @@ start:
if (ret != 0)
{
if (ret == READ_INTR)
- sigs |= S_INTERRUPT;
+ sigs |= S_SWINTERRUPT;
reading = FALSE;
return (ret);
}
@@ -287,7 +287,7 @@ start:
int c;
c = WIN32getch();
- sigs |= S_INTERRUPT;
+ sigs |= S_SWINTERRUPT;
reading = FALSE;
if (c != CONTROL('C') && c != intr_char)
WIN32ungetch((char) c);
@@ -348,7 +348,7 @@ public int iopen(constant char *filename, int flags)
while (!opening && SET_JUMP(open_label))
{
opening = FALSE;
- if (sigs & S_INTERRUPT)
+ if (sigs & (S_INTERRUPT|S_SWINTERRUPT))
{
sigs = 0;
#if HAVE_SETTABLE_ERRNO
diff --git a/contrib/less/version.c b/contrib/less/version.c
index 9a97f1658940..68a42a6272fa 100644
--- a/contrib/less/version.c
+++ b/contrib/less/version.c
@@ -1047,6 +1047,8 @@ v675 4/3/25 Add ESC-b.
v676 4/16/25 Fix two OSC 8 display bugs.
v677 4/27/25 Fix & filtering bug.
v678 5/1/25 Don't change stty tab setting.
+v679 5/28/25 Fix lesskey parsing bug when env var is prefix of another;
+ fix unexpected exit when using -K.
*/
-char version[] = "678";
+char version[] = "679";
diff --git a/contrib/libbegemot/rpoll.c b/contrib/libbegemot/rpoll.c
index c61b84057eba..f5ce43140205 100644
--- a/contrib/libbegemot/rpoll.c
+++ b/contrib/libbegemot/rpoll.c
@@ -285,8 +285,8 @@ poll_register(int fd, poll_f func, void *arg, int mask)
poll_unblocksig();
if(rpoll_trace)
- fprintf(stderr, "poll_register(%d, %p, %p, %#x)->%tu",
- fd, (void *)func, (void *)arg, mask, p - regs);
+ fprintf(stderr, "%s(%d, %p, %p, %#x)->%tu\n", __func__, fd,
+ (void *)func, (void *)arg, mask, p - regs);
return p - regs;
}
@@ -297,7 +297,7 @@ void
poll_unregister(int handle)
{
if(rpoll_trace)
- fprintf(stderr, "poll_unregister(%d)", handle);
+ fprintf(stderr, "%s(%d)\n", __func__, handle);
poll_blocksig();
@@ -399,8 +399,8 @@ poll_start_utimer(unsigned long long usecs, int repeat, timer_f func, void *arg)
resort = 1;
if(rpoll_trace)
- fprintf(stderr, "poll_start_utimer(%llu, %d, %p, %p)->%tu",
- usecs, repeat, (void *)func, (void *)arg, p - tims);
+ fprintf(stderr, "%s(%llu, %d, %p, %p)->%tu\n", __func__, usecs,
+ repeat, (void *)func, (void *)arg, p - tims);
return p - tims;
}
@@ -418,7 +418,7 @@ poll_stop_timer(int handle)
u_int i;
if(rpoll_trace)
- fprintf(stderr, "poll_stop_timer(%d)", handle);
+ fprintf(stderr, "%s(%d)\n", __func__, handle);
tims[handle].func = NULL;
tims_used--;
@@ -597,9 +597,10 @@ poll_dispatch(int wait)
if(mask) {
if(rpoll_trace)
- fprintf(stderr, "poll_dispatch() -- "
- "file %d/%d %x",
- regs[idx].fd, idx, mask);
+ fprintf(stderr,
+ "%s() -- file %d/%d %x\n",
+ __func__, regs[idx].fd,
+ idx, mask);
(*regs[idx].func)(regs[idx].fd, mask, regs[idx].arg);
}
}
@@ -617,7 +618,8 @@ poll_dispatch(int wait)
if(tims[tfd[i]].when > now)
break;
if(rpoll_trace)
- fprintf(stderr, "rpoll_dispatch() -- timeout %d",tfd[i]);
+ fprintf(stderr, "%s() -- timeout %d\n",
+ __func__, tfd[i]);
(*tims[tfd[i]].func)(tfd[i], tims[tfd[i]].arg);
if(tfd[i] < 0)
continue;
diff --git a/contrib/llvm-project/clang/include/clang/Sema/Sema.h b/contrib/llvm-project/clang/include/clang/Sema/Sema.h
index 7bfdaaae45a9..a59a9342341d 100644
--- a/contrib/llvm-project/clang/include/clang/Sema/Sema.h
+++ b/contrib/llvm-project/clang/include/clang/Sema/Sema.h
@@ -13052,12 +13052,19 @@ public:
/// ForConstraintInstantiation indicates we should continue looking when
/// encountering a lambda generic call operator, and continue looking for
/// arguments on an enclosing class template.
+ ///
+ /// \param SkipForSpecialization when specified, any template specializations
+ /// in a traversal would be ignored.
+ /// \param ForDefaultArgumentSubstitution indicates we should continue looking
+ /// when encountering a specialized member function template, rather than
+ /// returning immediately.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
bool ForConstraintInstantiation = false,
- bool SkipForSpecialization = false);
+ bool SkipForSpecialization = false,
+ bool ForDefaultArgumentSubstitution = false);
/// RAII object to handle the state changes required to synthesize
/// a function body.
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a09e3be83c45..c2e8ed0c602e 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -269,7 +269,8 @@ HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec,
Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
MultiLevelTemplateArgumentList &Result,
const FunctionDecl *Pattern, bool RelativeToPrimary,
- bool ForConstraintInstantiation) {
+ bool ForConstraintInstantiation,
+ bool ForDefaultArgumentSubstitution) {
// Add template arguments from a function template specialization.
if (!RelativeToPrimary &&
Function->getTemplateSpecializationKindForInstantiation() ==
@@ -299,7 +300,8 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
// If this function was instantiated from a specialized member that is
// a function template, we're done.
assert(Function->getPrimaryTemplate() && "No function template?");
- if (Function->getPrimaryTemplate()->isMemberSpecialization())
+ if (!ForDefaultArgumentSubstitution &&
+ Function->getPrimaryTemplate()->isMemberSpecialization())
return Response::Done();
// If this function is a generic lambda specialization, we are done.
@@ -465,7 +467,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
const NamedDecl *ND, const DeclContext *DC, bool Final,
std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
const FunctionDecl *Pattern, bool ForConstraintInstantiation,
- bool SkipForSpecialization) {
+ bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) {
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
// Accumulate the set of template argument lists in this structure.
MultiLevelTemplateArgumentList Result;
@@ -507,7 +509,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
SkipForSpecialization);
} else if (const auto *Function = dyn_cast<FunctionDecl>(CurDecl)) {
R = HandleFunction(*this, Function, Result, Pattern, RelativeToPrimary,
- ForConstraintInstantiation);
+ ForConstraintInstantiation,
+ ForDefaultArgumentSubstitution);
} else if (const auto *Rec = dyn_cast<CXXRecordDecl>(CurDecl)) {
R = HandleRecordDecl(*this, Rec, Result, Context,
ForConstraintInstantiation);
@@ -3231,7 +3234,6 @@ bool Sema::SubstDefaultArgument(
// default argument expression appears.
ContextRAII SavedContext(*this, FD);
std::unique_ptr<LocalInstantiationScope> LIS;
- MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;
if (ForCallExpr) {
// When instantiating a default argument due to use in a call expression,
@@ -3244,19 +3246,10 @@ bool Sema::SubstDefaultArgument(
/*ForDefinition*/ false);
if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
return true;
- const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
- if (PrimaryTemplate && PrimaryTemplate->isOutOfLine()) {
- TemplateArgumentList *CurrentTemplateArgumentList =
- TemplateArgumentList::CreateCopy(getASTContext(),
- TemplateArgs.getInnermost());
- NewTemplateArgs = getTemplateInstantiationArgs(
- FD, FD->getDeclContext(), /*Final=*/false,
- CurrentTemplateArgumentList->asArray(), /*RelativeToPrimary=*/true);
- }
}
runWithSufficientStackSpace(Loc, [&] {
- Result = SubstInitializer(PatternExpr, NewTemplateArgs,
+ Result = SubstInitializer(PatternExpr, TemplateArgs,
/*DirectInit*/ false);
});
}
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a12d2eff1d2c..614e6ea12541 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4659,10 +4659,12 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
//
// template<typename T>
// A<T> Foo(int a = A<T>::FooImpl());
- MultiLevelTemplateArgumentList TemplateArgs =
- getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
- /*Final=*/false, /*Innermost=*/std::nullopt,
- /*RelativeToPrimary=*/true);
+ MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
+ FD, FD->getLexicalDeclContext(),
+ /*Final=*/false, /*Innermost=*/std::nullopt,
+ /*RelativeToPrimary=*/true, /*Pattern=*/nullptr,
+ /*ForConstraintInstantiation=*/false, /*SkipForSpecialization=*/false,
+ /*ForDefaultArgumentSubstitution=*/true);
if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true))
return true;
diff --git a/contrib/tzcode/localtime.c b/contrib/tzcode/localtime.c
index f5814a43da54..a6ec3d8e4e21 100644
--- a/contrib/tzcode/localtime.c
+++ b/contrib/tzcode/localtime.c
@@ -18,6 +18,7 @@
#ifndef DETECT_TZ_CHANGES_INTERVAL
#define DETECT_TZ_CHANGES_INTERVAL 61
#endif
+int __tz_change_interval = DETECT_TZ_CHANGES_INTERVAL;
#include <sys/stat.h>
#endif
#include <fcntl.h>
@@ -408,10 +409,8 @@ change_in_tz(const char *name)
static char old_name[PATH_MAX];
static struct stat old_sb;
struct stat sb;
- int error;
- error = stat(name, &sb);
- if (error != 0)
+ if (stat(name, &sb) != 0)
return -1;
if (strcmp(name, old_name) != 0) {
@@ -510,13 +509,13 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
* 'doextend' to ignore TZDEFRULES; the change_in_tz()
* function can only keep state for a single file.
*/
- int ret = change_in_tz(name);
- if (ret <= 0) {
- /*
- * Returns an errno value if there was an error,
- * and 0 if the timezone had not changed.
- */
+ switch (change_in_tz(name)) {
+ case -1:
return errno;
+ case 0:
+ return 0;
+ case 1:
+ break;
}
}
fid = _open(name, O_RDONLY | O_BINARY);
@@ -1376,22 +1375,13 @@ recheck_tzdata()
{
static time_t last_checked;
struct timespec now;
- time_t current_time;
- int error;
- /*
- * We want to recheck the timezone file every 61 sec.
- */
- error = clock_gettime(CLOCK_MONOTONIC, &now);
- if (error < 0) {
- /* XXX: Can we somehow report this? */
+ if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
return 0;
- }
- current_time = now.tv_sec;
- if ((current_time - last_checked > DETECT_TZ_CHANGES_INTERVAL) ||
- (last_checked > current_time)) {
- last_checked = current_time;
+ if ((now.tv_sec - last_checked >= __tz_change_interval) ||
+ (last_checked > now.tv_sec)) {
+ last_checked = now.tv_sec;
return 1;
}