Module Name:    src
Committed By:   rillig
Date:           Sun Aug 16 12:30:45 UTC 2020

Modified Files:
        src/usr.bin/make/unit-tests: Makefile modmisc.exp modmisc.mk
            varmod-loop.exp varmod-loop.mk varmod-subst-regex.exp
            varmod-subst-regex.mk varmod-subst.exp varmod-subst.mk

Log Message:
make(1): move tests for :S, :C, :@ from modmisc to their separate tests


To generate a diff of this commit:
cvs rdiff -u -r1.93 -r1.94 src/usr.bin/make/unit-tests/Makefile
cvs rdiff -u -r1.41 -r1.42 src/usr.bin/make/unit-tests/modmisc.exp \
    src/usr.bin/make/unit-tests/modmisc.mk
cvs rdiff -u -r1.1 -r1.2 src/usr.bin/make/unit-tests/varmod-loop.exp \
    src/usr.bin/make/unit-tests/varmod-loop.mk \
    src/usr.bin/make/unit-tests/varmod-subst-regex.exp \
    src/usr.bin/make/unit-tests/varmod-subst-regex.mk \
    src/usr.bin/make/unit-tests/varmod-subst.exp \
    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/unit-tests/Makefile
diff -u src/usr.bin/make/unit-tests/Makefile:1.93 src/usr.bin/make/unit-tests/Makefile:1.94
--- src/usr.bin/make/unit-tests/Makefile:1.93	Sun Aug 16 12:07:51 2020
+++ src/usr.bin/make/unit-tests/Makefile	Sun Aug 16 12:30:45 2020
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.93 2020/08/16 12:07:51 rillig Exp $
+# $NetBSD: Makefile,v 1.94 2020/08/16 12:30:45 rillig Exp $
 #
 # Unit tests for make(1)
 #
@@ -320,8 +320,8 @@ FLAGS.recursive=	-dL -r
 FLAGS.vardebug=		-k -dv FROM_CMDLINE=
 
 # Some tests need extra post-processing.
-SED_CMDS.moderrs+=	-e 's,\(Regex compilation error:\).*,\1 (details omitted),'
-SED_CMDS.modmisc+=	-e 's,\(Regex compilation error:\).*,\1 (details omitted),'
+SED_CMDS.varmod-subst-regex+= \
+			-e 's,\(Regex compilation error:\).*,\1 (details omitted),'
 SED_CMDS.varmod-edge+=	-e 's, line [0-9]*:, line omitted:,'
 SED_CMDS.varshell+=	-e 's,^[a-z]*sh: ,,'
 SED_CMDS.varshell+=	-e '/command/s,No such.*,not found,'
@@ -440,7 +440,7 @@ sync-mi:
 	cvs diff "$$mi" || true
 
 .if exists(${TEST_MAKE})
-${TESTS:=.rawout}: ${TEST_MAKE}
+${TESTS:=.rawout}: ${TEST_MAKE} ${.PARSEDIR}/Makefile
 .endif
 
 .-include <bsd.obj.mk>

Index: src/usr.bin/make/unit-tests/modmisc.exp
diff -u src/usr.bin/make/unit-tests/modmisc.exp:1.41 src/usr.bin/make/unit-tests/modmisc.exp:1.42
--- src/usr.bin/make/unit-tests/modmisc.exp:1.41	Sun Aug  9 08:03:31 2020
+++ src/usr.bin/make/unit-tests/modmisc.exp	Sun Aug 16 12:30:45 2020
@@ -18,100 +18,6 @@ C:
 S:empty
 C:empty
 @:
-mod-subst:
-:a b b c:
-:a b b c:
-: b c:
-:a c:
-:x__ 3 x__ 3:
-12345
-mod-subst-delimiter:
-1 two 3 horizontal tabulator
-1 two 3 space
-1 two 3 exclamation mark
-1 two 3 double quotes
-1 two 3 hash
-1 two 3 dollar
-1 two 3 percent
-1 two 3 apostrophe
-1 two 3 opening parenthesis
-1 two 3 closing parenthesis
-1 two 3 digit
-1 two 3 colon
-1 two 3 less than sign
-1 two 3 equal sign
-1 two 3 greater than sign
-1 two 3 question mark
-1 two 3 at
-1 two 3 letter
-1 two 3 opening bracket
-1 two 3 backslash
-1 two 3 closing bracket
-1 two 3 caret
-1 two 3 opening brace
-1 two 3 vertical line
-1 two 3 closing brace
-1 two 3 tilde
-mod-subst-chain:
-A B c.
-make: Unknown modifier 'i'
-.
-mod-regex:
-:a b b c:
-:a b b c:
-: b c:
-make: Regex compilation error: (details omitted)
-:C,word,____,:Q}:
-:a c:
-:x__ 3 x__ 3:
-:+one+ +two+ +three+:
-:x1y x2y x3y:
-:x1y x2y x3y:
-:mod-loop-varname: :x1y x2y x3y: ::
-:x1y x2y x3y:
-mod-loop-resolve:w1d2d3w w2i3w w1i2d3 2i${RES3}w w1d2d3 2i${RES3} 1i${RES2}w:
-mod-loop-varname-dollar:(1) (2) (3).
-mod-loop-varname-dollar:() () ().
-mod-loop-varname-dollar:() () ().
-mod-subst-dollar:$1:
-mod-subst-dollar:$2:
-mod-subst-dollar:$3:
-mod-subst-dollar:$4:
-mod-subst-dollar:$5:
-mod-subst-dollar:$6:
-mod-subst-dollar:$7:
-mod-subst-dollar:$8:
-mod-subst-dollar:$40:
-mod-subst-dollar:U8:
-mod-subst-dollar:$$$$:
-mod-subst-dollar:$$$good3
-mod-loop-dollar:1:
-mod-loop-dollar:${word}$:
-mod-loop-dollar:$3$:
-mod-loop-dollar:$${word}$$:
-mod-loop-dollar:$$5$$:
-mod-loop-dollar:$$${word}$$$:
-mod-regex-limits:00-ok:1 2323 45456
-make: No subexpression \1
-make: No subexpression \1
-make: No subexpression \1
-make: No subexpression \1
-mod-regex-limits:11-missing:1 6
-mod-regex-limits:11-ok:1 22 446
-make: No subexpression \2
-make: No subexpression \2
-make: No subexpression \2
-make: No subexpression \2
-mod-regex-limits:22-missing:1 6
-make: No subexpression \2
-make: No subexpression \2
-make: No subexpression \2
-make: No subexpression \2
-mod-regex-limits:22-missing:1 6
-mod-regex-limits:22-ok:1 33 556
-mod-regex-limits:capture:ihgfedcbaabcdefghijABCDEFGHIJa0a1a2rest
-make: Regex compilation error: (details omitted)
-mod-regex-errors:
 mod-assign: first=1.
 mod-assign: last=3.
 mod-assign: appended=1 2 3.
Index: src/usr.bin/make/unit-tests/modmisc.mk
diff -u src/usr.bin/make/unit-tests/modmisc.mk:1.41 src/usr.bin/make/unit-tests/modmisc.mk:1.42
--- src/usr.bin/make/unit-tests/modmisc.mk:1.41	Sun Aug  9 09:32:04 2020
+++ src/usr.bin/make/unit-tests/modmisc.mk	Sun Aug 16 12:30:45 2020
@@ -1,4 +1,4 @@
-# $Id: modmisc.mk,v 1.41 2020/08/09 09:32:04 rillig Exp $
+# $Id: modmisc.mk,v 1.42 2020/08/16 12:30:45 rillig Exp $
 #
 # miscellaneous modifier tests
 
