Thu Sep 3 18:52:37 2020 UTC ()
make(1): add tests for the :D and :U modifiers

This prepares a refactoring for ApplyModifier_Defined.


(rillig)
diff -r1.3 -r1.4 src/usr.bin/make/unit-tests/varmod-defined.mk
diff -r1.3 -r1.4 src/usr.bin/make/unit-tests/varmod-undefined.mk

cvs diff -r1.3 -r1.4 src/usr.bin/make/unit-tests/varmod-defined.mk (expand / switch to context diff)
--- src/usr.bin/make/unit-tests/varmod-defined.mk 2020/08/25 21:58:08 1.3
+++ src/usr.bin/make/unit-tests/varmod-defined.mk 2020/09/03 18:52:36 1.4
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-defined.mk,v 1.3 2020/08/25 21:58:08 rillig Exp $
+# $NetBSD: varmod-defined.mk,v 1.4 2020/09/03 18:52:36 rillig Exp $
 #
 # Tests for the :D variable modifier, which returns the given string
 # if the variable is defined.  It is closely related to the :U modifier.
@@ -23,6 +23,45 @@
 .if ${UNDEF:Dvalue} != ""
 .error
 .endif
+
+# The modifier text may contain plain text as well as expressions.
+#
+.if ${DEF:D<${DEF}>} != "<defined>"
+.  error
+.endif
+
+# Special characters that would be interpreted differently can be escaped.
+# These are '}' (the closing character of the expression), ':', '$' and '\'.
+# Any other backslash sequences are preserved.
+#
+# The escaping rules for string literals in conditions are completely
+# different though. There, any character may be escaped using a backslash.
+#
+.if ${DEF:D \} \: \$ \\ \) \n } != " } : \$ \\ \\) \\n "
+.  error
+.endif
+
+# Like in several other places in variable expressions, when
+# ApplyModifier_Defined calls Var_Parse, double dollars lead to a parse
+# error that is silently ignored.  This makes all dollar signs disappear,
+# except for the last, which is a well-formed variable expression.
+#
+.if ${DEF:D$$$$$${DEF}} != "defined"
+.  error
+.endif
+
+# Any other text is written without any further escaping.  In contrast
+# to the :M modifier, parentheses and braces do not need to be nested.
+# Instead, the :D modifier is implemented sanely by parsing nested
+# expressions as such, without trying any shortcuts. See ApplyModifier_Match
+# for an inferior variant.
+#
+.if ${DEF:D!&((((} != "!&(((("
+.  error
+.endif
+
+# TODO: Add more tests for parsing the plain text part, to cover each branch
+# of ApplyModifier_Defined.
 
 all:
 	@:;

cvs diff -r1.3 -r1.4 src/usr.bin/make/unit-tests/varmod-undefined.mk (expand / switch to context diff)
--- src/usr.bin/make/unit-tests/varmod-undefined.mk 2020/08/23 20:49:33 1.3
+++ src/usr.bin/make/unit-tests/varmod-undefined.mk 2020/09/03 18:52:36 1.4
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-undefined.mk,v 1.3 2020/08/23 20:49:33 rillig Exp $
+# $NetBSD: varmod-undefined.mk,v 1.4 2020/09/03 18:52:36 rillig Exp $
 #
 # Tests for the :U variable modifier, which returns the given string
 # if the variable is undefined.
@@ -46,9 +46,19 @@
 # the .newline variable is for.
 #
 # Whitespace at the edges is preserved, on both sides of the comparison.
-
+#
 .if ${:U \: \} \$ \\ \a \b \n } != " : } \$ \\ \\a \\b \\n "
 .error
+.endif
+
+# Even after the :U modifier has been applied, the expression still remembers
+# that it originated from an undefined variable, and the :U modifier can
+# be used to overwrite the value of the expression.
+#
+.if ${UNDEF:Uvalue:S,a,X,} != "vXlue"
+.  error
+.elif ${UNDEF:Uvalue:S,a,X,:Uwas undefined} != "was undefined"
+.  error
 .endif
 
 all: