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