Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/make/unit-tests make(1): add test for the .for direc...



details:   https://anonhg.NetBSD.org/src/rev/bed01e6af185
branches:  trunk
changeset: 938100:bed01e6af185
user:      rillig <rillig%NetBSD.org@localhost>
date:      Wed Sep 02 05:33:57 2020 +0000

description:
make(1): add test for the .for directive

For a long time, I had assumed that the iteration variables of a .for
loop are just normal global variables.  This assumption was wrong but
didn't have any consequences.

The iteration variables of a .for loop can just be accessed like global
variables, therefore it is not obvious that they are implemented in a
completely different way.

There are some edge cases in conditions used inside .for loops, in which
the iteration variables cannot be used like normal variables.  An
example is brought up in https://gnats.netbsd.org/47888, which observes
that the defined() and empty() functions in conditions only work with
variables but ignore the iteration "variables", simply because these are
not variables but only expressions.

diffstat:

 distrib/sets/lists/tests/mi               |   4 +-
 usr.bin/make/unit-tests/Makefile          |   3 +-
 usr.bin/make/unit-tests/directive-for.exp |   1 +
 usr.bin/make/unit-tests/directive-for.mk  |  97 +++++++++++++++++++++++++++++++
 4 files changed, 103 insertions(+), 2 deletions(-)

diffs (141 lines):

diff -r 0ac483edd3eb -r bed01e6af185 distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi       Wed Sep 02 04:32:13 2020 +0000
+++ b/distrib/sets/lists/tests/mi       Wed Sep 02 05:33:57 2020 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.914 2020/08/29 18:50:25 rillig Exp $
+# $NetBSD: mi,v 1.915 2020/09/02 05:33:57 rillig Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -4730,6 +4730,8 @@
 ./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.exp                  tests-usr.bin-tests     compattestfile,atf
+./usr/tests/usr.bin/make/unit-tests/directive-for.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-if.exp   tests-usr.bin-tests     compattestfile,atf
diff -r 0ac483edd3eb -r bed01e6af185 usr.bin/make/unit-tests/Makefile
--- a/usr.bin/make/unit-tests/Makefile  Wed Sep 02 04:32:13 2020 +0000
+++ b/usr.bin/make/unit-tests/Makefile  Wed Sep 02 05:33:57 2020 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.129 2020/08/29 19:35:38 rillig Exp $
+# $NetBSD: Makefile,v 1.130 2020/09/02 05:33:57 rillig Exp $
 #
 # Unit tests for make(1)
 #
@@ -132,6 +132,7 @@
 TESTS+=                directive-export
 TESTS+=                directive-export-env
 TESTS+=                directive-export-literal
+TESTS+=                directive-for
 TESTS+=                directive-for-generating-endif
 TESTS+=                directive-if
 TESTS+=                directive-ifdef
diff -r 0ac483edd3eb -r bed01e6af185 usr.bin/make/unit-tests/directive-for.exp
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/make/unit-tests/directive-for.exp Wed Sep 02 05:33:57 2020 +0000
@@ -0,0 +1,1 @@
+exit status 0
diff -r 0ac483edd3eb -r bed01e6af185 usr.bin/make/unit-tests/directive-for.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/make/unit-tests/directive-for.mk  Wed Sep 02 05:33:57 2020 +0000
@@ -0,0 +1,97 @@
+# $NetBSD: directive-for.mk,v 1.1 2020/09/02 05:33:57 rillig Exp $
+#
+# Tests for the .for directive.
+
+# Using the .for loop, lists of values can be produced.
+# In simple cases, the :@var@${var}@ variable modifier can be used to
+# reach the same effects.
+#
+.undef NUMBERS
+.for num in 1 2 3
+NUMBERS+=      ${num}
+.endfor
+.if ${NUMBERS} != "1 2 3"
+.  error
+.endif
+
+# The .for loop also works for multiple iteration variables.
+.for name value in VARNAME value NAME2 value2
+${name}=       ${value}
+.endfor
+.if ${VARNAME} != "value" || ${NAME2} != "value2"
+.  error
+.endif
+
+# The .for loop splits the items at whitespace, taking quotes into account,
+# just like the :M or :S variable modifiers.
+#
+# Until 2012-06-03, it had split the items exactly at whitespace, without
+# taking the quotes into account.
+#
+.undef WORDS
+.for var in one t\ w\ o "three three" 'four four' `five six`
+WORDS+=        counted
+.endfor
+.if ${WORDS:[#]} != 6
+.  error
+.endif
+
+# In the body of the .for loop, the iteration variables can be accessed
+# like normal variables, even though they are not really variables.
+#
+# Instead, the expression ${var} is transformed into ${:U1}, ${:U2} and so
+# on, before the loop body is evaluated.
+#
+# A notable effect of this implementation technique is that the .for
+# iteration variables and the normal global variables live in separate
+# namespaces and do not influence each other.
+#
+var=   value before
+var2=  value before
+.for var var2 in 1 2 3 4
+.endfor
+.if ${var} != "value before"
+.  warning var must be undefined.
+.endif
+.if ${var2} != "value before"
+.  warning var2 must be undefined.
+.endif
+
+# Everything from the paragraph above also applies if the loop body is
+# empty, even if there is no actual iteration since the loop items are
+# also empty.
+#
+var=   value before
+var2=  value before
+.for var var2 in ${:U}
+.endfor
+.if ${var} != "value before"
+.  warning var must be undefined.
+.endif
+.if ${var2} != "value before"
+.  warning var2 must be undefined.
+.endif
+
+# Until 2008-12-21, the values of the iteration variables were simply
+# inserted as plain text and then parsed as usual, which made it possible
+# to achieve all kinds of strange effects.
+#
+# Before that date, the .for loop expanded to:
+#      EXPANSION+= value
+# Since that date, the .for loop expands to:
+#      EXPANSION${:U+}= value
+#
+EXPANSION=     before
+EXPANSION+ =   before
+.for plus in +
+EXPANSION${plus}=      value
+.endfor
+.if ${EXPANSION} != "before"
+.  error This must be a make from before 2009.
+.endif
+.if ${EXPANSION+} != "value"
+.  error This must be a make from before 2009.
+.endif
+
+all:
+       @:;



Home | Main Index | Thread Index | Old Index