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