Module Name:    src
Committed By:   rillig
Date:           Sat Jul 20 11:05:12 UTC 2024

Modified Files:
        src/usr.bin/make: compat.c
        src/usr.bin/make/unit-tests: check-expect.lua cmd-errors-lint.exp
            cmd-errors-lint.mk cmd-errors.exp cmd-errors.mk lint.exp
            moderrs.exp moderrs.mk varmisc.exp varmisc.mk varmod-assign.exp
            varmod-assign.mk varmod-hash.exp varmod-hash.mk
            varmod-select-words.exp varmod-select-words.mk
            varmod-subst-regex.exp varmod-subst-regex.mk varmod-subst.exp
            varmod-subst.mk

Log Message:
make: don't run erroneous commands in compat mode

When there is a parse or evaluation error in an expression that becomes
part of the command, don't run that command, as the result of the failed
evaluation typically contains garbage characters. Skip the remaining
commands from that target as well, as they may depend on the erroneous
command.


To generate a diff of this commit:
cvs rdiff -u -r1.260 -r1.261 src/usr.bin/make/compat.c
cvs rdiff -u -r1.8 -r1.9 src/usr.bin/make/unit-tests/check-expect.lua \
    src/usr.bin/make/unit-tests/cmd-errors-lint.exp
cvs rdiff -u -r1.4 -r1.5 src/usr.bin/make/unit-tests/cmd-errors-lint.mk \
    src/usr.bin/make/unit-tests/varmod-select-words.exp \
    src/usr.bin/make/unit-tests/varmod-select-words.mk
cvs rdiff -u -r1.12 -r1.13 src/usr.bin/make/unit-tests/cmd-errors.exp
cvs rdiff -u -r1.9 -r1.10 src/usr.bin/make/unit-tests/cmd-errors.mk
cvs rdiff -u -r1.5 -r1.6 src/usr.bin/make/unit-tests/lint.exp \
    src/usr.bin/make/unit-tests/varmod-hash.mk
cvs rdiff -u -r1.43 -r1.44 src/usr.bin/make/unit-tests/moderrs.exp
cvs rdiff -u -r1.39 -r1.40 src/usr.bin/make/unit-tests/moderrs.mk
cvs rdiff -u -r1.23 -r1.24 src/usr.bin/make/unit-tests/varmisc.exp \
    src/usr.bin/make/unit-tests/varmod-assign.mk
cvs rdiff -u -r1.35 -r1.36 src/usr.bin/make/unit-tests/varmisc.mk
cvs rdiff -u -r1.27 -r1.28 src/usr.bin/make/unit-tests/varmod-assign.exp
cvs rdiff -u -r1.6 -r1.7 src/usr.bin/make/unit-tests/varmod-hash.exp
cvs rdiff -u -r1.10 -r1.11 src/usr.bin/make/unit-tests/varmod-subst-regex.exp
cvs rdiff -u -r1.11 -r1.12 src/usr.bin/make/unit-tests/varmod-subst-regex.mk
cvs rdiff -u -r1.7 -r1.8 src/usr.bin/make/unit-tests/varmod-subst.exp
cvs rdiff -u -r1.14 -r1.15 src/usr.bin/make/unit-tests/varmod-subst.mk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/compat.c
diff -u src/usr.bin/make/compat.c:1.260 src/usr.bin/make/compat.c:1.261
--- src/usr.bin/make/compat.c:1.260	Thu Jul 11 20:09:16 2024
+++ src/usr.bin/make/compat.c	Sat Jul 20 11:05:11 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: compat.c,v 1.260 2024/07/11 20:09:16 sjg Exp $	*/
+/*	$NetBSD: compat.c,v 1.261 2024/07/20 11:05:11 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -91,7 +91,7 @@
 #include "pathnames.h"
 
 /*	"@(#)compat.c	8.2 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: compat.c,v 1.260 2024/07/11 20:09:16 sjg Exp $");
+MAKE_RCSID("$NetBSD: compat.c,v 1.261 2024/07/20 11:05:11 rillig Exp $");
 
 static GNode *curTarg = NULL;
 static pid_t compatChild;
@@ -248,13 +248,18 @@ Compat_RunCommand(const char *cmdp, GNod
 	const char *cmd = cmdp;
 	char cmd_file[MAXPATHLEN];
 	size_t cmd_len;
+	int parseErrorsBefore;
 
 	silent = (gn->type & OP_SILENT) != OP_NONE;
 	errCheck = !(gn->type & OP_IGNORE);
 	doIt = false;
 
+	parseErrorsBefore = parseErrors;
 	cmdStart = Var_SubstInTarget(cmd, gn);
-	/* TODO: handle errors */
+	if (parseErrors != parseErrorsBefore) {
+		free(cmdStart);
+		return false;
+	}
 
 	if (cmdStart[0] == '\0') {
 		free(cmdStart);

Index: src/usr.bin/make/unit-tests/check-expect.lua
diff -u src/usr.bin/make/unit-tests/check-expect.lua:1.8 src/usr.bin/make/unit-tests/check-expect.lua:1.9
--- src/usr.bin/make/unit-tests/check-expect.lua:1.8	Sun Dec 17 09:44:00 2023
+++ src/usr.bin/make/unit-tests/check-expect.lua	Sat Jul 20 11:05:11 2024
@@ -1,5 +1,5 @@
 #!  /usr/bin/lua
--- $NetBSD: check-expect.lua,v 1.8 2023/12/17 09:44:00 rillig Exp $
+-- $NetBSD: check-expect.lua,v 1.9 2024/07/20 11:05:11 rillig Exp $
 
 --[[
 
@@ -19,6 +19,10 @@ expected text in the corresponding .exp 
 # expect[+-]offset: <message>
         Each message must occur in the .exp file and refer back to the
         source line in the .mk file.
+
+# expect-not: <substring>
+        The substring must not occur as part of any line of the .exp file.
+
 ]]
 
 
@@ -104,6 +108,18 @@ local function check_mk(mk_fname)
   local prev_expect_line = 0
 
   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)
+      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
Index: src/usr.bin/make/unit-tests/cmd-errors-lint.exp
diff -u src/usr.bin/make/unit-tests/cmd-errors-lint.exp:1.8 src/usr.bin/make/unit-tests/cmd-errors-lint.exp:1.9
--- src/usr.bin/make/unit-tests/cmd-errors-lint.exp:1.8	Fri Jul  5 18:59:33 2024
+++ src/usr.bin/make/unit-tests/cmd-errors-lint.exp	Sat Jul 20 11:05:11 2024
@@ -1,9 +1,6 @@
 : undefined 
 make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
-: unclosed-expression 
 make: in target "unclosed-modifier": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}'
-: unclosed-modifier 
 make: in target "unknown-modifier": while evaluating variable "UNKNOWN" with value "": Unknown modifier "Z"
-: unknown-modifier 
 : end
 exit status 2

Index: src/usr.bin/make/unit-tests/cmd-errors-lint.mk
diff -u src/usr.bin/make/unit-tests/cmd-errors-lint.mk:1.4 src/usr.bin/make/unit-tests/cmd-errors-lint.mk:1.5
--- src/usr.bin/make/unit-tests/cmd-errors-lint.mk:1.4	Fri Jul  5 18:59:33 2024
+++ src/usr.bin/make/unit-tests/cmd-errors-lint.mk	Sat Jul 20 11:05:11 2024
@@ -1,4 +1,4 @@
-# $NetBSD: cmd-errors-lint.mk,v 1.4 2024/07/05 18:59:33 rillig Exp $
+# $NetBSD: cmd-errors-lint.mk,v 1.5 2024/07/20 11:05:11 rillig Exp $
 #
 # Demonstrate how errors in expressions affect whether the commands
 # are actually executed.
@@ -15,20 +15,17 @@ undefined:
 
 unclosed-expression:
 # expect: make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unclosed-expression
+# expect-not: : unclosed-expression
 	: $@ ${UNCLOSED
 
 unclosed-modifier:
 # expect: make: in target "unclosed-modifier": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}'
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unclosed-modifier
+# expect-not: : unclosed-modifier
 	: $@ ${UNCLOSED:
 
 unknown-modifier:
 # expect: make: in target "unknown-modifier": while evaluating variable "UNKNOWN" with value "": Unknown modifier "Z"
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unknown-modifier
+# expect-not: : unknown-modifier
 	: $@ ${UNKNOWN:Z}
 
 end:
Index: src/usr.bin/make/unit-tests/varmod-select-words.exp
diff -u src/usr.bin/make/unit-tests/varmod-select-words.exp:1.4 src/usr.bin/make/unit-tests/varmod-select-words.exp:1.5
--- src/usr.bin/make/unit-tests/varmod-select-words.exp:1.4	Tue Jul  9 19:43:01 2024
+++ src/usr.bin/make/unit-tests/varmod-select-words.exp	Sat Jul 20 11:05:12 2024
@@ -1,5 +1,4 @@
-make: in target "mod-squarebrackets-0-star-at": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[]"
-LIST:[]="" is an error
+make: in target "mod-squarebrackets-empty": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[]"
 LIST:[0]="one two three four five six"
 LIST:[0x0]="one two three four five six"
 LIST:[000]="one two three four five six"
@@ -37,18 +36,14 @@ REALLYSPACE=" "
 REALLYSPACE:[1]="" == "" ?
 REALLYSPACE:[*]:[1]=" " == " " ?
 LIST:[1]="one"
-make: in target "mod-squarebrackets-n": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.]"
-LIST:[1.]="" is an error
-make: in target "mod-squarebrackets-n": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1]."
-LIST:[1].="}" is an error
+make: in target "mod-squarebrackets-n-error-1": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.]"
+make: in target "mod-squarebrackets-n-error-2": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1]."
 LIST:[2]="two"
 LIST:[6]="six"
 LIST:[7]=""
 LIST:[999]=""
-make: in target "mod-squarebrackets-n": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[-]"
-LIST:[-]="" is an error
-make: in target "mod-squarebrackets-n": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[--]"
-LIST:[--]="" is an error
+make: in target "mod-squarebrackets-n-error-3": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[-]"
+make: in target "mod-squarebrackets-n-error-4": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[--]"
 LIST:[-1]="six"
 LIST:[-2]="five"
 LIST:[-6]="one"
@@ -67,23 +62,17 @@ LIST:[*]:C/ /,/:[2]=""
 LIST:[*]:C/ /,/:[*]:[2]=""
 LIST:[*]:C/ /,/:[@]:[2]="three"
 LONGLIST:[012..0x12]="10 11 12 13 14 15 16 17 18"
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.]"
-LIST:[1.]="" is an error
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1..]"
-LIST:[1..]="" is an error
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.. ]"
-LIST:[1.. ]="" is an error
+make: in target "mod-squarebrackets-start-end-error-1": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.]"
+make: in target "mod-squarebrackets-start-end-error-2": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1..]"
+make: in target "mod-squarebrackets-start-end-error-3": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.. ]"
 LIST:[1..1]="one"
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1..1.]"
-LIST:[1..1.]="" is an error
+make: in target "mod-squarebrackets-start-end-error-4": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1..1.]"
 LIST:[1..2]="one two"
 LIST:[2..1]="two one"
 LIST:[3..-2]="three four five"
 LIST:[-4..4]="three four"
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[0..1]"
-LIST:[0..1]="" is an error
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[-1..0]"
-LIST:[-1..0]="" is an error
+make: in target "mod-squarebrackets-start-end-error-5": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[0..1]"
+make: in target "mod-squarebrackets-start-end-error-6": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[-1..0]"
 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"
@@ -97,8 +86,7 @@ LIST:[${ONE}]="one"
 LIST:[${MINUSONE}]="six"
 LIST:[${STAR}]="one two three four five six"
 LIST:[${AT}]="one two three four five six"
