1 1.38 rillig # $NetBSD: varmisc.mk,v 1.38 2025/06/28 22:39:29 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.38 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