varmisc.mk revision 1.37 1 1.37 rillig # $NetBSD: varmisc.mk,v 1.37 2024/08/29 20:20:36 rillig Exp $
2 1.1 apb #
3 1.1 apb # Miscellaneous variable tests.
4 1.1 apb
5 1.6 sjg all: unmatched_var_paren D_true U_true D_false U_false Q_lhs Q_rhs NQ_none \
6 1.33 rillig cmpv
7 1.12 rillig all: save-dollars
8 1.14 rillig all: export-appended
9 1.15 rillig all: parse-dynamic
10 1.36 rillig all: varerror-unclosed-{1,2,3,4,5,6,7,8}
11 1.1 apb
12 1.1 apb unmatched_var_paren:
13 1.2 sjg @echo ${foo::=foo-text}
14 1.3 sjg
15 1.26 rillig True= ${echo true >&2:L:sh}TRUE
16 1.26 rillig False= ${echo false >&2:L:sh}FALSE
17 1.3 sjg
18 1.26 rillig VSET= is set
19 1.3 sjg .undef UNDEF
20 1.3 sjg
21 1.3 sjg U_false:
22 1.3 sjg @echo :U skipped when var set
23 1.3 sjg @echo ${VSET:U${False}}
24 1.3 sjg
25 1.3 sjg D_false:
26 1.3 sjg @echo :D skipped if var undef
27 1.3 sjg @echo ${UNDEF:D${False}}
28 1.3 sjg
29 1.3 sjg U_true:
30 1.3 sjg @echo :U expanded when var undef
31 1.3 sjg @echo ${UNDEF:U${True}}
32 1.3 sjg
33 1.3 sjg D_true:
34 1.3 sjg @echo :D expanded when var set
35 1.3 sjg @echo ${VSET:D${True}}
36 1.3 sjg
37 1.3 sjg Q_lhs:
38 1.3 sjg @echo :? only lhs when value true
39 1.3 sjg @echo ${1:L:?${True}:${False}}
40 1.3 sjg
41 1.3 sjg Q_rhs:
42 1.3 sjg @echo :? only rhs when value false
43 1.3 sjg @echo ${0:L:?${True}:${False}}
44 1.5 sjg
45 1.5 sjg NQ_none:
46 1.5 sjg @echo do not evaluate or expand :? if discarding
47 1.5 sjg @echo ${VSET:U${1:L:?${True}:${False}}}
48 1.6 sjg
49 1.7 sjg # big jumps to handle 3 digits per step
50 1.26 rillig M_cmpv.units= 1 1000 1000000
51 1.26 rillig M_cmpv= S,., ,g:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh
52 1.7 sjg
53 1.26 rillig Version= 123.456.789
54 1.26 rillig cmpv.only= target specific vars
55 1.7 sjg
56 1.7 sjg cmpv:
57 1.7 sjg @echo Version=${Version} == ${Version:${M_cmpv}}
58 1.7 sjg @echo Literal=3.4.5 == ${3.4.5:L:${M_cmpv}}
59 1.8 sjg @echo We have ${${.TARGET:T}.only}
60 1.9 sjg
61 1.10 rillig
62 1.31 rillig # Test parsing of boolean values.
63 1.28 rillig # begin .MAKE.SAVE_DOLLARS; see Var_SetWithFlags and ParseBoolean.
64 1.12 rillig SD_VALUES= 0 1 2 False True false true Yes No yes no On Off ON OFF on off
65 1.12 rillig SD_4_DOLLARS= $$$$
66 1.12 rillig
67 1.12 rillig .for val in ${SD_VALUES}
68 1.32 rillig # The assignment must be done using ':=' since a simple '=' would be
69 1.32 rillig # interpreted as 'yes', due to the leading '$'; see ParseBoolean.
70 1.32 rillig .MAKE.SAVE_DOLLARS:= ${val}
71 1.12 rillig SD.${val}:= ${SD_4_DOLLARS}
72 1.12 rillig .endfor
73 1.12 rillig .MAKE.SAVE_DOLLARS:= yes
74 1.12 rillig
75 1.12 rillig save-dollars:
76 1.12 rillig .for val in ${SD_VALUES}
77 1.12 rillig @printf '%s: %-8s = %s\n' $@ ${val} ${SD.${val}:Q}
78 1.12 rillig .endfor
79 1.31 rillig # end .MAKE.SAVE_DOLLARS
80 1.13 rillig
81 1.13 rillig # Appending to an undefined variable does not add a space in front.
82 1.13 rillig .undef APPENDED
83 1.13 rillig APPENDED+= value
84 1.13 rillig .if ${APPENDED} != "value"
85 1.25 rillig . error "${APPENDED}"
86 1.13 rillig .endif
87 1.13 rillig
88 1.13 rillig # Appending to an empty variable adds a space between the old value
89 1.13 rillig # and the additional value.
90 1.13 rillig APPENDED= # empty
91 1.13 rillig APPENDED+= value
92 1.13 rillig .if ${APPENDED} != " value"
93 1.25 rillig . error "${APPENDED}"
94 1.13 rillig .endif
95 1.13 rillig
96 1.13 rillig # Appending to parameterized variables works as well.
97 1.13 rillig PARAM= param
98 1.13 rillig VAR.${PARAM}= 1
99 1.13 rillig VAR.${PARAM}+= 2
100 1.13 rillig .if ${VAR.param} != "1 2"
101 1.25 rillig . error "${VAR.param}"
102 1.13 rillig .endif
103 1.13 rillig
104 1.13 rillig # The variable name can contain arbitrary characters.
105 1.13 rillig # If the expanded variable name ends in a +, this still does not influence
106 1.13 rillig # the parser. The assignment operator is still a simple assignment.
107 1.13 rillig # Therefore, there is no need to add a space between the variable name
108 1.13 rillig # and the assignment operator.
109 1.13 rillig PARAM= +
110 1.13 rillig VAR.${PARAM}= 1
111 1.13 rillig VAR.${PARAM}+= 2
112 1.13 rillig .if ${VAR.+} != "1 2"
113 1.25 rillig . error "${VAR.+}"
114 1.13 rillig .endif
115 1.33 rillig .for param in : + ! ?
116 1.13 rillig VAR.${param}= ${param}
117 1.13 rillig .endfor
118 1.33 rillig .if ${VAR.${:U\:}} != ":" || ${VAR.+} != "+" || ${VAR.!} != "!" || ${VAR.?} != "?"
119 1.25 rillig . error "${VAR.+}" "${VAR.!}" "${VAR.?}"
120 1.13 rillig .endif
121 1.14 rillig
122 1.14 rillig # Appending to a variable from the environment creates a copy of that variable
123 1.30 rillig # in the global scope.
124 1.14 rillig # The appended value is not exported automatically.
125 1.14 rillig # When a variable is exported, the exported value is taken at the time of the
126 1.14 rillig # .export directive. Later changes to the variable have no effect.
127 1.14 rillig .export FROM_ENV_BEFORE
128 1.14 rillig FROM_ENV+= mk
129 1.14 rillig FROM_ENV_BEFORE+= mk
130 1.14 rillig FROM_ENV_AFTER+= mk
131 1.14 rillig .export FROM_ENV_AFTER
132 1.14 rillig
133 1.14 rillig export-appended:
134 1.14 rillig @echo $@: "$$FROM_ENV"
135 1.14 rillig @echo $@: "$$FROM_ENV_BEFORE"
136 1.14 rillig @echo $@: "$$FROM_ENV_AFTER"
137 1.15 rillig
138 1.15 rillig # begin parse-dynamic
139 1.15 rillig #
140 1.15 rillig # Demonstrate that the target-specific variables are not evaluated in
141 1.30 rillig # the global scope. Their expressions are preserved until there is a local
142 1.30 rillig # scope in which resolving them makes sense.
143 1.15 rillig
144 1.17 rillig # There are different code paths for short names ...
145 1.15 rillig ${:U>}= before
146 1.17 rillig GS_TARGET:= $@
147 1.17 rillig GS_MEMBER:= $%
148 1.17 rillig GS_PREFIX:= $*
149 1.17 rillig GS_ARCHIVE:= $!
150 1.17 rillig GS_ALLSRC:= $>
151 1.15 rillig ${:U>}= after
152 1.17 rillig # ... and for braced short names ...
153 1.17 rillig GB_TARGET:= ${@}
154 1.17 rillig GB_MEMBER:= ${%}
155 1.17 rillig GB_PREFIX:= ${*}
156 1.17 rillig GB_ARCHIVE:= ${!}
157 1.17 rillig GB_ALLSRC:= ${>}
158 1.17 rillig # ... and for long names.
159 1.17 rillig GL_TARGET:= ${.TARGET}
160 1.17 rillig GL_MEMBER:= ${.MEMBER}
161 1.17 rillig GL_PREFIX:= ${.PREFIX}
162 1.17 rillig GL_ARCHIVE:= ${.ARCHIVE}
163 1.17 rillig GL_ALLSRC:= ${.ALLSRC}
164 1.15 rillig
165 1.15 rillig parse-dynamic:
166 1.17 rillig @echo $@: ${GS_TARGET} ${GS_MEMBER} ${GS_PREFIX} ${GS_ARCHIVE} ${GS_ALLSRC}
167 1.17 rillig @echo $@: ${GB_TARGET} ${GB_MEMBER} ${GB_PREFIX} ${GB_ARCHIVE} ${GB_ALLSRC}
168 1.17 rillig @echo $@: ${GL_TARGET} ${GL_MEMBER} ${GL_PREFIX} ${GL_ARCHIVE} ${GL_ALLSRC}
169 1.16 rillig
170 1.18 rillig # Since 2020-07-28, make complains about unclosed variables.
171 1.21 rillig # Before that, it had complained about unclosed variables only when
172 1.18 rillig # parsing the modifiers, but not when parsing the variable name.
173 1.20 rillig
174 1.20 rillig UNCLOSED_INDIR_1= ${UNCLOSED_ORIG
175 1.20 rillig UNCLOSED_INDIR_2= ${UNCLOSED_INDIR_1}
176 1.20 rillig
177 1.23 sjg FLAGS= one two
178 1.26 rillig FLAGS+= ${FLAGS.${.ALLSRC:M*.c:T:u}}
179 1.26 rillig FLAGS.target2.c= three four
180 1.23 sjg
181 1.23 sjg target1.c:
182 1.23 sjg target2.c:
183 1.23 sjg
184 1.23 sjg all: target1-flags target2-flags
185 1.23 sjg target1-flags: target1.c
186 1.23 sjg @echo $@: we have: ${FLAGS}
187 1.23 sjg
188 1.23 sjg target2-flags: target2.c
189 1.23 sjg @echo $@: we have: ${FLAGS}
190 1.23 sjg
191 1.36 rillig varerror-unclosed-1:
192 1.16 rillig @echo $@:begin
193 1.36 rillig varerror-unclosed-2:
194 1.37 rillig # expect: make: Unclosed variable ""
195 1.18 rillig @echo $(
196 1.36 rillig varerror-unclosed-3:
197 1.37 rillig # expect: make: Unclosed variable "UNCLOSED"
198 1.18 rillig @echo $(UNCLOSED
199 1.36 rillig varerror-unclosed-4:
200 1.37 rillig # expect: make: Unclosed variable "UNCLOSED"
201 1.16 rillig @echo ${UNCLOSED
202 1.36 rillig varerror-unclosed-5:
203 1.37 rillig # expect: make: Unclosed expression, expecting '}' for modifier "M${PATTERN"
204 1.16 rillig @echo ${UNCLOSED:M${PATTERN
205 1.36 rillig varerror-unclosed-6:
206 1.37 rillig # expect: make: Unclosed variable "param"
207 1.37 rillig # expect: make: Unclosed variable "UNCLOSED."
208 1.16 rillig @echo ${UNCLOSED.${param
209 1.36 rillig varerror-unclosed-7:
210 1.18 rillig @echo $
211 1.18 rillig .for i in 1 2 3
212 1.37 rillig # expect: make: Unclosed variable "UNCLOSED.1"
213 1.18 rillig @echo ${UNCLOSED.${i}
214 1.18 rillig .endfor
215 1.36 rillig varerror-unclosed-8:
216 1.20 rillig @echo ${UNCLOSED_INDIR_2}
217 1.16 rillig @echo $@:end
218