summaryrefslogtreecommitdiff
path: root/unit-tests/moderrs.mk
blob: 77ba39a3d57d45b66d2f7aefbb6d5ed494741f6d (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
# $NetBSD: moderrs.mk,v 1.24 2020/11/01 14:36:25 rillig Exp $
#
# various modifier error tests

'=		'\''
VAR=		TheVariable
# in case we have to change it ;-)
MOD_UNKN=	Z
MOD_TERM=	S,V,v
MOD_S:=		${MOD_TERM},

FIB=	1 1 2 3 5 8 13 21 34

all:	mod-unknown-direct mod-unknown-indirect
all:	unclosed-direct unclosed-indirect
all:	unfinished-indirect unfinished-loop
all:	loop-close
all:	words
all:	exclam
all:	mod-subst-delimiter
all:	mod-regex-delimiter
all:	mod-regex-undefined-subexpression
all:	mod-ts-parse
all:	mod-t-parse
all:	mod-ifelse-parse
all:	mod-remember-parse
all:	mod-sysv-parse

mod-unknown-direct: print-header print-footer
	@echo 'want: Unknown modifier $'Z$''
	@echo 'VAR:Z=before-${VAR:Z}-after'

mod-unknown-indirect: print-header print-footer
	@echo 'want: Unknown modifier $'Z$''
	@echo 'VAR:${MOD_UNKN}=before-${VAR:${MOD_UNKN}:inner}-after'

unclosed-direct: print-header print-footer
	@echo 'want: Unclosed variable specification (expecting $'}$') for "VAR" (value "Thevariable") modifier S'
	@echo VAR:S,V,v,=${VAR:S,V,v,

unclosed-indirect: print-header print-footer
	@echo 'want: Unclosed variable specification after complex modifier (expecting $'}$') for VAR'
	@echo VAR:${MOD_TERM},=${VAR:${MOD_S}

unfinished-indirect: print-header print-footer
	@echo 'want: Unfinished modifier for VAR ($',$' missing)'
	-@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}"

unfinished-loop: print-header print-footer
	@echo 'want: Unfinished modifier for UNDEF ($'@$' missing)'
	@echo ${UNDEF:U1 2 3:@var}
	@echo 'want: Unfinished modifier for UNDEF ($'@$' missing)'
	@echo ${UNDEF:U1 2 3:@var@...}
	@echo ${UNDEF:U1 2 3:@var@${var}@}

# The closing brace after the ${var} is part of the replacement string.
# In ParseModifierPart, braces and parentheses don't have to be balanced.
# This is contrary to the :M, :N modifiers, where both parentheses and
# braces must be balanced.
# This is also contrary to the SysV modifier, where only the actually
# used delimiter (either braces or parentheses) must be balanced.
loop-close: print-header print-footer
	@echo ${UNDEF:U1 2 3:@var@${var}}...@
	@echo ${UNDEF:U1 2 3:@var@${var}}...@}

words: print-header print-footer
	@echo 'want: Unfinished modifier for UNDEF ($']$' missing)'
	@echo ${UNDEF:U1 2 3:[}
	@echo 'want: Unfinished modifier for UNDEF ($']$' missing)'
	@echo ${UNDEF:U1 2 3:[#}

	# out of bounds => empty
	@echo 13=${UNDEF:U1 2 3:[13]}

	# Word index out of bounds.
	#
	# Until 2020-11-01, the behavior in this case depended upon the size
	# of unsigned long.
	#
	# On LP64I32, strtol returns LONG_MAX, which was then truncated to
	# int (undefined behavior), typically resulting in -1.  This -1 was
	# interpreted as "the last word".
	#
	# On ILP32, strtol returns LONG_MAX, which is a large number.  This
	# resulted in a range from LONG_MAX - 1 to 3, which was empty.
	#
	# Since 2020-11-01, the numeric overflow is detected and generates an
	# error.  In the remainder of the text, the '$,' is no longer parsed
	# as part of a variable modifier, where it would have been interpreted
	# as an anchor to the :S modifier, but as a normal variable named ','.
	# That variable is undefined, resulting in an empty string.
	@echo 12345=${UNDEF:U1 2 3:[123451234512345123451234512345]:S,^$,ok,:S,^3$,ok,}

exclam: print-header print-footer
	@echo 'want: Unfinished modifier for VARNAME ($'!$' missing)'
	@echo ${VARNAME:!echo}
	# When the final exclamation mark is missing, there is no
	# fallback to the SysV substitution modifier.
	# If there were a fallback, the output would be "exclam",
	# and the above would have produced an "Unknown modifier '!'".
	@echo 'want: Unfinished modifier for ! ($'!$' missing)'
	@echo ${!:L:!=exclam}

mod-subst-delimiter: print-header print-footer
	@echo 1: ${VAR:S
	@echo 2: ${VAR:S,
	@echo 3: ${VAR:S,from
	@echo 4: ${VAR:S,from,
	@echo 5: ${VAR:S,from,to
	@echo 6: ${VAR:S,from,to,
	@echo 7: ${VAR:S,from,to,}

mod-regex-delimiter: print-header print-footer
	@echo 1: ${VAR:C
	@echo 2: ${VAR:C,
	@echo 3: ${VAR:C,from
	@echo 4: ${VAR:C,from,
	@echo 5: ${VAR:C,from,to
	@echo 6: ${VAR:C,from,to,
	@echo 7: ${VAR:C,from,to,}

# In regular expressions with alternatives, not all capturing groups are
# always set; some may be missing.  Warn about these.
#
# Since there is no way to turn off this warning, the combination of
# alternative matches and capturing groups is not widely used.
#
# A newly added modifier 'U' such as in :C,(a.)|(b.),\1\2,U might be added
# for treating undefined capturing groups as empty, but that would create a
# syntactical ambiguity since the :S and :C modifiers are open-ended (see
# mod-subst-chain).  Luckily the modifier :U does not make sense after :C,
# therefore this case does not happen in practice.
# The sub-modifier for the :S and :C modifiers would have to be chosen
# wisely, to not create ambiguities while parsing.
mod-regex-undefined-subexpression: print-header print-footer
	@echo ${FIB:C,1(.*),one\1,}		# all ok
	@echo ${FIB:C,1(.*)|2(.*),(\1)+(\2),:Q}	# no match for subexpression

mod-ts-parse: print-header print-footer
	@echo ${FIB:ts}
	@echo ${FIB:ts\65}	# octal 065 == U+0035 == '5'
	@echo ${FIB:ts\65oct}	# bad modifier
	@echo ${FIB:tsxy}	# modifier too long

mod-t-parse: print-header print-footer
	@echo ${FIB:t
	@echo ${FIB:txy}
	@echo ${FIB:t}
	@echo ${FIB:t:M*}

mod-ifelse-parse: print-header print-footer
	@echo ${FIB:?
	@echo ${FIB:?then
	@echo ${FIB:?then:
	@echo ${FIB:?then:else
	@echo ${FIB:?then:else}

mod-remember-parse: print-header print-footer
	@echo ${FIB:_}		# ok
	@echo ${FIB:__}		# modifier name too long

mod-sysv-parse: print-header print-footer
	@echo ${FIB:3
	@echo ${FIB:3=
	@echo ${FIB:3=x3
	@echo ${FIB:3=x3}	# ok

print-header: .USEBEFORE
	@echo $@:
print-footer: .USE
	@echo