aboutsummaryrefslogtreecommitdiff
path: root/unit-tests
diff options
context:
space:
mode:
Diffstat (limited to 'unit-tests')
-rw-r--r--unit-tests/Makefile33
-rw-r--r--unit-tests/cmd-errors-jobs.exp12
-rw-r--r--unit-tests/cmd-errors-lint.exp6
-rw-r--r--unit-tests/cmd-errors.exp6
-rw-r--r--unit-tests/cond-func-exists.mk16
-rwxr-xr-xunit-tests/cond-undef-lint.mk4
-rwxr-xr-xunit-tests/directive-dinclude.mk2
-rw-r--r--unit-tests/directive-export-gmake.mk11
-rwxr-xr-xunit-tests/directive-hyphen-include.mk2
-rw-r--r--unit-tests/directive-include-guard.mk2
-rwxr-xr-xunit-tests/directive-include.mk2
-rwxr-xr-xunit-tests/directive-sinclude.mk2
-rw-r--r--unit-tests/gnode-submake.exp20
-rw-r--r--unit-tests/gnode-submake.mk4
-rwxr-xr-xunit-tests/lint.exp2
-rw-r--r--unit-tests/moderrs.exp80
-rw-r--r--unit-tests/opt-chdir.mk6
-rw-r--r--unit-tests/opt-debug-graph1.exp1
-rw-r--r--unit-tests/opt-debug-graph2.exp1
-rw-r--r--unit-tests/opt-debug-graph3.exp1
-rw-r--r--unit-tests/opt-debug-jobs.exp1
-rw-r--r--unit-tests/opt-jobs-internal.exp8
-rw-r--r--unit-tests/opt-jobs-internal.mk27
-rw-r--r--unit-tests/opt-where-am-i.mk6
-rw-r--r--unit-tests/opt.exp14
-rw-r--r--unit-tests/opt.mk4
-rw-r--r--unit-tests/sh-errctl.exp1
-rw-r--r--unit-tests/suff-main-several.exp1
-rw-r--r--unit-tests/suff-transform-debug.exp1
-rw-r--r--unit-tests/var-recursive.exp2
-rw-r--r--unit-tests/var-scope-local.exp10
-rw-r--r--unit-tests/var-scope-local.mk47
-rw-r--r--unit-tests/varmisc.exp18
-rw-r--r--unit-tests/varmod-assign.exp12
-rw-r--r--unit-tests/varmod-hash.exp6
-rw-r--r--unit-tests/varmod-loop-delete.exp12
-rw-r--r--unit-tests/varmod-loop-delete.mk48
-rw-r--r--unit-tests/varmod-select-words.exp24
-rw-r--r--unit-tests/varmod-subst-regex.exp30
-rw-r--r--unit-tests/varmod-subst-regex.mk47
-rw-r--r--unit-tests/varmod-subst.exp7
-rw-r--r--unit-tests/varmod-subst.mk18
-rw-r--r--unit-tests/varname-dot-make-save_dollars.mk12
-rw-r--r--unit-tests/varname-make_stack_trace.exp22
-rw-r--r--unit-tests/varname-make_stack_trace.mk36
45 files changed, 429 insertions, 198 deletions
diff --git a/unit-tests/Makefile b/unit-tests/Makefile
index 63671a6d9b74..b12ef7decb4d 100644
--- a/unit-tests/Makefile
+++ b/unit-tests/Makefile
@@ -1,6 +1,6 @@
-# $Id: Makefile,v 1.251 2025/11/15 17:17:18 sjg Exp $
+# $Id: Makefile,v 1.260 2026/03/10 15:45:51 sjg Exp $
#
-# $NetBSD: Makefile,v 1.373 2025/11/12 22:14:08 sjg Exp $
+# $NetBSD: Makefile,v 1.383 2026/03/10 15:38:26 sjg Exp $
#
# Unit tests for make(1)
#
@@ -629,6 +629,9 @@ SED_CMDS.opt-chdir= -e 's,\(nonexistent\).[1-9][0-9]*,\1,' \
-e 's,no such,No such,' \
-e 's,Filename,File name,'
+SED_CMDS.gnode-submake= ${STD_SED_CMDS.dj}
+SED_CMDS.gnode-submake= ${STD_SED_CMDS.dg2}
+
# meta line numbers can vary based on filemon implementation
SED_CMDS.meta-ignore= -e 's,\(\.meta:\)[1-9][0-9]*:,\1<line>:,'
@@ -642,6 +645,7 @@ SED_CMDS.opt-debug-lint+= ${STD_SED_CMDS.regex}
SED_CMDS.opt-jobs-no-action= ${STD_SED_CMDS.hide-from-output}
SED_CMDS.opt-no-action-runflags= ${STD_SED_CMDS.hide-from-output}
SED_CMDS.opt-where-am-i= -e '/usr.obj/d'
+SED_CMDS.opt-where-am-i+= -e '/\/\//d'
# For Compat_RunCommand, useShell == false.
SED_CMDS.sh-dots= -e 's,^.*\.\.\.:.*,<not found: ...>,'
# For Compat_RunCommand, useShell == true.
@@ -662,6 +666,7 @@ SED_CMDS.var-op-shell+= -e '/command/s,No such.*,not found,'
SED_CMDS.var-op-shell+= ${STD_SED_CMDS.white-space}
SED_CMDS.vardebug+= -e 's,${.SHELL},</path/to/shell>,'
SED_CMDS.varmod-mtime+= -e "s,\(mtime for .*\): .*,\1: <ENOENT>,"
+SED_CMDS.varmod-subst+= ${STD_SED_CMDS.regex}
SED_CMDS.varmod-subst-regex+= ${STD_SED_CMDS.regex}
SED_CMDS.varparse-errors+= ${STD_SED_CMDS.timestamp}
SED_CMDS.varname-dot-make-meta-ignore_filter+= ${SED_CMDS.meta-ignore}
@@ -677,7 +682,10 @@ SED_CMDS.varname-empty= ${.OBJDIR .PARSEDIR .PATH .SHELL .SYSPATH:L:@v@-e '/\\$
# Some tests need an additional round of postprocessing.
POSTPROC.depsrc-wait= sed -e '/^---/d' -e 's,^\(: Making 3[abc]\)[123]$$,\1,'
POSTPROC.deptgt-suffixes= awk '/^\#\*\*\* Suffixes/,/^never-stop/'
-POSTPROC.gnode-submake= awk '/Begin input graph/, /^$$/'
+POSTPROC.gnode-submake= \
+ awk '/Begin input graph/, /^\# \.END/ { \
+ if (/made,/) print $$0 \
+ }'
POSTPROC.varname-dot-make-mode= sed 's,^\(: Making [abc]\)[123]$$,\1,'
# Some tests reuse other tests, which makes them unnecessarily fragile.
@@ -700,6 +708,7 @@ STD_SED_CMDS.dg1= -e '/\#.* \.$$/d'
STD_SED_CMDS.dg1+= -e '/\.MAKE.PATH_FILEMON/d'
STD_SED_CMDS.dg1+= -e '/^\#.*\/mk/d'
STD_SED_CMDS.dg1+= -e 's, ${DEFSYSPATH:U/usr/share/mk}$$, <defsyspath>,'
+STD_SED_CMDS.dg1+= -e '/^\.MAKE\.PATH_FILEMON/d'
STD_SED_CMDS.dg1+= -e 's,^\(\.MAKE *=\) .*,\1 <details omitted>,'
STD_SED_CMDS.dg1+= -e 's,^\(\.MAKE\.[A-Z_]* *=\) .*,\1 <details omitted>,'
STD_SED_CMDS.dg1+= -e 's,^\(\.MAKE\.JOBS\.C *=\) .*,\1 <details omitted>,'
@@ -710,6 +719,7 @@ STD_SED_CMDS.dg1+= -e '/\.SYSPATH/d'
STD_SED_CMDS.dg2= ${STD_SED_CMDS.dg1}
STD_SED_CMDS.dg2+= -e 's,\(last modified\) ..:..:.. ... ..\, ....,\1 <timestamp>,'
+
STD_SED_CMDS.dg3= ${STD_SED_CMDS.dg2}
# Omit details such as process IDs from the output of the -dj option.
@@ -792,6 +802,16 @@ clean:
rm -f ${CLEANFILES}
TEST_MAKE?= ${.MAKE}
+.if ${TEST_MAKE:M/*} == ""
+# we want an absolute path for TEST_MAKE
+tm!= for d in ${PATH:S,:, ,g:M/*}; do \
+ test -x $$d/${TEST_MAKE} || continue; \
+ echo $$d/${TEST_MAKE}; break; done
+.if ${tm:M/*}
+TEST_MAKE:= ${tm}
+.endif
+.endif
+
TOOL_SED?= sed
TOOL_TR?= tr
TOOL_DIFF?= diff
@@ -831,7 +851,7 @@ LIMIT_RESOURCES?= :
# each other, and because they use different environment variables and
# command line options.
.SUFFIXES: .mk .rawout .out
-.mk.rawout:
+.mk.rawout: .META
@${_MKMSG_TEST:Uecho '# test '} ${.PREFIX}
@set -eu; \
${LIMIT_RESOURCES}; \
@@ -873,7 +893,8 @@ _SED_CMDS+= -e 's,^usage: ${TEST_MAKE:T:S,.,\\.,g} ,usage: make ,'
_SED_CMDS+= -e 's,${TEST_MAKE:T:S,.,\\.,g}\(\[[1-9][0-9]*\][: ]\),make\1,'
_SED_CMDS+= -e 's,<curdir>/,,g'
_SED_CMDS+= -e 's,${UNIT_TESTS:S,.,\\.,g}/,,g'
-_SED_CMDS+= -e '/MAKE_VERSION/d'
+_SED_CMDS+= -e 's,\(\.make\)[1-9][0-9]*,\1,g'
+_SED_CMDS+= -e '/MAKE.VERSION/d'
_SED_CMDS+= -e '/EGREP=/d'
# on AT&T derived systems: false exits 255 not 1
@@ -886,7 +907,7 @@ SED_CMDS.opt-debug-jobs+= -e 's,Command: ksh -v,Command: <shell>,'
SED_CMDS.opt-debug-jobs+= -e 's,Command: <shell> -v,Command: <shell>,'
.endif
-.rawout.out:
+.rawout.out: .META
@${TOOL_SED} ${_SED_CMDS} ${SED_CMDS.${.PREFIX:T}} ${_SED_CMDS_LAST} \
< ${.IMPSRC} > ${.TARGET}.tmp
@${POSTPROC.${.PREFIX:T}:D \
diff --git a/unit-tests/cmd-errors-jobs.exp b/unit-tests/cmd-errors-jobs.exp
index 3be1bb9b0773..3846f9eef260 100644
--- a/unit-tests/cmd-errors-jobs.exp
+++ b/unit-tests/cmd-errors-jobs.exp
@@ -9,34 +9,34 @@ end undefined-indirect with status 0
begin parse-error-direct
make: Unclosed variable "UNCLOSED"
in command ": unexpected $@-${UNCLOSED"
- in target "parse-error-unclosed-expression"
+ in target "parse-error-unclosed-expression" from cmd-errors-jobs.mk:42
in make[1] in directory "<curdir>"
make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": unexpected $@-${UNCLOSED:"
- in target "parse-error-unclosed-modifier"
+ in target "parse-error-unclosed-modifier" from cmd-errors-jobs.mk:45
in make[1] in directory "<curdir>"
make: Unknown modifier ":Z"
while evaluating variable "UNKNOWN" with value ""
in command ": unexpected $@-${UNKNOWN:Z}-eol"
- in target "parse-error-unknown-modifier"
+ in target "parse-error-unknown-modifier" from cmd-errors-jobs.mk:48
in make[1] in directory "<curdir>"
end parse-error-direct with status 2
begin parse-error-indirect
make: Unclosed variable "UNCLOSED"
in command ": unexpected $@-${UNCLOSED"
- in target "parse-error-unclosed-expression"
+ in target "parse-error-unclosed-expression" from cmd-errors-jobs.mk:42
in make[1] in directory "<curdir>"
make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": unexpected $@-${UNCLOSED:"
- in target "parse-error-unclosed-modifier"
+ in target "parse-error-unclosed-modifier" from cmd-errors-jobs.mk:45
in make[1] in directory "<curdir>"
make: Unknown modifier ":Z"
while evaluating variable "UNKNOWN" with value ""
in command ": unexpected $@-${UNKNOWN:Z}-eol"
- in target "parse-error-unknown-modifier"
+ in target "parse-error-unknown-modifier" from cmd-errors-jobs.mk:48
in make[1] in directory "<curdir>"
end parse-error-indirect with status 2
diff --git a/unit-tests/cmd-errors-lint.exp b/unit-tests/cmd-errors-lint.exp
index b08a65ff96dc..4b010732f8b2 100644
--- a/unit-tests/cmd-errors-lint.exp
+++ b/unit-tests/cmd-errors-lint.exp
@@ -1,14 +1,14 @@
: undefined
make: Unclosed variable "UNCLOSED"
in command ": $@ ${UNCLOSED"
- in target "unclosed-expression"
+ in target "unclosed-expression" from cmd-errors-lint.mk:19
make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": $@ ${UNCLOSED:"
- in target "unclosed-modifier"
+ in target "unclosed-modifier" from cmd-errors-lint.mk:24
make: Unknown modifier ":Z"
while evaluating variable "UNKNOWN" with value ""
in command ": $@ ${UNKNOWN:Z}"
- in target "unknown-modifier"
+ in target "unknown-modifier" from cmd-errors-lint.mk:29
: end
exit status 2
diff --git a/unit-tests/cmd-errors.exp b/unit-tests/cmd-errors.exp
index 2916d423029e..8936c0a671ae 100644
--- a/unit-tests/cmd-errors.exp
+++ b/unit-tests/cmd-errors.exp
@@ -1,14 +1,14 @@
: undefined--eol
make: Unclosed variable "UNCLOSED"
in command ": $@-${UNCLOSED"
- in target "unclosed-expression"
+ in target "unclosed-expression" from cmd-errors.mk:17
make: Unclosed expression, expecting "}"
while evaluating variable "UNCLOSED" with value ""
in command ": $@-${UNCLOSED:"
- in target "unclosed-modifier"
+ in target "unclosed-modifier" from cmd-errors.mk:22
make: Unknown modifier ":Z"
while evaluating variable "UNKNOWN" with value ""
in command ": $@-${UNKNOWN:Z}-eol"
- in target "unknown-modifier"
+ in target "unknown-modifier" from cmd-errors.mk:27
: end-eol
exit status 2
diff --git a/unit-tests/cond-func-exists.mk b/unit-tests/cond-func-exists.mk
index c68507ca1ab9..360c4741f9c0 100644
--- a/unit-tests/cond-func-exists.mk
+++ b/unit-tests/cond-func-exists.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-exists.mk,v 1.8 2025/01/10 23:00:38 rillig Exp $
+# $NetBSD: cond-func-exists.mk,v 1.9 2026/03/02 21:49:37 rillig Exp $
#
# Tests for the exists() function in .if conditions.
@@ -52,5 +52,17 @@ _!= > cond-func-exists.just-created
.endif
_!= rm cond-func-exists.just-created
+
+# The exists function aims at source and target files, but not at makefiles.
+# In particular, the file is not searched in ${.PARSEDIR}.
+_!= mkdir -p cond-func-exists && \
+ printf '%s\n' \
+ '.if exists(file.inc)' \
+ '. error' \
+ '.endif' \
+ > cond-func-exists/file.inc
+.include "cond-func-exists/file.inc"
+_!= rm -f cond-func-exists/file.inc
+
+
all:
- @:;
diff --git a/unit-tests/cond-undef-lint.mk b/unit-tests/cond-undef-lint.mk
index 1b4d19636c41..27e42d208aa3 100755
--- a/unit-tests/cond-undef-lint.mk
+++ b/unit-tests/cond-undef-lint.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-undef-lint.mk,v 1.8 2025/01/11 21:21:33 rillig Exp $
+# $NetBSD: cond-undef-lint.mk,v 1.9 2026/02/13 03:16:15 lukem Exp $
#
# Tests for defined and undefined variables in .if conditions, in lint mode.
#
@@ -51,7 +51,7 @@ DEF= defined
# Variables that are referenced indirectly may be undefined in a condition.
#
-# A practical example for this is CFLAGS, which consists of CWARNS, COPTS
+# A practical example for this is CFLAGS, which consists of CWARNFLAGS, COPTS
# and a few others. Just because these nested variables are not defined,
# this does not make the condition invalid.
#
diff --git a/unit-tests/directive-dinclude.mk b/unit-tests/directive-dinclude.mk
index c05d1a55f51b..40fcb5306bb8 100755
--- a/unit-tests/directive-dinclude.mk
+++ b/unit-tests/directive-dinclude.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-dinclude.mk,v 1.5 2025/06/28 22:39:28 rillig Exp $
+# $NetBSD: directive-dinclude.mk,v 1.6 2025/11/16 16:43:56 sjg Exp $
#
# Tests for the .dinclude directive, which includes another file,
# silently skipping it if it cannot be opened. This is primarily used for
diff --git a/unit-tests/directive-export-gmake.mk b/unit-tests/directive-export-gmake.mk
index 6e1d57c6a62d..36efc96e5114 100644
--- a/unit-tests/directive-export-gmake.mk
+++ b/unit-tests/directive-export-gmake.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-export-gmake.mk,v 1.10 2025/06/28 22:39:28 rillig Exp $
+# $NetBSD: directive-export-gmake.mk,v 1.11 2026/01/02 14:21:46 rillig Exp $
#
# Tests for the export directive (without leading dot), as in GNU make.
@@ -104,3 +104,12 @@ export ${INDIRECT_NAME}=${INDIRECT_VALUE}
.if ${:!env!:MI_NAME=*}
. error
.endif
+
+
+# Quotes and other special characters are preserved.
+export DQUOT="dquot"
+export SQUOT='squot'
+export PLAIN=plain
+.if ${:!echo "\$DQUOT \$SQUOT \$PLAIN"!} != "\"dquot\" 'squot' plain"
+. error
+.endif
diff --git a/unit-tests/directive-hyphen-include.mk b/unit-tests/directive-hyphen-include.mk
index e3817ef15539..e3cc48238eff 100755
--- a/unit-tests/directive-hyphen-include.mk
+++ b/unit-tests/directive-hyphen-include.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-hyphen-include.mk,v 1.5 2025/06/28 22:39:28 rillig Exp $
+# $NetBSD: directive-hyphen-include.mk,v 1.6 2025/11/16 16:43:57 sjg Exp $
#
# Tests for the .-include directive, which includes another file,
# silently skipping it if it cannot be opened.
diff --git a/unit-tests/directive-include-guard.mk b/unit-tests/directive-include-guard.mk
index 5dc7f1aac178..acbe61d66d41 100644
--- a/unit-tests/directive-include-guard.mk
+++ b/unit-tests/directive-include-guard.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-include-guard.mk,v 1.19 2025/04/11 17:21:31 rillig Exp $
+# $NetBSD: directive-include-guard.mk,v 1.20 2025/11/16 16:43:57 sjg Exp $
#
# Tests for multiple-inclusion guards in makefiles.
#
diff --git a/unit-tests/directive-include.mk b/unit-tests/directive-include.mk
index a694b9ca4e91..eedb9ce220e0 100755
--- a/unit-tests/directive-include.mk
+++ b/unit-tests/directive-include.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-include.mk,v 1.20 2025/06/28 22:39:28 rillig Exp $
+# $NetBSD: directive-include.mk,v 1.21 2025/11/16 16:43:57 sjg Exp $
#
# Tests for the .include directive, which includes another file.
diff --git a/unit-tests/directive-sinclude.mk b/unit-tests/directive-sinclude.mk
index 3c2ffbdc9f6c..d995d315518b 100755
--- a/unit-tests/directive-sinclude.mk
+++ b/unit-tests/directive-sinclude.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-sinclude.mk,v 1.7 2025/06/28 22:39:28 rillig Exp $
+# $NetBSD: directive-sinclude.mk,v 1.8 2025/11/16 16:43:57 sjg Exp $
#
# Tests for the .sinclude directive, which includes another file,
# silently skipping it if it cannot be opened.
diff --git a/unit-tests/gnode-submake.exp b/unit-tests/gnode-submake.exp
index c9cfada91c69..7ed8335bf73d 100644
--- a/unit-tests/gnode-submake.exp
+++ b/unit-tests/gnode-submake.exp
@@ -1,11 +1,11 @@
-#*** Begin input graph for pass 1 in <curdir>:
-# all, unmade, type OP_DEPENDS, flags none
-# makeinfo, unmade, type OP_DEPENDS|OP_HAS_COMMANDS, flags none
-# make-index, unmade, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none
-# braces-dot, unmade, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none
-# braces-no-dot, unmade, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none
-# braces-no-dot-modifier, unmade, type OP_DEPENDS|OP_HAS_COMMANDS, flags none
-# parentheses-dot, unmade, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none
-# parentheses-no-dot, unmade, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none
-
+# .MAIN, made, type OP_DEPENDS|OP_PHONY, flags REMAKE|CHILDMADE|FORCE|DONE_WAIT|DONE_ALLSRC
+# all, made, type OP_DEPENDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|CHILDMADE|FORCE|DONE_WAIT|DONE_ALLSRC|DONECYCLE
+# makeinfo, made, type OP_DEPENDS|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
+# make-index, made, type OP_DEPENDS|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
+# braces-dot, made, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
+# braces-no-dot, made, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
+# braces-no-dot-modifier, made, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
+# parentheses-dot, made, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
+# parentheses-no-dot, made, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS|OP_DEPS_FOUND|OP_MARK, flags REMAKE|DONE_WAIT|DONE_ALLSRC|DONE_SUBMAKE
+# .END, unmade, type OP_SPECIAL, flags none
exit status 0
diff --git a/unit-tests/gnode-submake.mk b/unit-tests/gnode-submake.mk
index 40ff20276df9..2cd7fac81f72 100644
--- a/unit-tests/gnode-submake.mk
+++ b/unit-tests/gnode-submake.mk
@@ -1,4 +1,4 @@
-# $NetBSD: gnode-submake.mk,v 1.1 2020/11/07 23:25:06 rillig Exp $
+# $NetBSD: gnode-submake.mk,v 1.2 2026/02/10 18:53:34 sjg Exp $
#
# Test whether OP_SUBMAKE is determined correctly. If it is, this node's
# shell commands are connected to the make process via pipes, to coordinate
@@ -8,7 +8,7 @@
# parsed. This information is only used in parallel mode, but the result
# from parsing is available in compat mode as well.
-.MAKEFLAGS: -n -dg1
+.MAKEFLAGS: -dg2 -j1
all: makeinfo make-index
all: braces-dot braces-no-dot
diff --git a/unit-tests/lint.exp b/unit-tests/lint.exp
index 61188d6d5c29..6c08bdcbe01b 100755
--- a/unit-tests/lint.exp
+++ b/unit-tests/lint.exp
@@ -1,5 +1,5 @@
make: In the :@ modifier, the variable name "${:Ubar:S,b,v,}" must not contain a dollar
while evaluating variable "VAR" with value "value"
in command "@echo ${VAR:Uvalue:@${:Ubar:S,b,v,}@x${var}y@:Q}"
- in target "mod-loop-varname"
+ in target "mod-loop-varname" from lint.mk:22
exit status 2
diff --git a/unit-tests/moderrs.exp b/unit-tests/moderrs.exp
index 4758294f0993..1fa7dd57f52a 100644
--- a/unit-tests/moderrs.exp
+++ b/unit-tests/moderrs.exp
@@ -1,173 +1,173 @@
make: Unknown modifier ":Z"
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 'VAR:Z=before-${VAR:Z}-after'"
- in target "mod-unknown-direct"
+ in target "mod-unknown-direct" from moderrs.mk:29
make: Unknown modifier ":Z"
while evaluating indirect modifiers "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"
+ in target "mod-unknown-indirect" from moderrs.mk:33
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"
+ in target "unclosed-direct" from moderrs.mk:37
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"
+ in target "unclosed-indirect" from moderrs.mk:41
make: Unfinished modifier after "v", expecting ","
while evaluating indirect modifiers "S,V,v"
while evaluating variable "VAR" with value "TheVariable"
in command "-@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}""
- in target "unfinished-indirect"
+ in target "unfinished-indirect" from moderrs.mk:45
make: Unfinished modifier after "var}", expecting "@"
while evaluating variable "UNDEF" with value "1 2 3"
in command "@echo ${UNDEF:U1 2 3:@var}"
- in target "unfinished-loop-1"
+ in target "unfinished-loop-1" from moderrs.mk:49
make: Unfinished modifier after "...}", expecting "@"
while evaluating variable "UNDEF" with value "1 2 3"
in command "@echo ${UNDEF:U1 2 3:@var@...}"
- in target "unfinished-loop-2"
+ in target "unfinished-loop-2" from moderrs.mk:52
1 2 3
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"
+ in target "loop-close-1" from moderrs.mk:64
1}... 2}... 3}...
make: Unfinished modifier after "}", expecting "]"
while evaluating variable "UNDEF" with value "1 2 3"
in command "@echo ${UNDEF:U1 2 3:[}"
- in target "words-1"
+ in target "words-1" from moderrs.mk:70
make: Unfinished modifier after "#}", expecting "]"
while evaluating variable "UNDEF" with value "1 2 3"
in command "@echo ${UNDEF:U1 2 3:[#}"
- in target "words-2"
+ in target "words-2" from moderrs.mk:73
13=
make: Invalid modifier ":[123451234512345123451234512345]"
while evaluating variable "UNDEF" with value "1 2 3"
in command "@echo 12345=${UNDEF:U1 2 3:[123451234512345123451234512345]:S,^$,ok,:S,^3$,ok,}"
- in target "words-3"
+ in target "words-3" from moderrs.mk:96
make: Unfinished modifier after "echo}", expecting "!"
while evaluating variable "VARNAME" with value ""
in command "@echo ${VARNAME:!echo}"
- in target "exclam-1"
+ in target "exclam-1" from moderrs.mk:100
make: Unfinished modifier after "=exclam}", expecting "!"
while evaluating variable "!" with value "!"
in command "@echo ${!:L:!=exclam}"
- in target "exclam-2"
+ in target "exclam-2" from moderrs.mk:107
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"
+ in target "mod-subst-delimiter-1" from moderrs.mk:111
make: Unfinished modifier after "", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 2: ${VAR:S,"
- in target "mod-subst-delimiter-2"
+ in target "mod-subst-delimiter-2" from moderrs.mk:114
make: Unfinished modifier after "from", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 3: ${VAR:S,from"
- in target "mod-subst-delimiter-3"
+ in target "mod-subst-delimiter-3" from moderrs.mk:117
make: Unfinished modifier after "", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 4: ${VAR:S,from,"
- in target "mod-subst-delimiter-4"
+ in target "mod-subst-delimiter-4" from moderrs.mk:120
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"
+ in target "mod-subst-delimiter-5" from moderrs.mk:123
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"
+ in target "mod-subst-delimiter-6" from moderrs.mk:126
7: TheVariable
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"
+ in target "mod-regex-delimiter-1" from moderrs.mk:132
make: Unfinished modifier after "", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 2: ${VAR:C,"
- in target "mod-regex-delimiter-2"
+ in target "mod-regex-delimiter-2" from moderrs.mk:135
make: Unfinished modifier after "from", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 3: ${VAR:C,from"
- in target "mod-regex-delimiter-3"
+ in target "mod-regex-delimiter-3" from moderrs.mk:138
make: Unfinished modifier after "", expecting ","
while evaluating variable "VAR" with value "TheVariable"
in command "@echo 4: ${VAR:C,from,"
- in target "mod-regex-delimiter-4"
+ in target "mod-regex-delimiter-4" from moderrs.mk:141
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"
+ in target "mod-regex-delimiter-5" from moderrs.mk:144
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"
+ in target "mod-regex-delimiter-6" from moderrs.mk:147
7: TheVariable
112358132134
15152535558513521534
make: Unknown modifier ":ts\65oct"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:ts\65oct} # bad modifier"
- in target "mod-ts-parse-3"
+ in target "mod-ts-parse-3" from moderrs.mk:157
make: Unknown modifier ":ts\65oct"
while evaluating "${:U${FIB}:ts\65oct} # bad modifier, variable name is """ with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${:U${FIB}:ts\65oct} # bad modifier, variable name is """
- in target "mod-ts-parse-4"
+ in target "mod-ts-parse-4" from moderrs.mk:160
make: Unknown modifier ":tsxy"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:tsxy} # modifier too long"
- in target "mod-ts-parse-5"
+ in target "mod-ts-parse-5" from moderrs.mk:163
make: Unknown modifier ":t"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:t"
- in target "mod-t-parse-1"
+ in target "mod-t-parse-1" from moderrs.mk:167
make: Unknown modifier ":txy"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:txy}"
- in target "mod-t-parse-2"
+ in target "mod-t-parse-2" from moderrs.mk:170
make: Unknown modifier ":t"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:t}"
- in target "mod-t-parse-3"
+ in target "mod-t-parse-3" from moderrs.mk:173
make: Unknown modifier ":t"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:t:M*}"
- in target "mod-t-parse-4"
+ in target "mod-t-parse-4" from moderrs.mk:176
make: Unfinished modifier after "", expecting ":"
while evaluating then-branch of condition "FIB"
in command "@echo ${FIB:?"
- in target "mod-ifelse-parse-1"
+ in target "mod-ifelse-parse-1" from moderrs.mk:180
make: Unfinished modifier after "then", expecting ":"
while evaluating then-branch of condition "FIB"
in command "@echo ${FIB:?then"
- in target "mod-ifelse-parse-2"
+ in target "mod-ifelse-parse-2" from moderrs.mk:183
make: Unfinished modifier after "", expecting "}"
while evaluating else-branch of condition "FIB"
in command "@echo ${FIB:?then:"
- in target "mod-ifelse-parse-3"
+ in target "mod-ifelse-parse-3" from moderrs.mk:186
make: Unfinished modifier after "else", expecting "}"
while evaluating else-branch of condition "FIB"
in command "@echo ${FIB:?then:else"
- in target "mod-ifelse-parse-4"
+ in target "mod-ifelse-parse-4" from moderrs.mk:189
then
1 1 2 3 5 8 13 21 34
make: Unknown modifier ":__"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:__} # modifier name too long"
- in target "mod-remember-parse"
+ in target "mod-remember-parse" from moderrs.mk:196
make: Unknown modifier ":3"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:3"
- in target "mod-sysv-parse-1"
+ in target "mod-sysv-parse-1" from moderrs.mk:200
make: Unfinished modifier after "", expecting "}"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:3="
- in target "mod-sysv-parse-2"
+ in target "mod-sysv-parse-2" from moderrs.mk:203
make: Unfinished modifier after "x3", expecting "}"
while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
in command "@echo ${FIB:3=x3"
- in target "mod-sysv-parse-3"
+ in target "mod-sysv-parse-3" from moderrs.mk:206
1 1 2 x3 5 8 1x3 21 34
exit status 2
diff --git a/unit-tests/opt-chdir.mk b/unit-tests/opt-chdir.mk
index e94b8799af2e..19055aba0824 100644
--- a/unit-tests/opt-chdir.mk
+++ b/unit-tests/opt-chdir.mk
@@ -1,4 +1,4 @@
-# $NetBSD: opt-chdir.mk,v 1.7 2024/04/02 11:11:00 rillig Exp $
+# $NetBSD: opt-chdir.mk,v 1.8 2026/02/10 21:22:13 sjg Exp $
#
# Tests for the -C command line option, which changes the directory at the
# beginning.
@@ -13,8 +13,10 @@ all: chdir-nonexistent
# Changing to another directory is possible via the command line.
# In this test, it is the root directory since almost any other directory
# is not guaranteed to exist on every platform.
+# Force MAKEOBJDIRPREFIX=/ to avoid looking elsewhere for .OBJDIR
chdir-root: .PHONY .IGNORE
- @MAKE_OBJDIR_CHECK_WRITABLE=no ${MAKE} -C / -V 'cwd: $${.CURDIR}'
+ @MAKE_OBJDIR_CHECK_WRITABLE=no MAKEOBJDIRPREFIX=/ \
+ ${MAKE} -C / -V 'cwd: $${.CURDIR}'
# Trying to change to a nonexistent directory exits immediately.
# Note: just because the whole point of /nonexistent is that it should
diff --git a/unit-tests/opt-debug-graph1.exp b/unit-tests/opt-debug-graph1.exp
index 9dae95302318..43c49a957ebb 100644
--- a/unit-tests/opt-debug-graph1.exp
+++ b/unit-tests/opt-debug-graph1.exp
@@ -29,6 +29,7 @@
.MAKE.OS = <details omitted>
.MAKE.PID = <details omitted>
.MAKE.PPID = <details omitted>
+.MAKE.SAVE_DOLLARS = <details omitted>
.MAKE.UID = <details omitted>
.MAKEFLAGS = -r -k -d g1
.MAKEOVERRIDES = # (empty)
diff --git a/unit-tests/opt-debug-graph2.exp b/unit-tests/opt-debug-graph2.exp
index e4160e413787..6fd8de68fd98 100644
--- a/unit-tests/opt-debug-graph2.exp
+++ b/unit-tests/opt-debug-graph2.exp
@@ -63,6 +63,7 @@ all : made-target error-target aborted-target
.MAKE.OS = <details omitted>
.MAKE.PID = <details omitted>
.MAKE.PPID = <details omitted>
+.MAKE.SAVE_DOLLARS = <details omitted>
.MAKE.UID = <details omitted>
.MAKEFLAGS = -r -k -d g2
.MAKEOVERRIDES = # (empty)
diff --git a/unit-tests/opt-debug-graph3.exp b/unit-tests/opt-debug-graph3.exp
index ccebfd7b16bc..8ce5d2e5cfa5 100644
--- a/unit-tests/opt-debug-graph3.exp
+++ b/unit-tests/opt-debug-graph3.exp
@@ -63,6 +63,7 @@ all : made-target error-target aborted-target
.MAKE.OS = <details omitted>
.MAKE.PID = <details omitted>
.MAKE.PPID = <details omitted>
+.MAKE.SAVE_DOLLARS = <details omitted>
.MAKE.UID = <details omitted>
.MAKEFLAGS = -r -k -d g3
.MAKEOVERRIDES = # (empty)
diff --git a/unit-tests/opt-debug-jobs.exp b/unit-tests/opt-debug-jobs.exp
index 6cda45107702..0e818245246f 100644
--- a/unit-tests/opt-debug-jobs.exp
+++ b/unit-tests/opt-debug-jobs.exp
@@ -1,6 +1,7 @@
job_pipe -1 -1, maxjobs 1, tokens 1, compat 0
TokenPool_Take: pid <pid>, aborting NONE, running 0
TokenPool_Take: pid <pid> took a token
+MaybeSubMake: Looking for "make"
echo ": expanded expression"
{ : expanded expression
} || exit $?
diff --git a/unit-tests/opt-jobs-internal.exp b/unit-tests/opt-jobs-internal.exp
index 61c96256a2e4..a13d44bb38ed 100644
--- a/unit-tests/opt-jobs-internal.exp
+++ b/unit-tests/opt-jobs-internal.exp
@@ -3,12 +3,12 @@ make: error: invalid internal option "-J garbage" in "<curdir>"
make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
in make[2] in directory "<curdir>"
direct-open: mode=compat
-make: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
- in make[2] in directory "<curdir>"
+.make[2]: 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: Invalid internal option "-J" in "<curdir>"; see the manual page
- in make[2] in directory "<curdir>"
+.make[2]: 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
indirect-expr-empty: mode=parallel
diff --git a/unit-tests/opt-jobs-internal.mk b/unit-tests/opt-jobs-internal.mk
index 13db820f86c1..4a1c39c75cd7 100644
--- a/unit-tests/opt-jobs-internal.mk
+++ b/unit-tests/opt-jobs-internal.mk
@@ -1,9 +1,12 @@
-# $NetBSD: opt-jobs-internal.mk,v 1.6 2025/05/23 21:05:56 rillig Exp $
+# $NetBSD: opt-jobs-internal.mk,v 1.10 2026/03/10 05:02:00 sjg Exp $
#
# Tests for the (intentionally undocumented) internal -J command line option.
+.if ${DEBUG_TEST:U:M${.PARSEFILE:R}} != ""
+.MAKEFLAGS: -djg2
+.endif
-# This test expects
-.MAKE.ALWAYS_PASS_JOB_QUEUE= no
+_make ?= .make${.MAKE.PID}
+.export _make
all: .PHONY
@${MAKE} -f ${MAKEFILE} -j1 direct
@@ -14,6 +17,7 @@ all: .PHONY
@${MAKE} -f ${MAKEFILE} -j1 indirect-comment
@${MAKE} -f ${MAKEFILE} -j1 indirect-silent-comment
@${MAKE} -f ${MAKEFILE} -j1 indirect-expr-empty
+ @rm -f ${_make}
detect-mode: .PHONY
@mode=parallel
@@ -33,8 +37,8 @@ direct-open: .PHONY
@${MAKE} -f ${MAKEFILE} -J 31,32 detect-mode HEADING=${.TARGET}
# expect: indirect-open: mode=compat
-indirect-open: .PHONY
- @${MAKE:U} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
+indirect-open: .PHONY ${_make}
+ @./${_make} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
# When a command in its unexpanded form contains the expression "${MAKE}"
# without any modifiers, the file descriptors get passed around.
@@ -45,9 +49,9 @@ indirect-expr: .PHONY
# The "# make" comment starts directly after the leading tab and is thus not
# considered a shell command line. No file descriptors are passed around.
# expect: indirect-comment: mode=compat
-indirect-comment: .PHONY
+indirect-comment: .PHONY ${_make}
# make
- @${MAKE:U} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
+ @./${_make} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
# When the "# make" comment is prefixed with "@", it becomes a shell command.
# As that shell command contains the plain word "make", the file descriptors
@@ -57,9 +61,12 @@ indirect-silent-comment: .PHONY
@# make
@${MAKE:U} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
-# When a command in its unexpanded form contains the plain word "make", the
-# file descriptors get passed around.
# expect: indirect-expr-empty: mode=parallel
indirect-expr-empty: .PHONY
- @${:D make}
@${MAKE:U} -f ${MAKEFILE} detect-mode HEADING=${.TARGET}
+
+${_make}:
+ @ln -s ${MAKE} ${.TARGET}
+
+# This test expects
+.MAKE.ALWAYS_PASS_JOB_QUEUE= no
diff --git a/unit-tests/opt-where-am-i.mk b/unit-tests/opt-where-am-i.mk
index f1eeca920a32..1d849b8d8047 100644
--- a/unit-tests/opt-where-am-i.mk
+++ b/unit-tests/opt-where-am-i.mk
@@ -1,4 +1,4 @@
-# $NetBSD: opt-where-am-i.mk,v 1.4 2022/01/27 02:24:46 sjg Exp $
+# $NetBSD: opt-where-am-i.mk,v 1.5 2026/02/10 22:33:36 sjg Exp $
#
# Tests for the -w command line option, which outputs the current directory
# at the beginning and end of running make. This is useful when building
@@ -6,9 +6,11 @@
# The first "Entering directory" is missing since the below .MAKEFLAGS comes
# too late for it.
+# We force MAKEOBJDIRPREFIX=/ to avoid looking elsewhere for .OBJDIR
.MAKEFLAGS: -w
all:
.if ${.CURDIR} != "/"
- @MAKE_OBJDIR_CHECK_WRITABLE=no ${MAKE} -r -f ${MAKEFILE:tA} -C /
+ @MAKE_OBJDIR_CHECK_WRITABLE=no MAKEOBJDIRPREFIX=/ \
+ ${MAKE} -r -f ${MAKEFILE:tA} -C /
.endif
diff --git a/unit-tests/opt.exp b/unit-tests/opt.exp
index daeecc8ca726..0680cbc2761f 100644
--- a/unit-tests/opt.exp
+++ b/unit-tests/opt.exp
@@ -1,11 +1,12 @@
-make -r -f /dev/null -V MAKEFLAGS
- -r -k -d 0
+make -r -f /dev/null -V 'begin ${MAKEFLAGS} end'
+begin -r -k -d 0 end
make -:
usage: make [-BeikNnqrSstWwX]
[-C directory] [-D variable] [-d flags] [-f makefile]
- [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]
- [-V variable] [-v variable] [variable=value] [target ...]
+ [-I directory] [-J private] [-j max_jobs] [-m directory]
+ [-T file] [-V variable] [-v variable]
+ [variable=value ...] [target ...]
*** Error code 2 (ignored)
make -r -f /dev/null -- -VAR=value -f /dev/null
@@ -19,8 +20,9 @@ make: stopped making "-f /dev/null" in unit-tests
make -?
usage: make [-BeikNnqrSstWwX]
[-C directory] [-D variable] [-d flags] [-f makefile]
- [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]
- [-V variable] [-v variable] [variable=value] [target ...]
+ [-I directory] [-J private] [-j max_jobs] [-m directory]
+ [-T file] [-V variable] [-v variable]
+ [variable=value ...] [target ...]
*** Error code 2 (ignored)
exit status 0
diff --git a/unit-tests/opt.mk b/unit-tests/opt.mk
index 939d5ec35aeb..e7861fffbf84 100644
--- a/unit-tests/opt.mk
+++ b/unit-tests/opt.mk
@@ -1,4 +1,4 @@
-# $NetBSD: opt.mk,v 1.7 2023/02/25 00:07:08 rillig Exp $
+# $NetBSD: opt.mk,v 1.8 2026/02/08 11:02:03 rillig Exp $
#
# Tests for the command line options.
@@ -8,7 +8,7 @@ all: .IGNORE
# The options from the top-level make are passed to the sub-makes via
# the environment variable MAKEFLAGS. This is where the " -r -k -d 0"
# comes from. See MainParseOption.
- ${MAKE} -r -f /dev/null -V MAKEFLAGS
+ ${MAKE} -r -f /dev/null -V 'begin $${MAKEFLAGS} end'
@echo
# Just to see how the custom argument parsing code reacts to a syntax
diff --git a/unit-tests/sh-errctl.exp b/unit-tests/sh-errctl.exp
index 8419d215fe38..6dfa3fafc85f 100644
--- a/unit-tests/sh-errctl.exp
+++ b/unit-tests/sh-errctl.exp
@@ -1,6 +1,7 @@
job_pipe -1 -1, maxjobs 1, tokens 1, compat 0
TokenPool_Take: pid <pid>, aborting NONE, running 0
TokenPool_Take: pid <pid> took a token
+MaybeSubMake: Looking for "make"
# echo off
echo silent
# echo on
diff --git a/unit-tests/suff-main-several.exp b/unit-tests/suff-main-several.exp
index bb1fc91ea21d..a7bf6eb088e9 100644
--- a/unit-tests/suff-main-several.exp
+++ b/unit-tests/suff-main-several.exp
@@ -94,6 +94,7 @@ ParseDependency(.MAKEFLAGS: -d0 -dg1)
.MAKE.OS = <details omitted>
.MAKE.PID = <details omitted>
.MAKE.PPID = <details omitted>
+.MAKE.SAVE_DOLLARS = <details omitted>
.MAKE.UID = <details omitted>
.MAKEFLAGS = -r -k -d mps -d 0 -d g1
.MAKEOVERRIDES = # (empty)
diff --git a/unit-tests/suff-transform-debug.exp b/unit-tests/suff-transform-debug.exp
index ad0584f204d1..14d8b9050a08 100644
--- a/unit-tests/suff-transform-debug.exp
+++ b/unit-tests/suff-transform-debug.exp
@@ -20,6 +20,7 @@
.MAKE.OS = <details omitted>
.MAKE.PID = <details omitted>
.MAKE.PPID = <details omitted>
+.MAKE.SAVE_DOLLARS = <details omitted>
.MAKE.UID = <details omitted>
.MAKEFLAGS = -r -k -d g1
.MAKEOVERRIDES = # (empty)
diff --git a/unit-tests/var-recursive.exp b/unit-tests/var-recursive.exp
index 97568873bf1b..768b41c4b0ff 100644
--- a/unit-tests/var-recursive.exp
+++ b/unit-tests/var-recursive.exp
@@ -23,7 +23,7 @@ sub-exit status 1
make: Variable VAR is recursive.
while evaluating variable "VAR" with value "${VAR}"
in command ": recursive-line-before <${VAR}> recursive-line-after"
- in target "runtime"
+ in target "runtime" from var-recursive.mk:56
in make[1] in directory "<curdir>"
sub-exit status 2
exit status 0
diff --git a/unit-tests/var-scope-local.exp b/unit-tests/var-scope-local.exp
index eddf5985a0ed..dbf3f474d69e 100644
--- a/unit-tests/var-scope-local.exp
+++ b/unit-tests/var-scope-local.exp
@@ -67,5 +67,15 @@ Making var-scope-local-default.o with make 'global' and env 'global'.
Making var-scope-local-subst.o with make 'global+local' and env 'global+local'.
Making var-scope-local-shell.o with make 'output' and env 'output'.
Making .USE var-scope-local-use.o with make 'global' and env 'global'.
+begin pr-59073 compat
+$@ is pr-59073/file.o59703
+$< is pr-59073/file.c59703
+$* is pr-59073/file
+end pr-59073 compat
+begin pr-59073 parallel
+$@ is pr-59073/file.o59703
+$< is pr-59073/file.c59703
+$* is file
+end pr-59073 parallel
: all overwritten
exit status 0
diff --git a/unit-tests/var-scope-local.mk b/unit-tests/var-scope-local.mk
index 7a031373e7da..be10c4c9f7da 100644
--- a/unit-tests/var-scope-local.mk
+++ b/unit-tests/var-scope-local.mk
@@ -1,4 +1,4 @@
-# $NetBSD: var-scope-local.mk,v 1.11 2024/03/05 23:07:58 rillig Exp $
+# $NetBSD: var-scope-local.mk,v 1.12 2026/01/05 22:44:14 rillig Exp $
#
# Tests for target-local variables, such as ${.TARGET} or $@. These variables
# are relatively short-lived as they are created just before making the
@@ -138,7 +138,9 @@ dir/subdir/inference-rule-chain.ir-gen-from: .PHONY
# Custom local variables
#
# Additional target-local variables may be defined in dependency lines.
+.if !make(pr-59703-mode)
.MAKEFLAGS: -dv
+.endif
# In the following line, the ':=' may either be interpreted as an assignment
# operator or as the dependency operator ':', followed by an empty variable
# name and the assignment operator '='. It is the latter since in an
@@ -154,7 +156,9 @@ one two:=three
# word.
# expect: Global: one two = three
${:Uone two}:=three
+.if !make(pr-59703-mode)
.MAKEFLAGS: -d0
+.endif
.SUFFIXES: .c .o
@@ -268,3 +272,44 @@ a_use: .USE VAR=use
all: var-scope-local-use.o
var-scope-local-use.o: a_use
+
+
+# begin https://gnats.netbsd.org/59073
+# make(1) sets $* / $(.PREFIX) wrong in -j mode
+
+all: pr-59073
+
+# expect: begin pr-59073 compat
+# expect: $@ is pr-59073/file.o59703
+# expect: $< is pr-59073/file.c59703
+# expect: $* is pr-59073/file
+# expect: end pr-59073 compat
+# expect: begin pr-59073 parallel
+# expect: $@ is pr-59073/file.o59703
+# expect: $< is pr-59073/file.c59703
+# FIXME: The subdirectory is missing.
+# expect: $* is file
+# expect: end pr-59073 parallel
+
+pr-59073: .PHONY
+ # This has to be an actual file; using a memory-only target
+ # generates the correct value for "$*".
+ @mkdir -p pr-59073 && touch pr-59073/file.c59703
+ @echo begin pr-59073 compat
+ @MAKEFLAGS= ${MAKE} -r -f ${MAKEFILE} pr-59703-mode
+ @echo end pr-59073 compat
+ @echo begin pr-59073 parallel
+ @MAKEFLAGS= ${MAKE} -r -f ${MAKEFILE} -j1 pr-59703-mode
+ @echo end pr-59073 parallel
+ @rm -rf pr-59073
+
+pr-59703-mode: pr-59073/file.o59703
+
+.SUFFIXES: .c59703 .o59703
+
+.c59703.o59703:
+ @echo '$$@ is $@'
+ @echo '$$< is $<'
+ @echo '$$* is $*'
+
+# end https://gnats.netbsd.org/59073
diff --git a/unit-tests/varmisc.exp b/unit-tests/varmisc.exp
index 44b3c8e759cb..4d09e691de42 100644
--- a/unit-tests/varmisc.exp
+++ b/unit-tests/varmisc.exp
@@ -46,36 +46,36 @@ parse-dynamic: parse-dynamic parse-dynamic after
varerror-unclosed-1:begin
make: Unclosed variable ""
in command "@echo $("
- in target "varerror-unclosed-2"
+ in target "varerror-unclosed-2" from varmisc.mk:195
make: Unclosed variable "UNCLOSED"
in command "@echo $(UNCLOSED"
- in target "varerror-unclosed-3"
+ in target "varerror-unclosed-3" from varmisc.mk:198
make: Unclosed variable "UNCLOSED"
in command "@echo ${UNCLOSED"
- in target "varerror-unclosed-4"
+ in target "varerror-unclosed-4" from varmisc.mk:201
make: Unclosed variable "PATTERN"
while evaluating variable "UNCLOSED" with value ""
in command "@echo ${UNCLOSED:M${PATTERN"
- in target "varerror-unclosed-5"
+ in target "varerror-unclosed-5" from varmisc.mk:204
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"
+ in target "varerror-unclosed-5" from varmisc.mk:204
make: Unclosed variable "param"
in command "@echo ${UNCLOSED.${param"
- in target "varerror-unclosed-6"
+ in target "varerror-unclosed-6" from varmisc.mk:208
make: Unclosed variable "UNCLOSED."
in command "@echo ${UNCLOSED.${param"
- in target "varerror-unclosed-6"
+ in target "varerror-unclosed-6" from varmisc.mk:208
make: Unclosed variable "UNCLOSED.1"
in command "@echo ${UNCLOSED.${:U1}"
- in target "varerror-unclosed-7"
+ in target "varerror-unclosed-7" from varmisc.mk:213
make: Unclosed variable "UNCLOSED_ORIG"
while evaluating variable "UNCLOSED_INDIR_1" with value "${UNCLOSED_ORIG"
while evaluating variable "UNCLOSED_INDIR_2" with value "${UNCLOSED_INDIR_1}"
in command "@echo ${UNCLOSED_INDIR_2}"
- in target "varerror-unclosed-8"
+ in target "varerror-unclosed-8" from varmisc.mk:217
target1-flags: we have: one two
target2-flags: we have: one two three four
exit status 2
diff --git a/unit-tests/varmod-assign.exp b/unit-tests/varmod-assign.exp
index ae7f6787d124..2cbd7e525449 100644
--- a/unit-tests/varmod-assign.exp
+++ b/unit-tests/varmod-assign.exp
@@ -40,30 +40,30 @@ Global: .MAKEFLAGS = -r -k -d v -d 0 -d v -d 0
make: Invalid attempt to assign "value" to variable "" via modifier "::="
while evaluating "${::=value}" with value ""
in command "@echo $@: ${::=value}"
- in target "mod-assign-empty-1"
+ in target "mod-assign-empty-1" from varmod-assign.mk:78
make: Invalid attempt to assign "overwritten" to variable "" via modifier "::="
while evaluating "${:Uvalue::=overwritten}" with value "value"
in command "@echo $@: ${:Uvalue::=overwritten}"
- in target "mod-assign-empty-2"
+ in target "mod-assign-empty-2" from varmod-assign.mk:84
make: Invalid attempt to assign "appended" to variable "" via modifier "::+="
while evaluating "${:Uvalue::+=appended}" with value "value"
in command "@echo $@: ${:Uvalue::+=appended}"
- in target "mod-assign-empty-3"
+ in target "mod-assign-empty-3" from varmod-assign.mk:90
mod-assign-empty-4: VAR=overwritten
make: Unknown modifier "::x"
while evaluating variable "ASSIGN" with value ""
in command "@echo ${ASSIGN::x}"
- in target "mod-assign-parse-1"
+ in target "mod-assign-parse-1" from varmod-assign.mk:103
sysv:y
make: Unfinished modifier after "value # missing closing brace", expecting "}"
while evaluating variable "ASSIGN" with value ""
in command "@echo ${ASSIGN::=value # missing closing brace"
- in target "mod-assign-parse-3"
+ in target "mod-assign-parse-3" from varmod-assign.mk:112
ok=word
make: warning: Command " echo word; (exit 13) " exited with status 13
while evaluating variable "SH_ERR" with value "previous"
in command "@${SH_ERR::!= echo word; (exit 13) } echo err=${SH_ERR}"
- in target "mod-assign-shell-error"
+ in target "mod-assign-shell-error" from varmod-assign.mk:120
err=previous
Command: TARGET_CMD_VAR = cmd-value
Global: TARGET_GLOBAL_VAR = global-value
diff --git a/unit-tests/varmod-hash.exp b/unit-tests/varmod-hash.exp
index 1abc6bc92a9f..eb2490d27c3f 100644
--- a/unit-tests/varmod-hash.exp
+++ b/unit-tests/varmod-hash.exp
@@ -1,15 +1,15 @@
make: Unknown modifier ":has"
while evaluating variable "12345" with value "12345"
in command "@echo ${12345:L:has} # modifier name too short"
- in target "step-1"
+ in target "step-1" from varmod-hash.mk:61
26bb0f5f
12345
make: Unknown modifier ":hasX"
while evaluating variable "12345" with value "12345"
in command "@echo ${12345:L:hasX} # misspelled"
- in target "step-4"
+ in target "step-4" from varmod-hash.mk:67
make: Unknown modifier ":hashed"
while evaluating variable "12345" with value "12345"
in command "@echo ${12345:L:hashed} # modifier name too long"
- in target "step-5"
+ in target "step-5" from varmod-hash.mk:69
exit status 2
diff --git a/unit-tests/varmod-loop-delete.exp b/unit-tests/varmod-loop-delete.exp
index daacafc35561..7f31a606c10c 100644
--- a/unit-tests/varmod-loop-delete.exp
+++ b/unit-tests/varmod-loop-delete.exp
@@ -1,6 +1,12 @@
-make: varmod-loop-delete.mk:20: Cannot delete variable "VAR" while it is used
+make -f varmod-loop-delete.mk delete-active-variable || true
+make: varmod-loop-delete.mk:31: Cannot delete variable "VAR" while it is used
while evaluating "${:U:@VAR@@} rest of the value" with value ""
while evaluating variable "VAR" with value "${:U:@VAR@@} rest of the value"
+ in make[1] in directory "<curdir>"
make: Fatal errors encountered -- cannot continue
-make: stopped making "all" in unit-tests
-exit status 1
+make: stopped making "delete-active-variable" in unit-tests
+
+make -f varmod-loop-delete.mk delete-active-variable-in-target || true
+: delete-active-variable-in-target: ' rest of the value'
+
+exit status 0
diff --git a/unit-tests/varmod-loop-delete.mk b/unit-tests/varmod-loop-delete.mk
index 478a25e91f6e..7b7dc0a77b25 100644
--- a/unit-tests/varmod-loop-delete.mk
+++ b/unit-tests/varmod-loop-delete.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-loop-delete.mk,v 1.7 2024/08/29 20:20:36 rillig Exp $
+# $NetBSD: varmod-loop-delete.mk,v 1.9 2026/02/09 22:04:54 rillig Exp $
#
# Tests for the variable modifier ':@', which as a side effect allows to
# delete an arbitrary variable.
@@ -11,6 +11,17 @@
#
# See Var_Parse, comment 'the value of the variable must not change'.
+all: .PHONY
+ ${MAKE} -f ${MAKEFILE} delete-active-variable || true
+ @echo
+ ${MAKE} -f ${MAKEFILE} delete-active-variable-in-target || true
+ @echo
+ # Disabled since the details of the crash depend on the execution
+ # environment.
+ #${MAKE} -f ${MAKEFILE} use-after-free
+
+delete-active-variable: .PHONY
+.if make(delete-active-variable)
# Set up the variable that deletes itself when it is evaluated.
VAR= ${:U:@VAR@@} rest of the value
@@ -18,12 +29,16 @@ VAR= ${:U:@VAR@@} rest of the value
# defined in the global scope, it deletes itself.
# expect+1: Cannot delete variable "VAR" while it is used
EVAL:= ${VAR}
-.if ${EVAL} != " rest of the value"
-. error
+. if ${EVAL} != " rest of the value"
+. error
+. endif
.endif
+delete-active-variable-in-target: .PHONY
+.if make(delete-active-variable-in-target)
VAR= ${:U:@VAR@@} rest of the value
-all: .PHONY
+
+delete-active-variable-in-target:
# In the command that is associated with a target, the scope is the
# one from the target. That scope only contains a few variables like
# '.TARGET', '.ALLSRC', '.IMPSRC'. Make does not expect that these
@@ -32,3 +47,28 @@ all: .PHONY
# There is no variable named 'VAR' in the local scope, so nothing
# happens.
: $@: '${VAR}'
+# expect: : delete-active-variable-in-target: ' rest of the value'
+.endif
+
+
+# On NetBSD 11.99.x with jemalloc and MALLOC_CONF=junk:true, the output is:
+# make: varmod-loop-delete.mk:72: Unknown modifier ":Z2"
+# while evaluating "${:U 333 :@v@...${:Z1}@:Z2}" with value "...${:Z1}"
+# while evaluating variable "INNER.1" with value "${:U 333 :@v@...${:Z1}@:Z2}"
+# while evaluating variable "ZZZZZZZZZZZZ...${:Z1}" with value "ZZZZZZZZ"
+# while evaluating "${:U 111 222 :@v@${v:S,^,${INNER.1},}@}" with value " 111 222 "
+# while evaluating variable "OUTER" with value "${:U 111 222 :@v@${v:S,^,${INNER.1},}@}"
+# in make in directory "<curdir>"
+# Modifier part: ""
+# ModifyWords: split "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" into 1 word
+# Result of ${ZZZZZZZZZZZZ:S,^,${INNER.1},} is "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" (eval-keep-undefined, regular)
+# Segmentation fault (core dumped)
+use-after-free: .PHONY
+.if make(use-after-free)
+OUTER= ${:U 111 222 :@v@${v:S,^,${INNER.1},}@}
+INNER.1= ${:U 333 :@v@...${:Z1}@:Z2}
+
+.MAKEFLAGS: -dcpv
+_:= ${OUTER}
+.MAKEFLAGS: -d0
+.endif
diff --git a/unit-tests/varmod-select-words.exp b/unit-tests/varmod-select-words.exp
index 4ac95ead0852..b731baf8869f 100644
--- a/unit-tests/varmod-select-words.exp
+++ b/unit-tests/varmod-select-words.exp
@@ -1,7 +1,7 @@
make: Invalid modifier ":[]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[]="${LIST:[]}" is an error'"
- in target "mod-squarebrackets-empty"
+ in target "mod-squarebrackets-empty" from varmod-select-words.mk:54
LIST:[0]="one two three four five six"
LIST:[0x0]="one two three four five six"
LIST:[000]="one two three four five six"
@@ -42,11 +42,11 @@ LIST:[1]="one"
make: Invalid modifier ":[1.]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1.]="${LIST:[1.]}" is an error'"
- in target "mod-squarebrackets-n-error-1"
+ in target "mod-squarebrackets-n-error-1" from varmod-select-words.mk:100
make: Extra text after "[1]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1].="${LIST:[1].}" is an error'"
- in target "mod-squarebrackets-n-error-2"
+ in target "mod-squarebrackets-n-error-2" from varmod-select-words.mk:103
LIST:[2]="two"
LIST:[6]="six"
LIST:[7]=""
@@ -54,11 +54,11 @@ LIST:[999]=""
make: Invalid modifier ":[-]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[-]="${LIST:[-]}" is an error'"
- in target "mod-squarebrackets-n-error-3"
+ in target "mod-squarebrackets-n-error-3" from varmod-select-words.mk:111
make: Invalid modifier ":[--]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[--]="${LIST:[--]}" is an error'"
- in target "mod-squarebrackets-n-error-4"
+ in target "mod-squarebrackets-n-error-4" from varmod-select-words.mk:114
LIST:[-1]="six"
LIST:[-2]="five"
LIST:[-6]="one"
@@ -80,20 +80,20 @@ LONGLIST:[012..0x12]="10 11 12 13 14 15 16 17 18"
make: Invalid modifier ":[1.]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1.]="${LIST:[1.]}" is an error'"
- in target "mod-squarebrackets-start-end-error-1"
+ in target "mod-squarebrackets-start-end-error-1" from varmod-select-words.mk:137
make: Invalid modifier ":[1..]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1..]="${LIST:[1..]}" is an error'"
- in target "mod-squarebrackets-start-end-error-2"
+ in target "mod-squarebrackets-start-end-error-2" from varmod-select-words.mk:140
make: Invalid modifier ":[1.. ]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1.. ]="${LIST:[1.. ]}" is an error'"
- in target "mod-squarebrackets-start-end-error-3"
+ in target "mod-squarebrackets-start-end-error-3" from varmod-select-words.mk:143
LIST:[1..1]="one"
make: Invalid modifier ":[1..1.]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[1..1.]="${LIST:[1..1.]}" is an error'"
- in target "mod-squarebrackets-start-end-error-4"
+ in target "mod-squarebrackets-start-end-error-4" from varmod-select-words.mk:148
LIST:[1..2]="one two"
LIST:[2..1]="two one"
LIST:[3..-2]="three four five"
@@ -101,11 +101,11 @@ LIST:[-4..4]="three four"
make: Invalid modifier ":[0..1]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[0..1]="${LIST:[0..1]}" is an error'"
- in target "mod-squarebrackets-start-end-error-5"
+ in target "mod-squarebrackets-start-end-error-5" from varmod-select-words.mk:156
make: Invalid modifier ":[-1..0]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[-1..0]="${LIST:[-1..0]}" is an error'"
- in target "mod-squarebrackets-start-end-error-6"
+ in target "mod-squarebrackets-start-end-error-6" from varmod-select-words.mk:159
LIST:[-1..1]="six five four three two one"
LIST:[0..0]="one two three four five six"
LIST:[3..99]="three four five six"
@@ -122,7 +122,7 @@ LIST:[${AT}]="one two three four five six"
make: Invalid modifier ":[]"
while evaluating variable "LIST" with value "one two three four five six"
in command "@echo 'LIST:[$${EMPTY}]="${LIST:[${EMPTY}]}" is an error'"
- in target "mod-squarebrackets-nested-error-1"
+ in target "mod-squarebrackets-nested-error-1" from varmod-select-words.mk:178
LIST:[${LONGLIST:[21]:S/2//}]="one"
LIST:[${LIST:[#]}]="six"
LIST:[${LIST:[${HASH}]}]="six"
diff --git a/unit-tests/varmod-subst-regex.exp b/unit-tests/varmod-subst-regex.exp
index 816b02248591..c8bc2ac035ea 100644
--- a/unit-tests/varmod-subst-regex.exp
+++ b/unit-tests/varmod-subst-regex.exp
@@ -1,67 +1,67 @@
make: Regex compilation error: (details omitted)
while evaluating "${:Uword1 word2:C,****,____,g:C,word,____,:Q}." with value "word1 word2"
in command "@echo $@: ${:Uword1 word2:C,****,____,g:C,word,____,:Q}."
- in target "mod-regex-compile-error"
+ in target "mod-regex-compile-error" from varmod-subst-regex.mk:154
make: No subexpression \1
while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
in command "@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}"
- in target "mod-regex-limits-1"
+ in target "mod-regex-limits-1" from varmod-subst-regex.mk:159
make: No subexpression \1
while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
in command "@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}"
- in target "mod-regex-limits-1"
+ in target "mod-regex-limits-1" from varmod-subst-regex.mk:159
make: No subexpression \1
while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
in command "@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}"
- in target "mod-regex-limits-1"
+ in target "mod-regex-limits-1" from varmod-subst-regex.mk:159
make: No subexpression \1
while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
in command "@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}"
- in target "mod-regex-limits-1"
+ in target "mod-regex-limits-1" from varmod-subst-regex.mk:159
mod-regex-limits-2:11-ok:1 22 446
make: No subexpression \2
while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}"
- in target "mod-regex-limits-3"
+ in target "mod-regex-limits-3" from varmod-subst-regex.mk:163
make: No subexpression \2
while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}"
- in target "mod-regex-limits-3"
+ in target "mod-regex-limits-3" from varmod-subst-regex.mk:163
make: No subexpression \2
while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}"
- in target "mod-regex-limits-3"
+ in target "mod-regex-limits-3" from varmod-subst-regex.mk:163
make: No subexpression \2
while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}"
- in target "mod-regex-limits-3"
+ in target "mod-regex-limits-3" from varmod-subst-regex.mk:163
make: No subexpression \2
while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}"
- in target "mod-regex-limits-4"
+ in target "mod-regex-limits-4" from varmod-subst-regex.mk:165
make: No subexpression \2
while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}"
- in target "mod-regex-limits-4"
+ in target "mod-regex-limits-4" from varmod-subst-regex.mk:165
make: No subexpression \2
while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}"
- in target "mod-regex-limits-4"
+ in target "mod-regex-limits-4" from varmod-subst-regex.mk:165
make: No subexpression \2
while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
in command "@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}"
- in target "mod-regex-limits-4"
+ in target "mod-regex-limits-4" from varmod-subst-regex.mk:165
mod-regex-limits-5:22-ok:1 33 556
mod-regex-limits-6:capture:ihgfedcbaabcdefghijABCDEFGHIJa0a1a2rest
make: Regex compilation error: (details omitted)
while evaluating variable "UNDEF" with value "value"
in command "@echo $@: ${UNDEF:Uvalue:C,[,,}"
- in target "mod-regex-errors-1"
+ in target "mod-regex-errors-1" from varmod-subst-regex.mk:174
make: Unknown modifier ":Z"
while evaluating "${:U:Z}y,W}" with value ""
while evaluating variable "word" with value "word"
in command "@echo $@: ${word:L:C,.*,x${:U:Z}y,W}"
- in target "mod-regex-errors-2"
+ in target "mod-regex-errors-2" from varmod-subst-regex.mk:179
unmatched-subexpression.ok: one one 2 3 5 8 one3 2one 34
make: No match for subexpression \2
unmatched-subexpression.1: ()()
diff --git a/unit-tests/varmod-subst-regex.mk b/unit-tests/varmod-subst-regex.mk
index bc04bc5fffb9..5af0236975bb 100644
--- a/unit-tests/varmod-subst-regex.mk
+++ b/unit-tests/varmod-subst-regex.mk
@@ -1,6 +1,6 @@
-# $NetBSD: varmod-subst-regex.mk,v 1.12 2024/07/20 11:05:12 rillig Exp $
+# $NetBSD: varmod-subst-regex.mk,v 1.13 2026/01/03 22:40:38 rillig Exp $
#
-# Tests for the :C,from,to, variable modifier.
+# Tests for the :C,from,to, modifier.
# report unmatched subexpressions
.MAKEFLAGS: -dL
@@ -23,7 +23,7 @@ all: unmatched-subexpression
. error
.endif
-# The 'W' modifier treats the whole variable value as a single big word,
+# The 'W' modifier treats the whole expression value as a single big word,
# containing whitespace. This big word matches the regular expression,
# therefore it gets replaced. Whitespace is preserved after replacing.
.if ${:Ua b b c:C,a b,,W} != " b c"
@@ -60,14 +60,16 @@ all: unmatched-subexpression
# The modifier '1' applies the replacement at most once, across the whole
# expression value, no matter whether it is a single big word or many small
# words.
-#
-# Up to 2020-08-28, the manual page said that the modifiers '1' and 'g'
-# were orthogonal, which was wrong. It doesn't make sense to specify both
-# 'g' and '1' at the same time.
.if ${:U12345 12345:C,.,\0\0,1} != "112345 12345"
. error
.endif
+# When both '1' and 'g' are given, this means to replace all occurrences,
+# but only in the first word where they are found, not in any remaining words.
+.if ${:U 11111 22222 22222 :C,2,0,g1} != "11111 00000 22222"
+. error
+.endif
+
# A regular expression that matches the empty string applies before every
# single character of the word.
# XXX: Most other places where regular expression are used match at the end
@@ -129,16 +131,30 @@ all: unmatched-subexpression
.endif
+# Just as in the ":S" modifier and the sed(1) utility, an "&" in the
+# replacement part stands for the whole matched string. It can be escaped
+# using a backslash.
+.if ${:U 123 234 345 :C,2,&\&&,} != "12&23 2&234 345"
+. error
+.endif
+
+# When the ":C" modifier uses "&" as the delimiter for its parts, the "&"
+# needs to be escaped. To get a literal "&" in the replacement, it needs
+# to be written as "\\\&". When parsing the modifier part, the "\\" and "\&"
+# result in "\" and "&", which then form the replacement "\&", and that is
+# interpreted as a literal "&".
+.if ${:U 123 234 345 :C&2&\&\\\&\&&} != "12&23 2&234 345"
+. error
+.endif
+
+
# Multiple asterisks form an invalid regular expression. This produces an
-# error message and (as of 2020-08-28) stops parsing in the middle of the
-# expression. The unparsed part of the expression is then copied
-# verbatim to the output, which is unexpected and can lead to strange shell
-# commands being run.
+# error message, and due to this error message, the shell command is not run.
mod-regex-compile-error:
@echo $@: ${:Uword1 word2:C,****,____,g:C,word,____,:Q}.
-# These tests generate error messages but as of 2020-08-28 just continue
-# parsing and execution as if nothing bad had happened.
+# These tests generate error messages for the missing capturing groups.
+# Due to these error messages, the echo commands are not executed.
mod-regex-limits-1:
@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}
mod-regex-limits-2:
@@ -158,9 +174,8 @@ mod-regex-errors-1:
@echo $@: ${UNDEF:Uvalue:C,[,,}
mod-regex-errors-2:
- # If the replacement pattern produces a parse error because of an
- # unknown modifier, the parse error is ignored in ParseModifierPart
- # and the faulty expression expands to "".
+ # If the replacement pattern produces a parse error due to an
+ # unknown modifier, the faulty expression expands to "".
@echo $@: ${word:L:C,.*,x${:U:Z}y,W}
# In regular expressions with alternatives, not all capturing groups are
diff --git a/unit-tests/varmod-subst.exp b/unit-tests/varmod-subst.exp
index 8eec26e33ef5..fcd5ab4cd856 100644
--- a/unit-tests/varmod-subst.exp
+++ b/unit-tests/varmod-subst.exp
@@ -43,12 +43,17 @@ mod-subst-delimiter:
1 two 3 vertical line
1 two 3 right curly bracket
1 two 3 tilde
+123 two34 345 circumflex accent
+make: Regex compilation error: (details omitted)
+ while evaluating "${:U 123 234 345 :C^^2^two^:Q} circumflex accent" with value " 123 234 345 "
+ in command "@echo ${:U 123 234 345 :C^^2^two^:Q} circumflex accent"
+ in target "mod-subst-delimiter-circumflex" from varmod-subst.mk:250
mod-subst-chain:
A B c.
make: Unknown modifier ":i"
while evaluating "${:Uvalue:S,a,x,i}." with value "vxlue"
in command "@echo ${:Uvalue:S,a,x,i}."
- in target "mod-subst-chain"
+ in target "mod-subst-chain" from varmod-subst.mk:268
mod-subst-dollar:$1:
mod-subst-dollar:$2:
mod-subst-dollar:$3:
diff --git a/unit-tests/varmod-subst.mk b/unit-tests/varmod-subst.mk
index e9da303515b2..ef7ad2358951 100644
--- a/unit-tests/varmod-subst.mk
+++ b/unit-tests/varmod-subst.mk
@@ -1,9 +1,10 @@
-# $NetBSD: varmod-subst.mk,v 1.17 2025/03/29 19:08:53 rillig Exp $
+# $NetBSD: varmod-subst.mk,v 1.18 2026/01/03 20:48:35 rillig Exp $
#
# Tests for the :S,from,to, variable modifier.
all: mod-subst
all: mod-subst-delimiter
+all: mod-subst-delimiter-circumflex
all: mod-subst-chain
all: mod-subst-dollar
@@ -237,11 +238,22 @@ mod-subst-delimiter:
@echo ${:U1 2 3:S}2}two}:Q} right curly bracket
@echo ${:U1 2 3:S~2~two~:Q} tilde
+
+# When the ":S" modifier uses "^" to separate its parts, and when the first
+# part starts with another "^", that "^" is interpreted as an anchor, not as
+# the delimiter between the parts.
+mod-subst-delimiter-circumflex: .PHONY
+ @echo ${:U 123 234 345 :S^^2^two^:Q} circumflex accent
+ # In the ":C" modifier, the "^" is not interpreted as an anchor,
+ # instead it is interpreted as the delimiter of the regular
+ # expression, thus making the regular expression empty and invalid.
+ @echo ${:U 123 234 345 :C^^2^two^:Q} circumflex accent
+
+
# The :S and :C modifiers can be chained without a separating ':'.
# This is not documented in the manual page.
# It works because ApplyModifier_Subst scans for the known modifiers g1W
-# and then just returns to ApplyModifiers. There, the colon is optionally
-# skipped (see the *st.next == ':' at the end of the loop).
+# and then just returns to ApplySingleModifier. There, the colon is skipped.
#
# Most other modifiers cannot be chained since their parsers skip until
# the next ':' or '}' or ')'.
diff --git a/unit-tests/varname-dot-make-save_dollars.mk b/unit-tests/varname-dot-make-save_dollars.mk
index 31f228c220b2..a2134af51330 100644
--- a/unit-tests/varname-dot-make-save_dollars.mk
+++ b/unit-tests/varname-dot-make-save_dollars.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varname-dot-make-save_dollars.mk,v 1.7 2021/12/03 18:43:52 rillig Exp $
+# $NetBSD: varname-dot-make-save_dollars.mk,v 1.8 2026/03/13 04:22:03 sjg Exp $
#
# Tests for the special .MAKE.SAVE_DOLLARS variable, which controls whether
# the assignment operator ':=' converts '$$' to a single '$' or keeps it
@@ -8,11 +8,11 @@
# var-op-expand.mk for ':=' in general
# varmisc.mk for parsing the boolean values
-# Initially, the variable .MAKE.SAVE_DOLLARS is undefined. At this point the
-# behavior of the assignment operator ':=' depends. NetBSD's usr.bin/make
-# preserves the '$$' as-is, while the bmake distribution replaces '$$' with
-# '$'.
-.if ${.MAKE.SAVE_DOLLARS:Uundefined} != "undefined"
+# The variable .MAKE.SAVE_DOLLARS is a boolean that controls the handling
+# of '$$' during ':='
+# If "yes" (default for NetBSD's usr.bin/make) '$$' is left as-is.
+# If "no" (default for bmake), '$$' is replaced with '$'.
+.if ${.MAKE.SAVE_DOLLARS:Uundefined} == "undefined"
. error
.endif
diff --git a/unit-tests/varname-make_stack_trace.exp b/unit-tests/varname-make_stack_trace.exp
index c0f46cc5aa1e..5de66aa8bb8f 100644
--- a/unit-tests/varname-make_stack_trace.exp
+++ b/unit-tests/varname-make_stack_trace.exp
@@ -1,7 +1,7 @@
make: Unknown modifier ":Z"
while evaluating "${:Z}" with value ""
in command "@echo ${:Z}"
- in target "provoke-error"
+ in target "provoke-error" from varname-make_stack_trace.mk:42
in make[2] in directory "<curdir>"
*** Error code 2 (continuing)
@@ -10,7 +10,7 @@ make: stopped making "disabled-compat" in unit-tests
make: Unknown modifier ":Z"
while evaluating "${:Z}" with value ""
in command "@echo ${:Z}"
- in target "provoke-error"
+ in target "provoke-error" from varname-make_stack_trace.mk:42
in make[2] in directory "<curdir>"
*** [disabled-parallel] Error code 2
@@ -18,10 +18,10 @@ make: stopped making "disabled-parallel" in unit-tests
make: Unknown modifier ":Z"
while evaluating "${:Z}" with value ""
in command "@echo ${:Z}"
- in target "provoke-error"
+ in target "provoke-error" from varname-make_stack_trace.mk:42
in make[2] in directory "<curdir>"
in command "make -f varname-make_stack_trace.mk provoke-error"
- in target "enabled-compat"
+ in target "enabled-compat" from varname-make_stack_trace.mk:35
in make[1] in directory "<curdir>"
*** Error code 2 (continuing)
@@ -30,11 +30,21 @@ make: stopped making "enabled-compat" in unit-tests
make: Unknown modifier ":Z"
while evaluating "${:Z}" with value ""
in command "@echo ${:Z}"
- in target "provoke-error"
+ in target "provoke-error" from varname-make_stack_trace.mk:42
in make[2] in directory "<curdir>"
- in target "enabled-parallel"
+ in target "enabled-parallel" from varname-make_stack_trace.mk:39
in make[1] in directory "<curdir>"
*** [enabled-parallel] Error code 2
make: stopped making "enabled-parallel" in unit-tests
+.make[5]: warning: Invalid internal option "-J" in "<curdir>"; see the manual page
+ in .make[5] in directory "<curdir>"
+ in target "multi-stage-4" from varname-make_stack_trace.mk:56
+ in make[4] in directory "<curdir>"
+ in target "multi-stage-3" from varname-make_stack_trace.mk:54
+ in make[3] in directory "<curdir>"
+ in target "multi-stage-2" from varname-make_stack_trace.mk:52
+ in make[2] in directory "<curdir>"
+ in target "multi-stage-1" from varname-make_stack_trace.mk:50
+ in make[1] in directory "<curdir>"
exit status 0
diff --git a/unit-tests/varname-make_stack_trace.mk b/unit-tests/varname-make_stack_trace.mk
index cba02559bafe..26b06448d583 100644
--- a/unit-tests/varname-make_stack_trace.mk
+++ b/unit-tests/varname-make_stack_trace.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varname-make_stack_trace.mk,v 1.1 2025/06/13 03:51:18 rillig Exp $
+# $NetBSD: varname-make_stack_trace.mk,v 1.8 2026/03/10 05:02:00 sjg Exp $
#
# Tests for the MAKE_STACK_TRACE environment variable, which controls whether
# to print inter-process stack traces that are useful to narrow down where an
@@ -11,27 +11,53 @@
# with the space for the command line arguments, and long command lines are
# already written to a temporary file by Cmd_Exec to not overwhelm this space.
+_make ?= .make${.MAKE.PID}
+.export _make
+
all: .PHONY
@${MAKE} -f ${MAKEFILE} disabled-compat || :
@${MAKE} -f ${MAKEFILE} -j1 disabled-parallel || :
@MAKE_STACK_TRACE=yes ${MAKE} -f ${MAKEFILE} enabled-compat || :
@MAKE_STACK_TRACE=yes ${MAKE} -f ${MAKEFILE} -j1 enabled-parallel || :
+ @MAKE_STACK_TRACE=yes ${MAKE} -f ${MAKEFILE} -j1 multi-stage-1
+ @rm -f ${_make}
-# expect-not: in target "disabled-compat"
+# expect-not-matches: in target "disabled%-compat"
disabled-compat: .PHONY
@${MAKE} -f ${MAKEFILE} provoke-error
-# expect-not: in target "disabled-parallel"
+# expect-not-matches: in target "disabled%-parallel"
disabled-parallel: .PHONY
@${MAKE} -f ${MAKEFILE} provoke-error
-# expect: in target "enabled-compat"
+# expect: in target "enabled-compat" from varname-make_stack_trace.mk:35
enabled-compat: .PHONY
@${MAKE} -f ${MAKEFILE} provoke-error
-# expect: in target "enabled-parallel"
+# expect: in target "enabled-parallel" from varname-make_stack_trace.mk:39
enabled-parallel: .PHONY
@${MAKE} -f ${MAKEFILE} provoke-error
provoke-error: .PHONY
@echo ${:Z}
+
+# The stack trace must be printed exactly once.
+# expect: in target "multi-stage-4" from varname-make_stack_trace.mk:56
+# expect: in target "multi-stage-1" from varname-make_stack_trace.mk:50
+# expect-not-matches: in target "multi%-stage%-4"
+# expect-not-matches: in target "multi%-stage%-1"
+multi-stage-1: .PHONY ${_make}
+ @${MAKE} -f ${MAKEFILE} -j1 multi-stage-2
+multi-stage-2: .PHONY
+ @${MAKE} -f ${MAKEFILE} -j1 multi-stage-3
+multi-stage-3: .PHONY
+ @${MAKE} -f ${MAKEFILE} -j1 multi-stage-4
+multi-stage-4: .PHONY
+ @./${_make} -f ${MAKEFILE} -j1 multi-stage-5
+multi-stage-5: .PHONY
+
+${_make}:
+ @ln -s ${MAKE} ${.TARGET}
+
+# for FreeBSD and similar make sure we get the expected errors.
+.MAKE.ALWAYS_PASS_JOB_QUEUE= no