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 63echo 'a b c 64s p q r 65x y' > $TEMP0 66echo 'a 67s p 68x' > $TEMP1 69$AWK '{ NF -= 2; $1 = $1; print }' < $TEMP0 > $TEMP2 70diff $TEMP1 $TEMP2 || fail "BAD: T.misc bad field self-assignment" 71 72echo '1 731' > $TEMP1 74$AWK 'BEGIN {x = 1; print x; x = x; print x}' > $TEMP2 75diff $TEMP1 $TEMP2 || fail "BAD: T.misc bad self-assignment" 76 77echo 573109312 | $AWK '{print $1*4}' > $TEMP1 78echo 2292437248 > $TEMP2 79diff $TEMP1 $TEMP2 || fail "BAD: T.misc bad overflow" 80 81# note that there are 8-bit characters in the echo 82# some shells will probably screw this up. 83echo '# 84code 1 85code 2' | 86$AWK '/^#/' > $TEMP1 87echo '#' > $TEMP2 88diff $TEMP1 $TEMP2 || fail "BAD: T.misc bad match of 8-bit char" 89 90echo hello | 91$AWK 'BEGIN { FILENAME = "/etc/passwd" } 92 { print $0 }' >/dev/null 93if [[ $? -eq 139 ]]; then fail "BAD: T.misc /etc/passwd dropped core"; fi 94 95echo '2 9610' | 97$AWK '{ x[NR] = $0 } # test whether $0 is NUM as well as STR 98END { if (x[1] > x[2]) print "BAD: T.misc: $0 is not NUM" }' 99 100 101$AWK 'BEGIN { 102 npad = substr("alexander" " ",1,15) 103 print npad 104 }' > $TEMP0 105grep '\\' $TEMP0 && fail "BAD: T.misc alexander fails" 106 107# This should give an error about function arguments 108$AWK ' 109function foo(x) { print "x is" x } 110BEGIN { foo(foo) } 111' 2> $TEMP0 112grep "can't use function foo" $TEMP0 >/dev/null || fail "BAD: T.misc fcn args" 113 114 115# gawk defref test; should give error about undefined function 116$AWK 'BEGIN { foo() }' 2> $TEMP0 117grep "calling undefined function foo" $TEMP0 >/dev/null || fail "BAD: T.misc undefined function" 118 119 120# gawk arrayparm test; should give error about function 121$AWK ' 122BEGIN { 123 foo[1]=1; 124 foo[2]=2; 125 bug1(foo); 126} 127function bug1(i) { 128 for (i in foo) { 129 bug2(i); 130 delete foo[i]; 131 print i,1,bot[1]; 132 } 133} 134function bug2(arg) { 135 bot[arg]=arg; 136} 137' 2> $TEMP0 138grep "can.t assign to foo" $TEMP0 >/dev/null || fail "BAD: T.misc foo bug" 139 140 141# This should print bbb 142$AWK ' 143BEGIN { up[1] = "a" 144 for (i in up) gsub("a", "A", x) 145 print x x "bbb" 146 exit 147 } 148' > $TEMP0 149grep bbb $TEMP0 >/dev/null || fail "BAD: T.misc gsub failed" 150 151echo yes | 152$AWK ' 153BEGIN { 154 printf "push return" >"/dev/null" 155 getline ans <"/dev/null" 156} ' 157if [[ $? -eq 139 ]]; then fail "BAD: T.misc getline ans dropped core"; fi 158 159$AWK 'BEGIN { unireghf() } 160function unireghf(hfeed) { hfeed[1] = 0 }' 161if [[ $? -eq 139 ]]; then fail "BAD: T.misc unireghf dropped core"; fi 162 163echo x | $AWK '/[/]/' 2> $TEMP0 164grep 'nonterminated character class' $TEMP0 >/dev/null || error 'BAD: T.misc nonterminated fails' 165if [[ $? -eq 139 ]]; then fail "BAD: T.misc nonterminated dropped core"; fi 166 167$AWK ' 168function f() { return 12345 } 169BEGIN { printf "<%s>\n", f() } 170' > $TEMP0 171grep '<12345>' $TEMP0 >/dev/null || fail 'BAD: T.misc <12345> fails' 172 173echo 'abc 174def 175 176ghi 177jkl' > $TEMP0 178$AWK ' 179BEGIN { RS = "" 180 while (getline <"'$TEMP0'") 181 print 182}' > $TEMP1 183$AWK 'END {print NR}' $TEMP1 | grep 4 >/dev/null || fail 'BAD: T.misc abcdef fails' 184 185 186# The following should not produce a warning about changing a constant 187# nor about a curdled tempcell list 188$AWK 'function f(x) { x = 2 } 189BEGIN { f(1) }' > $TEMP0 190grep '^' $TEMP0 && fail 'BAD: test constant change fails' 191 192# The following should not produce a warning about a curdled tempcell list 193$AWK 'function f(x) { x } 194BEGIN { f(1) }' > $TEMP0 195grep '^' $TEMP0 && fail 'BAD: test tempcell list fails' 196 197$AWK 'BEGIN { print 9, a=10, 11; print a; exit }' > $TEMP1 198echo '9 10 11 19910' > $TEMP2 200diff $TEMP1 $TEMP2 || fail 'BAD: T.misc (embedded expression)' 201 202echo "abc defgh ijkl" | $AWK ' 203 { $1 = ""; line = $0; print line; print $0; $0 = line; print $0 }' > $TEMP1 204echo " defgh ijkl 205 defgh ijkl 206 defgh ijkl" > $TEMP2 207diff $TEMP1 $TEMP2 || fail 'BAD: T.misc (assignment to $0)' 208 209$AWK ' 210function min(a, b) 211{ 212 if (a < b) 213 return a 214 else 215 return b 216} 217BEGIN { exit } 218' 219if [[ $? -eq 139 ]]; then fail "BAD: T.misc function min dropped core"; fi 220 221# The following should not give a syntax error message: 222$AWK ' 223function expand(chart) { 224 getline chart < "CHAR.ticks" 225} 226' > $TEMP0 227grep '^' $TEMP0 >/dev/null && fail 'BAD: T.misc expand error' 228 229$AWK 'BEGIN { print 1e40 }' >/dev/null 230if [[ $? -eq 139 ]]; then fail "BAD: T.misc 1E40 dropped core"; fi 231 232# The following syntax error should not dump core: 233$AWK ' 234$NF==3 {first=1} 235$NF==2 && first==0 && (abs($1-o1)>120||abs($2-o2)>120) {print $0} 236$NF==2 {o1=%1; o2=$2; first=0} 237' 2>/dev/null 238if [[ $? -eq 139 ]]; then fail "BAD: T.misc first/abs dropped core"; fi 239 240# The following syntax error should not dump core: 241$AWK '{ n = split($1, address, !); print address[1] }' 2> $TEMP0 242grep 'illegal statement' $TEMP0 >/dev/null || fail 'BAD: T.misc split error' 243if [[ $? -eq 139 ]]; then fail "BAD: T.misc split! dropped core"; fi 244 245# The following should cause a syntax error message 246$AWK 'BEGIN {"hello"}' 2> $TEMP0 247grep 'illegal statement' $TEMP0 >/dev/null || fail 'BAD: T.misc hello error' 248 249# The following should give a syntax error message: 250$AWK ' 251function pile(c, r) { 252 r = ++pile[c] 253} 254 255{ pile($1) } 256' 2> $TEMP0 257grep 'context is' $TEMP0 >/dev/null || fail 'BAD: T.misc pile error' 258 259# This should complain about missing atan2 argument: 260$AWK 'BEGIN { atan2(1) }' 2> $TEMP0 261grep 'requires two arg' $TEMP0 >/dev/null || fail 'BAD: T.misc atan2 error' 262 263# This should not core dump: 264$AWK 'BEGIN { f() } 265function f(A) { delete A[1] } 266' 267if [[ $? -eq 139 ]]; then fail "BAD: T.misc delete dropped core"; fi 268 269# nasty one: should not be able to overwrite constants 270$AWK 'BEGIN { gsub(/ana/,"anda","banana") 271 printf "the monkey ate a %s\n", "banana" } 272' >/dev/null 2> $TEMP0 273grep 'syntax error' $TEMP0 >/dev/null || fail 'BAD: T.misc gsub banana error' 274 275# nasty one: should not be able to overwrite constants 276$AWK 'BEGIN { sub(/ana/,"anda","banana") 277 printf "the monkey ate a %s\n", "banana" } 278' >/dev/null 2> $TEMP0 279grep 'syntax error' $TEMP0 >/dev/null || fail 'BAD: T.misc sub banana error' 280 281# line numbers used to double-count comments 282$AWK '# 283# 284# 285/x 286' >/dev/null 2> $TEMP0 287grep 'line [45]' $TEMP0 >/dev/null || fail 'BAD: T.misc lineno' 288 289echo 'x 290\y' > $TEMP1 291$AWK 'BEGIN { print "x\f\r\b\v\a\\y" }' > $TEMP2 292cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc weird chars' 293 294echo 0 > $TEMP1 295$AWK ' BEGIN { exit } 296 { print } 297 END { print NR }' > $TEMP2 298cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc BEGIN exit' 299 300echo 1 > $TEMP1 301$AWK ' { exit } 302 END { print NR }' /etc/passwd > $TEMP2 303cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc immmediate exit' 304 305echo 1 > $TEMP1 306$AWK ' {i = 1; while (i <= NF) {if (i == NF) exit; i++ } } 307 END { print NR }' /etc/passwd > $TEMP2 308cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc immmediate exit 2' 309 310echo 1 > $TEMP1 311$AWK ' function f() { 312 i = 1; while (i <= NF) {if (i == NF) return NR; i++ } 313 } 314 { if (f() == 1) exit } 315 END { print NR }' /etc/passwd > $TEMP2 316cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc while return' 317 318echo 1 > $TEMP1 319$AWK ' function f() { 320 split("a b c", arr) 321 for (i in arr) {if (i == 3) return NR; i++ } 322 } 323 { if (f() == 1) exit } 324 END { print NR }' /etc/passwd > $TEMP2 325cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc while return' 326 327echo 1 > $TEMP1 328$AWK ' {i = 1; do { if (i == NF) exit; i++ } while (i <= NF) } 329 END { print NR }' /etc/passwd > $TEMP2 330cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc immmediate exit 3' 331 332echo 1 > $TEMP1 333$AWK ' function f() { 334 i = 1; do { if (i == NF) return NR; i++ } while (i <= NF) 335 } 336 { if (f() == 1) exit } 337 END { print NR }' /etc/passwd > $TEMP2 338cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc do return' 339 340echo 1 > $TEMP1 341$AWK ' {i = 1; do { if (i == NF) break; i++ } while (i <= NF); exit } 342 END { print NR }' /etc/passwd > $TEMP2 343cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc immmediate exit 4' 344 345echo 1 > $TEMP1 346$AWK ' { n = split($0, x) 347 for (i in x) { 348 if (i == 1) 349 exit } } 350 END { print NR }' /etc/passwd > $TEMP2 351cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc immmediate exit 5' 352 353echo XXXXXXXX > $TEMP1 354$AWK 'BEGIN { s = "ab\fc\rd\be" 355 t = s; gsub("[" s "]", "X", t); print t }' > $TEMP2 356cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc weird escapes in char class' 357 358$AWK '{}' /etc/passwd glop/glop > $TEMP0 2> $TEMP2 359grep "can't open.*glop" $TEMP2 >/dev/null || fail "BAD: T.misc can't open" 360 361echo ' 362 363 364a 365aa 366 367b 368 369 370c 371 372' > $TEMP0 373echo 3 > $TEMP1 374$AWK 'BEGIN { RS = "" }; END { print NR }' $TEMP0 > $TEMP2 375cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc RS botch' 376 377$AWK 'BEGIN \ 378 { 379 print "hello, world" 380 } 381}}}' > $TEMP1 2> $TEMP2 382grep 'source line 5' $TEMP2 >/dev/null 2>&1 || fail 'BAD: T.misc continuation line number' 383 384 385echo 111 222 333 > $TEMP0 386$AWK '{ f[1]=1; f[2]=2; print $f[1], $f[1]++, $f[2], f[1], f[2] }' $TEMP0 > $TEMP2 387echo 111 111 222 2 2 > $TEMP1 388cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc $f[1]++' 389 390 391# These should be syntax errors 392$AWK . 2> $TEMP0 393grep "syntax error" $TEMP0 >/dev/null || fail "BAD: T.misc syntax error . fails" 394 395$AWK .. 2> $TEMP0 396grep "syntax error" $TEMP0 >/dev/null || fail "BAD: T.misc syntax error .. fails" 397 398$AWK .E. 2> $TEMP0 399grep "syntax error" $TEMP0 >/dev/null || fail "BAD: T.misc syntax error .E. fails" 400 401$AWK .++. 2> $TEMP0 402grep "syntax error" $TEMP0 >/dev/null || fail "BAD: T.misc syntax error .++. fails" 403 404 405# next several were infinite loops, found by brian tsang. 406# this is his example: 407 408$AWK 'BEGIN { 409 switch (substr("x",1,1)) { 410 case /ask.com/: 411 break 412 case "google": 413 break 414 } 415}' > $TEMP0 2>&1 416grep "illegal statement" $TEMP0 >/dev/null || fail "BAD: T.misc looping syntax error 1" 417 418$AWK 'BEGIN { s { c /./ } }' > $TEMP0 2>&1 419grep "illegal statement" $TEMP0 >/dev/null || fail "BAD: T.misc looping syntax error 2" 420 421$AWK 'BEGIN { s { c /../ } }' > $TEMP0 2>&1 422grep "illegal statement" $TEMP0 >/dev/null || fail "BAD: T.misc looping syntax error 3" 423 424echo '' > $TEMP0 425$AWK 'END { print NF, $0 }' $TEMP0 > $TEMP1 426awk '{ print NF, $0 }' $TEMP0| tail -1 > $TEMP2 427cmp -s $TEMP1 $TEMP2 || fail 'BAD: T.misc END must preserve $0' 428 429exit $RESULT 430