1########################################################################
2#                                                                      #
3#               This software is part of the ast package               #
4#          Copyright (c) 1982-2012 AT&T Intellectual Property          #
5#                      and is licensed under the                       #
6#                 Eclipse Public License, Version 1.0                  #
7#                    by AT&T Intellectual Property                     #
8#                                                                      #
9#                A copy of the License is available at                 #
10#          http://www.eclipse.org/org/documents/epl-v10.html           #
11#         (with md5 checksum b35adb5213ca9657e911e9befb180842)         #
12#                                                                      #
13#              Information and Software Systems Research               #
14#                            AT&T Research                             #
15#                           Florham Park NJ                            #
16#                                                                      #
17#                  David Korn <dgk@research.att.com>                   #
18#                                                                      #
19########################################################################
20function err_exit
21{
22	print -u2 -r $'\t'"${Command}[$1] ${@:2}"
23	((Errors++))
24}
25alias err_exit='err_exit $LINENO'
26
27Command=${0##*/}
28integer aware=0 contrary=0 Errors=0 ignorant=0
29
30tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
31trap "cd /; rm -rf $tmp" EXIT
32
33function test_glob
34{
35	typeset lineno expected drop arg got sep op val add del
36	lineno=$1
37	shift
38	if	[[ $1 == --* ]]
39	then	del=${1#--}
40		shift
41	fi
42	if	[[ $1 == ++* ]]
43	then	add=${1#++}
44		shift
45	fi
46	expected=$1
47	shift
48	if	(( contrary ))
49	then	if	[[ $expected == "<Beware> "* ]]
50		then	expected=${expected#"<Beware> "}
51			expected="$expected <Beware>"
52		fi
53		if	[[ $expected == *"<aXb> <abd>"* ]]
54		then	expected=${expected/"<aXb> <abd>"/"<abd> <aXb>"}
55		fi
56	fi
57	for arg
58	do	got="$got$sep<$arg>"
59		sep=" "
60	done
61	if	(( ignorant && aware ))
62	then	if	[[ $del ]]
63		then	got="<$del> $got"
64		fi
65		if	[[ $add ]]
66		then	expected="<$add> $expected"
67		fi
68	fi
69	if	[[ $got != "$expected" ]]
70	then	'err_exit' $lineno "glob -- expected '$expected', got '$got'"
71	fi
72}
73alias test_glob='test_glob $LINENO'
74
75function test_case
76{
77	typeset lineno expected subject pattern got
78	lineno=$1 expected=$2 subject=$3 pattern=$4
79	eval "
80		case $subject in
81		$pattern)	got='<match>' ;;
82		*)		got='<nomatch>' ;;
83		esac
84	"
85	if	[[ $got != "$expected" ]]
86	then	'err_exit' $lineno "case $subject in $pattern) -- expected '$expected', got '$got'"
87	fi
88}
89alias test_case='test_case $LINENO'
90
91unset undefined
92
93cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
94
95export LC_COLLATE=C
96touch B b
97set -- *
98case $* in
99'b B')	contrary=1 ;;
100b|B)	ignorant=1 ;;
101esac
102set -- $(LC_ALL=C /bin/sh -c 'echo [a-c]')
103case $* in
104B)	aware=1 ;;
105esac
106rm -rf *
107
108touch a b c d abc abd abe bb bcd ca cb dd de Beware
109mkdir bdir
110
111test_glob '<a> <abc> <abd> <abe> <X*>' a* X*
112test_glob '<a> <abc> <abd> <abe>' \a*
113
114if	( set --nullglob ) 2>/dev/null
115then
116	set --nullglob
117
118	test_glob '<a> <abc> <abd> <abe>' a* X*
119
120	set --nonullglob
121fi
122
123if	( set --failglob ) 2>/dev/null
124then
125	set --failglob
126	mkdir tmp
127	touch tmp/l1 tmp/l2 tmp/l3
128
129	test_glob '' tmp/l[12] tmp/*4 tmp/*3
130	test_glob '' tmp/l[12] tmp/*4 tmp/*3
131
132	rm -r tmp
133	set --nofailglob
134fi
135
136test_glob '<bdir/>' b*/
137test_glob '<*>' \*
138test_glob '<a*>' 'a*'
139test_glob '<a*>' a\*
140test_glob '<c> <ca> <cb> <a*> <*q*>' c* a\* *q*
141test_glob '<**>' "*"*
142test_glob '<**>' \**
143test_glob '<\.\./*/>' "\.\./*/"
144test_glob '<s/\..*//>' 's/\..*//'
145test_glob '</^root:/{s/^[!:]*:[!:]*:\([!:]*\).*$/\1/>' "/^root:/{s/^[!:]*:[!:]*:\([!:]*\).*"'$'"/\1/"
146test_glob '<abc> <abd> <abe> <bb> <cb>' [a-c]b*
147test_glob ++Beware '<abd> <abe> <bb> <bcd> <bdir> <ca> <cb> <dd> <de>' [a-y]*[!c]
148test_glob '<abd> <abe>' a*[!c]
149
150touch a-b aXb
151
152test_glob '<a-b> <aXb>' a[X-]b
153
154touch .x .y
155
156test_glob --Beware '<Beware> <d> <dd> <de>' [!a-c]*
157
158if	mkdir a\*b 2>/dev/null
159then
160	touch a\*b/ooo
161
162	test_glob '<a*b/ooo>' a\*b/*
163	test_glob '<a*b/ooo>' a\*?/*
164	test_case '<match>' '!7' '*\!*'
165	test_case '<match>' 'r.*' '*.\*'
166	test_glob '<abc>' a[b]c
167	test_glob '<abc>' a["b"]c
168	test_glob '<abc>' a[\b]c
169	test_glob '<abc>' a?c
170	test_case '<match>' 'abc' 'a"b"c'
171	test_case '<match>' 'abc' 'a*c'
172	test_case '<nomatch>' 'abc' '"a?c"'
173	test_case '<nomatch>' 'abc' 'a\*c'
174	test_case '<nomatch>' 'abc' 'a\[b]c'
175	test_case '<match>' '"$undefined"' '""'
176	test_case '<match>' 'abc' 'a["\b"]c'
177
178	rm -rf mkdir a\*b
179fi
180
181mkdir man
182mkdir man/man1
183touch man/man1/sh.1
184
185test_glob '<man/man1/sh.1>' */man*/sh.*
186test_glob '<man/man1/sh.1>' $(echo */man*/sh.*)
187test_glob '<man/man1/sh.1>' "$(echo */man*/sh.*)"
188
189test_case '<match>' 'abc' 'a***c'
190test_case '<match>' 'abc' 'a*****?c'
191test_case '<match>' 'abc' '?*****??'
192test_case '<match>' 'abc' '*****??'
193test_case '<match>' 'abc' '*****??c'
194test_case '<match>' 'abc' '?*****?c'
195test_case '<match>' 'abc' '?***?****c'
196test_case '<match>' 'abc' '?***?****?'
197test_case '<match>' 'abc' '?***?****'
198test_case '<match>' 'abc' '*******c'
199test_case '<match>' 'abc' '*******?'
200test_case '<match>' 'abcdecdhjk' 'a*cd**?**??k'
201test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??k'
202test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??k***'
203test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k'
204test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k**'
205test_case '<match>' 'abcdecdhjk' 'a****c**?**??*****'
206test_case '<match>' "'-'" '[-abc]'
207test_case '<match>' "'-'" '[abc-]'
208test_case '<match>' "'\\'" '\\'
209test_case '<match>' "'\\'" '[\\]'
210test_case '<match>' "'\\'" "'\\'"
211test_case '<match>' "'['" '[[]'
212test_case '<match>' '[' '[[]'
213test_case '<match>' "'['" '['
214test_case '<match>' '[' '['
215test_case '<match>' "'[abc'" "'['*"
216test_case '<nomatch>' "'[abc'" '[*'
217test_case '<match>' '[abc' "'['*"
218test_case '<nomatch>' '[abc' '[*'
219test_case '<match>' 'abd' "a[b/c]d"
220test_case '<match>' 'a/d' "a[b/c]d"
221test_case '<match>' 'acd' "a[b/c]d"
222test_case '<match>' "']'" '[]]'
223test_case '<match>' "'-'" '[]-]'
224test_case '<match>' 'p' '[a-\z]'
225test_case '<match>' '"/tmp"' '[/\\]*'
226test_case '<nomatch>' 'abc' '??**********?****?'
227test_case '<nomatch>' 'abc' '??**********?****c'
228test_case '<nomatch>' 'abc' '?************c****?****'
229test_case '<nomatch>' 'abc' '*c*?**'
230test_case '<nomatch>' 'abc' 'a*****c*?**'
231test_case '<nomatch>' 'abc' 'a********???*******'
232test_case '<nomatch>' "'a'" '[]'
233test_case '<nomatch>' 'a' '[]'
234test_case '<nomatch>' "'['" '[abc'
235test_case '<nomatch>' '[' '[abc'
236
237test_glob ++Beware '<b> <bb> <bcd> <bdir>' b*
238test_glob '<Beware> <b> <bb> <bcd> <bdir>' [bB]*
239
240if	( set --nocaseglob ) 2>/dev/null
241then
242	set --nocaseglob
243
244	test_glob '<Beware> <b> <bb> <bcd> <bdir>' b*
245	test_glob '<Beware> <b> <bb> <bcd> <bdir>' [b]*
246	test_glob '<Beware> <b> <bb> <bcd> <bdir>' [bB]*
247
248	set --nonocaseglob
249fi
250
251if	( set -f ) 2>/dev/null
252then
253	set -f
254
255	test_glob '<*>' *
256
257	set +f
258fi
259
260if	( set --noglob ) 2>/dev/null
261then
262	set --noglob
263
264	test_glob '<*>' *
265
266	set --glob
267fi
268
269FIGNORE='@(.*|*)'
270test_glob '<*>' *
271
272FIGNORE='@(.*|*c|*e|?)'
273test_glob '<a-b> <aXb> <abd> <bb> <bcd> <bdir> <ca> <cb> <dd> <man>' *
274
275FIGNORE='@(.*|*b|*d|?)'
276test_glob '<Beware> <abc> <abe> <bdir> <ca> <de> <man>' *
277
278FIGNORE=
279test_glob '<man/man1/sh.1>' */man*/sh.*
280
281unset FIGNORE
282test_glob '<bb> <ca> <cb> <dd> <de>' ??
283test_glob '<man/man1/sh.1>' */man*/sh.*
284
285GLOBIGNORE='.*:*'
286set -- *
287if	[[ $1 == '*' ]]
288then
289	GLOBIGNORE='.*:*c:*e:?'
290	test_glob '<>' *
291
292	GLOBIGNORE='.*:*b:*d:?'
293	test_glob '<>' *
294
295	unset GLOBIGNORE
296	test_glob '<>' *
297	test_glob '<man/man1/sh.1>' */man*/sh.*
298
299	GLOBIGNORE=
300	test_glob '<man/man1/sh.1>' */man*/sh.*
301fi
302unset GLOBIGNORE
303
304function test_sub
305{
306	x='${subject'$2'}'
307	eval g=$x
308	if	[[ "$g" != "$3" ]]
309	then	'err_exit' $1 subject="'$subject' $x failed, expected '$3', got '$g'"
310	fi
311}
312alias test_sub='test_sub $LINENO'
313
314set --noglob --nobraceexpand
315
316subject='A regular expressions test'
317
318test_sub '/e/#'               'A r#gular expressions test'
319test_sub '//e/#'              'A r#gular #xpr#ssions t#st'
320test_sub '/[^e]/#'            '# regular expressions test'
321test_sub '//[^e]/#'           '###e######e###e########e##'
322test_sub '/+(e)/#'            'A r#gular expressions test'
323test_sub '//+(e)/#'           'A r#gular #xpr#ssions t#st'
324test_sub '/@-(e)/#'           'A r#gular expressions test'
325test_sub '//@-(e)/#'          'A r#gular #xpr#ssions t#st'
326test_sub '/?(e)/#'            '#A regular expressions test'
327test_sub '//?(e)/#'           '#A# #r#g#u#l#a#r# #x#p#r#s#s#i#o#n#s# #t#s#t#'
328test_sub '/*(e)/#'            '#A regular expressions test'
329test_sub '//*(e)/#'           '#A# #r#g#u#l#a#r# #x#p#r#s#s#i#o#n#s# #t#s#t#'
330test_sub '//@(e)/[\1]'        'A r[e]gular [e]xpr[e]ssions t[e]st'
331test_sub '//@-(e)/[\1]'       'A r[e]gular [e]xpr[e]ssions t[e]st'
332test_sub '//+(e)/[\1]'        'A r[e]gular [e]xpr[e]ssions t[e]st'
333test_sub '//+-(e)/[\1]'       'A r[e]gular [e]xpr[e]ssions t[e]st'
334test_sub '//@(+(e))/[\1]'     'A r[e]gular [e]xpr[e]ssions t[e]st'
335test_sub '//@(+-(e))/[\1]'    'A r[e]gular [e]xpr[e]ssions t[e]st'
336test_sub '//-(e)/#'           'A regular expressions test'
337test_sub '//--(e)/#'          'A regular expressions test'
338test_sub '//?(e)/[\1]'        '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
339test_sub '//{0,1}(e)/[\1]'    '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
340test_sub '//*(e)/[\1]'        '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
341test_sub '//{0,}(e)/[\1]'     '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
342test_sub '//@(?(e))/[\1]'     '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
343test_sub '//@({0,1}(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
344test_sub '//@(*(e))/[\1]'     '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
345test_sub '//@({0,}(e))/[\1]'  '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
346test_sub '/?-(e)/#'           '#A regular expressions test'
347test_sub '/@(?-(e))/[\1]'     '[]A regular expressions test'
348test_sub '/!(e)/#'            '#'
349test_sub '//!(e)/#'           '#'
350test_sub '/@(!(e))/[\1]'      '[A regular expressions test]'
351test_sub '//@(!(e))/[\1]'     '[A regular expressions test]'
352
353subject='e'
354
355test_sub '/!(e)/#'            '#e'
356test_sub '//!(e)/#'           '#e#'
357test_sub '/!(e)/[\1]'         '[]e'
358test_sub '//!(e)/[\1]'        '[]e[]'
359test_sub '/@(!(e))/[\1]'      '[]e'
360test_sub '//@(!(e))/[\1]'     '[]e[]'
361
362subject='a'
363
364test_sub '/@(!(a))/[\1]'      '[]a'
365test_sub '//@(!(a))/[\1]'     '[]a[]'
366
367subject='aha'
368
369test_sub '/@(!(a))/[\1]'      '[aha]'
370test_sub '//@(!(a))/[\1]'     '[aha]'
371test_sub '/@(!(aha))/[\1]'    '[ah]a'
372test_sub '//@(!(aha))/[\1]'   '[ah][a]'
373
374exit $((Errors<125?Errors:125))
375