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