1# $NetBSD: varmod-subst.mk,v 1.12 2023/06/16 07:20:45 rillig Exp $ 2# 3# Tests for the :S,from,to, variable modifier. 4 5all: mod-subst 6all: mod-subst-delimiter 7all: mod-subst-chain 8all: mod-subst-dollar 9 10WORDS= sequences of letters 11 12# The empty pattern never matches anything. 13.if ${WORDS:S,,,} != ${WORDS} 14. error 15.endif 16 17# The :S modifier flag '1' is applied exactly once. 18.if ${WORDS:S,e,*,1} != "s*quences of letters" 19. error 20.endif 21 22# The :S modifier flag '1' is applied to the first occurrence, no matter if 23# the occurrence is in the first word or not. 24.if ${WORDS:S,f,*,1} != "sequences o* letters" 25. error 26.endif 27 28# The :S modifier replaces every first match per word. 29.if ${WORDS:S,e,*,} != "s*quences of l*tters" 30. error 31.endif 32 33# The :S modifier flag 'g' replaces every occurrence. 34.if ${WORDS:S,e,*,g} != "s*qu*nc*s of l*tt*rs" 35. error 36.endif 37 38# The '^' in the search pattern anchors the pattern at the beginning of each 39# word, thereby matching a prefix. 40.if ${WORDS:S,^sequ,occurr,} != "occurrences of letters" 41. error 42.endif 43 44# The :S modifier with a '^' anchor replaces the whole word if that word is 45# exactly the pattern. 46.if ${WORDS:S,^of,with,} != "sequences with letters" 47. error 48.endif 49 50# The :S modifier does not match if the pattern is longer than the word. 51.if ${WORDS:S,^office,does not match,} != ${WORDS} 52. warning 53.endif 54 55# The '$' in the search pattern anchors the pattern at the end of each word, 56# thereby matching a suffix. 57.if ${WORDS:S,f$,r,} != "sequences or letters" 58. error 59.endif 60 61# The :S modifier with a '$' anchor replaces at most one occurrence per word. 62.if ${WORDS:S,s$,,} != "sequence of letter" 63. error 64.endif 65 66# The :S modifier with a '$' anchor replaces the whole word if that word is 67# exactly the pattern. 68.if ${WORDS:S,of$,,} != "sequences letters" 69. error 70.endif 71 72# The :S modifier with a '$' anchor and a pattern that is longer than a word 73# cannot match that word. 74.if ${WORDS:S,eof$,,} != ${WORDS} 75. warning 76.endif 77 78# The :S modifier with the '^' and '$' anchors matches an exact word. 79.if ${WORDS:S,^of$,,} != "sequences letters" 80. error 81.endif 82 83# The :S modifier with the '^' and '$' anchors does not match a word that 84# starts with the pattern but is longer than the pattern. 85.if ${WORDS:S,^o$,,} != ${WORDS} 86. error 87.endif 88 89# The :S modifier with the '^' and '$' anchors does not match a word that ends 90# with the pattern but is longer than the pattern. 91.if ${WORDS:S,^f$,,} != ${WORDS} 92. error 93.endif 94 95# The :S modifier with the '^' and '$' anchors does not match a word if the 96# pattern ends with the word but is longer than the word. 97.if ${WORDS:S,^eof$,,} != ${WORDS} 98. error 99.endif 100 101# The :S modifier with the '^' and '$' anchors does not match a word if the 102# pattern starts with the word but is longer than the word. 103.if ${WORDS:S,^office$,,} != ${WORDS} 104. error 105.endif 106 107# Except for the '^' and '$' anchors, the pattern does not contain any special 108# characters, so the '*' from the pattern would only match a literal '*' in a 109# word. 110.if ${WORDS:S,*,replacement,} != ${WORDS} 111. error 112.endif 113 114# Except for the '^' and '$' anchors, the pattern does not contain any special 115# characters, so the '.' from the pattern would only match a literal '.' in a 116# word. 117.if ${WORDS:S,.,replacement,} != ${WORDS} 118. error 119.endif 120 121# The '&' in the replacement is a placeholder for the text matched by the 122# pattern. 123.if ${:Uvalue:S,^val,&,} != "value" 124. error 125.endif 126.if ${:Uvalue:S,ue$,&,} != "value" 127. error 128.endif 129.if ${:Uvalue:S,^val,&-&-&,} != "val-val-value" 130. error 131.endif 132.if ${:Uvalue:S,ue$,&-&-&,} != "value-ue-ue" 133. error 134.endif 135 136 137# When a word is replaced with nothing, the remaining words are separated by a 138# single space, not two. 139.if ${1 2 3:L:S,2,,} != "1 3" 140. error 141.endif 142 143 144mod-subst: 145 @echo $@: 146 @echo :${:Ua b b c:S,a b,,:Q}: 147 @echo :${:Ua b b c:S,a b,,1:Q}: 148 @echo :${:Ua b b c:S,a b,,W:Q}: 149 @echo :${:Ua b b c:S,b,,g:Q}: 150 @echo :${:U1 2 3 1 2 3:S,1 2,___,Wg:S,_,x,:Q}: 151 @echo ${:U12345:S,,sep,g:Q} 152 153# The :S and :C modifiers accept an arbitrary character as the delimiter, 154# including characters that are otherwise used as escape characters or 155# interpreted in a special way. This can be used to confuse humans. 156mod-subst-delimiter: 157 @echo $@: 158 @echo ${:U1 2 3:S 2 two :Q} horizontal tabulator 159 @echo ${:U1 2 3:S 2 two :Q} space 160 @echo ${:U1 2 3:S!2!two!:Q} exclamation mark 161 @echo ${:U1 2 3:S"2"two":Q} quotation mark 162 # In shell command lines, the hash does not need to be escaped. 163 # It needs to be escaped in variable assignment lines though. 164 @echo ${:U1 2 3:S#2#two#:Q} number sign 165 @echo ${:U1 2 3:S$2$two$:Q} dollar sign 166 @echo ${:U1 2 3:S%2%two%:Q} percent sign 167 @echo ${:U1 2 3:S&2&two&:Q} ampersand 168 @echo ${:U1 2 3:S'2'two':Q} apostrophe 169 @echo ${:U1 2 3:S(2(two(:Q} left parenthesis 170 @echo ${:U1 2 3:S)2)two):Q} right parenthesis 171 @echo ${:U1 2 3:S*2*two*:Q} asterisk 172 @echo ${:U1 2 3:S+2+two+:Q} plus sign 173 @echo ${:U1 2 3:S,2,two,:Q} comma 174 @echo ${:U1 2 3:S-2-two-:Q} hyphen-minus 175 @echo ${:U1 2 3:S.2.two.:Q} full stop 176 @echo ${:U1 2 3:S/2/two/:Q} solidus 177 @echo ${:U1 2 3:S121two1:Q} digit 178 @echo ${:U1 2 3:S:2:two::Q} colon 179 @echo ${:U1 2 3:S;2;two;:Q} semicolon 180 @echo ${:U1 2 3:S<2<two<:Q} less-than sign 181 @echo ${:U1 2 3:S=2=two=:Q} equals sign 182 @echo ${:U1 2 3:S>2>two>:Q} greater-than sign 183 @echo ${:U1 2 3:S?2?two?:Q} question mark 184 @echo ${:U1 2 3:S@2@two@:Q} commercial at 185 @echo ${:U1 2 3:SA2AtwoA:Q} capital letter 186 @echo ${:U1 2 3:S[2[two[:Q} left square bracket 187 @echo ${:U1 2 3:S\2\two\:Q} reverse solidus 188 @echo ${:U1 2 3:S]2]two]:Q} right square bracket 189 @echo ${:U1 2 3:S^2^two^:Q} circumflex accent 190 @echo ${:U1 2 3:S_2_two_:Q} low line 191 @echo ${:U1 2 3:S`2`two`:Q} grave accent 192 @echo ${:U1 2 3:Sa2atwoa:Q} small letter 193 @echo ${:U1 2 3:S{2{two{:Q} left curly bracket 194 @echo ${:U1 2 3:S|2|two|:Q} vertical line 195 @echo ${:U1 2 3:S}2}two}:Q} right curly bracket 196 @echo ${:U1 2 3:S~2~two~:Q} tilde 197 198# The :S and :C modifiers can be chained without a separating ':'. 199# This is not documented in the manual page. 200# It works because ApplyModifier_Subst scans for the known modifiers g1W 201# and then just returns to ApplyModifiers. There, the colon is optionally 202# skipped (see the *st.next == ':' at the end of the loop). 203# 204# Most other modifiers cannot be chained since their parsers skip until 205# the next ':' or '}' or ')'. 206mod-subst-chain: 207 @echo $@: 208 @echo ${:Ua b c:S,a,A,S,b,B,}. 209 # There is no 'i' modifier for the :S or :C modifiers. 210 # The error message is "make: Unknown modifier 'i'", which is 211 # kind of correct, although it is mixing the terms for variable 212 # modifiers with the matching modifiers. 213 @echo ${:Uvalue:S,a,x,i}. 214 215# No matter how many dollar signs there are, they all get merged 216# into a single dollar by the :S modifier. 217# 218# As of 2020-08-09, this is because ParseModifierPart sees a '$' and 219# calls Var_Parse to expand the variable. In all other places, the "$$" 220# is handled outside of Var_Parse. Var_Parse therefore considers "$$" 221# one of the "really stupid names", skips the first dollar, and parsing 222# continues with the next character. This repeats for the other dollar 223# signs, except the one before the delimiter. That one is handled by 224# the code that optionally interprets the '$' as the end-anchor in the 225# first part of the :S modifier. That code doesn't call Var_Parse but 226# simply copies the dollar to the result. 227mod-subst-dollar: 228 @echo $@:${:U1:S,^,$,:Q}: 229 @echo $@:${:U2:S,^,$$,:Q}: 230 @echo $@:${:U3:S,^,$$$,:Q}: 231 @echo $@:${:U4:S,^,$$$$,:Q}: 232 @echo $@:${:U5:S,^,$$$$$,:Q}: 233 @echo $@:${:U6:S,^,$$$$$$,:Q}: 234 @echo $@:${:U7:S,^,$$$$$$$,:Q}: 235 @echo $@:${:U8:S,^,$$$$$$$$,:Q}: 236 @echo $@:${:U40:S,^,$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$,:Q}: 237# This generates no dollar at all: 238 @echo $@:${:UU8:S,^,${:U$$$$$$$$},:Q}: 239# Here is an alternative way to generate dollar signs. 240# It's unexpectedly complicated though. 241 @echo $@:${:U:range=5:ts\x24:C,[0-9],,g:Q}: 242# In modifiers, dollars are escaped using the backslash, not using another 243# dollar sign. Therefore, creating a dollar sign is pretty simple: 244 @echo $@:${:Ugood3:S,^,\$\$\$,:Q} 245