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