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