Module Name:    src
Committed By:   rillig
Date:           Thu Dec 31 03:05:12 UTC 2020

Modified Files:
        src/distrib/sets/lists/tests: mi
        src/usr.bin/make/unit-tests: Makefile
Added Files:
        src/usr.bin/make/unit-tests: directive-for-errors.exp
            directive-for-errors.mk directive-for-escape.exp
            directive-for-escape.mk

Log Message:
make(1): add test for error handling and expansion in .for loops


To generate a diff of this commit:
cvs rdiff -u -r1.1002 -r1.1003 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.259 -r1.260 src/usr.bin/make/unit-tests/Makefile
cvs rdiff -u -r0 -r1.1 src/usr.bin/make/unit-tests/directive-for-errors.exp \
    src/usr.bin/make/unit-tests/directive-for-errors.mk \
    src/usr.bin/make/unit-tests/directive-for-escape.exp \
    src/usr.bin/make/unit-tests/directive-for-escape.mk

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

Modified files:

Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.1002 src/distrib/sets/lists/tests/mi:1.1003
--- src/distrib/sets/lists/tests/mi:1.1002	Wed Dec 30 14:50:08 2020
+++ src/distrib/sets/lists/tests/mi	Thu Dec 31 03:05:12 2020
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1002 2020/12/30 14:50:08 rillig Exp $
+# $NetBSD: mi,v 1.1003 2020/12/31 03:05:12 rillig Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -5058,6 +5058,10 @@
 ./usr/tests/usr.bin/make/unit-tests/directive-export-literal.mk			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/directive-export.exp			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/directive-export.mk				tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/make/unit-tests/directive-for-errors.exp			tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/make/unit-tests/directive-for-errors.mk			tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/make/unit-tests/directive-for-escape.exp			tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/make/unit-tests/directive-for-escape.mk			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/directive-for-generating-endif.exp		tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/directive-for-generating-endif.mk		tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/make/unit-tests/directive-for-lines.exp			tests-usr.bin-tests	compattestfile,atf

Index: src/usr.bin/make/unit-tests/Makefile
diff -u src/usr.bin/make/unit-tests/Makefile:1.259 src/usr.bin/make/unit-tests/Makefile:1.260
--- src/usr.bin/make/unit-tests/Makefile:1.259	Wed Dec 30 14:50:08 2020
+++ src/usr.bin/make/unit-tests/Makefile	Thu Dec 31 03:05:12 2020
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.259 2020/12/30 14:50:08 rillig Exp $
+# $NetBSD: Makefile,v 1.260 2020/12/31 03:05:12 rillig Exp $
 #
 # Unit tests for make(1)
 #
@@ -162,6 +162,8 @@ TESTS+=		directive-export-impl
 TESTS+=		directive-export-gmake
 TESTS+=		directive-export-literal
 TESTS+=		directive-for
+TESTS+=		directive-for-errors
+TESTS+=		directive-for-escape
 TESTS+=		directive-for-generating-endif
 TESTS+=		directive-for-lines
 TESTS+=		directive-for-null

Added files:

