Module Name: src
Committed By: rillig
Date: Tue Aug 23 19:22:02 UTC 2022
Modified Files:
src/usr.bin/make: var.c
src/usr.bin/make/unit-tests: parse-var.exp parse-var.mk
var-eval-short.exp varmod-defined.exp varmod-loop.exp
varmod-loop.mk varname-dot-suffixes.exp
Log Message:
make: revert parsing of modifier parts (since 2022-08-08)
The modifier ':@var@body@' parses the body in parse-only mode and later
uses Var_Subst on it, in which each literal '$' must be written as '$$'.
Trying to parse the loop body using Var_Parse treated the text
'$${var:-0}' as a single '$' followed by the expression '${var:-0}',
wrongly complaining about the 'Unknown modifier "-0"'.
Found by sjg.
To generate a diff of this commit:
cvs rdiff -u -r1.1028 -r1.1029 src/usr.bin/make/var.c
cvs rdiff -u -r1.3 -r1.4 src/usr.bin/make/unit-tests/parse-var.exp
cvs rdiff -u -r1.4 -r1.5 src/usr.bin/make/unit-tests/parse-var.mk \
src/usr.bin/make/unit-tests/varname-dot-suffixes.exp
cvs rdiff -u -r1.19 -r1.20 src/usr.bin/make/unit-tests/var-eval-short.exp \
src/usr.bin/make/unit-tests/varmod-loop.mk
cvs rdiff -u -r1.12 -r1.13 src/usr.bin/make/unit-tests/varmod-defined.exp
cvs rdiff -u -r1.16 -r1.17 src/usr.bin/make/unit-tests/varmod-loop.exp
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/var.c
diff -u src/usr.bin/make/var.c:1.1028 src/usr.bin/make/var.c:1.1029
--- src/usr.bin/make/var.c:1.1028 Mon Aug 8 18:23:30 2022
+++ src/usr.bin/make/var.c Tue Aug 23 19:22:01 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.1028 2022/08/08 18:23:30 rillig Exp $ */
+/* $NetBSD: var.c,v 1.1029 2022/08/23 19:22:01 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -139,7 +139,7 @@
#include "metachar.h"
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.1028 2022/08/08 18:23:30 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.1029 2022/08/23 19:22:01 rillig Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -2131,33 +2131,49 @@ ParseModifierPartExpr(const char **pp, L
*pp = p;
}
-/* In a part of a modifier, parse a subexpression but don't evaluate it. */
+/*
+ * In a part of a modifier, parse a subexpression but don't evaluate it.
+ *
+ * XXX: This whole block is very similar to Var_Parse with VARE_PARSE_ONLY.
+ * There may be subtle edge cases though that are not yet covered in the unit
+ * tests and that are parsed differently, depending on whether they are
+ * evaluated or not.
+ *
+ * This subtle difference is not documented in the manual page, neither is
+ * the difference between parsing ':D' and ':M' documented. No code should
+ * ever depend on these details, but who knows.
+ *
+ * TODO: Before trying to replace this code with Var_Parse, there need to be
+ * more unit tests in varmod-loop.mk. The modifier ':@' uses Var_Subst
+ * internally, in which a '$' is escaped as '$$', not as '\$' like in other
+ * modifiers. When parsing the body text '$${var}', skipping over the first
+ * '$' would treat '${var}' as a make expression, not as a shell variable.
+ */
static void
ParseModifierPartDollar(const char **pp, LazyBuf *part)
{
const char *p = *pp;
+ const char *start = *pp;
if (p[1] == '(' || p[1] == '{') {
- FStr unused;
- Var_Parse(&p, SCOPE_GLOBAL, VARE_PARSE_ONLY, &unused);
- /* TODO: handle errors */
- FStr_Done(&unused);
+ char startc = p[1];
+ int endc = startc == '(' ? ')' : '}';
+ int depth = 1;
+
+ for (p += 2; *p != '\0' && depth > 0; p++) {
+ if (p[-1] != '\\') {
+ if (*p == startc)
+ depth++;
+ if (*p == endc)
+ depth--;
+ }
+ }
+ LazyBuf_AddBytesBetween(part, start, p);
+ *pp = p;
} else {
- /*
- * Only skip the '$' but not the next character; see
- * ParseModifierPartSubst, the case for "Unescaped '$' at
- * end", which also doesn't skip '$' + delimiter. That is a
- * hack as well, but for now it's consistent in both cases.
- */
- p++;
+ LazyBuf_Add(part, *start);
+ *pp = p + 1;
}
-
- /*
- * XXX: There should be no need to add anything to the buffer, as it
- * will be discarded anyway.
- */
- LazyBuf_AddBytesBetween(part, *pp, p);
- *pp = p;
}
/* See ParseModifierPart for the documentation. */
Index: src/usr.bin/make/unit-tests/parse-var.exp
diff -u src/usr.bin/make/unit-tests/parse-var.exp:1.3 src/usr.bin/make/unit-tests/parse-var.exp:1.4
--- src/usr.bin/make/unit-tests/parse-var.exp:1.3 Mon Aug 8 18:23:30 2022
+++ src/usr.bin/make/unit-tests/parse-var.exp Tue Aug 23 19:22:01 2022
@@ -1 +1,5 @@
-exit status 0
+make: Unfinished modifier for "BRACE_GROUP" (',' missing)
+make: "parse-var.mk" line 57: Malformed conditional (0 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,})
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
+exit status 1
Index: src/usr.bin/make/unit-tests/parse-var.mk
diff -u src/usr.bin/make/unit-tests/parse-var.mk:1.4 src/usr.bin/make/unit-tests/parse-var.mk:1.5
--- src/usr.bin/make/unit-tests/parse-var.mk:1.4 Mon Aug 8 19:53:28 2022
+++ src/usr.bin/make/unit-tests/parse-var.mk Tue Aug 23 19:22:01 2022
@@ -1,4 +1,4 @@
-# $NetBSD: parse-var.mk,v 1.4 2022/08/08 19:53:28 rillig Exp $
+# $NetBSD: parse-var.mk,v 1.5 2022/08/23 19:22:01 rillig Exp $
#
# Tests for parsing variable expressions.
@@ -13,8 +13,10 @@ VAR.${:U param }= value
. error
.endif
+# XXX: The following paragraph already uses past tense, in the hope that the
+# parsing behavior can be cleaned up soon.
-# Since var.c 1.323 from 202-07-26 18:11 and before var.c 1.1028 from
+# Since var.c 1.323 from 2020-07-26 18:11 and except for var.c 1.1028 from
# 2022-08-08, the exact way of parsing an expression depended on whether the
# expression was actually evaluated or merely parsed.
#
@@ -30,7 +32,7 @@ VAR.${:U param }= value
# braces.
#
# This naive brace counting was implemented in ParseModifierPartDollar. As of
-# var.c 1., there are still several other places that merely count braces
+# var.c 1.1029, there are still several other places that merely count braces
# instead of properly parsing subexpressions.
#.MAKEFLAGS: -dcpv
@@ -51,7 +53,7 @@ BRACE_GROUP= {{{{}}}}
# the parts of the outer ':S' modifier, make only counted the braces, and since
# the inner expression '${BRACE_PAIR:...}' contains more '{' than '}', parsing
# failed with the error message 'Unfinished modifier for "BRACE_GROUP"'. Fixed
-# in var.c 1.1028 from 2022-08-08.
+# in var.c 1.1028 from 2022-08-08, reverted in var.c 1.1029 from 2022-08-23.
.if 0 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,}
.endif
#.MAKEFLAGS: -d0
Index: src/usr.bin/make/unit-tests/varname-dot-suffixes.exp
diff -u src/usr.bin/make/unit-tests/varname-dot-suffixes.exp:1.4 src/usr.bin/make/unit-tests/varname-dot-suffixes.exp:1.5
--- src/usr.bin/make/unit-tests/varname-dot-suffixes.exp:1.4 Mon Aug 8 18:23:30 2022
+++ src/usr.bin/make/unit-tests/varname-dot-suffixes.exp Tue Aug 23 19:22:01 2022
@@ -24,7 +24,6 @@ Evaluating modifier ${1 2:L} on value ""
Result of ${1 2:L} is "1 2" (eval-defined, defined)
Evaluating modifier ${1 2:@...} on value "1 2" (eval-defined, defined)
Modifier part: ".SUFFIXES"
-Var_Parse: ${.SUFFIXES}@} != ".c .o .1 .err .tar.gz .c .o .1 .err .tar.gz" (parse-only)
Modifier part: "${.SUFFIXES}"
ModifyWords: split "1 2" into 2 words
Command: .SUFFIXES = 1 ignored (read-only)
Index: src/usr.bin/make/unit-tests/var-eval-short.exp
diff -u src/usr.bin/make/unit-tests/var-eval-short.exp:1.19 src/usr.bin/make/unit-tests/var-eval-short.exp:1.20
--- src/usr.bin/make/unit-tests/var-eval-short.exp:1.19 Mon Aug 8 18:23:30 2022
+++ src/usr.bin/make/unit-tests/var-eval-short.exp Tue Aug 23 19:22:01 2022
@@ -7,9 +7,7 @@ make: "var-eval-short.mk" line 98: Malfo
CondParser_Eval: 0 && ${0:?${FAIL}then:${FAIL}else}
Var_Parse: ${0:?${FAIL}then:${FAIL}else} (parse-only)
Parsing modifier ${0:?...}
-Var_Parse: ${FAIL}then:${FAIL}else} (parse-only)
Modifier part: "${FAIL}then"
-Var_Parse: ${FAIL}else} (parse-only)
Modifier part: "${FAIL}else"
Result of ${0:?${FAIL}then:${FAIL}else} is "" (parse-only, defined)
Parsing line 163: DEFINED= defined
@@ -19,9 +17,7 @@ Var_Parse: ${DEFINED:L:?${FAIL}then:${FA
Parsing modifier ${DEFINED:L}
Result of ${DEFINED:L} is "defined" (parse-only, regular)
Parsing modifier ${DEFINED:?...}
-Var_Parse: ${FAIL}then:${FAIL}else} (parse-only)
Modifier part: "${FAIL}then"
-Var_Parse: ${FAIL}else} (parse-only)
Modifier part: "${FAIL}else"
Result of ${DEFINED:?${FAIL}then:${FAIL}else} is "defined" (parse-only, regular)
Parsing line 166: .MAKEFLAGS: -d0
Index: src/usr.bin/make/unit-tests/varmod-loop.mk
diff -u src/usr.bin/make/unit-tests/varmod-loop.mk:1.19 src/usr.bin/make/unit-tests/varmod-loop.mk:1.20
--- src/usr.bin/make/unit-tests/varmod-loop.mk:1.19 Tue Aug 23 17:40:43 2022
+++ src/usr.bin/make/unit-tests/varmod-loop.mk Tue Aug 23 19:22:01 2022
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-loop.mk,v 1.19 2022/08/23 17:40:43 rillig Exp $
+# $NetBSD: varmod-loop.mk,v 1.20 2022/08/23 19:22:01 rillig Exp $
#
# Tests for the :@var@...${var}...@ variable modifier.
@@ -192,7 +192,8 @@ CMDLINE= global # needed for deleting t
# except for '$i', which is replaced with the then-current value '1' of the
# iteration variable.
#
-# FIXME: broken since var.c 1.1028 from 2022-08-08.
+# XXX: was broken in var.c 1.1028 from 2022-08-08, reverted in var.c 1.1029
+# from 2022-08-23; see parse-var.mk, keyword 'BRACE_GROUP'.
all: varmod-loop-literal-dollar
varmod-loop-literal-dollar: .PHONY
: ${:U1:@i@ t=$$(( $${t:-0} + $i ))@}
Index: src/usr.bin/make/unit-tests/varmod-defined.exp
diff -u src/usr.bin/make/unit-tests/varmod-defined.exp:1.12 src/usr.bin/make/unit-tests/varmod-defined.exp:1.13
--- src/usr.bin/make/unit-tests/varmod-defined.exp:1.12 Mon Aug 8 18:23:30 2022
+++ src/usr.bin/make/unit-tests/varmod-defined.exp Tue Aug 23 19:22:01 2022
@@ -10,7 +10,6 @@ Global: VAR = $$$$$$$$
Var_Parse: ${VAR:@var@${8_DOLLARS}@} (eval-keep-dollar-and-undefined)
Evaluating modifier ${VAR:@...} on value "$$$$$$$$" (eval-keep-dollar-and-undefined, regular)
Modifier part: "var"
-Var_Parse: ${8_DOLLARS}@} (parse-only)
Modifier part: "${8_DOLLARS}"
ModifyWords: split "$$$$$$$$" into 1 word
Global: var = $$$$$$$$
Index: src/usr.bin/make/unit-tests/varmod-loop.exp
diff -u src/usr.bin/make/unit-tests/varmod-loop.exp:1.16 src/usr.bin/make/unit-tests/varmod-loop.exp:1.17
--- src/usr.bin/make/unit-tests/varmod-loop.exp:1.16 Tue Aug 23 17:40:43 2022
+++ src/usr.bin/make/unit-tests/varmod-loop.exp Tue Aug 23 19:22:01 2022
@@ -13,6 +13,5 @@ mod-loop-dollar:$3$:
mod-loop-dollar:$${word}$$:
mod-loop-dollar:$$5$$:
mod-loop-dollar:$$${word}$$$:
-make: Unknown modifier "-0"
: t=$(( ${t:-0} + 1 ))
exit status 0