xref: /freebsd/contrib/one-true-awk/testdir/T.misc (revision a91a2465)
1#!/bin/sh
2
3echo T.misc: miscellaneous buglets now watched for
4
5awk=${awk-../a.out}
6
7rm -f core
8
9echo 'The big brown over the lazy doe
10The big brown over the lazy dog
11x
12The big brown over the lazy dog' >foo
13echo 'failed
14succeeded
15failed
16succeeded' >foo1
17$awk '{ if (match($0, /^The big brown over the lazy dog/) == 0) {
18		printf("failed\n")
19	} else {
20		printf("succeeded\n")
21	}
22} ' foo >foo2
23cmp -s foo1 foo2 || echo 'BAD: T.misc ghosh RE bug'
24
25echo '123
261234567890
2712345678901' >foo
28echo '12345678901' >foo1
29$awk 'length($0) > 10' foo >foo2
30cmp -s foo1 foo2 || echo 'BAD: T.misc last number bug'
31
32# check some \ sequences in strings (ascii)
33echo HIJKL >foo1
34echo foo | $awk '{ print "H\x49\x4a\x4BL" }' >foo2
35cmp -s foo1 foo2 || echo 'BAD: T.misc hex string cvt'
36
37echo 012x45 >foo1
38$awk 'BEGIN { print "0\061\62x\0645" }' >foo2
39cmp -s foo1 foo2 || echo 'BAD: T.misc oct string cvt'
40
41# $i++ means ($i)++
42echo 3 5 | $awk '{ i = 1; print $i++ ; print $1, i }' >foo1
43echo '3
444 1' >foo2
45cmp -s foo1 foo2 || echo 'BAD: T.misc bad field increment'
46
47# makes sure that fields are recomputed even if self-assignment
48# take into account that subtracting from NF now rebuilds the record
49echo 'a b c
50s p q r
51x y z' >foo
52echo 'a
53s p
54x' >foo1
55$awk '{ NF -= 2; $1 = $1; print }' <foo >foo2
56diff foo1 foo2 || echo 1>&2 "BAD: T.misc bad field self-assignment"
57
58echo '1
591' >foo1
60$awk 'BEGIN {x = 1; print x; x = x; print x}' >foo2
61diff foo1 foo2 || echo 1>&2 "BAD: T.misc bad self-assignment"
62
63echo 573109312 | $awk '{print $1*4}' >foo1
64echo 2292437248 >foo2
65diff foo1 foo2 || echo 1>&2 "BAD: T.misc bad overflow"
66
67# note that there are 8-bit characters in the echo
68# some shells will probably screw this up.
69echo '#
70code € 1
71code € 2' |
72$awk '/^#/' >foo1
73echo '#' >foo2
74diff foo1 foo2 || echo 1>&2 "BAD: T.misc bad match of 8-bit char"
75
76echo hello |
77$awk 'BEGIN	{ FILENAME = "/etc/passwd" }
78	{ print $0 }' >/dev/null
79if test -r core; then echo 1>&2 "BAD: T.misc /etc/passwd dropped core"; fi
80
81echo hello |
82$awk '  function foo(foo) {
83                foo = 1
84                foo()
85        }
86	{ foo(bar) }
87' >/dev/null 2>&1
88if test -r core; then
89	echo 1>&2 "BAD: T.misc function foo(foo) dropped core"
90	rm -f core
91fi
92
93echo '2
9410' |
95$awk '{ x[NR] = $0 }	# test whether $0 is NUM as well as STR
96END { if (x[1] > x[2]) print "BAD: T.misc: $0 is not NUM" }'
97
98
99$awk 'BEGIN {
100	npad = substr("alexander" "           ",1,15)
101	print npad
102	}' >foo
103grep '\\' foo && echo 1>&2 "BAD: T.misc alexander fails"
104
105# This should give an error about function arguments
106$awk '
107function foo(x) { print "x is" x }
108BEGIN { foo(foo) }
109' 2>foo
110grep "can't use function foo" foo >/dev/null || echo 1>&2 "BAD: T.misc fcn args"
111
112
113# gawk defref test; should give error about undefined function
114$awk 'BEGIN { foo() }' 2>foo
115grep "calling undefined function foo" foo >/dev/null || echo 1>&2 "BAD: T.misc undefined function"
116
117
118# gawk arrayparm test; should give error about function
119$awk '
120BEGIN {
121    foo[1]=1;
122    foo[2]=2;
123    bug1(foo);
124}
125function bug1(i) {
126    for (i in foo) {
127	bug2(i);
128	delete foo[i];
129	print i,1,bot[1];
130    }
131}
132function bug2(arg) {
133    bot[arg]=arg;
134}
135' 2>foo
136grep "can.t assign to foo" foo >/dev/null || echo 1>&2 "BAD: T.misc foo bug"
137
138
139# This should be a syntax error
140$awk '
141!x = y
142' 2>foo
143grep "syntax error" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error !x=y fails"
144
145# This should print bbb
146$awk '
147BEGIN { up[1] = "a"
148	for (i in up) gsub("a", "A", x)
149	print x x "bbb"
150	exit
151      }
152' >foo
153grep bbb foo >/dev/null || echo 1>&2 "BAD: T.misc gsub failed"
154
155echo yes |
156$awk '
157BEGIN {
158	printf "push return" >"/dev/null"
159	getline ans <"/dev/null"
160} '
161if test -r core; then echo 1>&2 "BAD: T.misc getline ans dropped core"; fi
162
163$awk 'BEGIN { unireghf() }
164function unireghf(hfeed) { hfeed[1] = 0 }'
165if test -r core; then echo 1>&2 "BAD: T.misc unireghf dropped core"; fi
166
167echo x | $awk '/[/]/' 2>foo
168grep 'nonterminated character class' foo >/dev/null || error 'BAD: T.misc nonterminated fails'
169if test -r core; then echo 1>&2 "BAD: T.misc nonterminated dropped core"; fi
170
171$awk '
172function f() { return 12345 }
173BEGIN { printf "<%s>\n", f() }
174' >foo
175grep '<12345>' foo >/dev/null || echo 'BAD: T.misc <12345> fails'
176
177echo 'abc
178def
179
180ghi
181jkl' >foo
182$awk '
183BEGIN {	RS = ""
184	while (getline <"foo")
185		print
186}' >foo1
187$awk 'END {print NR}' foo1 | grep 4 >/dev/null || echo 'BAD: T.misc abcdef fails'
188
189# Test for RS regex matching an empty record at EOF
190echo a | $awk 1 RS='a\n' > foo1
191cat << \EOF > foo2
192
193EOF
194diff foo1 foo2 || echo 'BAD: T.misc RS regex matching an empty record at EOF fails'
195
196# Test for RS regex being reapplied
197echo aaa1a2a | $awk 1 RS='^a' >foo1
198cat << \EOF > foo2
199
200aa1a2a
201
202EOF
203diff foo1 foo2 || echo 'BAD: T.misc ^regex reapplied fails'
204
205# ^-anchored RS matching should be active at the start of each input file
206tee foo1 foo2 >foo3 << \EOF
207aaa
208EOF
209$awk 1 RS='^a' foo1 foo2 foo3 >foo4
210cat << \EOF > foo5
211
212aa
213
214
215aa
216
217
218aa
219
220EOF
221diff foo4 foo5 || echo 'BAD: T.misc ^RS matches the start of every input file fails'
222
223# The following should not produce a warning about changing a constant
224# nor about a curdled tempcell list
225$awk 'function f(x) { x = 2 }
226BEGIN { f(1) }' >foo
227grep '^' foo && echo 'BAD: test constant change fails'
228
229# The following should not produce a warning about a curdled tempcell list
230$awk 'function f(x) { x }
231BEGIN { f(1) }' >foo
232grep '^' foo && echo 'BAD: test tempcell list fails'
233
234$awk 'BEGIN { print 9, a=10, 11; print a; exit }' >foo1
235echo '9 10 11
23610' >foo2
237diff foo1 foo2 || echo 'BAD: T.misc (embedded expression)'
238
239echo "abc defgh ijkl" | $awk '
240  { $1 = ""; line = $0; print line; print $0; $0 = line; print $0 }' >foo1
241echo " defgh ijkl
242 defgh ijkl
243 defgh ijkl" >foo2
244diff foo1 foo2 || echo 'BAD: T.misc (assignment to $0)'
245
246$awk '
247function min(a, b)
248{
249	if (a < b)
250		return a
251	else
252		return b
253}
254BEGIN { exit }
255'
256if test -r core; then echo 1>&2 "BAD: T.misc function min dropped core"; fi
257
258# The following should not give a syntax error message:
259$awk '
260function expand(chart) {
261	getline chart < "CHAR.ticks"
262}
263' >foo
264grep '^' foo >/dev/null && echo 'BAD: T.misc expand error'
265
266$awk 'BEGIN { print 1e40 }' >/dev/null
267if test -r core; then echo 1>&2 "BAD: T.misc 1E40 dropped core"; fi
268
269# The following syntax error should not dump core:
270$awk '
271$NF==3	{first=1}
272$NF==2 && first==0 && (abs($1-o1)>120||abs($2-o2)>120)	{print $0}
273$NF==2	{o1=%1; o2=$2; first=0}
274' 2>/dev/null
275if test -r core; then echo 1>&2 "BAD: T.misc first/abs dropped core"; fi
276
277# The following syntax error should not dump core:
278$awk '{ n = split($1, address, !); print address[1] }' 2>foo
279grep 'illegal statement' foo >/dev/null || echo 'BAD: T.misc split error'
280if test -r core; then echo 1>&2 "BAD: T.misc split! dropped core"; fi
281
282# The following should cause a syntax error message
283$awk 'BEGIN {"hello"}' 2>foo
284grep 'illegal statement' foo >/dev/null || echo 'BAD: T.misc hello error'
285
286# The following should give a syntax error message:
287$awk '
288function pile(c,     r) {
289	r = ++pile[c]
290}
291
292{ pile($1) }
293' 2>foo
294grep 'context is' foo >/dev/null || echo 'BAD: T.misc pile error'
295
296# This should complain about missing atan2 argument:
297$awk 'BEGIN { atan2(1) }' 2>foo
298grep 'requires two arg' foo >/dev/null || echo 'BAD: T.misc atan2 error'
299
300# This should not core dump:
301$awk 'BEGIN { f() }
302function f(A) { delete A[1] }
303'
304if test -r core; then echo 1>&2 "BAD: T.misc delete dropped core"; fi
305
306# nasty one:  should not be able to overwrite constants
307$awk 'BEGIN { gsub(/ana/,"anda","banana")
308		printf "the monkey ate a %s\n", "banana" }
309' >/dev/null 2>foo
310grep 'syntax error' foo >/dev/null || echo 'BAD: T.misc gsub banana error'
311
312# nasty one:  should not be able to overwrite constants
313$awk 'BEGIN { sub(/ana/,"anda","banana")
314		printf "the monkey ate a %s\n", "banana" }
315' >/dev/null 2>foo
316grep 'syntax error' foo >/dev/null || echo 'BAD: T.misc sub banana error'
317
318# line numbers used to double-count comments
319$awk '#
320#
321#
322/x
323' >/dev/null 2>foo
324grep 'line [45]' foo >/dev/null || echo 'BAD: T.misc lineno'
325
326echo 'x
327\y' >foo1
328$awk 'BEGIN { print "x\f\r\b\v\a\\y" }' >foo2
329cmp -s foo1 foo2 || echo 'BAD: T.misc weird chars'
330
331echo 0 >foo1
332$awk '	BEGIN { exit }
333	{ print }
334	END { print NR }' >foo2
335cmp -s foo1 foo2 || echo 'BAD: T.misc BEGIN exit'
336
337echo 1 >foo1
338$awk '	{ exit }
339	END { print NR }' /etc/passwd >foo2
340cmp -s foo1 foo2 || echo 'BAD: T.misc immmediate exit'
341
342echo 1 >foo1
343$awk '	{i = 1; while (i <= NF) {if (i == NF) exit; i++ } }
344	END { print NR }' /etc/passwd >foo2
345cmp -s foo1 foo2 || echo 'BAD: T.misc immmediate exit 2'
346
347echo 1 >foo1
348$awk '	function f() {
349		i = 1; while (i <= NF) {if (i == NF) return NR; i++ }
350	}
351	{ if (f() == 1) exit }
352	END { print NR }' /etc/passwd >foo2
353cmp -s foo1 foo2 || echo 'BAD: T.misc while return'
354
355echo 1 >foo1
356$awk '	function f() {
357		split("a b c", arr)
358		for (i in arr) {if (i == 3) return NR; i++ }
359	}
360	{ if (f() == 1) exit }
361	END { print NR }' /etc/passwd >foo2
362cmp -s foo1 foo2 || echo 'BAD: T.misc while return'
363
364echo 1 >foo1
365$awk '	{i = 1; do { if (i == NF) exit; i++ } while (i <= NF) }
366	END { print NR }' /etc/passwd >foo2
367cmp -s foo1 foo2 || echo 'BAD: T.misc immmediate exit 3'
368
369echo 1 >foo1
370$awk '	function f() {
371		i = 1; do { if (i == NF) return NR; i++ } while (i <= NF)
372	}
373	{ if (f() == 1) exit }
374	END { print NR }' /etc/passwd >foo2
375cmp -s foo1 foo2 || echo 'BAD: T.misc do return'
376
377echo 1 >foo1
378$awk '	{i = 1; do { if (i == NF) break; i++ } while (i <= NF); exit }
379	END { print NR }' /etc/passwd >foo2
380cmp -s foo1 foo2 || echo 'BAD: T.misc immmediate exit 4'
381
382echo 1 >foo1
383$awk '	{ n = split($0, x)
384	  for (i in x) {
385	 	if (i == 1)
386			exit } }
387	END { print NR }' /etc/passwd >foo2
388cmp -s foo1 foo2 || echo 'BAD: T.misc immmediate exit 5'
389
390echo XXXXXXXX >foo1
391$awk 'BEGIN { s = "ab\fc\rd\be"
392	t = s; 	gsub("[" s "]", "X", t); print t }' >foo2
393cmp -s foo1 foo2 || echo 'BAD: T.misc weird escapes in char class'
394
395$awk '{}' /etc/passwd glop/glop >foo 2>foo2
396grep "can't open.*glop" foo2 >/dev/null || echo "BAD: T.misc can't open"
397
398echo '
399
400
401a
402aa
403
404b
405
406
407c
408
409' >foo
410echo 3 >foo1
411$awk 'BEGIN { RS = "" }; END { print NR }' foo >foo2
412cmp -s foo1 foo2 || echo 'BAD: T.misc RS botch'
413
414$awk 'BEGIN \
415	{
416		print "hello, world"
417	}
418}}}' >foo1 2>foo2
419grep 'source line 4' foo2 >/dev/null 2>&1 || echo 'BAD: T.misc continuation line number'
420
421
422echo 111 222 333 >foo
423$awk '{ f[1]=1; f[2]=2; print $f[1], $f[1]++, $f[2], f[1], f[2] }' foo >foo2
424echo 111 111 222 2 2 >foo1
425cmp -s foo1 foo2 || echo 'BAD: T.misc $f[1]++'
426
427
428# These should be syntax errors
429$awk . 2>foo
430grep "syntax error" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error . fails"
431
432$awk .. 2>foo
433grep "syntax error" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error .. fails"
434
435$awk .E. 2>foo
436grep "syntax error" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error .E. fails"
437
438$awk .++. 2>foo
439grep "syntax error" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error .++. fails"
440
441
442
443# These should be syntax errors
444$awk '$' 2>foo
445grep "unexpected" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error $ fails"
446
447$awk '{print $' 2>foo
448grep "unexpected" foo >/dev/null || echo 1>&2 "BAD: T.misc syntax error $2 fails"
449
450$awk '"' 2>foo
451grep "non-terminated" foo >/dev/null || echo 1>&2 "BAD: T.misc bare quote fails"
452
453
454# %c of 0 is explicit null byte
455
456./echo '3' >foo1
457$awk 'BEGIN {printf("%c%c\n", 0, 0) }' | wc | $awk '{print $3}' >foo2
458cmp -s foo1 foo2 || echo 'BAD: T.misc null byte'
459
460# non-terminated RE
461
462$awk /xyz >foo 2>&1
463grep "non-terminated" foo >/dev/null || echo 1>&2 "BAD: T.misc non-terminated RE"
464
465# next several were infinite loops, found by brian tsang.
466# this is his example:
467
468$awk 'BEGIN {
469    switch (substr("x",1,1)) {
470    case /ask.com/:
471	break
472    case "google":
473	break
474    }
475}' >foo 2>&1
476grep "illegal statement" foo >/dev/null || echo 1>&2 "BAD: T.misc looping syntax error 1"
477
478$awk 'BEGIN { s { c /./ } }' >foo 2>&1
479grep "illegal statement" foo >/dev/null || echo 1>&2 "BAD: T.misc looping syntax error 2"
480
481$awk 'BEGIN { s { c /../ } }' >foo 2>&1
482grep "illegal statement" foo >/dev/null || echo 1>&2 "BAD: T.misc looping syntax error 3"
483
484$awk 'BEGIN {printf "%2$s %1$s\n", "a", "b"}' >foo 2>&1
485grep "'$' not permitted in awk formats" foo >/dev/null || echo 1>&2 "BAD: T.misc '$' not permitted in formats"
486
487echo 'a
488b c
489de fg hi' >foo0
490$awk 'END { print NF, $0 }' foo0 >foo1
491awk '{ print NF, $0 }' foo0| tail -1 >foo2
492cmp -s foo1 foo2 || echo 'BAD: T.misc END must preserve $0'
493
494echo 'fg hi' >foo0
495$awk 'END { print NF, $0 }' foo0 >foo1
496awk '{ print NF, $0 }' foo0| tail -1 >foo2
497cmp -s foo1 foo2 || echo 'BAD: T.misc END must preserve $0'
498
499echo '' >foo0
500$awk 'END { print NF, $0 }' foo0 >foo1
501awk '{ print NF, $0 }' foo0| tail -1 >foo2
502cmp -s foo1 foo2 || echo 'BAD: T.misc END must preserve $0'
503
504# Check for nonzero exit status on I/O error.
505echo 'E 2' >foo1
506(trap '' PIPE; "$awk" 'BEGIN { print "hi"; }' 2>/dev/null; echo "E $?" >foo2) | :
507cmp -s foo1 foo2 || echo 'BAD: T.misc exit status on I/O error'
508
509# Check for clobbering of the lexer's regular expression buffer.
510# If the output is "a1" instead of "1b", /b/ clobbered /a/.
511echo 1b >foo1
512echo ab | $awk '{ sub(/a/, "b" ~ /b/); print }' >foo2
513cmp -s foo1 foo2 || echo 'BAD: T.misc lexer regex buffer clobbered'
514
515# Check handling of octal \OOO and hex \xHH esc. seqs. in strings.
516echo 'hello888
517hello
518hello
519helloxGOO
520hello
5210A' > foo1
522$awk 'BEGIN { print "hello\888" }'   > foo2
523$awk 'BEGIN { print "hello\x000A" }' >> foo2
524$awk 'BEGIN { printf "hello\x0A" }'  >> foo2
525$awk 'BEGIN { print "hello\xGOO" }'  >> foo2
526$awk 'BEGIN { print "hello\x0A0A" }' >> foo2
527cmp -s foo1 foo2 || echo '�BAD: T.misc escape sequences in strings mishandled'
528