Index: src/usr.bin/make/unit-tests/directive-for-errors.exp
diff -u /dev/null src/usr.bin/make/unit-tests/directive-for-errors.exp:1.1
--- /dev/null	Thu Dec 31 03:05:12 2020
+++ src/usr.bin/make/unit-tests/directive-for-errors.exp	Thu Dec 31 03:05:12 2020
@@ -0,0 +1,22 @@
+make: "directive-for-errors.mk" line 7: Unknown directive "fori"
+make: "directive-for-errors.mk" line 8: warning: 
+make: "directive-for-errors.mk" line 9: for-less endfor
+make: "directive-for-errors.mk" line 19: Unknown directive "for"
+make: "directive-for-errors.mk" line 20: warning: 
+make: "directive-for-errors.mk" line 21: for-less endfor
+make: "directive-for-errors.mk" line 37: Dollar $ 1 1 and backslash 2 2 2.
+make: "directive-for-errors.mk" line 37: Dollar $ 3 3 and backslash 4 4 4.
+make: "directive-for-errors.mk" line 43: no iteration variables in for
+make: "directive-for-errors.mk" line 47: warning: Should not be reached.
+make: "directive-for-errors.mk" line 48: for-less endfor
+make: "directive-for-errors.mk" line 53: Wrong number of words (5) in .for substitution list with 3 variables
+make: "directive-for-errors.mk" line 64: missing `in' in for
+make: "directive-for-errors.mk" line 66: warning: Should not be reached.
+make: "directive-for-errors.mk" line 67: for-less endfor
+make: "directive-for-errors.mk" line 73: Unknown modifier 'Z'
+make: "directive-for-errors.mk" line 74: warning: Should not be reached.
+make: "directive-for-errors.mk" line 74: warning: Should not be reached.
+make: "directive-for-errors.mk" line 74: warning: Should not be reached.
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
+exit status 1
Index: src/usr.bin/make/unit-tests/directive-for-errors.mk
diff -u /dev/null src/usr.bin/make/unit-tests/directive-for-errors.mk:1.1
--- /dev/null	Thu Dec 31 03:05:12 2020
+++ src/usr.bin/make/unit-tests/directive-for-errors.mk	Thu Dec 31 03:05:12 2020
@@ -0,0 +1,75 @@
+# $NetBSD: directive-for-errors.mk,v 1.1 2020/12/31 03:05:12 rillig Exp $
+#
+# Tests for error handling in .for loops.
+
+# A .for directive must be followed by whitespace, everything else results
+# in a parse error.
+.fori in 1 2 3
+.  warning ${i}
+.endfor
+
+# A slash is not whitespace, therefore this is not parsed as a .for loop.
+#
+# XXX: The error message is misleading though.  As of 2020-12-31, it says
+# "Unknown directive "for"", but that directive is actually known.  This is
+# because ForEval does not detect the .for loop as such, so parsing
+# continues in ParseLine > ParseDependency > ParseDoDependency >
+# ParseDoDependencyTargets > ParseErrorNoDependency, and there the directive
+# name is parsed a bit differently.
+.for/i in 1 2 3
+.  warning ${i}
+.endfor
+
+# As of 2020-12-31, the variable name can be an arbitrary word, it just needs
+# to be separated by whitespace.  Even '$' and '\' are valid variable names,
+# which is not useful in practice.
+#
+# The '$$' is not replaced with the values '1' or '3' from the .for loop,
+# instead it is kept as-is, and when the .info directive expands its argument,
+# each '$$' gets replaced with a single '$'.  The "long variable expression"
+# ${$} gets replaced though, even though this would be a parse error everywhere
+# outside a .for loop.
+#
+# The '\' on the other hand is treated as a normal variable name.
+${:U\$}=	dollar		# see whether the "variable" '$' is local
+${:U\\}=	backslash	# see whether the "variable" '\' is local
+.for $ \ in 1 2 3 4
+.  info Dollar $$ ${$} $($) and backslash $\ ${\} $(\).
+.endfor
+
+# If there are no variables, there is no point in expanding the .for loop
+# since this would end up in an endless loop, each time consuming 0 of the
+# 3 values.
+.for in 1 2 3
+# XXX: This should not be reached.  It should be skipped, as already done
+# when the number of values is not a multiple of the number of variables,
+# see below.
+.  warning Should not be reached.
+.endfor
+
+# There are 3 variables and 5 values.  These 5 values cannot be split evenly
+# among the variables, therefore the loop is not expanded at all, it is
+# rather skipped.
+.for a b c in 1 2 3 4 5
+.  warning Should not be reached.
+.endfor
+
+# The list of values after the 'in' may be empty, no matter if this emptiness
+# comes from an empty expansion or even from a syntactically empty line.
+.for i in
+.  info Would be reached if there were items to loop over.
+.endfor
+
+# A missing 'in' should parse the .for loop but skip the body.
+.for i : k
+# XXX: As of 2020-12-31, this line is reached once.
+.  warning Should not be reached.
+.endfor
+
+# A malformed modifier should be detected and skip the body of the loop.
+#
+# XXX: As of 2020-12-31, Var_Subst doesn't report any errors, therefore
+# the loop body is expanded as if no error had happened.
+.for i in 1 2 ${:U3:Z} 4
+.  warning Should not be reached.
+.endfor
Index: src/usr.bin/make/unit-tests/directive-for-escape.exp
diff -u /dev/null src/usr.bin/make/unit-tests/directive-for-escape.exp:1.1
--- /dev/null	Thu Dec 31 03:05:12 2020
+++ src/usr.bin/make/unit-tests/directive-for-escape.exp	Thu Dec 31 03:05:12 2020
@@ -0,0 +1,44 @@
+For: end for 1
+For: loop body:
+.  info ${:U!"#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
+make: Unclosed variable specification (expecting '}') for "" (value "!"") modifier U
+make: "directive-for-escape.mk" line 19: !"
+For: end for 1
+For: loop body:
+.  info ${:U!"\\\\#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
+make: Unclosed variable specification (expecting '}') for "" (value "!"\\") modifier U
+make: "directive-for-escape.mk" line 29: !"\\
+For: end for 1
+For: loop body:
+.  info ${:U\$}
+make: "directive-for-escape.mk" line 41: $
+For: loop body:
+.  info ${:U${V}}
+make: "directive-for-escape.mk" line 41: value
+For: loop body:
+.  info ${:U${V:=-with-modifier}}
+make: "directive-for-escape.mk" line 41: value-with-modifier
+For: loop body:
+.  info ${:U$(V)}
+make: "directive-for-escape.mk" line 41: value
+For: loop body:
+.  info ${:U$(V:=-with-modifier)}
+make: "directive-for-escape.mk" line 41: value-with-modifier
+For: end for 1
+For: loop body:
+.  info ${:U\${UNDEF\:U\\$\\$}
+make: "directive-for-escape.mk" line 52: ${UNDEF:U\$
+For: loop body:
+.  info ${:U{{\}\}}
+make: "directive-for-escape.mk" line 52: {{}}
+For: loop body:
+.  info ${:Uend\}}
+make: "directive-for-escape.mk" line 52: end}
+For: end for 1
+For: loop body:
+.  info ${:U\$}
+make: "directive-for-escape.mk" line 60: $
+make: no target to make.
+
+make: stopped in unit-tests
+exit status 2
Index: src/usr.bin/make/unit-tests/directive-for-escape.mk
diff -u /dev/null src/usr.bin/make/unit-tests/directive-for-escape.mk:1.1
--- /dev/null	Thu Dec 31 03:05:12 2020
+++ src/usr.bin/make/unit-tests/directive-for-escape.mk	Thu Dec 31 03:05:12 2020
@@ -0,0 +1,61 @@
+# $NetBSD: directive-for-escape.mk,v 1.1 2020/12/31 03:05:12 rillig Exp $
+#
+# Test escaping of special characters in the iteration values of a .for loop.
+# These values get expanded later using the :U variable modifier, and this
+# escaping and unescaping must pass all characters and strings effectively
+# unmodified.
+
+.MAKEFLAGS: -df
+
+# Even though the .for loops takes quotes into account when splitting the
+# string into words, the quotes don't need to be balances, as of 2020-12-31.
+# This could be considered a bug.
+ASCII=	!"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
+
+# XXX: As of 2020-12-31, the '#' is not preserved in the expanded body of
+# the loop since it would not need only the escaping for the :U variable
+# modifier but also the escaping for the line-end comment.
+.for chars in ${ASCII}
+.  info ${chars}
+.endfor
+
+# As of 2020-12-31, using 2 backslashes before be '#' would treat the '#'
+# as comment character.  Using 3 backslashes doesn't help either since
+# then the situation is essentially the same as with 1 backslash.
+# This means that a '#' sign cannot be passed in the value of a .for loop
+# at all.
+ASCII.2020-12-31=	!"\\\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
+.for chars in ${ASCII.2020-12-31}
+.  info ${chars}
+.endfor
+
+# Cover the code in for_var_len.
+#
+# XXX: It is unexpected that the variable V gets expanded in the loop body.
+# The double '$$' should prevent exactly this.  Probably nobody was
+# adventurous enough to use literal dollar signs in the values for a .for
+# loop.
+V=		value
+VALUES=		$$ $${V} $${V:=-with-modifier} $$(V) $$(V:=-with-modifier)
+.for i in ${VALUES}
+.  info $i
+.endfor
+
+# Cover the code for nested '{}' in for_var_len.
+#
+# The value of VALUES is not a variable expression.  Instead, it is meant to
+# represent dollar, lbrace, "UNDEF:U", backslash, dollar, backslash, dollar,
+# space, nested braces, space, "end}".
+VALUES=		$${UNDEF:U\$$\$$ {{}} end}
+# XXX: Where does the '\$$\$$' get converted into a single '\$'?
+.for i in ${VALUES}
+.  info $i
+.endfor
+
+# A single trailing dollar doesn't happen in practice.
+# The dollar sign is correctly passed through to the body of the .for loop.
+# There, it is expanded by the .info directive, but even there a trailing
+# dollar sign is kept as-is.
+.for i in ${:U\$}
+.  info ${i}
+.endfor

Reply via email to