-make: in target "mod-squarebrackets-nested": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[${EMPTY"
-LIST:[${EMPTY}]="" is an error
+make: in target "mod-squarebrackets-nested-error-1": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[${EMPTY"
 LIST:[${LONGLIST:[21]:S/2//}]="one"
 LIST:[${LIST:[#]}]="six"
 LIST:[${LIST:[${HASH}]}]="six"
Index: src/usr.bin/make/unit-tests/varmod-select-words.mk
diff -u src/usr.bin/make/unit-tests/varmod-select-words.mk:1.4 src/usr.bin/make/unit-tests/varmod-select-words.mk:1.5
--- src/usr.bin/make/unit-tests/varmod-select-words.mk:1.4	Sun Jan 23 16:09:38 2022
+++ src/usr.bin/make/unit-tests/varmod-select-words.mk	Sat Jul 20 11:05:12 2024
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-select-words.mk,v 1.4 2022/01/23 16:09:38 rillig Exp $
+# $NetBSD: varmod-select-words.mk,v 1.5 2024/07/20 11:05:12 rillig Exp $
 #
 # Tests for the :[...] variable modifier, which selects a single word
 # or a range of words from a variable.
@@ -24,15 +24,36 @@ ZERO=		0
 ONE=		1
 MINUSONE=	-1
 
-mod-squarebrackets: mod-squarebrackets-0-star-at \
+mod-squarebrackets: \
+	mod-squarebrackets-empty \
+	mod-squarebrackets-0-star-at \
 	mod-squarebrackets-hash \
-	mod-squarebrackets-n \
-	mod-squarebrackets-start-end \
-	mod-squarebrackets-nested \
+	mod-squarebrackets-n-ok-1 \
+	mod-squarebrackets-n-error-1 \
+	mod-squarebrackets-n-error-2 \
+	mod-squarebrackets-n-ok-2 \
+	mod-squarebrackets-n-error-3 \
+	mod-squarebrackets-n-error-4 \
+	mod-squarebrackets-n-ok-3 \
+	mod-squarebrackets-start-end-error-1 \
+	mod-squarebrackets-start-end-error-2 \
+	mod-squarebrackets-start-end-error-3 \
+	mod-squarebrackets-start-end-ok-1 \
+	mod-squarebrackets-start-end-error-4 \
+	mod-squarebrackets-start-end-ok-2 \
+	mod-squarebrackets-start-end-error-5 \
+	mod-squarebrackets-start-end-error-6 \
+	mod-squarebrackets-start-end-ok-3 \
+	mod-squarebrackets-nested-ok-1 \
+	mod-squarebrackets-nested-error-1 \
+	mod-squarebrackets-nested-ok-2 \
 	mod-squarebrackets-space
 
-mod-squarebrackets-0-star-at:
+mod-squarebrackets-empty:
+# expect: make: in target "mod-squarebrackets-empty": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[]"
 	@echo 'LIST:[]="${LIST:[]}" is an error'
+
+mod-squarebrackets-0-star-at:
 	@echo 'LIST:[0]="${LIST:[0]}"'
 	@echo 'LIST:[0x0]="${LIST:[0x0]}"'
 	@echo 'LIST:[000]="${LIST:[000]}"'
@@ -66,7 +87,7 @@ mod-squarebrackets-hash:
 	@echo 'LIST:[1]:[#]="${LIST:[1]:[#]}"'
 	@echo 'LIST:[1..3]:[#]="${LIST:[1..3]:[#]}"'
 
-mod-squarebrackets-n:
+mod-squarebrackets-n-ok-1:
 	@echo 'EMPTY:[1]="${EMPTY:[1]}"'
 	@echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"'
 	@echo 'ESCAPEDSPACE:[1]="${ESCAPEDSPACE:[1]}"'
@@ -74,14 +95,24 @@ mod-squarebrackets-n:
 	@echo 'REALLYSPACE:[1]="${REALLYSPACE:[1]}" == "" ?'
 	@echo 'REALLYSPACE:[*]:[1]="${REALLYSPACE:[*]:[1]}" == " " ?'
 	@echo 'LIST:[1]="${LIST:[1]}"'
+mod-squarebrackets-n-error-1:
+# expect: make: in target "mod-squarebrackets-n-error-1": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.]"
 	@echo 'LIST:[1.]="${LIST:[1.]}" is an error'
+mod-squarebrackets-n-error-2:
+# expect: make: in target "mod-squarebrackets-n-error-2": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1]."
 	@echo 'LIST:[1].="${LIST:[1].}" is an error'
+mod-squarebrackets-n-ok-2:
 	@echo 'LIST:[2]="${LIST:[2]}"'
 	@echo 'LIST:[6]="${LIST:[6]}"'
 	@echo 'LIST:[7]="${LIST:[7]}"'
 	@echo 'LIST:[999]="${LIST:[999]}"'
+mod-squarebrackets-n-error-3:
+# expect: make: in target "mod-squarebrackets-n-error-3": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[-]"
 	@echo 'LIST:[-]="${LIST:[-]}" is an error'
+mod-squarebrackets-n-error-4:
+# expect: make: in target "mod-squarebrackets-n-error-4": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[--]"
 	@echo 'LIST:[--]="${LIST:[--]}" is an error'
+mod-squarebrackets-n-ok-3:
 	@echo 'LIST:[-1]="${LIST:[-1]}"'
 	@echo 'LIST:[-2]="${LIST:[-2]}"'
 	@echo 'LIST:[-6]="${LIST:[-6]}"'
@@ -101,25 +132,39 @@ mod-squarebrackets-n:
 	@echo 'LIST:[*]:C/ /,/:[@]:[2]="${LIST:[*]:C/ /,/:[@]:[2]}"'
 	@echo 'LONGLIST:[012..0x12]="${LONGLIST:[012..0x12]}"'
 
-mod-squarebrackets-start-end:
+mod-squarebrackets-start-end-error-1:
+# expect: make: in target "mod-squarebrackets-start-end-error-1": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.]"
 	@echo 'LIST:[1.]="${LIST:[1.]}" is an error'
+mod-squarebrackets-start-end-error-2:
+# expect: make: in target "mod-squarebrackets-start-end-error-2": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1..]"
 	@echo 'LIST:[1..]="${LIST:[1..]}" is an error'
+mod-squarebrackets-start-end-error-3:
+# expect: make: in target "mod-squarebrackets-start-end-error-3": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.. ]"
 	@echo 'LIST:[1.. ]="${LIST:[1.. ]}" is an error'
+mod-squarebrackets-start-end-ok-1:
 	@echo 'LIST:[1..1]="${LIST:[1..1]}"'
+mod-squarebrackets-start-end-error-4:
+# expect: make: in target "mod-squarebrackets-start-end-error-4": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1..1.]"
 	@echo 'LIST:[1..1.]="${LIST:[1..1.]}" is an error'
+mod-squarebrackets-start-end-ok-2:
 	@echo 'LIST:[1..2]="${LIST:[1..2]}"'
 	@echo 'LIST:[2..1]="${LIST:[2..1]}"'
 	@echo 'LIST:[3..-2]="${LIST:[3..-2]}"'
 	@echo 'LIST:[-4..4]="${LIST:[-4..4]}"'
+mod-squarebrackets-start-end-error-5:
+# expect: make: in target "mod-squarebrackets-start-end-error-5": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[0..1]"
 	@echo 'LIST:[0..1]="${LIST:[0..1]}" is an error'
+mod-squarebrackets-start-end-error-6:
+# expect: make: in target "mod-squarebrackets-start-end-error-6": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[-1..0]"
 	@echo 'LIST:[-1..0]="${LIST:[-1..0]}" is an error'
+mod-squarebrackets-start-end-ok-3:
 	@echo 'LIST:[-1..1]="${LIST:[-1..1]}"'
 	@echo 'LIST:[0..0]="${LIST:[0..0]}"'
 	@echo 'LIST:[3..99]="${LIST:[3..99]}"'
 	@echo 'LIST:[-3..-99]="${LIST:[-3..-99]}"'
 	@echo 'LIST:[-99..-3]="${LIST:[-99..-3]}"'
 
-mod-squarebrackets-nested:
+mod-squarebrackets-nested-ok-1:
 	@echo 'HASH="${HASH}" == "#" ?'
 	@echo 'LIST:[$${HASH}]="${LIST:[${HASH}]}"'
 	@echo 'LIST:[$${ZERO}]="${LIST:[${ZERO}]}"'
@@ -128,7 +173,10 @@ mod-squarebrackets-nested:
 	@echo 'LIST:[$${MINUSONE}]="${LIST:[${MINUSONE}]}"'
 	@echo 'LIST:[$${STAR}]="${LIST:[${STAR}]}"'
 	@echo 'LIST:[$${AT}]="${LIST:[${AT}]}"'
+mod-squarebrackets-nested-error-1:
+# expect: make: in target "mod-squarebrackets-nested-error-1": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[${EMPTY"
 	@echo 'LIST:[$${EMPTY}]="${LIST:[${EMPTY}]}" is an error'
+mod-squarebrackets-nested-ok-2:
 	@echo 'LIST:[$${LONGLIST:[21]:S/2//}]="${LIST:[${LONGLIST:[21]:S/2//}]}"'
 	@echo 'LIST:[$${LIST:[#]}]="${LIST:[${LIST:[#]}]}"'
 	@echo 'LIST:[$${LIST:[$${HASH}]}]="${LIST:[${LIST:[${HASH}]}]}"'

Index: src/usr.bin/make/unit-tests/cmd-errors.exp
diff -u src/usr.bin/make/unit-tests/cmd-errors.exp:1.12 src/usr.bin/make/unit-tests/cmd-errors.exp:1.13
--- src/usr.bin/make/unit-tests/cmd-errors.exp:1.12	Tue Jul  9 19:43:01 2024
+++ src/usr.bin/make/unit-tests/cmd-errors.exp	Sat Jul 20 11:05:11 2024
@@ -1,9 +1,6 @@
 : undefined--eol
 make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
-: unclosed-expression-
 make: in target "unclosed-modifier": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}'
-: unclosed-modifier-
 make: in target "unknown-modifier": while evaluating variable "UNKNOWN" with value "": Unknown modifier "Z"
-: unknown-modifier--eol
 : end-eol
 exit status 2

Index: src/usr.bin/make/unit-tests/cmd-errors.mk
diff -u src/usr.bin/make/unit-tests/cmd-errors.mk:1.9 src/usr.bin/make/unit-tests/cmd-errors.mk:1.10
--- src/usr.bin/make/unit-tests/cmd-errors.mk:1.9	Tue Jul  9 19:43:01 2024
+++ src/usr.bin/make/unit-tests/cmd-errors.mk	Sat Jul 20 11:05:11 2024
@@ -1,4 +1,4 @@
-# $NetBSD: cmd-errors.mk,v 1.9 2024/07/09 19:43:01 rillig Exp $
+# $NetBSD: cmd-errors.mk,v 1.10 2024/07/20 11:05:11 rillig Exp $
 #
 # Demonstrate how errors in expressions affect whether the commands
 # are actually executed in compat mode.
@@ -13,20 +13,17 @@ undefined:
 
 unclosed-expression:
 # expect: make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unclosed-expression-
+# expect-not: : unclosed-expression-
 	: $@-${UNCLOSED
 
 unclosed-modifier:
 # expect: make: in target "unclosed-modifier": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}'
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unclosed-modifier-
+# expect-not: : unclosed-modifier-
 	: $@-${UNCLOSED:
 
 unknown-modifier:
 # expect: make: in target "unknown-modifier": while evaluating variable "UNKNOWN" with value "": Unknown modifier "Z"
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unknown-modifier--eol
+# expect-not: : unknown-modifier--eol
 	: $@-${UNKNOWN:Z}-eol
 
 end:

Index: src/usr.bin/make/unit-tests/lint.exp
diff -u src/usr.bin/make/unit-tests/lint.exp:1.5 src/usr.bin/make/unit-tests/lint.exp:1.6
--- src/usr.bin/make/unit-tests/lint.exp:1.5	Thu Jul  4 17:47:54 2024
+++ src/usr.bin/make/unit-tests/lint.exp	Sat Jul 20 11:05:11 2024
@@ -1,4 +1,2 @@
 make: in target "mod-loop-varname": while evaluating variable "VAR" with value "value": In the :@ modifier, the variable name "${:Ubar:S,b,v,}" must not contain a dollar
-y@:Q}
-xvaluey
 exit status 2
Index: src/usr.bin/make/unit-tests/varmod-hash.mk
diff -u src/usr.bin/make/unit-tests/varmod-hash.mk:1.5 src/usr.bin/make/unit-tests/varmod-hash.mk:1.6
--- src/usr.bin/make/unit-tests/varmod-hash.mk:1.5	Fri Sep  4 06:54:07 2020
+++ src/usr.bin/make/unit-tests/varmod-hash.mk	Sat Jul 20 11:05:12 2024
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-hash.mk,v 1.5 2020/09/04 06:54:07 rillig Exp $
+# $NetBSD: varmod-hash.mk,v 1.6 2024/07/20 11:05:12 rillig Exp $
 #
 # Tests for the :hash variable modifier, which computes a 32-bit hash from
 # the value of the expression.
@@ -56,9 +56,14 @@ VECTORS+=	de41416c abcdefghijklmnopqrstu
 .  endif
 .endfor
 
-all:
+all: step-{1,2,3,4,5}
+step-1:
 	@echo ${12345:L:has}			# modifier name too short
+step-2:
 	@echo ${12345:L:hash}			# ok
+step-3:
 	@echo ${12345:L:hash=SHA-256}		# :hash does not accept '='
+step-4:
 	@echo ${12345:L:hasX}			# misspelled
+step-5:
 	@echo ${12345:L:hashed}			# modifier name too long

Index: src/usr.bin/make/unit-tests/moderrs.exp
diff -u src/usr.bin/make/unit-tests/moderrs.exp:1.43 src/usr.bin/make/unit-tests/moderrs.exp:1.44
--- src/usr.bin/make/unit-tests/moderrs.exp:1.43	Sat Jul 20 09:22:19 2024
+++ src/usr.bin/make/unit-tests/moderrs.exp	Sat Jul 20 11:05:12 2024
@@ -1,94 +1,54 @@
 make: in target "mod-unknown-direct": while evaluating variable "VAR" with value "TheVariable": Unknown modifier "Z"
-VAR:Z=before--after
 make: in target "mod-unknown-indirect": while evaluating variable "VAR" with value "TheVariable": Unknown modifier "Z"
-VAR:Z=before-inner}-after
 make: in target "unclosed-direct": while evaluating variable "VAR" with value "Thevariable": Unclosed expression, expecting '}' for modifier "S,V,v,"
-VAR:S,V,v,=Thevariable
 make: in target "unclosed-indirect": while evaluating variable "VAR" with value "Thevariable": Unclosed expression after indirect modifier, expecting '}'
-VAR:S,V,v,=Thevariable
 make: in target "unfinished-indirect": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-VAR:S,V,v=
-make: in target "unfinished-loop": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
-
-make: in target "unfinished-loop": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
-
+make: in target "unfinished-loop-1": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
+make: in target "unfinished-loop-2": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
 1 2 3
-make: in target "loop-close": while evaluating variable "UNDEF" with value "1}... 2}... 3}...": Unclosed expression, expecting '}' for modifier "@var@${var}}...@"
+make: in target "loop-close-1": while evaluating variable "UNDEF" with value "1}... 2}... 3}...": Unclosed expression, expecting '}' for modifier "@var@${var}}...@"
 1}... 2}... 3}...
-1}... 2}... 3}...
-make: in target "words": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
-
-make: in target "words": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
-
+make: in target "words-1": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
+make: in target "words-2": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
 13=
-make: in target "words": while evaluating variable "UNDEF" with value "1 2 3": Bad modifier ":[123451234512345123451234512345]"
-12345=S,^ok,:S,^3ok,}
-make: in target "exclam": while evaluating variable "VARNAME" with value "": Unfinished modifier ('!' missing)
-
-make: in target "exclam": while evaluating variable "!" with value "!": Unfinished modifier ('!' missing)
-
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':S'
-1:
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-2:
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-3:
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-4:
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-5:
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "S,from,to,"
-6: TheVariable
+make: in target "words-3": while evaluating variable "UNDEF" with value "1 2 3": Bad modifier ":[123451234512345123451234512345]"
+make: in target "exclam-1": while evaluating variable "VARNAME" with value "": Unfinished modifier ('!' missing)
+make: in target "exclam-2": while evaluating variable "!" with value "!": Unfinished modifier ('!' missing)
+make: in target "mod-subst-delimiter-1": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':S'
+make: in target "mod-subst-delimiter-2": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+make: in target "mod-subst-delimiter-3": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+make: in target "mod-subst-delimiter-4": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+make: in target "mod-subst-delimiter-5": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+make: in target "mod-subst-delimiter-6": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "S,from,to,"
 7: TheVariable
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':C'
-1:
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-2:
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-3:
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-4:
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-5:
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "C,from,to,"
-6: TheVariable
+make: in target "mod-regex-delimiter-1": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':C'
+make: in target "mod-regex-delimiter-2": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+make: in target "mod-regex-delimiter-3": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+make: in target "mod-regex-delimiter-4": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+make: in target "mod-regex-delimiter-5": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+make: in target "mod-regex-delimiter-6": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "C,from,to,"
 7: TheVariable
 112358132134
 15152535558513521534
-make: in target "mod-ts-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
-65oct}
-make: in target "mod-ts-parse": while evaluating "${:U${FIB}:ts\65oct} # bad modifier, variable name is """ with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
-65oct}
-make: in target "mod-ts-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":tsxy"
-xy}
-make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
-
-make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":txy"
-y}
-make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
-
-make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
-M*}
-make: in target "mod-ifelse-parse": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
-
-make: in target "mod-ifelse-parse": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
-
-make: in target "mod-ifelse-parse": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
-
-make: in target "mod-ifelse-parse": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
-
+make: in target "mod-ts-parse-3": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
+make: in target "mod-ts-parse-4": while evaluating "${:U${FIB}:ts\65oct} # bad modifier, variable name is """ with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
+make: in target "mod-ts-parse-5": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":tsxy"
+make: in target "mod-t-parse-1": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
+make: in target "mod-t-parse-2": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":txy"
+make: in target "mod-t-parse-3": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
+make: in target "mod-t-parse-4": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
+make: in target "mod-ifelse-parse-1": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
+make: in target "mod-ifelse-parse-2": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
+make: in target "mod-ifelse-parse-3": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
+make: in target "mod-ifelse-parse-4": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
 then
 1 1 2 3 5 8 13 21 34
 make: in target "mod-remember-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "__"
