Module Name: src
Committed By: rillig
Date: Sun Jun 30 13:01:01 UTC 2024
Modified Files:
src/usr.bin/make: var.c
src/usr.bin/make/unit-tests: cond-late.exp cond-late.mk
varmod-ifelse.exp varmod-ifelse.mk
Log Message:
make: error out on syntax error in conditions in ':?then:else' modifier
The 'Error' function only reports errors but does not affect the exit
status, the 'Parse_Error' function does, while providing more details to
find the cause of the syntax error.
To generate a diff of this commit:
cvs rdiff -u -r1.1123 -r1.1124 src/usr.bin/make/var.c
cvs rdiff -u -r1.5 -r1.6 src/usr.bin/make/unit-tests/cond-late.exp
cvs rdiff -u -r1.6 -r1.7 src/usr.bin/make/unit-tests/cond-late.mk
cvs rdiff -u -r1.20 -r1.21 src/usr.bin/make/unit-tests/varmod-ifelse.exp
cvs rdiff -u -r1.29 -r1.30 src/usr.bin/make/unit-tests/varmod-ifelse.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/var.c
diff -u src/usr.bin/make/var.c:1.1123 src/usr.bin/make/var.c:1.1124
--- src/usr.bin/make/var.c:1.1123 Sun Jun 30 11:44:14 2024
+++ src/usr.bin/make/var.c Sun Jun 30 13:01:01 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.1123 2024/06/30 11:44:14 rillig Exp $ */
+/* $NetBSD: var.c,v 1.1124 2024/06/30 13:01:01 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -132,7 +132,7 @@
#include "metachar.h"
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.1123 2024/06/30 11:44:14 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.1124 2024/06/30 13:01:01 rillig Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -262,6 +262,9 @@ typedef struct SepBuf {
typedef enum {
VSK_TARGET,
VSK_VARNAME,
+ VSK_COND,
+ VSK_COND_THEN,
+ VSK_COND_ELSE,
VSK_EXPR
} EvalStackElementKind;
@@ -375,11 +378,17 @@ EvalStack_Details(void)
buf->len = 0;
for (i = 0; i < evalStack.len; i++) {
+ static const char descr[][42] = {
+ "in target",
+ "while evaluating variable",
+ "while evaluating condition",
+ "while evaluating then-branch of condition",
+ "while evaluating else-branch of condition",
+ "while evaluating",
+ };
EvalStackElement *elem = evalStack.elems + i;
- Buf_AddStr(buf,
- elem->kind == VSK_TARGET ? "in target \"" :
- elem->kind == VSK_EXPR ? "while evaluating \"" :
- "while evaluating variable \"");
+ Buf_AddStr(buf, descr[elem->kind]);
+ Buf_AddStr(buf, " \"");
Buf_AddStr(buf, elem->str);
Buf_AddStr(buf, "\": ");
}
@@ -3443,6 +3452,7 @@ ApplyModifier_IfElse(const char **pp, Mo
CondResult cond_rc = CR_TRUE; /* just not CR_ERROR */
if (Expr_ShouldEval(expr)) {
+ evalStack.elems[evalStack.len - 1].kind = VSK_COND;
cond_rc = Cond_EvalCondition(expr->name);
if (cond_rc == CR_TRUE)
then_emode = expr->emode;
@@ -3450,11 +3460,13 @@ ApplyModifier_IfElse(const char **pp, Mo
else_emode = expr->emode;
}
+ evalStack.elems[evalStack.len - 1].kind = VSK_COND_THEN;
(*pp)++; /* skip past the '?' */
if (!ParseModifierPart(pp, ':', ':', then_emode,
ch, &thenBuf, NULL, NULL))
return AMR_CLEANUP;
+ evalStack.elems[evalStack.len - 1].kind = VSK_COND_ELSE;
if (!ParseModifierPart(pp, ch->endc, ch->endc, else_emode,
ch, &elseBuf, NULL, NULL)) {
LazyBuf_Done(&thenBuf);
@@ -3464,12 +3476,8 @@ ApplyModifier_IfElse(const char **pp, Mo
(*pp)--; /* Go back to the ch->endc. */
if (cond_rc == CR_ERROR) {
- Substring thenExpr = LazyBuf_Get(&thenBuf);
- Substring elseExpr = LazyBuf_Get(&elseBuf);
- Error("Bad conditional expression '%s' before '?%.*s:%.*s'",
- expr->name,
- (int)Substring_Length(thenExpr), thenExpr.start,
- (int)Substring_Length(elseExpr), elseExpr.start);
+ evalStack.elems[evalStack.len - 1].kind = VSK_COND;
+ Parse_Error(PARSE_FATAL, "Bad condition");
LazyBuf_Done(&thenBuf);
LazyBuf_Done(&elseBuf);
return AMR_CLEANUP;
Index: src/usr.bin/make/unit-tests/cond-late.exp
diff -u src/usr.bin/make/unit-tests/cond-late.exp:1.5 src/usr.bin/make/unit-tests/cond-late.exp:1.6
--- src/usr.bin/make/unit-tests/cond-late.exp:1.5 Sun Dec 10 20:12:28 2023
+++ src/usr.bin/make/unit-tests/cond-late.exp Sun Jun 30 13:01:01 2024
@@ -1,4 +1,6 @@
-make: Bad conditional expression ' != "no"' before '?:'
+make: "cond-late.mk" line 38: while evaluating variable "VAR": while evaluating condition " != "no"": Bad condition
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
yes
no
exit status 0
Index: src/usr.bin/make/unit-tests/cond-late.mk
diff -u src/usr.bin/make/unit-tests/cond-late.mk:1.6 src/usr.bin/make/unit-tests/cond-late.mk:1.7
--- src/usr.bin/make/unit-tests/cond-late.mk:1.6 Sun Dec 10 20:12:28 2023
+++ src/usr.bin/make/unit-tests/cond-late.mk Sun Jun 30 13:01:01 2024
@@ -1,4 +1,4 @@
-# $NetBSD: cond-late.mk,v 1.6 2023/12/10 20:12:28 rillig Exp $
+# $NetBSD: cond-late.mk,v 1.7 2024/06/30 13:01:01 rillig Exp $
#
# Using the :? modifier, expressions can contain conditional
# expressions that are evaluated late, at expansion time.
@@ -15,7 +15,10 @@
# actually interpreted as these operators. This is demonstrated below.
#
-all: cond-literal
+all: parse-time cond-literal
+
+parse-time: .PHONY
+ @${MAKE} -f ${MAKEFILE} do-parse-time || true
COND.true= "yes" == "yes"
COND.false= "yes" != "yes"
@@ -29,8 +32,9 @@ cond-literal:
@echo ${ ${COND.true} :?yes:no}
@echo ${ ${COND.false} :?yes:no}
+.if make(do-parse-time)
VAR= ${${UNDEF} != "no":?:}
-# expect-reset
-# expect: make: Bad conditional expression ' != "no"' before '?:'
-.if empty(VAR:Mpattern)
+# expect+1: while evaluating variable "VAR": while evaluating condition " != "no"": Bad condition
+. if empty(VAR:Mpattern)
+. endif
.endif
Index: src/usr.bin/make/unit-tests/varmod-ifelse.exp
diff -u src/usr.bin/make/unit-tests/varmod-ifelse.exp:1.20 src/usr.bin/make/unit-tests/varmod-ifelse.exp:1.21
--- src/usr.bin/make/unit-tests/varmod-ifelse.exp:1.20 Sat Apr 20 10:18:55 2024
+++ src/usr.bin/make/unit-tests/varmod-ifelse.exp Sun Jun 30 13:01:01 2024
@@ -1,32 +1,32 @@
-make: Bad conditional expression 'bare words == "literal"' before '?bad:bad'
-make: "varmod-ifelse.mk" line 28: Malformed conditional (${${:Ubare words} == "literal":?bad:bad})
-make: Bad conditional expression ' == ""' before '?bad-assign:bad-assign'
-make: Bad conditional expression ' == ""' before '?bad-cond:bad-cond'
-make: "varmod-ifelse.mk" line 46: Malformed conditional (${${UNDEF} == "":?bad-cond:bad-cond})
-make: Bad conditional expression '1 == == 2' before '?yes:no'
-make: "varmod-ifelse.mk" line 69: Malformed conditional (${1 == == 2:?yes:no} != "")
+make: "varmod-ifelse.mk" line 29: while evaluating condition "bare words == "literal"": Bad condition
+make: "varmod-ifelse.mk" line 29: Malformed conditional (${${:Ubare words} == "literal":?bad:bad})
+make: "varmod-ifelse.mk" line 40: while evaluating condition " == """: Bad condition
+make: "varmod-ifelse.mk" line 49: while evaluating condition " == """: Bad condition
+make: "varmod-ifelse.mk" line 49: Malformed conditional (${${UNDEF} == "":?bad-cond:bad-cond})
+make: "varmod-ifelse.mk" line 73: while evaluating condition "1 == == 2": Bad condition
+make: "varmod-ifelse.mk" line 73: Malformed conditional (${1 == == 2:?yes:no} != "")
CondParser_Eval: "${1 == == 2:?yes:no}" != ""
CondParser_Eval: 1 == == 2
Comparing 1.000000 == 0.000000
-make: Bad conditional expression '1 == == 2' before '?yes:no'
+make: "varmod-ifelse.mk" line 97: while evaluating condition "1 == == 2": Bad condition
Comparing "" != ""
-make: "varmod-ifelse.mk" line 96: warning: Oops, the parse error should have been propagated.
+make: "varmod-ifelse.mk" line 101: warning: Oops, the parse error should have been propagated.
CondParser_Eval: ${ ${:U\$}{VAR} == value:?ok:bad} != "ok"
CondParser_Eval: ${VAR} == value
Comparing "value" == "value"
Comparing "ok" != "ok"
-make: "varmod-ifelse.mk" line 158: no.
-make: "varmod-ifelse.mk" line 162: while evaluating variable "string == "literal" || no >= 10": Comparison with '>=' requires both operands 'no' and '10' to be numeric
-make: Bad conditional expression 'string == "literal" || no >= 10' before '?yes:no'
-make: "varmod-ifelse.mk" line 162: .
-make: Bad conditional expression 'string == "literal" && >= 10' before '?yes:no'
-make: "varmod-ifelse.mk" line 169: .
-make: Bad conditional expression 'string == "literal" || >= 10' before '?yes:no'
-make: "varmod-ifelse.mk" line 172: .
-make: "varmod-ifelse.mk" line 180: <true>
-make: "varmod-ifelse.mk" line 183: <false>
-make: Bad conditional expression ' ' before '?true:false'
-make: "varmod-ifelse.mk" line 186: <>
+make: "varmod-ifelse.mk" line 163: no.
+make: "varmod-ifelse.mk" line 167: while evaluating condition "string == "literal" || no >= 10": Comparison with '>=' requires both operands 'no' and '10' to be numeric
+make: "varmod-ifelse.mk" line 167: while evaluating condition "string == "literal" || no >= 10": Bad condition
+make: "varmod-ifelse.mk" line 167: .
+make: "varmod-ifelse.mk" line 174: while evaluating condition "string == "literal" && >= 10": Bad condition
+make: "varmod-ifelse.mk" line 174: .
+make: "varmod-ifelse.mk" line 177: while evaluating condition "string == "literal" || >= 10": Bad condition
+make: "varmod-ifelse.mk" line 177: .
+make: "varmod-ifelse.mk" line 185: <true>
+make: "varmod-ifelse.mk" line 188: <false>
+make: "varmod-ifelse.mk" line 192: while evaluating condition " ": Bad condition
+make: "varmod-ifelse.mk" line 192: <>
CondParser_Eval: 0 && ${1:?${:Uthen0:S,}},,}:${:Uelse0:S,}},,}} != "not evaluated"
CondParser_Eval: 1 && ${0:?${:Uthen1:S,}},,}:${:Uelse1:S,}},,}} != "else1"
CondParser_Eval: 0
@@ -36,16 +36,18 @@ CondParser_Eval: 1
Comparing "then2" != "then2"
CondParser_Eval: ${DELAYED} == "one"
Comparing "two" == "one"
-make: "varmod-ifelse.mk" line 282: no
+make: "varmod-ifelse.mk" line 288: no
CondParser_Eval: ${DELAYED} == "two"
Comparing "two" == "two"
-make: "varmod-ifelse.mk" line 284: yes
+make: "varmod-ifelse.mk" line 290: yes
CondParser_Eval: ${DELAYED} == "one"
Comparing "two" == "one"
-make: "varmod-ifelse.mk" line 287: no
+make: "varmod-ifelse.mk" line 293: no
CondParser_Eval: ${DELAYED} == "two"
Comparing "two" == "two"
-make: "varmod-ifelse.mk" line 290: yes
+make: "varmod-ifelse.mk" line 296: yes
+make: "varmod-ifelse.mk" line 318: while evaluating then-branch of condition "1": while evaluating "${:X-then}:${:X-else}}": Unknown modifier "X-then"
+make: "varmod-ifelse.mk" line 318: while evaluating else-branch of condition "1": while evaluating "${:X-else}}": Unknown modifier "X-else"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
Index: src/usr.bin/make/unit-tests/varmod-ifelse.mk
diff -u src/usr.bin/make/unit-tests/varmod-ifelse.mk:1.29 src/usr.bin/make/unit-tests/varmod-ifelse.mk:1.30
--- src/usr.bin/make/unit-tests/varmod-ifelse.mk:1.29 Sun Jun 2 15:31:26 2024
+++ src/usr.bin/make/unit-tests/varmod-ifelse.mk Sun Jun 30 13:01:01 2024
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-ifelse.mk,v 1.29 2024/06/02 15:31:26 rillig Exp $
+# $NetBSD: varmod-ifelse.mk,v 1.30 2024/06/30 13:01:01 rillig Exp $
#
# Tests for the ${cond:?then:else} variable modifier, which evaluates either
# the then-expression or the else-expression, depending on the condition.
@@ -24,6 +24,7 @@
# Evaluating the variable name lazily would require additional code in
# Var_Parse and ParseVarname, it would be more useful and predictable
# though.
+# expect+2: while evaluating condition "bare words == "literal"": Bad condition
# expect+1: Malformed conditional (${${:Ubare words} == "literal":?bad:bad})
.if ${${:Ubare words} == "literal":?bad:bad}
. error
@@ -35,6 +36,7 @@
# Because of the early expansion, the whole condition evaluates to
# ' == ""' though, which cannot be parsed because the left-hand side looks
# empty.
+# expect+1: while evaluating condition " == """: Bad condition
COND:= ${${UNDEF} == "":?bad-assign:bad-assign}
# In a condition, undefined variables generate a "Malformed conditional"
@@ -42,6 +44,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-
# "Undefined variable" error message is generated.
# The difference to the ':=' variable assignment is the additional
# "Malformed conditional" error message.
+# expect+2: while evaluating condition " == """: Bad condition
# expect+1: Malformed conditional (${${UNDEF} == "":?bad-cond:bad-cond})
.if ${${UNDEF} == "":?bad-cond:bad-cond}
. error
@@ -65,6 +68,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-
# conditional therefore returns a parse error from Var_Parse, and this parse
# error propagates to CondEvalExpression, where the "Malformed conditional"
# comes from.
+# expect+2: while evaluating condition "1 == == 2": Bad condition
# expect+1: Malformed conditional (${1 == == 2:?yes:no} != "")
.if ${1 == == 2:?yes:no} != ""
. error
@@ -89,6 +93,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-
# condition should be detected as being malformed before any comparison is
# done since there is no well-formed comparison in the condition at all.
.MAKEFLAGS: -dc
+# expect+1: while evaluating condition "1 == == 2": Bad condition
.if "${1 == == 2:?yes:no}" != ""
. error
.else
@@ -156,18 +161,18 @@ STRING= string
NUMBER= no # not really a number
# expect+1: no.
.info ${${STRING} == "literal" && ${NUMBER} >= 10:?yes:no}.
-# expect+3: while evaluating variable "string == "literal" || no >= 10": Comparison with '>=' requires both operands 'no' and '10' to be numeric
-# expect: make: Bad conditional expression 'string == "literal" || no >= 10' before '?yes:no'
+# expect+3: while evaluating condition "string == "literal" || no >= 10": Comparison with '>=' requires both operands 'no' and '10' to be numeric
+# expect+2: while evaluating condition "string == "literal" || no >= 10": Bad condition
# expect+1: .
.info ${${STRING} == "literal" || ${NUMBER} >= 10:?yes:no}.
# The following situation occasionally occurs with MKINET6 or similar
# variables.
NUMBER= # empty, not really a number either
-# expect: make: Bad conditional expression 'string == "literal" && >= 10' before '?yes:no'
+# expect+2: while evaluating condition "string == "literal" && >= 10": Bad condition
# expect+1: .
.info ${${STRING} == "literal" && ${NUMBER} >= 10:?yes:no}.
-# expect: make: Bad conditional expression 'string == "literal" || >= 10' before '?yes:no'
+# expect+2: while evaluating condition "string == "literal" || >= 10": Bad condition
# expect+1: .
.info ${${STRING} == "literal" || ${NUMBER} >= 10:?yes:no}.
@@ -182,6 +187,7 @@ EMPTY= # empty
# expect+1: <false>
.info <${${ASTERISK} :?true:false}>
# syntax error since the condition is completely blank.
+# expect+2: while evaluating condition " ": Bad condition
# expect+1: <>
.info <${${EMPTY} :?true:false}>
@@ -305,3 +311,9 @@ BOTH= <${YES}> <${NO}>
.if ${BOTH} != "<yes> <no>"
. error
.endif
+
+
+# expect+2: while evaluating then-branch of condition "1": while evaluating "${:X-then}:${:X-else}}": Unknown modifier "X-then"
+# expect+1: while evaluating else-branch of condition "1": while evaluating "${:X-else}}": Unknown modifier "X-else"
+.if ${1:?${:X-then}:${:X-else}}
+.endif