xref: /freebsd/contrib/bmake/unit-tests/varmod-remember.mk (revision dc1b8c9a846e78a87789fe1473350c3260722148)
1*dc1b8c9aSSimon J. Gerraty# $NetBSD: varmod-remember.mk,v 1.9 2023/02/09 22:21:57 rillig Exp $
22c3632d1SSimon J. Gerraty#
3*dc1b8c9aSSimon J. Gerraty# Tests for the :_ modifier, which saves the current expression value
42c3632d1SSimon J. Gerraty# in the _ variable or another, to be used later again.
52c3632d1SSimon J. Gerraty
6*dc1b8c9aSSimon J. Gerraty
7*dc1b8c9aSSimon J. Gerraty# The ':_' modifier is typically used in situations where the value of an
8*dc1b8c9aSSimon J. Gerraty# expression is needed at the same time as a sequence of numbers.  In these
9*dc1b8c9aSSimon J. Gerraty# cases, the value of the expression is saved in the temporary variable '_',
10*dc1b8c9aSSimon J. Gerraty# from where it is taken later in the same expression.
11*dc1b8c9aSSimon J. GerratyABC=	${A B C:L:_:range:@i@$i=${_:[$i]}@}
12*dc1b8c9aSSimon J. GerratyDEF=	${D E F:L:_:range:@i@$i=${_:[$i]}@}
13*dc1b8c9aSSimon J. GerratyGHI=	${G H I:L:_:range:@i@$i=${_:[$i]}@}
14*dc1b8c9aSSimon J. Gerraty
15*dc1b8c9aSSimon J. GerratyABC.global:=	${ABC}		# is evaluated in the global scope
16*dc1b8c9aSSimon J. Gerraty.if ${ABC.global} != "1=A 2=B 3=C"
17b0c40a00SSimon J. Gerraty.  error
18b0c40a00SSimon J. Gerraty.endif
19b0c40a00SSimon J. Gerraty
20*dc1b8c9aSSimon J. Gerraty.if ${DEF} != "1=D 2=E 3=F"	# is evaluated in the command line scope
21*dc1b8c9aSSimon J. Gerraty.  error
22*dc1b8c9aSSimon J. Gerraty.endif
23*dc1b8c9aSSimon J. Gerraty
24*dc1b8c9aSSimon J. Gerraty# Before var.c 1.1040 from 2023-02-09, the temporary variable '_' was placed
25*dc1b8c9aSSimon J. Gerraty# in the scope of the current evaluation, which meant that after the first
26*dc1b8c9aSSimon J. Gerraty# ':_' modifier had been evaluated in command line scope, all further
27*dc1b8c9aSSimon J. Gerraty# evaluations in global scope could not overwrite the variable '_' anymore,
28*dc1b8c9aSSimon J. Gerraty# as the command line scope takes precedence over the global scope.
29*dc1b8c9aSSimon J. Gerraty# The expression ${GHI} therefore evaluated to '1=D 2=E 3=F', reusing the
30*dc1b8c9aSSimon J. Gerraty# value of '_' from the previous evaluation in command line scope.
31*dc1b8c9aSSimon J. GerratyGHI.global:=	${GHI}		# is evaluated in the global scope
32*dc1b8c9aSSimon J. Gerraty.if ${GHI.global} != "1=G 2=H 3=I"
33*dc1b8c9aSSimon J. Gerraty.  error
34*dc1b8c9aSSimon J. Gerraty.endif
35*dc1b8c9aSSimon J. Gerraty
36*dc1b8c9aSSimon J. Gerraty
372c3632d1SSimon J. Gerraty# In the parameterized form, having the variable name on the right side of
38*dc1b8c9aSSimon J. Gerraty# the = assignment operator looks confusing.  In almost all other situations,
39*dc1b8c9aSSimon J. Gerraty# the variable name is on the left-hand side of the = operator, therefore
40*dc1b8c9aSSimon J. Gerraty# '_=SAVED' looks like it would copy 'SAVED' to '_'.  Luckily, this modifier
41*dc1b8c9aSSimon J. Gerraty# is only rarely needed.
42b0c40a00SSimon J. Gerraty.if ${1 2 3:L:@var@${var:_=SAVED:}@} != "1 2 3"
43b0c40a00SSimon J. Gerraty.  error
44b0c40a00SSimon J. Gerraty.elif ${SAVED} != "3"
45b0c40a00SSimon J. Gerraty.  error
46b0c40a00SSimon J. Gerraty.endif
47b0c40a00SSimon J. Gerraty
48*dc1b8c9aSSimon J. Gerraty
49*dc1b8c9aSSimon J. Gerraty# The ':_' modifier takes a variable name as optional argument.  Before var.c
50*dc1b8c9aSSimon J. Gerraty# 1.867 from 2021-03-14, this variable name could refer to other variables,
51*dc1b8c9aSSimon J. Gerraty# such as in 'VAR.$p'.  It was not possible to refer to 'VAR.${param}' though,
52*dc1b8c9aSSimon J. Gerraty# as that form caused a parse error.  The cause for the parse error in
53*dc1b8c9aSSimon J. Gerraty# '${...:_=VAR.${param}}' is that the variable name is parsed in an ad-hoc
54*dc1b8c9aSSimon J. Gerraty# manner, stopping at the first ':', ')' or '}', without taking any nested
55*dc1b8c9aSSimon J. Gerraty# expressions into account.  Due to this inconsistency that short expressions
56*dc1b8c9aSSimon J. Gerraty# are possible but long expressions aren't, the name of the temporary variable
57*dc1b8c9aSSimon J. Gerraty# is no longer expanded.
58b0c40a00SSimon J. Gerraty#
59*dc1b8c9aSSimon J. Gerraty# TODO: Warn about the unusual variable name '$S'.
60b0c40a00SSimon J. GerratyS=	INDIRECT_VARNAME
61b0c40a00SSimon J. Gerraty.if ${value:L:@var@${var:_=$S}@} != "value"
62b0c40a00SSimon J. Gerraty.  error
63b0c40a00SSimon J. Gerraty.elif defined(INDIRECT_VARNAME)
64b0c40a00SSimon J. Gerraty.  error
65b0c40a00SSimon J. Gerraty.endif
66b0c40a00SSimon J. Gerraty
67*dc1b8c9aSSimon J. Gerraty
68*dc1b8c9aSSimon J. Gerraty# When a variable using ':_' refers to another variable that also uses ':_',
69*dc1b8c9aSSimon J. Gerraty# the value of the temporary variable '_' from the inner expression leaks into
70*dc1b8c9aSSimon J. Gerraty# the evaluation of the outer expression.  If the expressions were evaluated
71*dc1b8c9aSSimon J. Gerraty# independently, the last word of the result would be outer_='outer' instead.
72*dc1b8c9aSSimon J. GerratyINNER=	${inner:L:_:@i@$i inner_='$_'@}
73*dc1b8c9aSSimon J. GerratyOUTER=	${outer:L:_:@o@$o ${INNER} outer_='$_'@}
74*dc1b8c9aSSimon J. Gerraty.if ${OUTER} != "outer inner inner_='inner' outer_='inner'"
75*dc1b8c9aSSimon J. Gerraty.endif
76*dc1b8c9aSSimon J. Gerraty
77*dc1b8c9aSSimon J. Gerraty
782c3632d1SSimon J. Gerratyall:
79