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