@@ -16,14 +16,6 @@ MOD_OPT=@d@$${exists($$d):?$$d:$${d:S,/u
 MOD_SEP=S,:, ,g
 
 all:	modvar modvarloop modsysv mod-HTE emptyvar undefvar
-all:	mod-subst
-all:	mod-subst-delimiter
-all:	mod-subst-chain
-all:	mod-regex
-all:	mod-loop-varname mod-loop-resolve mod-loop-varname-dollar
-all:	mod-subst-dollar mod-loop-dollar
-all:	mod-regex-limits
-all:	mod-regex-errors
 all:	mod-assign
 all:	mod-assign-nested
 all:	mod-tu-space
@@ -80,225 +72,6 @@ undefvar:
 	@echo C:${:U:C,^$,empty,}
 	@echo @:${:U:@var@empty@}
 
-WORDS=		sequences of letters
-.if ${WORDS:S,,,} != ${WORDS}
-.warning The empty pattern matches something.
-.endif
-.if ${WORDS:S,e,*,1} != "s*quences of letters"
-.warning The :S modifier flag '1' is not applied exactly once.
-.endif
-.if ${WORDS:S,e,*,} != "s*quences of l*tters"
-.warning The :S modifier does not replace every first match per word.
-.endif
-.if ${WORDS:S,e,*,g} != "s*qu*nc*s of l*tt*rs"
-.warning The :S modifier flag 'g' does not replace every occurrence.
-.endif
-.if ${WORDS:S,^sequ,occurr,} != "occurrences of letters"
-.warning The :S modifier fails for a short match anchored at the start.
-.endif
-.if ${WORDS:S,^of,with,} != "sequences with letters"
-.warning The :S modifier fails for an exact match anchored at the start.
-.endif
-.if ${WORDS:S,^office,does not match,} != ${WORDS}
-.warning The :S modifier matches a too long pattern anchored at the start.
-.endif
-.if ${WORDS:S,f$,r,} != "sequences or letters"
-.warning The :S modifier fails for a short match anchored at the end.
-.endif
-.if ${WORDS:S,s$,,} != "sequence of letter"
-.warning The :S modifier fails to replace one occurrence per word.
-.endif
-.if ${WORDS:S,of$,,} != "sequences letters"
-.warning The :S modifier fails for an exact match anchored at the end.
-.endif
-.if ${WORDS:S,eof$,,} != ${WORDS}
-.warning The :S modifier matches a too long pattern anchored at the end.
-.endif
-.if ${WORDS:S,^of$,,} != "sequences letters"
-.warning The :S modifier does not match a word anchored at both ends.
-.endif
-.if ${WORDS:S,^o$,,} != ${WORDS}
-.warning The :S modifier matches a prefix anchored at both ends.
-.endif
-.if ${WORDS:S,^f$,,} != ${WORDS}
-.warning The :S modifier matches a suffix anchored at both ends.
-.endif
-.if ${WORDS:S,^eof$,,} != ${WORDS}
-.warning The :S modifier matches a too long prefix anchored at both ends.
-.endif
-.if ${WORDS:S,^office$,,} != ${WORDS}
-.warning The :S modifier matches a too long suffix anchored at both ends.
-.endif
-
-mod-subst:
-	@echo $@:
-	@echo :${:Ua b b c:S,a b,,:Q}:
-	@echo :${:Ua b b c:S,a b,,1:Q}:
-	@echo :${:Ua b b c:S,a b,,W:Q}:
-	@echo :${:Ua b b c:S,b,,g:Q}:
-	@echo :${:U1 2 3 1 2 3:S,1 2,___,Wg:S,_,x,:Q}:
-	@echo ${:U12345:S,,sep,g:Q}
-
-# The :S and :C modifiers accept an arbitrary character as the delimiter,
-# including characters that are otherwise used as escape characters or
-# interpreted in a special way.  This can be used to confuse humans.
-mod-subst-delimiter:
-	@echo $@:
-	@echo ${:U1 2 3:S	2	two	:Q} horizontal tabulator
-	@echo ${:U1 2 3:S 2 two :Q} space
-	@echo ${:U1 2 3:S!2!two!:Q} exclamation mark
-	@echo ${:U1 2 3:S"2"two":Q} double quotes
-	# In shell command lines, the hash does not need to be escaped.
-	# It needs to be escaped in variable assignment lines though.
-	@echo ${:U1 2 3:S#2#two#:Q} hash
-	@echo ${:U1 2 3:S$2$two$:Q} dollar
-	@echo ${:U1 2 3:S%2%two%:Q} percent
-	@echo ${:U1 2 3:S'2'two':Q} apostrophe
-	@echo ${:U1 2 3:S(2(two(:Q} opening parenthesis
-	@echo ${:U1 2 3:S)2)two):Q} closing parenthesis
-	@echo ${:U1 2 3:S121two1:Q} digit
-	@echo ${:U1 2 3:S:2:two::Q} colon
-	@echo ${:U1 2 3:S<2<two<:Q} less than sign
-	@echo ${:U1 2 3:S=2=two=:Q} equal sign
-	@echo ${:U1 2 3:S>2>two>:Q} greater than sign
-	@echo ${:U1 2 3:S?2?two?:Q} question mark
-	@echo ${:U1 2 3:S@2@two@:Q} at
-	@echo ${:U1 2 3:Sa2atwoa:Q} letter
-	@echo ${:U1 2 3:S[2[two[:Q} opening bracket
-	@echo ${:U1 2 3:S\2\two\:Q} backslash
-	@echo ${:U1 2 3:S]2]two]:Q} closing bracket
-	@echo ${:U1 2 3:S^2^two^:Q} caret
-	@echo ${:U1 2 3:S{2{two{:Q} opening brace
-	@echo ${:U1 2 3:S|2|two|:Q} vertical line
-	@echo ${:U1 2 3:S}2}two}:Q} closing brace
-	@echo ${:U1 2 3:S~2~two~:Q} tilde
-
-# 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).
-#
-# Most other modifiers cannot be chained since their parsers skip until
-# the next ':' or '}' or ')'.
-mod-subst-chain:
-	@echo $@:
-	@echo ${:Ua b c:S,a,A,S,b,B,}.
-	# There is no 'i' modifier for the :S or :C modifiers.
-	# 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.
-	@echo ${:Uvalue:S,a,x,i}.
-
-mod-regex:
-	@echo $@:
-	@echo :${:Ua b b c:C,a b,,:Q}:
-	@echo :${:Ua b b c:C,a b,,1:Q}:
-	@echo :${:Ua b b c:C,a b,,W:Q}:
-	@echo :${:Uword1 word2:C,****,____,g:C,word,____,:Q}:
-	@echo :${:Ua b b c:C,b,,g:Q}:
-	@echo :${:U1 2 3 1 2 3:C,1 2,___,Wg:C,_,x,:Q}:
-
-# In the :@ modifier, the name of the loop variable can even be generated
-# dynamically.  There's no practical use-case for this, and hopefully nobody
-# will ever depend on this, but technically it's possible.
-# Therefore, in -dL mode, this is forbidden, see lint.mk.
-mod-loop-varname:
-	@echo :${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@:Q}:
-	# ":::" is a very creative variable name, unlikely in practice
-	# The expression ${\:\:\:} would not work since backslashes can only
-	# be escaped in the modifiers, but not in the variable name.
-	@echo :${:U1 2 3:@:::@x${${:U\:\:\:}}y@}:
-	# "@@" is another creative variable name.
-	@echo :${:U1 2 3:@\@\@@x${@@}y@}:
-	# Even "@" works as a variable name since the variable is installed
-	# in the "current" scope, which in this case is the one from the
-	# target.
-	@echo :$@: :${:U1 2 3:@\@@x${@}y@}: :$@:
-	# In extreme cases, even the backslash can be used as variable name.
-	# It needs to be doubled though.
-	@echo :${:U1 2 3:@\\@x${${:Ux:S,x,\\,}}y@}:
-
-# The :@ modifier resolves the variables a little more often than expected.
-# In particular, it resolves _all_ variables from the context, and not only
-# the loop variable (in this case v).
-#
-# The d means direct reference, the i means indirect reference.
-RESOLVE=	${RES1} $${RES1}
-RES1=		1d${RES2} 1i$${RES2}
-RES2=		2d${RES3} 2i$${RES3}
-RES3=		3
-
-mod-loop-resolve:
-	@echo $@:${RESOLVE:@v@w${v}w@:Q}:
-
-# Until 2020-07-20, the variable name of the :@ modifier could end with one
-# or two dollar signs, which were silently ignored.
-# There's no point in allowing a dollar sign in that position.
-mod-loop-varname-dollar:
-	@echo $@:${1 2 3:L:@v$@($v)@:Q}.
-	@echo $@:${1 2 3:L:@v$$@($v)@:Q}.
-	@echo $@:${1 2 3:L:@v$$$@($v)@:Q}.
-
-# No matter how many dollar characters there are, they all get merged
-# into a single dollar by the :S modifier.
-#
-# As of 2020-08-09, this is because ParseModifierPart sees a '$' and
-# calls Var_Parse to expand the variable.  In all other places, the "$$"
-# is handled outside of Var_Parse.  Var_Parse therefore considers "$$"
-# one of the "really stupid names", skips the first dollar, and parsing
-# continues with the next character.  This repeats for the other dollar
-# signs, except the one before the delimiter.  That one is handled by
-# the code that optionally interprets the '$' as the end-anchor in the
-# first part of the :S modifier.  That code doesn't call Var_Parse but
-# simply copies the dollar to the result.
-mod-subst-dollar:
-	@echo $@:${:U1:S,^,$,:Q}:
-	@echo $@:${:U2:S,^,$$,:Q}:
-	@echo $@:${:U3:S,^,$$$,:Q}:
-	@echo $@:${:U4:S,^,$$$$,:Q}:
-	@echo $@:${:U5:S,^,$$$$$,:Q}:
-	@echo $@:${:U6:S,^,$$$$$$,:Q}:
-	@echo $@:${:U7:S,^,$$$$$$$,:Q}:
-	@echo $@:${:U8:S,^,$$$$$$$$,:Q}:
-	@echo $@:${:U40:S,^,$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$,:Q}:
-# This generates no dollar at all:
-	@echo $@:${:UU8:S,^,${:U$$$$$$$$},:Q}:
-# Here is an alternative way to generate dollar characters.
-# It's unexpectedly complicated though.
-	@echo $@:${:U:range=5:ts\x24:C,[0-9],,g:Q}:
-# In modifiers, dollars are escaped using the backslash, not using another
-# dollar sign.  Therefore, creating a dollar sign is pretty simple:
-	@echo $@:${:Ugood3:S,^,\$\$\$,:Q}
-
-# Demonstrate that it is possible to generate dollar characters using the
-# :@ modifier.
-#
-# These are edge cases that could have resulted in a parse error as well
-# since the $@ at the end could have been interpreted as a variable, which
-# would mean a missing closing @ delimiter.
-mod-loop-dollar:
-	@echo $@:${:U1:@word@${word}$@:Q}:
-	@echo $@:${:U2:@word@$${word}$$@:Q}:
-	@echo $@:${:U3:@word@$$${word}$$$@:Q}:
-	@echo $@:${:U4:@word@$$$${word}$$$$@:Q}:
-	@echo $@:${:U5:@word@$$$$${word}$$$$$@:Q}:
-	@echo $@:${:U6:@word@$$$$$${word}$$$$$$@:Q}:
-
-mod-regex-limits:
-	@echo $@:00-ok:${:U1 23 456:C,..,\0\0,:Q}
-	@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}
-	@echo $@:11-ok:${:U1 23 456:C,(.).,\1\1,:Q}
-	@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}
-	@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}
-	@echo $@:22-ok:${:U1 23 456:C,(.)(.),\2\2,:Q}
-	# The :C modifier only handles single-digit capturing groups,
-	# which is more than enough for daily use.
-	@echo $@:capture:${:UabcdefghijABCDEFGHIJrest:C,(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.),\9\8\7\6\5\4\3\2\1\0\10\11\12,}
-
-mod-regex-errors:
-	@echo $@: ${UNDEF:Uvalue:C,[,,}
-
 # Just a bit of basic code coverage for the obscure ::= assignment modifiers.
 mod-assign:
 	@echo $@: ${1 2 3:L:@i@${FIRST::?=$i}@} first=${FIRST}.

Index: src/usr.bin/make/unit-tests/varmod-loop.exp
diff -u src/usr.bin/make/unit-tests/varmod-loop.exp:1.1 src/usr.bin/make/unit-tests/varmod-loop.exp:1.2
--- src/usr.bin/make/unit-tests/varmod-loop.exp:1.1	Sun Aug 16 12:07:51 2020
+++ src/usr.bin/make/unit-tests/varmod-loop.exp	Sun Aug 16 12:30:45 2020
@@ -1 +1,16 @@
+:+one+ +two+ +three+:
+:x1y x2y x3y:
+:x1y x2y x3y:
+:mod-loop-varname: :x1y x2y x3y: ::
+:x1y x2y x3y:
+mod-loop-resolve:w1d2d3w w2i3w w1i2d3 2i${RES3}w w1d2d3 2i${RES3} 1i${RES2}w:
+mod-loop-varname-dollar:(1) (2) (3).
+mod-loop-varname-dollar:() () ().
+mod-loop-varname-dollar:() () ().
+mod-loop-dollar:1:
+mod-loop-dollar:${word}$:
+mod-loop-dollar:$3$:
+mod-loop-dollar:$${word}$$:
+mod-loop-dollar:$$5$$:
+mod-loop-dollar:$$${word}$$$:
 exit status 0
Index: src/usr.bin/make/unit-tests/varmod-loop.mk
diff -u src/usr.bin/make/unit-tests/varmod-loop.mk:1.1 src/usr.bin/make/unit-tests/varmod-loop.mk:1.2
--- src/usr.bin/make/unit-tests/varmod-loop.mk:1.1	Sun Aug 16 12:07:51 2020
+++ src/usr.bin/make/unit-tests/varmod-loop.mk	Sun Aug 16 12:30:45 2020
@@ -1,8 +1,63 @@
-# $NetBSD: varmod-loop.mk,v 1.1 2020/08/16 12:07:51 rillig Exp $
+# $NetBSD: varmod-loop.mk,v 1.2 2020/08/16 12:30:45 rillig Exp $
 #
-# TODO: Description
+# Tests for the :@var@...${var}...@ variable modifier.
 
-# TODO: Implementation
+all: mod-loop-varname
+all: mod-loop-resolve
+all: mod-loop-varname-dollar
+all: mod-loop-dollar
 
-all:
-	@:;
+# In the :@ modifier, the name of the loop variable can even be generated
+# dynamically.  There's no practical use-case for this, and hopefully nobody
+# will ever depend on this, but technically it's possible.
+# Therefore, in -dL mode, this is forbidden, see lint.mk.
+mod-loop-varname:
+	@echo :${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@:Q}:
+	# ":::" is a very creative variable name, unlikely in practice
+	# The expression ${\:\:\:} would not work since backslashes can only
+	# be escaped in the modifiers, but not in the variable name.
+	@echo :${:U1 2 3:@:::@x${${:U\:\:\:}}y@}:
+	# "@@" is another creative variable name.
+	@echo :${:U1 2 3:@\@\@@x${@@}y@}:
+	# Even "@" works as a variable name since the variable is installed
+	# in the "current" scope, which in this case is the one from the
+	# target.
+	@echo :$@: :${:U1 2 3:@\@@x${@}y@}: :$@:
+	# In extreme cases, even the backslash can be used as variable name.
+	# It needs to be doubled though.
+	@echo :${:U1 2 3:@\\@x${${:Ux:S,x,\\,}}y@}:
+
+# The :@ modifier resolves the variables a little more often than expected.
+# In particular, it resolves _all_ variables from the context, and not only
+# the loop variable (in this case v).
+#
+# The d means direct reference, the i means indirect reference.
+RESOLVE=	${RES1} $${RES1}
+RES1=		1d${RES2} 1i$${RES2}
+RES2=		2d${RES3} 2i$${RES3}
+RES3=		3
+
+mod-loop-resolve:
+	@echo $@:${RESOLVE:@v@w${v}w@:Q}:
+
+# Until 2020-07-20, the variable name of the :@ modifier could end with one
+# or two dollar signs, which were silently ignored.
+# There's no point in allowing a dollar sign in that position.
+mod-loop-varname-dollar:
+	@echo $@:${1 2 3:L:@v$@($v)@:Q}.
+	@echo $@:${1 2 3:L:@v$$@($v)@:Q}.
+	@echo $@:${1 2 3:L:@v$$$@($v)@:Q}.
+
+# Demonstrate that it is possible to generate dollar characters using the
+# :@ modifier.
+#
+# These are edge cases that could have resulted in a parse error as well
+# since the $@ at the end could have been interpreted as a variable, which
+# would mean a missing closing @ delimiter.
+mod-loop-dollar:
+	@echo $@:${:U1:@word@${word}$@:Q}:
+	@echo $@:${:U2:@word@$${word}$$@:Q}:
+	@echo $@:${:U3:@word@$$${word}$$$@:Q}:
+	@echo $@:${:U4:@word@$$$${word}$$$$@:Q}:
+	@echo $@:${:U5:@word@$$$$${word}$$$$$@:Q}:
+	@echo $@:${:U6:@word@$$$$$${word}$$$$$$@:Q}:
Index: src/usr.bin/make/unit-tests/varmod-subst-regex.exp
diff -u src/usr.bin/make/unit-tests/varmod-subst-regex.exp:1.1 src/usr.bin/make/unit-tests/varmod-subst-regex.exp:1.2
--- src/usr.bin/make/unit-tests/varmod-subst-regex.exp:1.1	Sun Aug 16 12:07:51 2020
+++ src/usr.bin/make/unit-tests/varmod-subst-regex.exp	Sun Aug 16 12:30:45 2020
@@ -1 +1,30 @@
+mod-regex:
+:a b b c:
+:a b b c:
+: b c:
+make: Regex compilation error: (details omitted)
+:C,word,____,:Q}:
+:a c:
+:x__ 3 x__ 3:
+mod-regex-limits:00-ok:1 2323 45456
+make: No subexpression \1
+make: No subexpression \1
+make: No subexpression \1
+make: No subexpression \1
+mod-regex-limits:11-missing:1 6
+mod-regex-limits:11-ok:1 22 446
+make: No subexpression \2
+make: No subexpression \2
+make: No subexpression \2
+make: No subexpression \2
+mod-regex-limits:22-missing:1 6
+make: No subexpression \2
+make: No subexpression \2
+make: No subexpression \2
+make: No subexpression \2
+mod-regex-limits:22-missing:1 6
+mod-regex-limits:22-ok:1 33 556
+mod-regex-limits:capture:ihgfedcbaabcdefghijABCDEFGHIJa0a1a2rest
+make: Regex compilation error: (details omitted)
+mod-regex-errors:
 exit status 0
Index: src/usr.bin/make/unit-tests/varmod-subst-regex.mk
diff -u src/usr.bin/make/unit-tests/varmod-subst-regex.mk:1.1 src/usr.bin/make/unit-tests/varmod-subst-regex.mk:1.2
--- src/usr.bin/make/unit-tests/varmod-subst-regex.mk:1.1	Sun Aug 16 12:07:51 2020
+++ src/usr.bin/make/unit-tests/varmod-subst-regex.mk	Sun Aug 16 12:30:45 2020
@@ -1,8 +1,30 @@
-# $NetBSD: varmod-subst-regex.mk,v 1.1 2020/08/16 12:07:51 rillig Exp $
+# $NetBSD: varmod-subst-regex.mk,v 1.2 2020/08/16 12:30:45 rillig Exp $
 #
-# TODO: Description
+# Tests for the :C,from,to, variable modifier.
 
-# TODO: Implementation
+all: mod-regex
+all: mod-regex-limits
+all: mod-regex-errors
 
-all:
-	@:;
+mod-regex:
+	@echo $@:
+	@echo :${:Ua b b c:C,a b,,:Q}:
+	@echo :${:Ua b b c:C,a b,,1:Q}:
+	@echo :${:Ua b b c:C,a b,,W:Q}:
+	@echo :${:Uword1 word2:C,****,____,g:C,word,____,:Q}:
+	@echo :${:Ua b b c:C,b,,g:Q}:
+	@echo :${:U1 2 3 1 2 3:C,1 2,___,Wg:C,_,x,:Q}:
+
+mod-regex-limits:
+	@echo $@:00-ok:${:U1 23 456:C,..,\0\0,:Q}
+	@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}
+	@echo $@:11-ok:${:U1 23 456:C,(.).,\1\1,:Q}
+	@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}
+	@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}
+	@echo $@:22-ok:${:U1 23 456:C,(.)(.),\2\2,:Q}
+	# The :C modifier only handles single-digit capturing groups,
+	# which is more than enough for daily use.
+	@echo $@:capture:${:UabcdefghijABCDEFGHIJrest:C,(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.),\9\8\7\6\5\4\3\2\1\0\10\11\12,}
+
+mod-regex-errors:
+	@echo $@: ${UNDEF:Uvalue:C,[,,}
Index: src/usr.bin/make/unit-tests/varmod-subst.exp
diff -u src/usr.bin/make/unit-tests/varmod-subst.exp:1.1 src/usr.bin/make/unit-tests/varmod-subst.exp:1.2
--- src/usr.bin/make/unit-tests/varmod-subst.exp:1.1	Sun Aug 16 12:07:51 2020
+++ src/usr.bin/make/unit-tests/varmod-subst.exp	Sun Aug 16 12:30:45 2020
@@ -1 +1,51 @@
+mod-subst:
+:a b b c:
+:a b b c:
+: b c:
+:a c:
+:x__ 3 x__ 3:
+12345
+mod-subst-delimiter:
+1 two 3 horizontal tabulator
+1 two 3 space
+1 two 3 exclamation mark
+1 two 3 double quotes
+1 two 3 hash
+1 two 3 dollar
+1 two 3 percent
+1 two 3 apostrophe
+1 two 3 opening parenthesis
+1 two 3 closing parenthesis
+1 two 3 digit
+1 two 3 colon
+1 two 3 less than sign
+1 two 3 equal sign
+1 two 3 greater than sign
+1 two 3 question mark
+1 two 3 at
+1 two 3 letter
+1 two 3 opening bracket
+1 two 3 backslash
+1 two 3 closing bracket
+1 two 3 caret
+1 two 3 opening brace
+1 two 3 vertical line
+1 two 3 closing brace
+1 two 3 tilde
+mod-subst-chain:
+A B c.
+make: Unknown modifier 'i'
+.
+mod-subst-dollar:$1:
+mod-subst-dollar:$2:
+mod-subst-dollar:$3:
+mod-subst-dollar:$4:
+mod-subst-dollar:$5:
+mod-subst-dollar:$6:
+mod-subst-dollar:$7:
+mod-subst-dollar:$8:
+mod-subst-dollar:$40:
+mod-subst-dollar:U8:
+mod-subst-dollar:$$$$:
+mod-subst-dollar:$$$good3
 exit status 0
Index: src/usr.bin/make/unit-tests/varmod-subst.mk
diff -u src/usr.bin/make/unit-tests/varmod-subst.mk:1.1 src/usr.bin/make/unit-tests/varmod-subst.mk:1.2
--- src/usr.bin/make/unit-tests/varmod-subst.mk:1.1	Sun Aug 16 12:07:51 2020
+++ src/usr.bin/make/unit-tests/varmod-subst.mk	Sun Aug 16 12:30:45 2020
@@ -1,8 +1,149 @@
-# $NetBSD: varmod-subst.mk,v 1.1 2020/08/16 12:07:51 rillig Exp $
+# $NetBSD: varmod-subst.mk,v 1.2 2020/08/16 12:30:45 rillig Exp $
 #
-# TODO: Description
+# Tests for the :S,from,to, variable modifier.
 
-# TODO: Implementation
+all: mod-subst
+all: mod-subst-delimiter
+all: mod-subst-chain
+all: mod-subst-dollar
 
-all:
-	@:;
+WORDS=		sequences of letters
+.if ${WORDS:S,,,} != ${WORDS}
+.warning The empty pattern matches something.
+.endif
+.if ${WORDS:S,e,*,1} != "s*quences of letters"
+.warning The :S modifier flag '1' is not applied exactly once.
+.endif
+.if ${WORDS:S,e,*,} != "s*quences of l*tters"
+.warning The :S modifier does not replace every first match per word.
+.endif
+.if ${WORDS:S,e,*,g} != "s*qu*nc*s of l*tt*rs"
+.warning The :S modifier flag 'g' does not replace every occurrence.
+.endif
+.if ${WORDS:S,^sequ,occurr,} != "occurrences of letters"
+.warning The :S modifier fails for a short match anchored at the start.
+.endif
+.if ${WORDS:S,^of,with,} != "sequences with letters"
+.warning The :S modifier fails for an exact match anchored at the start.
+.endif
+.if ${WORDS:S,^office,does not match,} != ${WORDS}
+.warning The :S modifier matches a too long pattern anchored at the start.
+.endif
+.if ${WORDS:S,f$,r,} != "sequences or letters"
+.warning The :S modifier fails for a short match anchored at the end.
+.endif
+.if ${WORDS:S,s$,,} != "sequence of letter"
+.warning The :S modifier fails to replace one occurrence per word.
+.endif
+.if ${WORDS:S,of$,,} != "sequences letters"
+.warning The :S modifier fails for an exact match anchored at the end.
+.endif
+.if ${WORDS:S,eof$,,} != ${WORDS}
+.warning The :S modifier matches a too long pattern anchored at the end.
+.endif
+.if ${WORDS:S,^of$,,} != "sequences letters"
+.warning The :S modifier does not match a word anchored at both ends.
+.endif
+.if ${WORDS:S,^o$,,} != ${WORDS}
+.warning The :S modifier matches a prefix anchored at both ends.
+.endif
+.if ${WORDS:S,^f$,,} != ${WORDS}
+.warning The :S modifier matches a suffix anchored at both ends.
+.endif
+.if ${WORDS:S,^eof$,,} != ${WORDS}
+.warning The :S modifier matches a too long prefix anchored at both ends.
+.endif
+.if ${WORDS:S,^office$,,} != ${WORDS}
+.warning The :S modifier matches a too long suffix anchored at both ends.
+.endif
+
+mod-subst:
+	@echo $@:
+	@echo :${:Ua b b c:S,a b,,:Q}:
+	@echo :${:Ua b b c:S,a b,,1:Q}:
+	@echo :${:Ua b b c:S,a b,,W:Q}:
+	@echo :${:Ua b b c:S,b,,g:Q}:
+	@echo :${:U1 2 3 1 2 3:S,1 2,___,Wg:S,_,x,:Q}:
+	@echo ${:U12345:S,,sep,g:Q}
+
+# The :S and :C modifiers accept an arbitrary character as the delimiter,
+# including characters that are otherwise used as escape characters or
+# interpreted in a special way.  This can be used to confuse humans.
+mod-subst-delimiter:
+	@echo $@:
+	@echo ${:U1 2 3:S	2	two	:Q} horizontal tabulator
+	@echo ${:U1 2 3:S 2 two :Q} space
+	@echo ${:U1 2 3:S!2!two!:Q} exclamation mark
+	@echo ${:U1 2 3:S"2"two":Q} double quotes
+	# In shell command lines, the hash does not need to be escaped.
+	# It needs to be escaped in variable assignment lines though.
+	@echo ${:U1 2 3:S#2#two#:Q} hash
+	@echo ${:U1 2 3:S$2$two$:Q} dollar
+	@echo ${:U1 2 3:S%2%two%:Q} percent
+	@echo ${:U1 2 3:S'2'two':Q} apostrophe
+	@echo ${:U1 2 3:S(2(two(:Q} opening parenthesis
+	@echo ${:U1 2 3:S)2)two):Q} closing parenthesis
+	@echo ${:U1 2 3:S121two1:Q} digit
+	@echo ${:U1 2 3:S:2:two::Q} colon
+	@echo ${:U1 2 3:S<2<two<:Q} less than sign
+	@echo ${:U1 2 3:S=2=two=:Q} equal sign
+	@echo ${:U1 2 3:S>2>two>:Q} greater than sign
+	@echo ${:U1 2 3:S?2?two?:Q} question mark
+	@echo ${:U1 2 3:S@2@two@:Q} at
+	@echo ${:U1 2 3:Sa2atwoa:Q} letter
+	@echo ${:U1 2 3:S[2[two[:Q} opening bracket
+	@echo ${:U1 2 3:S\2\two\:Q} backslash
+	@echo ${:U1 2 3:S]2]two]:Q} closing bracket
+	@echo ${:U1 2 3:S^2^two^:Q} caret
+	@echo ${:U1 2 3:S{2{two{:Q} opening brace
+	@echo ${:U1 2 3:S|2|two|:Q} vertical line
+	@echo ${:U1 2 3:S}2}two}:Q} closing brace
+	@echo ${:U1 2 3:S~2~two~:Q} tilde
+
+# 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).
+#
+# Most other modifiers cannot be chained since their parsers skip until
+# the next ':' or '}' or ')'.
+mod-subst-chain:
+	@echo $@:
+	@echo ${:Ua b c:S,a,A,S,b,B,}.
+	# There is no 'i' modifier for the :S or :C modifiers.
+	# 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.
+	@echo ${:Uvalue:S,a,x,i}.
+
+# No matter how many dollar characters there are, they all get merged
+# into a single dollar by the :S modifier.
+#
+# As of 2020-08-09, this is because ParseModifierPart sees a '$' and
+# calls Var_Parse to expand the variable.  In all other places, the "$$"
+# is handled outside of Var_Parse.  Var_Parse therefore considers "$$"
+# one of the "really stupid names", skips the first dollar, and parsing
+# continues with the next character.  This repeats for the other dollar
+# signs, except the one before the delimiter.  That one is handled by
+# the code that optionally interprets the '$' as the end-anchor in the
+# first part of the :S modifier.  That code doesn't call Var_Parse but
+# simply copies the dollar to the result.
+mod-subst-dollar:
+	@echo $@:${:U1:S,^,$,:Q}:
+	@echo $@:${:U2:S,^,$$,:Q}:
+	@echo $@:${:U3:S,^,$$$,:Q}:
+	@echo $@:${:U4:S,^,$$$$,:Q}:
+	@echo $@:${:U5:S,^,$$$$$,:Q}:
+	@echo $@:${:U6:S,^,$$$$$$,:Q}:
+	@echo $@:${:U7:S,^,$$$$$$$,:Q}:
+	@echo $@:${:U8:S,^,$$$$$$$$,:Q}:
+	@echo $@:${:U40:S,^,$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$,:Q}:
+# This generates no dollar at all:
+	@echo $@:${:UU8:S,^,${:U$$$$$$$$},:Q}:
+# Here is an alternative way to generate dollar characters.
+# It's unexpectedly complicated though.
+	@echo $@:${:U:range=5:ts\x24:C,[0-9],,g:Q}:
+# In modifiers, dollars are escaped using the backslash, not using another
+# dollar sign.  Therefore, creating a dollar sign is pretty simple:
+	@echo $@:${:Ugood3:S,^,\$\$\$,:Q}

Reply via email to