-
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3"
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3"
-
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3="
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3="
-
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3=x3"
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3=x3"
-
+make: in target "mod-sysv-parse-1": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3"
+make: in target "mod-sysv-parse-1": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3"
+make: in target "mod-sysv-parse-2": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3="
+make: in target "mod-sysv-parse-2": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3="
+make: in target "mod-sysv-parse-3": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3=x3"
+make: in target "mod-sysv-parse-3": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3=x3"
 1 1 2 x3 5 8 1x3 21 34
 exit status 2

Index: src/usr.bin/make/unit-tests/moderrs.mk
diff -u src/usr.bin/make/unit-tests/moderrs.mk:1.39 src/usr.bin/make/unit-tests/moderrs.mk:1.40
--- src/usr.bin/make/unit-tests/moderrs.mk:1.39	Sat Jul 20 09:22:19 2024
+++ src/usr.bin/make/unit-tests/moderrs.mk	Sat Jul 20 11:05:12 2024
@@ -1,4 +1,4 @@
-# $NetBSD: moderrs.mk,v 1.39 2024/07/20 09:22:19 rillig Exp $
+# $NetBSD: moderrs.mk,v 1.40 2024/07/20 11:05:12 rillig Exp $
 #
 # various modifier error tests
 
@@ -12,17 +12,17 @@ FIB=	1 1 2 3 5 8 13 21 34
 
 all:	mod-unknown-direct mod-unknown-indirect
 all:	unclosed-direct unclosed-indirect
