xref: /freebsd/contrib/bmake/unit-tests/varparse-errors.mk (revision 759b177aecbfc49ebc900739954ac56b1aa5fc53)
1# $NetBSD: varparse-errors.mk,v 1.24 2025/03/30 09:51:51 rillig Exp $
2
3# Tests for parsing and evaluating all kinds of expressions.
4#
5# This is the basis for redesigning the error handling in Var_Parse and
6# Var_Subst, collecting typical and not so typical use cases.
7#
8# See also:
9#	Var_Parse
10#	Var_Subst
11
12PLAIN=		plain value
13
14LITERAL_DOLLAR=	To get a dollar, double $$ it.
15
16INDIRECT=	An ${:Uindirect} value.
17
18REF_UNDEF=	A reference to an ${UNDEF}undefined variable.
19
20ERR_UNCLOSED=	An ${UNCLOSED expression.
21
22ERR_BAD_MOD=	An ${:Uindirect:Z} expression with an unknown modifier.
23
24ERR_EVAL=	An evaluation error ${:Uvalue:C,.,\3,}.
25
26# In a conditional, an expression that is not enclosed in quotes is
27# expanded using the mode VARE_EVAL_DEFINED.
28# The variable itself must be defined.
29# It may refer to undefined variables though.
30.if ${REF_UNDEF} != "A reference to an undefined variable."
31.  error
32.endif
33
34# As of 2020-12-01, errors in the variable name are silently ignored.
35# Since var.c 1.754 from 2020-12-20, unknown modifiers at parse time result
36# in an error message and a non-zero exit status.
37# expect+1: Unknown modifier ":Z"
38VAR.${:U:Z}=	unknown modifier in the variable name
39.if ${VAR.} != "unknown modifier in the variable name"
40.  error
41.endif
42
43# As of 2020-12-01, errors in the variable name are silently ignored.
44# Since var.c 1.754 from 2020-12-20, unknown modifiers at parse time result
45# in an error message and a non-zero exit status.
46# expect+1: Unknown modifier ":Z"
47VAR.${:U:Z}post=	unknown modifier with text in the variable name
48.if ${VAR.post} != "unknown modifier with text in the variable name"
49.  error
50.endif
51
52# Demonstrate an edge case in which the 'static' for 'errorReported' in
53# Var_Subst actually makes a difference, preventing "a plethora of messages".
54# Given that this is an edge case and the error message is wrong and thus
55# misleading anyway, that piece of code is probably not necessary.  The wrong
56# condition was added in var.c 1.185 from 2014-05-19.
57#
58# To trigger this difference, the variable assignment must use the assignment
59# operator ':=' to make VarEvalMode_ShouldKeepUndef return true.  There must
60# be 2 expressions that create a parse error, which in this case is ':OX'.
61# These expressions must be nested in some way.  The below expressions are
62# minimal, that is, removing any part of it destroys the effect.
63#
64# Without the 'static', there would be one more message like this:
65#	Undefined variable "${:U:OX"
66#
67#.MAKEFLAGS: -dv
68IND=	${:OX}
69# expect+4: Unknown modifier ":OX"
70# expect+3: Unknown modifier ":OX"
71# expect+2: Unknown modifier ":OX"
72# expect+1: Unknown modifier ":OX"
73_:=	${:U:OX:U${IND}} ${:U:OX:U${IND}}
74#.MAKEFLAGS: -d0
75
76
77# Before var.c 1.032 from 2022-08-24, make complained about 'Unknown modifier'
78# or 'Bad modifier' when in fact the modifier was entirely correct, it was
79# just not delimited by either ':' or '}' but instead by '\0'.
80# expect+1: Unclosed expression, expecting '}' for modifier "Q"
81UNCLOSED:=	${:U:Q
82# expect+1: Unclosed expression, expecting '}' for modifier "sh"
83UNCLOSED:=	${:U:sh
84# expect+1: Unclosed expression, expecting '}' for modifier "tA"
85UNCLOSED:=	${:U:tA
86# expect+1: Unclosed expression, expecting '}' for modifier "tsX"
87UNCLOSED:=	${:U:tsX
88# expect+1: Unclosed expression, expecting '}' for modifier "ts"
89UNCLOSED:=	${:U:ts
90# expect+1: Unclosed expression, expecting '}' for modifier "ts\040"
91UNCLOSED:=	${:U:ts\040
92# expect+1: Unclosed expression, expecting '}' for modifier "u"
93UNCLOSED:=	${:U:u
94# expect+1: Unclosed expression, expecting '}' for modifier "H"
95UNCLOSED:=	${:U:H
96# expect+1: Unclosed expression, expecting '}' for modifier "[1]"
97UNCLOSED:=	${:U:[1]
98# expect+1: Unclosed expression, expecting '}' for modifier "hash"
99UNCLOSED:=	${:U:hash
100# expect+1: Unclosed expression, expecting '}' for modifier "range"
101UNCLOSED:=	${:U:range
102# expect+1: Unclosed expression, expecting '}' for modifier "_"
103UNCLOSED:=	${:U:_
104# expect+1: Unclosed expression, expecting '}' for modifier "gmtime"
105UNCLOSED:=	${:U:gmtime
106# expect+1: Unclosed expression, expecting '}' for modifier "localtime"
107UNCLOSED:=	${:U:localtime
108
109
110# In a stack trace that has both evaluation details and included files, list
111# the current file twice: Once in the first line and once in the call
112# hierarchy. While this is redundant, omitting the current file from the
113# call hierarchy is more confusing, as the '.include' line does not contain
114# the faulty expression.
115#
116# expect: make: varparse-errors.tmp:1: Unknown modifier ":Z"
117# expect:	while evaluating "${:Z}" with value ""
118# expect:	while evaluating variable "INDIRECT" with value "${:Z}"
119# expect:	while evaluating variable "VALUE" with value "${INDIRECT}"
120# expect:	in varparse-errors.tmp:1
121# expect:	in varparse-errors.mk:126
122_!=	echo '.info $${VALUE}' > varparse-errors.tmp
123VALUE=	${INDIRECT}
124INDIRECT=	${:Z}
125# The "${.OBJDIR}/" is necessary to skip the directory cache.
126.include "${.OBJDIR}/varparse-errors.tmp"
127_!=	rm -f varparse-errors.tmp
128