aboutsummaryrefslogtreecommitdiff
path: root/contrib/bmake/unit-tests/varmod-to-separator.mk
blob: 8b8aeb4d3c336d18adfd18f248d9e2eb6762761b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# $NetBSD: varmod-to-separator.mk,v 1.14 2024/04/20 10:18:55 rillig Exp $
#
# Tests for the :ts variable modifier, which joins the words of the variable
# using an arbitrary character as word separator.

WORDS=	one two three four five six

# The words are separated by a single space, just as usual.
.if ${WORDS:ts } != "one two three four five six"
.  warning Space as separator does not work.
.endif

# The separator can be an arbitrary character, for example a comma.
.if ${WORDS:ts,} != "one,two,three,four,five,six"
.  warning Comma as separator does not work.
.endif

# After the :ts modifier, other modifiers can follow.
.if ${WORDS:ts/:tu} != "ONE/TWO/THREE/FOUR/FIVE/SIX"
.  warning Chaining modifiers does not work.
.endif

# To use the ':' as the separator, just write it normally.
# The first colon is the separator, the second ends the modifier.
.if ${WORDS:ts::tu} != "ONE:TWO:THREE:FOUR:FIVE:SIX"
.  warning Colon as separator does not work.
.endif

# When there is just a colon but no other character, the words are
# "separated" by an empty string, that is, they are all squashed
# together.
.if ${WORDS:ts:tu} != "ONETWOTHREEFOURFIVESIX"
.  warning Colon as separator does not work.
.endif

# Applying the :tu modifier first and then the :ts modifier does not change
# anything since neither of these modifiers is related to how the string is
# split into words.  Beware of separating the words using a single or double
# quote though, or other special characters like dollar or backslash.
#
# This example also demonstrates that the closing brace is not interpreted
# as a separator, but as the closing delimiter of the whole
# expression.
.if ${WORDS:tu:ts} != "ONETWOTHREEFOURFIVESIX"
.  warning Colon as separator does not work.
.endif

# The '}' plays the same role as the ':' in the preceding examples.
# Since there is a single character before it, that character is taken as
# the separator.
.if ${WORDS:tu:ts/} != "ONE/TWO/THREE/FOUR/FIVE/SIX"
.  warning Colon as separator does not work.
.endif

# Now it gets interesting and ambiguous:  The separator could either be empty
# since it is followed by a colon.  Or it could be the colon since that
# colon is followed by the closing brace.  It's the latter case.
.if ${WORDS:ts:} != "one:two:three:four:five:six"
.  warning Colon followed by closing brace does not work.
.endif

# As in the ${WORDS:tu:ts} example above, the separator is empty.
.if ${WORDS:ts} != "onetwothreefourfivesix"
.  warning Empty separator before closing brace does not work.
.endif

# The :ts modifier can be followed by other modifiers.
.if ${WORDS:ts:S/two/2/} != "one2threefourfivesix"
.  warning Separator followed by :S modifier does not work.
.endif

# The :ts modifier can follow other modifiers.
.if ${WORDS:S/two/2/:ts} != "one2threefourfivesix"
.  warning :S modifier followed by :ts modifier does not work.
.endif

# The :ts modifier with an actual separator can be followed by other
# modifiers.
.if ${WORDS:ts/:S/two/2/} != "one/2/three/four/five/six"
.  warning The :ts modifier followed by an :S modifier does not work.
.endif

# After the modifier ':ts/', the expression value is a single word since all
# spaces have been replaced with '/'.  This single word does not start with
# 'two', which makes the modifier ':S' a no-op.
.if ${WORDS:ts/:S/^two/2/} != "one/two/three/four/five/six"
.  error
.endif

# After the :ts modifier, the whole string is interpreted as a single
# word since all spaces have been replaced with x.  Because of this single
# word, only the first 'b' is replaced with 'B'.
.if ${aa bb aa bb aa bb:L:tsx:S,b,B,} != "aaxBbxaaxbbxaaxbb"
.  error
.endif

# The :ts modifier also applies to word separators that are added
# afterwards.  First, the modifier ':tsx' joins the 3 words, then the modifier
# ':S' replaces the 2 'b's with spaces.  These spaces are part of the word,
# so when the words are joined at the end of the modifier ':S', there is only
# a single word, and the custom separator from the modifier ':tsx' has no
# effect.
.if ${a ababa c:L:tsx:S,b, ,g} != "axa a axc"
.  error
.endif

# Adding the modifier ':M*' at the end of the above chain splits the
# expression value and then joins it again.  At this point of splitting, the
# newly added spaces are treated as word separators, resulting in 3 words.
# When these 3 words are joined, the separator from the modifier ':tsx' is
# used.
.if ${a ababa c:L:tsx:S,b, ,g:M*} != "axaxaxaxc"
.  error
.endif

# Not all modifiers use the separator from the previous modifier ':ts' though.
# The modifier ':@' always uses a space as word separator instead.  This has
# probably been an oversight during implementation.  For consistency, the
# result should rather be "axaxaxaxc", as in the previous example.
.if ${a ababa c:L:tsx:S,b, ,g:@v@$v@} != "axa a axc"
.  error
.endif

# Adding a final :M* modifier applies the :ts separator again, though.
.if ${a ababa c:L:tsx:S,b, ,g:@v@${v}@:M*} != "axaxaxaxc"
.  error
.endif

# The separator can be \n, which is a newline.
.if ${WORDS:[1..3]:ts\n} != "one${.newline}two${.newline}three"
.  warning The separator \n does not produce a newline.
.endif

# The separator can be \t, which is a tab.
.if ${WORDS:[1..3]:ts\t} != "one	two	three"
.  warning The separator \t does not produce a tab.
.endif

# The separator can be given as octal number.
.if ${WORDS:[1..3]:ts\012:tu} != "ONE${.newline}TWO${.newline}THREE"
.  warning The separator \012 is not interpreted in octal ASCII.
.endif

# The octal number can have as many digits as it wants.
.if ${WORDS:[1..2]:ts\000000000000000000000000012:tu} != "ONE${.newline}TWO"
.  warning The separator \012 cannot have many leading zeroes.
.endif

# The value of the separator character must not be outside the value space
# for an unsigned character though.
#
# Since 2020-11-01, these out-of-bounds values are rejected.
# expect+2: while evaluating variable "WORDS": Invalid character number at "400:tu}"
# expect+1: Malformed conditional (${WORDS:[1..3]:ts\400:tu})
.if ${WORDS:[1..3]:ts\400:tu}
.  warning The separator \400 is accepted even though it is out of bounds.
.else
.  warning The separator \400 is accepted even though it is out of bounds.
.endif

# The separator can be given as hexadecimal number.
.if ${WORDS:[1..3]:ts\xa:tu} != "ONE${.newline}TWO${.newline}THREE"
.  warning The separator \xa is not interpreted in hexadecimal ASCII.
.endif

# The hexadecimal number must be in the range of an unsigned char.
#
# Since 2020-11-01, these out-of-bounds values are rejected.
# expect+2: while evaluating variable "WORDS": Invalid character number at "100:tu}"
# expect+1: Malformed conditional (${WORDS:[1..3]:ts\x100:tu})
.if ${WORDS:[1..3]:ts\x100:tu}
.  warning The separator \x100 is accepted even though it is out of bounds.
.else
.  warning The separator \x100 is accepted even though it is out of bounds.
.endif

# Negative numbers are not allowed for the separator character.
# expect+1: Malformed conditional (${WORDS:[1..3]:ts\-300:tu})
.if ${WORDS:[1..3]:ts\-300:tu}
.  warning The separator \-300 is accepted even though it is negative.
.else
.  warning The separator \-300 is accepted even though it is negative.
.endif

# The character number is interpreted as octal number by default.
# The digit '8' is not an octal digit though.
# expect+1: Malformed conditional (${1 2 3:L:ts\8:tu})
.if ${1 2 3:L:ts\8:tu}
.  warning The separator \8 is accepted even though it is not octal.
.else
.  warning The separator \8 is accepted even though it is not octal.
.endif

# Trailing characters after the octal character number are rejected.
# expect+1: Malformed conditional (${1 2 3:L:ts\100L})
.if ${1 2 3:L:ts\100L}
.  warning The separator \100L is accepted even though it contains an 'L'.
.else
.  warning The separator \100L is accepted even though it contains an 'L'.
.endif

# Trailing characters after the hexadecimal character number are rejected.
# expect+1: Malformed conditional (${1 2 3:L:ts\x40g})
.if ${1 2 3:L:ts\x40g}
.  warning The separator \x40g is accepted even though it contains a 'g'.
.else
.  warning The separator \x40g is accepted even though it contains a 'g'.
.endif


# In the :t modifier, the :t must be followed by any of A, l, s, u.
# expect: make: Bad modifier ":tx" for variable "WORDS"
# expect+1: Malformed conditional (${WORDS:tx})
.if ${WORDS:tx}
.  error
.else
.  error
.endif

# The word separator can only be a single character.
# expect: make: Bad modifier ":ts\X" for variable "WORDS"
# expect+1: Malformed conditional (${WORDS:ts\X})
.if ${WORDS:ts\X}
.  error
.else
.  error
.endif

# After the backslash, only n, t, an octal number, or x and a hexadecimal
# number are allowed.
# expect+1: Malformed conditional (${WORDS:t\X} != "anything")
.if ${WORDS:t\X} != "anything"
.  info This line is not reached.
.endif


# Since 2003.07.23.18.06.46 and before 2016.03.07.20.20.35, the modifier ':ts'
# interpreted an "octal escape" as decimal if the first digit was not '0'.
.if ${:Ua b:ts\61} != "a1b"	# decimal would have been "a=b"
.  error
.endif

# Since the character escape is always interpreted as octal, let's see what
# happens for non-octal digits.  From 2003.07.23.18.06.46 to
# 2016.02.27.16.20.06, the result was '1E2', since 2016.03.07.20.20.35 make no
# longer accepts this escape and complains.
# expect: make: Bad modifier ":ts\69" for variable ""
# expect+1: Malformed conditional (${:Ua b:ts\69})
.if ${:Ua b:ts\69}
.  error
.else
.  error
.endif

# Try whether bmake is Unicode-ready.
# expect+2: while evaluating "${:Ua b:ts\x1F60E}": Invalid character number at "1F60E}"
# expect+1: Malformed conditional (${:Ua b:ts\x1F60E})
.if ${:Ua b:ts\x1F60E}		# U+1F60E "smiling face with sunglasses"
.  error
.else
.  error
.endif