-all:	unfinished-indirect unfinished-loop
-all:	loop-close
-all:	words
-all:	exclam
-all:	mod-subst-delimiter
-all:	mod-regex-delimiter
-all:	mod-ts-parse
-all:	mod-t-parse
-all:	mod-ifelse-parse
+all:	unfinished-indirect unfinished-loop-{1,2,3}
+all:	loop-close-{1,2}
+all:	words-{1,2,3}
+all:	exclam-{1,2}
+all:	mod-subst-delimiter-{1,2,3,4,5,6,7}
+all:	mod-regex-delimiter-{1,2,3,4,5,6,7}
+all:	mod-ts-parse-{1,2,3,4,5}
+all:	mod-t-parse-{1,2,3,4}
+all:	mod-ifelse-parse-{1,2,3,4,5}
 all:	mod-remember-parse
-all:	mod-sysv-parse
+all:	mod-sysv-parse-{1,2,3,4}
 
 mod-unknown-direct:
 # expect: make: in target "mod-unknown-direct": while evaluating variable "VAR" with value "TheVariable": Unknown modifier "Z"
@@ -44,11 +44,13 @@ unfinished-indirect:
 # expect: make: in target "unfinished-indirect": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
 	-@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}"
 
-unfinished-loop:
-# expect: make: in target "unfinished-loop": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
+unfinished-loop-1:
+# expect: make: in target "unfinished-loop-1": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
 	@echo ${UNDEF:U1 2 3:@var}
-# expect: make: in target "unfinished-loop": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
+unfinished-loop-2:
+# expect: make: in target "unfinished-loop-2": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
 	@echo ${UNDEF:U1 2 3:@var@...}
+unfinished-loop-3:
 	@echo ${UNDEF:U1 2 3:@var@${var}@}
 
 # The closing brace after the ${var} is part of the replacement string.
@@ -57,17 +59,20 @@ unfinished-loop:
 # braces must be balanced.
 # This is also contrary to the SysV modifier, where only the actually
 # used delimiter (either braces or parentheses) must be balanced.
-loop-close:
-# expect: make: in target "loop-close": while evaluating variable "UNDEF" with value "1}... 2}... 3}...": Unclosed expression, expecting '}' for modifier "@var@${var}}...@"
+loop-close-1:
+# expect: make: in target "loop-close-1": while evaluating variable "UNDEF" with value "1}... 2}... 3}...": Unclosed expression, expecting '}' for modifier "@var@${var}}...@"
 	@echo ${UNDEF:U1 2 3:@var@${var}}...@
+loop-close-2:
 	@echo ${UNDEF:U1 2 3:@var@${var}}...@}
 
