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