Module Name:    src
Committed By:   rillig
Date:           Sun Jun 12 16:09:21 UTC 2022

Modified Files:
        src/usr.bin/make: for.c
        src/usr.bin/make/unit-tests: directive-for-escape.exp
            directive-for-escape.mk

Log Message:
make: document ExprLen, which is part of a .for loop

No binary change


To generate a diff of this commit:
cvs rdiff -u -r1.167 -r1.168 src/usr.bin/make/for.c
cvs rdiff -u -r1.16 -r1.17 \
    src/usr.bin/make/unit-tests/directive-for-escape.exp
cvs rdiff -u -r1.15 -r1.16 \
    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/usr.bin/make/for.c
diff -u src/usr.bin/make/for.c:1.167 src/usr.bin/make/for.c:1.168
--- src/usr.bin/make/for.c:1.167	Fri Feb  4 23:22:19 2022
+++ src/usr.bin/make/for.c	Sun Jun 12 16:09:21 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: for.c,v 1.167 2022/02/04 23:22:19 rillig Exp $	*/
+/*	$NetBSD: for.c,v 1.168 2022/06/12 16:09:21 rillig Exp $	*/
 
 /*
  * Copyright (c) 1992, The Regents of the University of California.
@@ -58,7 +58,7 @@
 #include "make.h"
 
 /*	"@(#)for.c	8.1 (Berkeley) 6/6/93"	*/
-MAKE_RCSID("$NetBSD: for.c,v 1.167 2022/02/04 23:22:19 rillig Exp $");
+MAKE_RCSID("$NetBSD: for.c,v 1.168 2022/06/12 16:09:21 rillig Exp $");
 
 
 typedef struct ForLoop {
@@ -269,7 +269,14 @@ For_Accum(const char *line, int *forLeve
 	return true;
 }
 
-
+/*
+ * When the body of a '.for i' loop is prepared for an iteration, each
+ * occurrence of $i in the body is replaced with ${:U...}, inserting the
+ * value of the item.  If this item contains a '$', it may be the start of a
+ * variable expression.  This expression is copied verbatim, its length is
+ * determined here, in a rather naive way, ignoring escape characters and
+ * funny delimiters in modifiers like ':S}from}to}'.
+ */
 static size_t
 ExprLen(const char *s, const char *e)
 {

Index: src/usr.bin/make/unit-tests/directive-for-escape.exp
diff -u src/usr.bin/make/unit-tests/directive-for-escape.exp:1.16 src/usr.bin/make/unit-tests/directive-for-escape.exp:1.17
--- src/usr.bin/make/unit-tests/directive-for-escape.exp:1.16	Thu Jan 27 20:15:14 2022
+++ src/usr.bin/make/unit-tests/directive-for-escape.exp	Sun Jun 12 16:09:21 2022
@@ -26,30 +26,37 @@ For: loop body:
 make: "directive-for-escape.mk" line 43: value-with-modifier
 For: end for 1
 For: loop body:
+# ${:U\${UNDEF\:U\\$\\$}
+For: loop body:
+# ${:U{{\}\}}
+For: loop body:
+# ${:Uend\}}
+For: end for 1
+For: loop body:
 .  info ${:U\${UNDEF\:U\\$\\$}
-make: "directive-for-escape.mk" line 72: ${UNDEF:U\backslash$
+make: "directive-for-escape.mk" line 92: ${UNDEF:U\backslash$
 For: loop body:
 .  info ${:U{{\}\}}
-make: "directive-for-escape.mk" line 72: {{}}
+make: "directive-for-escape.mk" line 92: {{}}
 For: loop body:
 .  info ${:Uend\}}
-make: "directive-for-escape.mk" line 72: end}
+make: "directive-for-escape.mk" line 92: end}
 For: end for 1
 For: loop body:
 .  info ${:Ubegin<${UNDEF:Ufallback:N{{{}}}}>end}
-make: "directive-for-escape.mk" line 84: begin<fallback>end
+make: "directive-for-escape.mk" line 113: begin<fallback>end
 For: end for 1
 For: loop body:
 .  info ${:U\$}
-make: "directive-for-escape.mk" line 92: $
+make: "directive-for-escape.mk" line 121: $
 For: end for 1
 For: loop body:
 .  info ${NUMBERS} ${:Ureplaced}
-make: "directive-for-escape.mk" line 100: one two three replaced
+make: "directive-for-escape.mk" line 129: one two three replaced
 For: end for 1
 For: loop body:
 .  info ${:Ureplaced}
-make: "directive-for-escape.mk" line 110: replaced
+make: "directive-for-escape.mk" line 139: replaced
 For: end for 1
 For: loop body:
 .  info .        $$i: ${:Uinner}
@@ -62,46 +69,46 @@ For: loop body:
 .  info .     $${i2}: ${i2}
 .  info .     $${i,}: ${i,}
 .  info .  adjacent: ${:Uinner}${:Uinner}${:Uinner:M*}${:Uinner}
-make: "directive-for-escape.mk" line 118: .        $i: inner
-make: "directive-for-escape.mk" line 119: .      ${i}: inner
-make: "directive-for-escape.mk" line 120: .   ${i:M*}: inner
-make: "directive-for-escape.mk" line 121: .      $(i): inner
-make: "directive-for-escape.mk" line 122: .   $(i:M*): inner
-make: "directive-for-escape.mk" line 123: . ${i${:U}}: outer
-make: "directive-for-escape.mk" line 124: .    ${i\}}: inner}
-make: "directive-for-escape.mk" line 125: .     ${i2}: two
-make: "directive-for-escape.mk" line 126: .     ${i,}: comma
-make: "directive-for-escape.mk" line 127: .  adjacent: innerinnerinnerinner
+make: "directive-for-escape.mk" line 147: .        $i: inner
+make: "directive-for-escape.mk" line 148: .      ${i}: inner
+make: "directive-for-escape.mk" line 149: .   ${i:M*}: inner
+make: "directive-for-escape.mk" line 150: .      $(i): inner
+make: "directive-for-escape.mk" line 151: .   $(i:M*): inner
+make: "directive-for-escape.mk" line 152: . ${i${:U}}: outer
+make: "directive-for-escape.mk" line 153: .    ${i\}}: inner}
+make: "directive-for-escape.mk" line 154: .     ${i2}: two
+make: "directive-for-escape.mk" line 155: .     ${i,}: comma
+make: "directive-for-escape.mk" line 156: .  adjacent: innerinnerinnerinner
 For: end for 1
 For: loop body:
 .  info eight $$$$$$$$ and no cents.
 .  info eight ${:Udollar}${:Udollar}${:Udollar}${:Udollar} and no cents.
-make: "directive-for-escape.mk" line 135: eight $$$$ and no cents.
-make: "directive-for-escape.mk" line 136: eight dollardollardollardollar and no cents.
-make: "directive-for-escape.mk" line 145: eight  and no cents.
+make: "directive-for-escape.mk" line 164: eight $$$$ and no cents.
+make: "directive-for-escape.mk" line 165: eight dollardollardollardollar and no cents.
+make: "directive-for-escape.mk" line 174: eight  and no cents.
 For: end for 1
-make: "directive-for-escape.mk" line 152: newline in .for value
-make: "directive-for-escape.mk" line 152: newline in .for value
+make: "directive-for-escape.mk" line 181: newline in .for value
+make: "directive-for-escape.mk" line 181: newline in .for value
 For: loop body:
 .  info short: ${:U" "}
 .  info long: ${:U" "}
-make: "directive-for-escape.mk" line 153: short: " "
-make: "directive-for-escape.mk" line 154: long: " "
+make: "directive-for-escape.mk" line 182: short: " "
+make: "directive-for-escape.mk" line 183: long: " "
 For: end for 1
 For: loop body:
 For: end for 1
-Parse_PushInput: .for loop in directive-for-escape.mk, line 167
-make: "directive-for-escape.mk" line 167: newline in .for value
-	in .for loop from directive-for-escape.mk:167 with i = "
+Parse_PushInput: .for loop in directive-for-escape.mk, line 196
+make: "directive-for-escape.mk" line 196: newline in .for value
+	in .for loop from directive-for-escape.mk:196 with i = "
 "
 For: loop body:
 : ${:U" "}
 SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `directive-for-escape.mk'
-Parsing line 168: : ${:U" "}
+Parsing line 197: : ${:U" "}
 ParseDependency(: " ")
-ParseEOF: returning to file directive-for-escape.mk, line 170
+ParseEOF: returning to file directive-for-escape.mk, line 199
 SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `directive-for-escape.mk'
-Parsing line 170: .MAKEFLAGS: -d0
+Parsing line 199: .MAKEFLAGS: -d0
 ParseDependency(.MAKEFLAGS: -d0)
 For: end for 1
 For: loop body:

Index: src/usr.bin/make/unit-tests/directive-for-escape.mk
diff -u src/usr.bin/make/unit-tests/directive-for-escape.mk:1.15 src/usr.bin/make/unit-tests/directive-for-escape.mk:1.16
--- src/usr.bin/make/unit-tests/directive-for-escape.mk:1.15	Thu Jan 27 20:15:14 2022
+++ src/usr.bin/make/unit-tests/directive-for-escape.mk	Sun Jun 12 16:09:21 2022
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for-escape.mk,v 1.15 2022/01/27 20:15:14 rillig Exp $
+# $NetBSD: directive-for-escape.mk,v 1.16 2022/06/12 16:09:21 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
@@ -43,38 +43,67 @@ VALUES=		$$ $${V} $${V:=-with-modifier} 
 .  info $i
 .endfor
 
+
 # Try to cover the code for nested '{}' in ExprLen, without success.
 #
 # The value of the variable VALUES is not meant to be a variable expression.
 # Instead, it is meant to represent literal text, the only escaping mechanism
 # being that each '$' is written as '$$'.
+VALUES=		$${UNDEF:U\$$\$$ {{}} end}
 #
 # The .for loop splits ${VALUES} into 3 words, at the space characters, since
 # the '$$' is an ordinary character and the spaces are not escaped.
 #	Word 1 is '${UNDEF:U\$\$'
 #	Word 2 is '{{}}'
 #	Word 3 is 'end}'
-# The first iteration expands the body of the .for loop to:
-# expect: .  info ${:U\${UNDEF\:U\\$\\$}
-# The modifier ':U' unescapes the '\$' to a simple '$'.
-# The modifier ':U' unescapes the '\:' to a simple ':'.
-# The modifier ':U' unescapes the '\\' to a simple '\'.
-# The modifier ':U' resolves the expression '$\' to the word 'backslash', due
-# to the following variable definition.
+#
+# Each of these words is now inserted in the body of the .for loop.
+.for i in ${VALUES}
+# $i
+.endfor
+#
+# When these words are injected into the body of the .for loop, each inside a
+# '${:U...}' expression, the result is:
+#
+# expect: For: loop body:
+# expect: # ${:U\${UNDEF\:U\\$\\$}
+# expect: For: loop body:
+# expect: # ${:U{{\}\}}
+# expect: For: loop body:
+# expect: # ${:Uend\}}
+# expect: For: end for 1
+#
+# The first of these expressions is the most interesting one, due to its many
+# special characters.  This expression is properly balanced:
+#
+#	Text	Meaning		Explanation
+#	\$	$		escaped
+#	{	{		ordinary text
+#	UNDEF	UNDEF		ordinary text
+#	\:	:		escaped
+#	U	U		ordinary text
+#	\\	\		escaped
+#	$\	(expr)		an expression, the variable name is '\'
+#	\$	$		escaped
+#
+# To make the expression '$\' visible, define it to an actual word:
 ${:U\\}=	backslash
-# FIXME: There was no expression '$\' in the original text of the previous
-# line, that's a surprise in the parser.
-# The modifier ':U' unescapes the '\$' to a simple '$'.
-# expect+4: ${UNDEF:U\backslash$
-VALUES=		$${UNDEF:U\$$\$$ {{}} end}
-# XXX: Where in the code does the '\$\$' get converted into a single '\$'?
 .for i in ${VALUES}
 .  info $i
 .endfor
+#
+# expect-3: ${UNDEF:U\backslash$
+# expect-4: {{}}
+# expect-5: end}
+#
+# FIXME: There was no expression '$\' in the original text of the variable
+# 'VALUES', that's a surprise in the parser.
+
 
 # Second try to cover the code for nested '{}' in ExprLen.
 #
-# XXX: It is wrong that ExprLen requires the braces to be balanced.
+# XXX: It is not the job of ExprLen to parse an expression, it is naive to
+# expect ExprLen to get all the details right in just a few lines of code.
 # Each variable modifier has its own inconsistent way of parsing nested
 # variable expressions, braces and parentheses.  (Compare ':M', ':S', and
 # ':D' for details.)  The only sensible thing to do is therefore to let

Reply via email to