var-op-expand.mk revision 1.10 1 1.10 rillig # $NetBSD: var-op-expand.mk,v 1.10 2020/12/28 00:19:41 rillig Exp $
2 1.1 rillig #
3 1.2 rillig # Tests for the := variable assignment operator, which expands its
4 1.2 rillig # right-hand side.
5 1.1 rillig
6 1.5 rillig
7 1.5 rillig # If the right-hand side does not contain a dollar sign, the ':=' assignment
8 1.5 rillig # operator has the same effect as the '=' assignment operator.
9 1.5 rillig VAR:= value
10 1.5 rillig .if ${VAR} != "value"
11 1.5 rillig . error
12 1.5 rillig .endif
13 1.5 rillig
14 1.5 rillig # When a ':=' assignment is performed, its right-hand side is evaluated and
15 1.5 rillig # expanded as far as possible. Contrary to other situations, '$$' and
16 1.5 rillig # variable expressions based on undefined variables are preserved though.
17 1.5 rillig #
18 1.5 rillig # Whether a variable expression is undefined or not is determined at the end
19 1.5 rillig # of evaluating the expression. The consequence is that ${:Ufallback} expands
20 1.5 rillig # to "fallback"; initially this expression is undefined since it is based on
21 1.5 rillig # the variable named "", which is guaranteed to be never defined, but at the
22 1.5 rillig # end of evaluating the expression ${:Ufallback}, the modifier ':U' has turned
23 1.5 rillig # the expression into a defined expression.
24 1.5 rillig
25 1.5 rillig
26 1.5 rillig # literal dollar signs
27 1.5 rillig VAR:= $$ $$$$ $$$$$$$$
28 1.5 rillig .if ${VAR} != "\$ \$\$ \$\$\$\$"
29 1.5 rillig . error
30 1.5 rillig .endif
31 1.5 rillig
32 1.5 rillig
33 1.5 rillig # reference to a variable containing a literal dollar sign
34 1.5 rillig REF= $$ $$$$ $$$$$$$$
35 1.5 rillig VAR:= ${REF}
36 1.5 rillig REF= too late
37 1.5 rillig .if ${VAR} != "\$ \$\$ \$\$\$\$"
38 1.5 rillig . error
39 1.5 rillig .endif
40 1.5 rillig
41 1.5 rillig
42 1.5 rillig # reference to an undefined variable
43 1.5 rillig .undef UNDEF
44 1.5 rillig VAR:= <${UNDEF}>
45 1.5 rillig UNDEF= after
46 1.5 rillig .if ${VAR} != "<after>"
47 1.5 rillig . error
48 1.5 rillig .endif
49 1.5 rillig
50 1.5 rillig
51 1.5 rillig # reference to a variable whose name is computed from another variable
52 1.5 rillig REF2= referred to
53 1.5 rillig REF= REF2
54 1.5 rillig VAR:= ${${REF}}
55 1.5 rillig REF= too late
56 1.5 rillig .if ${VAR} != "referred to"
57 1.5 rillig . error
58 1.5 rillig .endif
59 1.5 rillig
60 1.5 rillig
61 1.5 rillig # expression with an indirect modifier referring to an undefined variable
62 1.5 rillig .undef UNDEF
63 1.5 rillig VAR:= ${:${UNDEF}}
64 1.5 rillig UNDEF= Uwas undefined
65 1.5 rillig .if ${VAR} != "was undefined"
66 1.5 rillig . error
67 1.5 rillig .endif
68 1.5 rillig
69 1.5 rillig
70 1.5 rillig # expression with an indirect modifier referring to another variable that
71 1.5 rillig # in turn refers to an undefined variable
72 1.5 rillig #
73 1.5 rillig # XXX: Even though this is a ':=' assignment, the '${UNDEF}' in the part of
74 1.5 rillig # the variable modifier is not preserved. To preserve it, ParseModifierPart
75 1.5 rillig # would have to call VarSubstExpr somehow since this is the only piece of
76 1.5 rillig # code that takes care of this global variable.
77 1.5 rillig .undef UNDEF
78 1.5 rillig REF= U${UNDEF}
79 1.5 rillig #.MAKEFLAGS: -dv
80 1.5 rillig VAR:= ${:${REF}}
81 1.5 rillig #.MAKEFLAGS: -d0
82 1.5 rillig REF= too late
83 1.5 rillig UNDEF= Uwas undefined
84 1.5 rillig .if ${VAR} != ""
85 1.5 rillig . error
86 1.5 rillig .endif
87 1.5 rillig
88 1.1 rillig
89 1.6 rillig # In variable assignments using the ':=' operator, undefined variables are
90 1.6 rillig # preserved, no matter how indirectly they are referenced.
91 1.6 rillig .undef REF3
92 1.6 rillig REF2= <${REF3}>
93 1.6 rillig REF= ${REF2}
94 1.6 rillig VAR:= ${REF}
95 1.6 rillig REF3= too late
96 1.6 rillig .if ${VAR} != "<too late>"
97 1.6 rillig . error
98 1.6 rillig .endif
99 1.6 rillig
100 1.6 rillig
101 1.6 rillig # In variable assignments using the ':=' operator, '$$' are preserved, no
102 1.6 rillig # matter how indirectly they are referenced.
103 1.6 rillig REF2= REF2:$$ $$$$
104 1.6 rillig REF= REF:$$ $$$$ ${REF2}
105 1.6 rillig VAR:= VAR:$$ $$$$ ${REF}
106 1.6 rillig .if ${VAR} != "VAR:\$ \$\$ REF:\$ \$\$ REF2:\$ \$\$"
107 1.6 rillig . error
108 1.6 rillig .endif
109 1.6 rillig
110 1.6 rillig
111 1.6 rillig # In variable assignments using the ':=' operator, '$$' are preserved in the
112 1.6 rillig # expressions of the top level, but not in expressions that are nested.
113 1.6 rillig VAR:= top:$$ ${:Unest1\:\$\$} ${:Unest2${:U\:\$\$}}
114 1.6 rillig .if ${VAR} != "top:\$ nest1:\$ nest2:\$"
115 1.6 rillig . error
116 1.6 rillig .endif
117 1.6 rillig
118 1.6 rillig
119 1.9 rillig # In variable assignments using the ':=' operator, there may be expressions
120 1.9 rillig # containing variable modifiers, and these modifiers may refer to other
121 1.10 rillig # variables. These referred-to variables are expanded at the time of
122 1.10 rillig # assignment. The undefined variables are kept as-is and are later expanded
123 1.10 rillig # when evaluating the condition.
124 1.9 rillig #
125 1.9 rillig # Contrary to the assignment operator '=', the assignment operator ':='
126 1.9 rillig # consumes the '$' from modifier parts.
127 1.9 rillig REF.word= 1:$$ 2:$$$$ 4:$$$$$$$$
128 1.10 rillig .undef REF.undef
129 1.10 rillig VAR:= ${:Uword undef:@word@${REF.${word}}@}, direct: ${REF.word} ${REF.undef}
130 1.10 rillig REF.word= word.after
131 1.10 rillig REF.undef= undef.after
132 1.10 rillig .if ${VAR} != "1:2:\$ 4:\$\$ undef.after, direct: 1:\$ 2:\$\$ 4:\$\$\$\$ undef.after"
133 1.9 rillig . error
134 1.9 rillig .endif
135 1.9 rillig
136 1.9 rillig # Just for comparison, the previous example using the assignment operator '='
137 1.10 rillig # instead of ':='. The right-hand side of the assignment is not evaluated at
138 1.10 rillig # the time of assignment but only later, when ${VAR} appears in the condition.
139 1.10 rillig #
140 1.10 rillig # At that point, both REF.word and REF.undef are defined.
141 1.9 rillig REF.word= 1:$$ 2:$$$$ 4:$$$$$$$$
142 1.10 rillig .undef REF.undef
143 1.10 rillig VAR= ${:Uword undef:@word@${REF.${word}}@}, direct: ${REF.word} ${REF.undef}
144 1.10 rillig REF.word= word.after
145 1.10 rillig REF.undef= undef.after
146 1.10 rillig .if ${VAR} != "word.after undef.after, direct: word.after undef.after"
147 1.9 rillig . error
148 1.9 rillig .endif
149 1.9 rillig
150 1.9 rillig
151 1.8 rillig # Between var.c 1.42 from 2000-05-11 and before parse.c 1.520 from 2020-12-27,
152 1.8 rillig # if the variable name in a ':=' assignment referred to an undefined variable,
153 1.8 rillig # there were actually 2 assignments to different variables:
154 1.8 rillig #
155 1.8 rillig # Global["VAR_SUBST_${UNDEF}"] = ""
156 1.8 rillig # Global["VAR_SUBST_"] = ""
157 1.8 rillig #
158 1.8 rillig # The variable name with the empty value actually included a dollar sign.
159 1.8 rillig # Variable names with dollars are not used in practice.
160 1.8 rillig #
161 1.8 rillig # It might be a good idea to forbid undefined variables on the left-hand side
162 1.8 rillig # of a variable assignment.
163 1.5 rillig .undef UNDEF
164 1.7 rillig VAR_ASSIGN_${UNDEF}= assigned by '='
165 1.7 rillig VAR_SUBST_${UNDEF}:= assigned by ':='
166 1.7 rillig .if ${VAR_ASSIGN_} != "assigned by '='"
167 1.7 rillig . error
168 1.7 rillig .endif
169 1.8 rillig .if defined(${:UVAR_SUBST_\${UNDEF\}})
170 1.7 rillig . error
171 1.7 rillig .endif
172 1.7 rillig .if ${VAR_SUBST_} != "assigned by ':='"
173 1.7 rillig . error
174 1.7 rillig .endif
175 1.3 rillig
176 1.1 rillig all:
177 1.1 rillig @:;
178