Module Name: src Committed By: rillig Date: Mon Aug 30 17:08:13 UTC 2021
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-if.exp directive-for-if.mk Log Message: tests/make: explain where "${var}" in .for loops comes from To generate a diff of this commit: cvs rdiff -u -r1.1119 -r1.1120 src/distrib/sets/lists/tests/mi cvs rdiff -u -r1.282 -r1.283 src/usr.bin/make/unit-tests/Makefile cvs rdiff -u -r0 -r1.1 src/usr.bin/make/unit-tests/directive-for-if.exp \ src/usr.bin/make/unit-tests/directive-for-if.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.1119 src/distrib/sets/lists/tests/mi:1.1120 --- src/distrib/sets/lists/tests/mi:1.1119 Sun Aug 29 09:54:18 2021 +++ src/distrib/sets/lists/tests/mi Mon Aug 30 17:08:13 2021 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1119 2021/08/29 09:54:18 christos Exp $ +# $NetBSD: mi,v 1.1120 2021/08/30 17:08:13 rillig Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -5423,6 +5423,8 @@ ./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-if.exp tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/make/unit-tests/directive-for-if.mk tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/make/unit-tests/directive-for-lines.exp tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/make/unit-tests/directive-for-lines.mk tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/make/unit-tests/directive-for-null.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.282 src/usr.bin/make/unit-tests/Makefile:1.283 --- src/usr.bin/make/unit-tests/Makefile:1.282 Sat Jul 31 20:55:46 2021 +++ src/usr.bin/make/unit-tests/Makefile Mon Aug 30 17:08:13 2021 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.282 2021/07/31 20:55:46 rillig Exp $ +# $NetBSD: Makefile,v 1.283 2021/08/30 17:08:13 rillig Exp $ # # Unit tests for make(1) # @@ -168,6 +168,7 @@ TESTS+= directive-for TESTS+= directive-for-errors TESTS+= directive-for-escape TESTS+= directive-for-generating-endif +TESTS+= directive-for-if TESTS+= directive-for-lines TESTS+= directive-for-null TESTS+= directive-hyphen-include Added files: Index: src/usr.bin/make/unit-tests/directive-for-if.exp diff -u /dev/null src/usr.bin/make/unit-tests/directive-for-if.exp:1.1 --- /dev/null Mon Aug 30 17:08:13 2021 +++ src/usr.bin/make/unit-tests/directive-for-if.exp Mon Aug 30 17:08:13 2021 @@ -0,0 +1,6 @@ +make: "directive-for-if.mk" line 48: if-less endif +make: "directive-for-if.mk" line 48: if-less endif +make: "directive-for-if.mk" line 48: if-less endif +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: src/usr.bin/make/unit-tests/directive-for-if.mk diff -u /dev/null src/usr.bin/make/unit-tests/directive-for-if.mk:1.1 --- /dev/null Mon Aug 30 17:08:13 2021 +++ src/usr.bin/make/unit-tests/directive-for-if.mk Mon Aug 30 17:08:13 2021 @@ -0,0 +1,86 @@ +# $NetBSD: directive-for-if.mk,v 1.1 2021/08/30 17:08:13 rillig Exp $ +# +# Test for a .for directive that contains an .if directive. +# +# Before for.c 1.39 from 2008-12-21, when expanding the variables of a .for +# loop, their values were placed verbatim in the expanded body. Since then, +# each variable value expands to an expression of the form ${:Uvalue}. +# +# Before that change, the following adventurous code was possible: +# +# .for directive in if ifdef ifndef +# . ${directive} "1" != "0" +# . endif +# .endfor +# +# A more practical usage of the .for loop that often led to surprises was the +# following: +# +# .for var in VAR1 VAR2 VAR3 +# . if ${var} != "VAR2" +# . endif +# .endfor +# +# The .for loop body expanded to this string: +# +# . if VAR1 != "VAR2" +# . endif +# +# Since bare words were not allowed at the left-hand side of a condition, +# make complained about a "Malformed conditional", which was surprising since +# the code before expanding the .for loop body looked quite well. +# +# In cond.c 1.48 from 2008-11-29, just a month before the expansion of .for +# loops changed from plain textual value to using expressions of the form +# ${:Uvalue}, this surprising behavior was documented in the code, and a +# workaround was implemented that allowed bare words when they are followed +# by either '!' or '=', as part of the operators '!=' or '=='. +# +# Since cond.c 1.68 from 2015-05-05, bare words are allowed on the left-hand +# side of a condition, but that applies only to expression of the form +# ${${cond} :? then : else}, it does not apply to conditions in ordinary .if +# directives. + +# The following snippet worked in 2005, when the variables from the .for loop +# expanded to their bare textual value. +.for directive in if ifdef ifndef +. ${directive} "1" != "0" +. endif +.endfor +# In 2021, the above code does not generate an error message, even though the +# code looks clearly malformed. This is due to the '!', which is interpreted +# as a dependency operator, similar to ':' and '::'. The parser turns this +# line into a dependency with the 3 targets '.', 'if', '"1"' and the 2 sources +# '=' and '"0"'. Since that line is not interpreted as an '.if' directive, +# the error message 'if-less endif' makes sense. + +# In 2005, make complained: +# +# .if line: Malformed conditional (VAR1 != "VAR2") +# .endif line: if-less endif +# .endif line: Need an operator +# +# 2008.11.30.22.37.55 does not complain about the left-hand side ${var}. +.for var in VAR1 VAR2 VAR3 +. if ${var} != "VAR2" +_!= echo "${var}" 1>&2; echo # In 2005, '.info' was not invented yet. +. endif +.endfor + +# Before for.c 1.39 from 2008-12-21, a common workaround was to surround the +# variable expression from the .for loop with '"'. Such a string literal +# has been allowed since cond.c 1.23 from 2004-04-13. Between that commit and +# the one from 2008, the parser would still get confused if the value from the +# .for loop contained '"', which was effectively a code injection. +# +# Surrounding ${var} with quotes disabled the check for typos though. For +# ordinary variables, referring to an undefined variable on the left-hand side +# of the comparison resulted in a "Malformed conditional". Since the .for +# loop was usually close to the .if clause, this was not a problem in +# practice. +.for var in VAR1 VAR2 VAR3 +. if "${var}" != "VAR2" +. endif +.endfor + +all: