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