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 8TEMP1=$WORKDIR/test.temp.1 9TEMP2=$WORKDIR/test.temp.2 10 11RESULT=0 12 13fail() { 14 echo "$1" >&2 15 RESULT=1 16} 17 18echo T.func: test user-defined functions 19 20echo '10 2 212 10 2210 10 2310 1e1 241e1 9' | $AWK ' 25# tests whether function returns sensible type bits 26 27function assert(cond) { # assertion 28 if (cond) print 1; else print 0 29} 30 31function i(x) { return x } 32 33{ m=$1; n=i($2); assert(m>n) } 34' > $TEMP1 35echo '1 360 370 380 391' > $TEMP2 40diff $TEMP1 $TEMP2 || fail 'BAD: T.func (function return type)' 41 42echo 'data: data' > $TEMP1 43$AWK ' 44function test1(array) { array["test"] = "data" } 45function test2(array) { return(array["test"]) } 46BEGIN { test1(foo); print "data: " test2(foo) } 47' > $TEMP2 48diff $TEMP1 $TEMP2 || fail 'BAD: T.func (array type)' 49 50$AWK ' 51BEGIN { code() } 52END { codeout("x") } 53function code() { ; } 54function codeout(ex) { print ex } 55' /dev/null > $TEMP1 56echo x > $TEMP2 57diff $TEMP1 $TEMP2 || fail 'BAD: T.func (argument passing)' 58 59$AWK ' 60BEGIN { unireghf() } 61 62function unireghf(hfeed) { 63 hfeed[1]=0 64 rcell("foo",hfeed) 65 hfeed[1]=0 66 rcell("bar",hfeed) 67} 68 69function rcell(cellname,hfeed) { 70 print cellname 71} 72' > $TEMP1 73echo "foo 74bar" > $TEMP2 75diff $TEMP1 $TEMP2 || fail 'BAD: T.func (convert arg to array)' 76 77$AWK ' 78function f(n) { 79 if (n <= 1) 80 return 1 81 else 82 return n * f(n-1) 83} 84{ print f($1) } 85' > $TEMP2 <<! 860 871 882 893 904 915 926 937 948 959 96! 97cat > $TEMP1 <<! 981 991 1002 1016 10224 103120 104720 1055040 10640320 107362880 108! 109diff $TEMP1 $TEMP2 || fail 'BAD: T.func (factorial)' 110 111$AWK ' 112function ack(m,n) { 113 k = k+1 114 if (m == 0) return n+1 115 if (n == 0) return ack(m-1, 1) 116 return ack(m-1, ack(m, n-1)) 117} 118{ k = 0; print ack($1,$2), "(" k " calls)" } 119' > $TEMP2 <<! 1200 0 1211 1 1222 2 1233 3 1243 4 1253 5 126! 127cat > $TEMP1 <<! 1281 (1 calls) 1293 (4 calls) 1307 (27 calls) 13161 (2432 calls) 132125 (10307 calls) 133253 (42438 calls) 134! 135diff $TEMP1 $TEMP2 || fail 'BAD: T.func (ackermann)' 136 137$AWK ' 138END { print "end" } 139{ print fib($1) } 140function fib(n) { 141 if (n <= 1) return 1 142 else return add(fib(n-1), fib(n-2)) 143} 144function add(m,n) { return m+n } 145BEGIN { print "begin" } 146' > $TEMP2 <<! 1471 1483 1495 15010 151! 152cat > $TEMP1 <<! 153begin 1541 1553 1568 15789 158end 159! 160diff $TEMP1 $TEMP2 || fail 'BAD: T.func (fib)' 161 162$AWK ' 163function foo() { 164 for (i = 1; i <= 2; i++) 165 return 3 166 print "should not see this" 167} 168BEGIN { foo(); exit } 169' > $TEMP1 170grep 'should not' $TEMP1 && fail 'BAD: T.func (return)' 171 172# this exercises multiple free of temp cells 173echo 'eqn 174eqn2' > $TEMP1 175$AWK 'BEGIN { eprocess("eqn", "x", contig) 176 process("tbl" ) 177 eprocess("eqn" "2", "x", contig) 178 } 179function eprocess(file, first, contig) { 180 print file 181} 182function process(file) { 183 close(file) 184}' > $TEMP2 185diff $TEMP1 $TEMP2 || fail 'BAD: T.func (eqn)' 186 187echo 1 > $TEMP1 188$AWK 'function f() { n = 1; exit } 189 BEGIN { n = 0; f(); n = 2 }; END { print n}' > $TEMP2 190diff $TEMP1 $TEMP2 || fail 'BAD: T.func (exit in function)' 191 192echo 1 > $TEMP1 193$AWK ' 194BEGIN { n = 10 195 for (i = 1; i <= n; i++) 196 for (j = 1; j <= n; j++) 197 x[i,j] = n * i + j 198 for (i = 1; i <= n; i++) 199 for (j = 1; j <= n; j++) 200 if ((i,j) in x) 201 k++ 202 print (k == n^2) 203 } 204' > $TEMP2 205diff $TEMP1 $TEMP2 || fail 'BAD: T.func (multi-dim subscript)' 206 207echo '<> 0' > $TEMP1 208$AWK ' 209function foo() { i = 0 } 210 BEGIN { x = foo(); printf "<%s> %d\n", x, x }' > $TEMP2 211diff $TEMP1 $TEMP2 || fail 'BAD: T.func (fall off end)' 212 213exit $RESULT 214