-words:
-# expect: make: in target "words": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
+words-1:
+# expect: make: in target "words-1": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
 	@echo ${UNDEF:U1 2 3:[}
-# expect: make: in target "words": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
+words-2:
+# expect: make: in target "words-2": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
 	@echo ${UNDEF:U1 2 3:[#}
 
+words-3:
 	# out of bounds => empty
 	@echo 13=${UNDEF:U1 2 3:[13]}
 
@@ -90,75 +95,99 @@ words:
 	# That variable is undefined, resulting in an empty string.
 	@echo 12345=${UNDEF:U1 2 3:[123451234512345123451234512345]:S,^$,ok,:S,^3$,ok,}
 
-exclam:
-# expect: make: in target "exclam": while evaluating variable "VARNAME" with value "": Unfinished modifier ('!' missing)
+exclam-1:
+# expect: make: in target "exclam-1": while evaluating variable "VARNAME" with value "": Unfinished modifier ('!' missing)
 	@echo ${VARNAME:!echo}
 	# When the final exclamation mark is missing, there is no
 	# fallback to the SysV substitution modifier.
 	# If there were a fallback, the output would be "exclam",
 	# and the above would have produced an "Unknown modifier '!'".
-# expect: make: in target "exclam": while evaluating variable "!" with value "!": Unfinished modifier ('!' missing)
+exclam-2:
+# expect: make: in target "exclam-2": while evaluating variable "!" with value "!": Unfinished modifier ('!' missing)
 	@echo ${!:L:!=exclam}
 
-mod-subst-delimiter:
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':S'
+mod-subst-delimiter-1:
+# expect: make: in target "mod-subst-delimiter-1": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':S'
 	@echo 1: ${VAR:S
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-subst-delimiter-2:
+# expect: make: in target "mod-subst-delimiter-2": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
 	@echo 2: ${VAR:S,
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-subst-delimiter-3:
+# expect: make: in target "mod-subst-delimiter-3": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
 	@echo 3: ${VAR:S,from
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-subst-delimiter-4:
+# expect: make: in target "mod-subst-delimiter-4": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
 	@echo 4: ${VAR:S,from,
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-subst-delimiter-5:
+# expect: make: in target "mod-subst-delimiter-5": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
 	@echo 5: ${VAR:S,from,to
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "S,from,to,"
+mod-subst-delimiter-6:
+# expect: make: in target "mod-subst-delimiter-6": while evaluating variable "VAR" with value "TheVariable": 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:
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':C'
+mod-regex-delimiter-1:
+# expect: make: in target "mod-regex-delimiter-1": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':C'
 	@echo 1: ${VAR:C
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-regex-delimiter-2:
+# expect: make: in target "mod-regex-delimiter-2": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
 	@echo 2: ${VAR:C,
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-regex-delimiter-3:
+# expect: make: in target "mod-regex-delimiter-3": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
 	@echo 3: ${VAR:C,from
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-regex-delimiter-4:
+# expect: make: in target "mod-regex-delimiter-4": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
 	@echo 4: ${VAR:C,from,
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-regex-delimiter-5:
+# expect: make: in target "mod-regex-delimiter-5": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
 	@echo 5: ${VAR:C,from,to
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "C,from,to,"
+mod-regex-delimiter-6:
+# expect: make: in target "mod-regex-delimiter-6": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "C,from,to,"
 	@echo 6: ${VAR:C,from,to,
+mod-regex-delimiter-7:
 	@echo 7: ${VAR:C,from,to,}
 
-mod-ts-parse:
+mod-ts-parse-1:
 	@echo ${FIB:ts}
+mod-ts-parse-2:
 	@echo ${FIB:ts\65}	# octal 065 == U+0035 == '5'
-# expect: make: in target "mod-ts-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
+mod-ts-parse-3:
+# expect: make: in target "mod-ts-parse-3": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
 	@echo ${FIB:ts\65oct}	# bad modifier
-# expect: make: in target "mod-ts-parse": while evaluating "${:U${FIB}:ts\65oct} # bad modifier, variable name is """ with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
+mod-ts-parse-4:
+# expect: make: in target "mod-ts-parse-4": while evaluating "${:U${FIB}:ts\65oct} # bad modifier, variable name is """ with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
 	@echo ${:U${FIB}:ts\65oct} # bad modifier, variable name is ""
-# expect: make: in target "mod-ts-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":tsxy"
+mod-ts-parse-5:
+# expect: make: in target "mod-ts-parse-5": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":tsxy"
 	@echo ${FIB:tsxy}	# modifier too long
 
-mod-t-parse:
-# expect: make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
+mod-t-parse-1:
+# expect: make: in target "mod-t-parse-1": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
 	@echo ${FIB:t
-# expect: make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":txy"
+mod-t-parse-2:
+# expect: make: in target "mod-t-parse-2": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":txy"
 	@echo ${FIB:txy}
-# expect: make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
+mod-t-parse-3:
+# expect: make: in target "mod-t-parse-3": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
 	@echo ${FIB:t}
-# expect: make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
+mod-t-parse-4:
+# expect: make: in target "mod-t-parse-4": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
 	@echo ${FIB:t:M*}
 
-mod-ifelse-parse:
-# expect: make: in target "mod-ifelse-parse": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
+mod-ifelse-parse-1:
+# expect: make: in target "mod-ifelse-parse-1": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
 	@echo ${FIB:?
-# expect: make: in target "mod-ifelse-parse": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
+mod-ifelse-parse-2:
+# expect: make: in target "mod-ifelse-parse-2": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
 	@echo ${FIB:?then
-# expect: make: in target "mod-ifelse-parse": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
+mod-ifelse-parse-3:
+# expect: make: in target "mod-ifelse-parse-3": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
 	@echo ${FIB:?then:
-# expect: make: in target "mod-ifelse-parse": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
+mod-ifelse-parse-4:
+# expect: make: in target "mod-ifelse-parse-4": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
 	@echo ${FIB:?then:else
+mod-ifelse-parse-5:
 	@echo ${FIB:?then:else}
 
 mod-remember-parse:
@@ -166,14 +195,17 @@ mod-remember-parse:
 # expect: make: in target "mod-remember-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "__"
 	@echo ${FIB:__}		# modifier name too long
 
-mod-sysv-parse:
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3"
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3"
+mod-sysv-parse-1:
+# expect: make: in target "mod-sysv-parse-1": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3"
+# expect: make: in target "mod-sysv-parse-1": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3"
 	@echo ${FIB:3
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3="
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3="
+mod-sysv-parse-2:
+# expect: make: in target "mod-sysv-parse-2": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3="
+# expect: make: in target "mod-sysv-parse-2": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3="
 	@echo ${FIB:3=
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3=x3"
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3=x3"
+mod-sysv-parse-3:
+# expect: make: in target "mod-sysv-parse-3": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3=x3"
+# expect: make: in target "mod-sysv-parse-3": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3=x3"
 	@echo ${FIB:3=x3
+mod-sysv-parse-4:
 	@echo ${FIB:3=x3}	# ok

Index: src/usr.bin/make/unit-tests/varmisc.exp
diff -u src/usr.bin/make/unit-tests/varmisc.exp:1.23 src/usr.bin/make/unit-tests/varmisc.exp:1.24
--- src/usr.bin/make/unit-tests/varmisc.exp:1.23	Tue Jul  9 19:43:01 2024
+++ src/usr.bin/make/unit-tests/varmisc.exp	Sat Jul 20 11:05:12 2024
@@ -43,29 +43,17 @@ export-appended: env mk
 parse-dynamic: parse-dynamic parse-dynamic before
 parse-dynamic: parse-dynamic parse-dynamic after
 parse-dynamic: parse-dynamic parse-dynamic after
-varerror-unclosed:begin
-make: in target "varerror-unclosed": Unclosed variable ""
+varerror-unclosed-1:begin
+make: in target "varerror-unclosed-2": Unclosed variable ""
+make: in target "varerror-unclosed-3": Unclosed variable "UNCLOSED"
+make: in target "varerror-unclosed-4": Unclosed variable "UNCLOSED"
+make: in target "varerror-unclosed-5": while evaluating variable "UNCLOSED" with value "": Unclosed variable "PATTERN"
+make: in target "varerror-unclosed-5": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}' for modifier "M${PATTERN"
+make: in target "varerror-unclosed-6": Unclosed variable "param"
+make: in target "varerror-unclosed-6": Unclosed variable "UNCLOSED."
 
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED"
-
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED"
-
-make: in target "varerror-unclosed": while evaluating variable "UNCLOSED" with value "": Unclosed variable "PATTERN"
-make: in target "varerror-unclosed": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}' for modifier "M${PATTERN"
-
-make: in target "varerror-unclosed": Unclosed variable "param"
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED."
-
-
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.1"
-
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.2"
-
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.3"
-
-make: in target "varerror-unclosed": while evaluating variable "UNCLOSED_INDIR_2" with value "${UNCLOSED_INDIR_1}": while evaluating variable "UNCLOSED_INDIR_1" with value "${UNCLOSED_ORIG": Unclosed variable "UNCLOSED_ORIG"
-
-varerror-unclosed:end
+make: in target "varerror-unclosed-7": Unclosed variable "UNCLOSED.1"
+make: in target "varerror-unclosed-8": while evaluating variable "UNCLOSED_INDIR_2" with value "${UNCLOSED_INDIR_1}": while evaluating variable "UNCLOSED_INDIR_1" with value "${UNCLOSED_ORIG": Unclosed variable "UNCLOSED_ORIG"
 target1-flags: we have: one two
 target2-flags: we have: one two three four
 exit status 2
Index: src/usr.bin/make/unit-tests/varmod-assign.mk
diff -u src/usr.bin/make/unit-tests/varmod-assign.mk:1.23 src/usr.bin/make/unit-tests/varmod-assign.mk:1.24
--- src/usr.bin/make/unit-tests/varmod-assign.mk:1.23	Thu Jul  4 17:47:54 2024
+++ src/usr.bin/make/unit-tests/varmod-assign.mk	Sat Jul 20 11:05:12 2024
@@ -1,12 +1,12 @@
-# $NetBSD: varmod-assign.mk,v 1.23 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: varmod-assign.mk,v 1.24 2024/07/20 11:05:12 rillig Exp $
 #
 # Tests for the obscure ::= variable modifiers, which perform variable
 # assignments during evaluation, just like the = operator in C.
 
 .if !make(target)
 
-all:	mod-assign-empty
-all:	mod-assign-parse
+all:	mod-assign-empty-{1,2,3}
+all:	mod-assign-parse-{1,2,3}
 all:	mod-assign-shell-error
 
 # In the following loop expression,
@@ -71,33 +71,38 @@ SINK4:=	${0:?${THEN4::=then4${IT4::=t4}}
 .  error
 .endif
 
-mod-assign-empty:
+mod-assign-empty-1:
 	# Assigning to the empty variable would obviously not work since that
-	# variable is write-protected.  Therefore it is rejected early with a
-	# "Bad modifier" message.
+	# variable is write-protected.
+# expect: make: in target "mod-assign-empty-1": while evaluating "${::=value}" with value "": Bad modifier ":"
 	@echo $@: ${::=value}
 
+mod-assign-empty-2:
 	# In this variant, it is not as obvious that the name of the
-	# expression is empty.  Assigning to it is rejected as well, with the
-	# same "Bad modifier" message.
+	# expression is empty.
+# expect: make: in target "mod-assign-empty-2": while evaluating "${:Uvalue::=overwritten}" with value "value": Bad modifier ":"
 	@echo $@: ${:Uvalue::=overwritten}
 
+mod-assign-empty-3:
 	# The :L modifier sets the value of the expression to its variable
 	# name.  The name of the expression is "VAR", therefore assigning to
 	# that variable works.
+# expect: mod-assign-empty-3: VAR=overwritten
 	@echo $@: ${VAR:L::=overwritten} VAR=${VAR}
 
-mod-assign-parse:
+mod-assign-parse-1:
 	# The modifier for assignment operators starts with a ':'.
 	# An 'x' after that is an invalid modifier.
-	# expect: make: in target "mod-assign-parse": while evaluating variable "ASSIGN" with value "": Unknown modifier ":x"
+# expect: make: in target "mod-assign-parse-1": while evaluating variable "ASSIGN" with value "": Unknown modifier ":x"
 	@echo ${ASSIGN::x}
 
+mod-assign-parse-2:
 	# When parsing an assignment operator fails because the operator is
 	# incomplete, make falls back to the SysV modifier.
 	@echo ${SYSV::=sysv\:x}${SYSV::x=:y}
 
-# expect: make: in target "mod-assign-parse": while evaluating variable "ASSIGN" with value "": Unfinished modifier ('}' missing)
+mod-assign-parse-3:
+# expect: make: in target "mod-assign-parse-3": while evaluating variable "ASSIGN" with value "": Unfinished modifier ('}' missing)
 	@echo ${ASSIGN::=value	# missing closing brace
 
 mod-assign-shell-error:

Index: src/usr.bin/make/unit-tests/varmisc.mk
diff -u src/usr.bin/make/unit-tests/varmisc.mk:1.35 src/usr.bin/make/unit-tests/varmisc.mk:1.36
--- src/usr.bin/make/unit-tests/varmisc.mk:1.35	Fri Jul  5 18:59:33 2024
+++ src/usr.bin/make/unit-tests/varmisc.mk	Sat Jul 20 11:05:12 2024
@@ -1,4 +1,4 @@
-# $NetBSD: varmisc.mk,v 1.35 2024/07/05 18:59:33 rillig Exp $
+# $NetBSD: varmisc.mk,v 1.36 2024/07/20 11:05:12 rillig Exp $
 #
 # Miscellaneous variable tests.
 
@@ -7,7 +7,7 @@ all: unmatched_var_paren D_true U_true D
 all: save-dollars
 all: export-appended
 all: parse-dynamic
-all: varerror-unclosed
+all: varerror-unclosed-{1,2,3,4,5,6,7,8}
 
 unmatched_var_paren:
 	@echo ${foo::=foo-text}
@@ -188,25 +188,30 @@ target1-flags: target1.c
 target2-flags: target2.c
 	@echo $@: we have: ${FLAGS}
 
-varerror-unclosed:
+varerror-unclosed-1:
 	@echo $@:begin
-# expect: make: in target "varerror-unclosed": Unclosed variable ""
+varerror-unclosed-2:
+# expect: make: in target "varerror-unclosed-2": Unclosed variable ""
 	@echo $(
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED"
+varerror-unclosed-3:
+# expect: make: in target "varerror-unclosed-3": Unclosed variable "UNCLOSED"
 	@echo $(UNCLOSED
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED"
+varerror-unclosed-4:
+# expect: make: in target "varerror-unclosed-4": Unclosed variable "UNCLOSED"
 	@echo ${UNCLOSED
-# expect: make: in target "varerror-unclosed": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}' for modifier "M${PATTERN"
+varerror-unclosed-5:
+# expect: make: in target "varerror-unclosed-5": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}' for modifier "M${PATTERN"
 	@echo ${UNCLOSED:M${PATTERN
-# expect: make: in target "varerror-unclosed": Unclosed variable "param"
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED."
+varerror-unclosed-6:
+# expect: make: in target "varerror-unclosed-6": Unclosed variable "param"
+# expect: make: in target "varerror-unclosed-6": Unclosed variable "UNCLOSED."
 	@echo ${UNCLOSED.${param
+varerror-unclosed-7:
 	@echo $
 .for i in 1 2 3
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.1"
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.2"
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.3"
+# expect: make: in target "varerror-unclosed-7": Unclosed variable "UNCLOSED.1"
 	@echo ${UNCLOSED.${i}
 .endfor
+varerror-unclosed-8:
 	@echo ${UNCLOSED_INDIR_2}
 	@echo $@:end

Index: src/usr.bin/make/unit-tests/varmod-assign.exp
diff -u src/usr.bin/make/unit-tests/varmod-assign.exp:1.27 src/usr.bin/make/unit-tests/varmod-assign.exp:1.28
--- src/usr.bin/make/unit-tests/varmod-assign.exp:1.27	Tue Jul  9 19:43:01 2024
+++ src/usr.bin/make/unit-tests/varmod-assign.exp	Sat Jul 20 11:05:12 2024
@@ -37,16 +37,12 @@ Global: .MAKEOVERRIDES =  FIRST LAST LAS
 Result of ${CMD_NEW_VAR::=new-value} is "" (eval, undefined)
 Global: .MAKEFLAGS =  -r -k -d v -d 0 -d v -d
 Global: .MAKEFLAGS =  -r -k -d v -d 0 -d v -d 0
-make: in target "mod-assign-empty": while evaluating "${::=value}" with value "": Bad modifier ":"
-mod-assign-empty: value}
-make: in target "mod-assign-empty": while evaluating "${:Uvalue::=overwritten}" with value "value": Bad modifier ":"
-mod-assign-empty: overwritten}
-mod-assign-empty: VAR=overwritten
-make: in target "mod-assign-parse": while evaluating variable "ASSIGN" with value "": Unknown modifier ":x"
-
+make: in target "mod-assign-empty-1": while evaluating "${::=value}" with value "": Bad modifier ":"
+make: in target "mod-assign-empty-2": while evaluating "${:Uvalue::=overwritten}" with value "value": Bad modifier ":"
+mod-assign-empty-3: VAR=overwritten
+make: in target "mod-assign-parse-1": while evaluating variable "ASSIGN" with value "": Unknown modifier ":x"
 sysv:y
-make: in target "mod-assign-parse": while evaluating variable "ASSIGN" with value "": Unfinished modifier ('}' missing)
-
+make: in target "mod-assign-parse-3": while evaluating variable "ASSIGN" with value "": Unfinished modifier ('}' missing)
 ok=word
 make: warning: in target "mod-assign-shell-error": while evaluating variable "SH_ERR" with value "previous": Command " echo word; (exit 13) " exited with status 13
 err=previous

Index: src/usr.bin/make/unit-tests/varmod-hash.exp
diff -u src/usr.bin/make/unit-tests/varmod-hash.exp:1.6 src/usr.bin/make/unit-tests/varmod-hash.exp:1.7
--- src/usr.bin/make/unit-tests/varmod-hash.exp:1.6	Tue Jul  9 19:43:01 2024
+++ src/usr.bin/make/unit-tests/varmod-hash.exp	Sat Jul 20 11:05:12 2024
@@ -1,9 +1,6 @@
-make: in target "all": while evaluating variable "12345" with value "12345": Unknown modifier "has"
-
+make: in target "step-1": while evaluating variable "12345" with value "12345": Unknown modifier "has"
 26bb0f5f
 12345
-make: in target "all": while evaluating variable "12345" with value "12345": Unknown modifier "hasX"
-
-make: in target "all": while evaluating variable "12345" with value "12345": Unknown modifier "hashed"
-
+make: in target "step-4": while evaluating variable "12345" with value "12345": Unknown modifier "hasX"
+make: in target "step-5": while evaluating variable "12345" with value "12345": Unknown modifier "hashed"
 exit status 2

Index: src/usr.bin/make/unit-tests/varmod-subst-regex.exp
diff -u src/usr.bin/make/unit-tests/varmod-subst-regex.exp:1.10 src/usr.bin/make/unit-tests/varmod-subst-regex.exp:1.11
--- src/usr.bin/make/unit-tests/varmod-subst-regex.exp:1.10	Fri Jul  5 19:47:22 2024
+++ src/usr.bin/make/unit-tests/varmod-subst-regex.exp	Sat Jul 20 11:05:12 2024
@@ -1,27 +1,21 @@
 make: in target "mod-regex-compile-error": while evaluating "${:Uword1 word2:C,****,____,g:C,word,____,:Q}." with value "word1 word2": Regex compilation error: (details omitted)
-mod-regex-compile-error: C,word,____,:Q}.
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
-mod-regex-limits:11-missing:1 6
-mod-regex-limits:11-ok:1 22 446
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
-mod-regex-limits:22-missing:1 6
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
-mod-regex-limits:22-missing:1 6
-mod-regex-limits:22-ok:1 33 556
-mod-regex-limits:capture:ihgfedcbaabcdefghijABCDEFGHIJa0a1a2rest
-make: in target "mod-regex-errors": while evaluating variable "UNDEF" with value "value": Regex compilation error: (details omitted)
-mod-regex-errors:
-make: in target "mod-regex-errors": while evaluating variable "word" with value "word": while evaluating "${:U:Z}y,W}" with value "": Unknown modifier "Z"
-mod-regex-errors: xy
+make: in target "mod-regex-limits-1": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
+make: in target "mod-regex-limits-1": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
+make: in target "mod-regex-limits-1": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
+make: in target "mod-regex-limits-1": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
+mod-regex-limits-2:11-ok:1 22 446
+make: in target "mod-regex-limits-3": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
+make: in target "mod-regex-limits-3": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
+make: in target "mod-regex-limits-3": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
+make: in target "mod-regex-limits-3": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
+make: in target "mod-regex-limits-4": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
+make: in target "mod-regex-limits-4": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
+make: in target "mod-regex-limits-4": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
+make: in target "mod-regex-limits-4": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
+mod-regex-limits-5:22-ok:1 33 556
+mod-regex-limits-6:capture:ihgfedcbaabcdefghijABCDEFGHIJa0a1a2rest
+make: in target "mod-regex-errors-1": while evaluating variable "UNDEF" with value "value": Regex compilation error: (details omitted)
+make: in target "mod-regex-errors-2": while evaluating variable "word" with value "word": while evaluating "${:U:Z}y,W}" with value "": Unknown modifier "Z"
 unmatched-subexpression.ok: one one 2 3 5 8 one3 2one 34
 make: No match for subexpression \2
 unmatched-subexpression.1: ()()

Index: src/usr.bin/make/unit-tests/varmod-subst-regex.mk
diff -u src/usr.bin/make/unit-tests/varmod-subst-regex.mk:1.11 src/usr.bin/make/unit-tests/varmod-subst-regex.mk:1.12
--- src/usr.bin/make/unit-tests/varmod-subst-regex.mk:1.11	Mon Dec 18 11:13:51 2023
+++ src/usr.bin/make/unit-tests/varmod-subst-regex.mk	Sat Jul 20 11:05:12 2024
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-subst-regex.mk,v 1.11 2023/12/18 11:13:51 rillig Exp $
+# $NetBSD: varmod-subst-regex.mk,v 1.12 2024/07/20 11:05:12 rillig Exp $
 #
 # Tests for the :C,from,to, variable modifier.
 
@@ -6,8 +6,8 @@
 .MAKEFLAGS: -dL
 
 all: mod-regex-compile-error
-all: mod-regex-limits
-all: mod-regex-errors
+all: mod-regex-limits-{1,2,3,4,5,6}
+all: mod-regex-errors-{1,2}
 all: unmatched-subexpression
 
 # The expression expands to 4 words.  Of these words, none matches
@@ -139,19 +139,25 @@ mod-regex-compile-error:
 
 # These tests generate error messages but as of 2020-08-28 just continue
 # parsing and execution as if nothing bad had happened.
-mod-regex-limits:
+mod-regex-limits-1:
 	@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}
+mod-regex-limits-2:
 	@echo $@:11-ok:${:U1 23 456:C,(.).,\1\1,:Q}
+mod-regex-limits-3:
 	@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}
+mod-regex-limits-4:
 	@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}
+mod-regex-limits-5:
 	@echo $@:22-ok:${:U1 23 456:C,(.)(.),\2\2,:Q}
+mod-regex-limits-6:
 	# The :C modifier only handles single-digit capturing groups,
 	# which is enough for all practical use cases.
 	@echo $@:capture:${:UabcdefghijABCDEFGHIJrest:C,(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.),\9\8\7\6\5\4\3\2\1\0\10\11\12,}
 
-mod-regex-errors:
+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 "".

Index: src/usr.bin/make/unit-tests/varmod-subst.exp
diff -u src/usr.bin/make/unit-tests/varmod-subst.exp:1.7 src/usr.bin/make/unit-tests/varmod-subst.exp:1.8
--- src/usr.bin/make/unit-tests/varmod-subst.exp:1.7	Tue Jul  9 19:43:01 2024
+++ src/usr.bin/make/unit-tests/varmod-subst.exp	Sat Jul 20 11:05:12 2024
@@ -46,7 +46,6 @@ mod-subst-delimiter:
 mod-subst-chain:
 A B c.
 make: in target "mod-subst-chain": while evaluating "${:Uvalue:S,a,x,i}." with value "vxlue": Unknown modifier "i"
-.
 mod-subst-dollar:$1:
 mod-subst-dollar:$2:
 mod-subst-dollar:$3:

Index: src/usr.bin/make/unit-tests/varmod-subst.mk
diff -u src/usr.bin/make/unit-tests/varmod-subst.mk:1.14 src/usr.bin/make/unit-tests/varmod-subst.mk:1.15
--- src/usr.bin/make/unit-tests/varmod-subst.mk:1.14	Mon Dec 18 11:13:51 2023
+++ src/usr.bin/make/unit-tests/varmod-subst.mk	Sat Jul 20 11:05:12 2024
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-subst.mk,v 1.14 2023/12/18 11:13:51 rillig Exp $
+# $NetBSD: varmod-subst.mk,v 1.15 2024/07/20 11:05:12 rillig Exp $
 #
 # Tests for the :S,from,to, variable modifier.
 
@@ -252,6 +252,7 @@ mod-subst-chain:
 	# The error message is "make: Unknown modifier 'i'", which is
 	# kind of correct, although it is mixing the terms for variable
 	# modifiers with the matching modifiers.
+# expect: make: in target "mod-subst-chain": while evaluating "${:Uvalue:S,a,x,i}." with value "vxlue": Unknown modifier "i"
 	@echo ${:Uvalue:S,a,x,i}.
 
 # No matter how many dollar signs there are, they all get merged

Reply via email to