1# $NetBSD: varmod-to-separator.mk,v 1.23 2025/03/30 00:35:52 rillig Exp $ 2# 3# Tests for the :ts variable modifier, which joins the words of the variable 4# using an arbitrary character as word separator. 5 6WORDS= one two three four five six 7 8# The words are separated by a single space, just as usual. 9.if ${WORDS:ts } != "one two three four five six" 10. error 11.endif 12 13# The separator can be an arbitrary character, for example a comma. 14.if ${WORDS:ts,} != "one,two,three,four,five,six" 15. error 16.endif 17 18# After the :ts modifier, other modifiers can follow. 19.if ${WORDS:ts/:tu} != "ONE/TWO/THREE/FOUR/FIVE/SIX" 20. error 21.endif 22 23# To use the ':' as the separator, just write it normally. 24# The first colon is the separator, the second ends the modifier. 25.if ${WORDS:ts::tu} != "ONE:TWO:THREE:FOUR:FIVE:SIX" 26. error 27.endif 28 29# When there is just a colon but no other character, the words are 30# "separated" by an empty string, that is, they are all squashed 31# together. 32.if ${WORDS:ts:tu} != "ONETWOTHREEFOURFIVESIX" 33. error 34.endif 35 36# Applying the :tu modifier first and then the :ts modifier does not change 37# anything since neither of these modifiers is related to how the string is 38# split into words. Beware of separating the words using a single or double 39# quote though, or other special characters like dollar or backslash. 40# 41# This example also demonstrates that the closing brace is not interpreted 42# as a separator, but as the closing delimiter of the whole 43# expression. 44.if ${WORDS:tu:ts} != "ONETWOTHREEFOURFIVESIX" 45. error 46.endif 47 48# The '}' plays the same role as the ':' in the preceding examples. 49# Since there is a single character before it, that character is taken as 50# the separator. 51.if ${WORDS:tu:ts/} != "ONE/TWO/THREE/FOUR/FIVE/SIX" 52. error 53.endif 54 55# Now it gets interesting and ambiguous: The separator could either be empty 56# since it is followed by a colon. Or it could be the colon since that 57# colon is followed by the closing brace. It's the latter case. 58.if ${WORDS:ts:} != "one:two:three:four:five:six" 59. error 60.endif 61 62# As in the ${WORDS:tu:ts} example above, the separator is empty. 63.if ${WORDS:ts} != "onetwothreefourfivesix" 64. error 65.endif 66 67# The :ts modifier can be followed by other modifiers. 68.if ${WORDS:ts:S/two/2/} != "one2threefourfivesix" 69. error 70.endif 71 72# The :ts modifier can follow other modifiers. 73.if ${WORDS:S/two/2/:ts} != "one2threefourfivesix" 74. error 75.endif 76 77# The :ts modifier with an actual separator can be followed by other 78# modifiers. 79.if ${WORDS:ts/:S/two/2/} != "one/2/three/four/five/six" 80. error 81.endif 82 83# After the modifier ':ts/', the expression value is a single word since all 84# spaces have been replaced with '/'. This single word does not start with 85# 'two', which makes the modifier ':S' a no-op. 86.if ${WORDS:ts/:S/^two/2/} != "one/two/three/four/five/six" 87. error 88.endif 89 90# After the :ts modifier, the whole string is interpreted as a single 91# word since all spaces have been replaced with x. Because of this single 92# word, only the first 'b' is replaced with 'B'. 93.if ${aa bb aa bb aa bb:L:tsx:S,b,B,} != "aaxBbxaaxbbxaaxbb" 94. error 95.endif 96 97# The :ts modifier also applies to word separators that are added 98# afterwards. First, the modifier ':tsx' joins the 3 words, then the modifier 99# ':S' replaces the 2 'b's with spaces. These spaces are part of the word, 100# so when the words are joined at the end of the modifier ':S', there is only 101# a single word, and the custom separator from the modifier ':tsx' has no 102# effect. 103.if ${a ababa c:L:tsx:S,b, ,g} != "axa a axc" 104. error 105.endif 106 107# Adding the modifier ':M*' at the end of the above chain splits the 108# expression value and then joins it again. At this point of splitting, the 109# newly added spaces are treated as word separators, resulting in 3 words. 110# When these 3 words are joined, the separator from the modifier ':tsx' is 111# used. 112.if ${a ababa c:L:tsx:S,b, ,g:M*} != "axaxaxaxc" 113. error 114.endif 115 116# Not all modifiers use the separator from the previous modifier ':ts' though. 117# The modifier ':@' always uses a space as word separator instead. This has 118# probably been an oversight during implementation. For consistency, the 119# result should rather be "axaxaxaxc", as in the previous example. 120.if ${a ababa c:L:tsx:S,b, ,g:@v@$v@} != "axa a axc" 121. error 122.endif 123 124# Adding a final :M* modifier applies the :ts separator again, though. 125.if ${a ababa c:L:tsx:S,b, ,g:@v@${v}@:M*} != "axaxaxaxc" 126. error 127.endif 128 129# The separator can be \n, which is a newline. 130.if ${WORDS:[1..3]:ts\n} != "one${.newline}two${.newline}three" 131. error 132.endif 133 134# The separator can be \t, which is a tab. 135.if ${WORDS:[1..3]:ts\t} != "one two three" 136. error 137.endif 138 139# The separator can be given as octal number. 140.if ${WORDS:[1..3]:ts\012:tu} != "ONE${.newline}TWO${.newline}THREE" 141. error 142.endif 143 144# The octal number can have as many digits as it wants. 145.if ${WORDS:[1..2]:ts\000000000000000000000000012:tu} != "ONE${.newline}TWO" 146. error 147.endif 148 149# The value of the separator character must not be outside the value space 150# for an unsigned character though. 151# 152# Since 2020-11-01, these out-of-bounds values are rejected. 153# expect+1: Invalid character number at "400:tu}" 154.if ${WORDS:[1..3]:ts\400:tu} 155. error 156.else 157. error 158.endif 159 160# The separator can be given as hexadecimal number. 161.if ${WORDS:[1..3]:ts\xa:tu} != "ONE${.newline}TWO${.newline}THREE" 162. error 163.endif 164 165# The hexadecimal number must be in the range of an unsigned char. 166# 167# Since 2020-11-01, these out-of-bounds values are rejected. 168# expect+1: Invalid character number at "100:tu}" 169.if ${WORDS:[1..3]:ts\x100:tu} 170. error 171.else 172. error 173.endif 174 175# The number after ':ts\x' must be hexadecimal. 176# expect+1: Invalid character number at ",}" 177.if ${word:L:ts\x,} 178.endif 179 180# The hexadecimal number must be in the range of 'unsigned long' on all 181# supported platforms. 182# expect+1: Invalid character number at "112233445566778899}" 183.if ${word:L:ts\x112233445566778899} 184.endif 185 186# Negative numbers are not allowed for the separator character. 187# expect+1: Unknown modifier ":ts\-300" 188.if ${WORDS:[1..3]:ts\-300:tu} 189. error 190.else 191. error 192.endif 193 194# The character number is interpreted as octal number by default. 195# The digit '8' is not an octal digit though. 196# expect+1: Unknown modifier ":ts\8" 197.if ${1 2 3:L:ts\8:tu} 198. error 199.else 200. error 201.endif 202 203# Trailing characters after the octal character number are rejected. 204# expect+1: Unknown modifier ":ts\100L" 205.if ${1 2 3:L:ts\100L} 206. error 207.else 208. error 209.endif 210 211# Trailing characters after the hexadecimal character number are rejected. 212# expect+1: Unknown modifier ":ts\x40g" 213.if ${1 2 3:L:ts\x40g} 214. error 215.else 216. error 217.endif 218 219 220# In the :t modifier, the :t must be followed by any of A, l, s, u. 221# expect+1: Unknown modifier ":tx" 222.if ${WORDS:tx} 223. error 224.else 225. error 226.endif 227 228# The word separator can only be a single character. 229# expect+1: Unknown modifier ":ts\X" 230.if ${WORDS:ts\X} 231. error 232.else 233. error 234.endif 235 236# After the backslash, only n, t, an octal number, or x and a hexadecimal 237# number are allowed. 238# expect+1: Unknown modifier ":ts\X" 239.if ${WORDS:ts\X} != "anything" 240. error 241.endif 242 243 244# Since 2003.07.23.18.06.46 and before 2016.03.07.20.20.35, the modifier ':ts' 245# interpreted an "octal escape" as decimal if the first digit was not '0'. 246.if ${:Ua b:ts\61} != "a1b" # decimal would have been "a=b" 247. error 248.endif 249 250# Since the character escape is always interpreted as octal, let's see what 251# happens for non-octal digits. From 2003.07.23.18.06.46 to 252# 2016.02.27.16.20.06, the result was '1E2', since 2016.03.07.20.20.35 make no 253# longer accepts this escape and complains. 254# expect+1: Unknown modifier ":ts\69" 255.if ${:Ua b:ts\69} 256. error 257.else 258. error 259.endif 260 261# Try whether bmake is Unicode-ready. 262# expect+1: Invalid character number at "1F60E}" 263.if ${:Ua b:ts\x1F60E} # U+1F60E "smiling face with sunglasses" 264. error 265.else 266. error 267.endif 268