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