####################################################################
#                                                                  #
#             This software is part of the ast package             #
#                Copyright (c) 1982-2003 AT&T Corp.                #
#        and it may only be used by you under license from         #
#                       AT&T Corp. ("AT&T")                        #
#         A copy of the Source Code Agreement is available         #
#                at the AT&T Internet web site URL                 #
#                                                                  #
#       http://www.research.att.com/sw/license/ast-open.html       #
#                                                                  #
#    If you have copied or used this software without agreeing     #
#        to the terms of the license you are infringing on         #
#           the license and copyright and are violating            #
#               AT&T's intellectual property rights.               #
#                                                                  #
#            Information and Software Systems Research             #
#                        AT&T Labs Research                        #
#                         Florham Park NJ                          #
#                                                                  #
#                David Korn <dgk@research.att.com>                 #
#                                                                  #
####################################################################
function err_exit
{
	print -u2 -n "\t"
	print -u2 -r ${Command}[$1]: "${@:2}"
	let Errors+=1
}
alias err_exit='err_exit $LINENO'

integer Errors=0
Command=$0
integer foo=33
bar=bye
# check for global variables and $0
function foobar
{
	case $1 in
	1) 	print -r - "$foo" "$bar";;
	2)	print -r - "$0";;
	3)	typeset foo=foo
		integer bar=10
	 	print -r - "$foo" "$bar";;
	4)	trap 'foo=36' EXIT
		typeset foo=20;;
	esac
}
function print
{
	command print hi
}
if	[[ $(print) != hi ]]
then	err_exit "command print not working inside print function"
fi
unset -f print

if	[[ $(foobar 1) != '33 bye' ]]
then	err_exit 'global variables not correct'
fi

if	[[ $(foobar 2) != 'foobar' ]]
then	err_exit '$0  not correct'
fi

if	[[ $(bar=foo foobar 1) != '33 foo' ]]
then	err_exit 'environment override not correct'
fi
if	[[ $bar == foo ]]
then	err_exit 'scoping error'
fi

if	[[ $(foobar 3) != 'foo 10' ]]
then	err_exit non-local variables
fi

foobar 4
if	[[ $foo != 36 ]]
then	err_exit EXIT trap in wrong scope
fi
unset -f foobar || err_exit "cannot unset function foobar"
typeset -f foobar>/dev/null  && err_exit "typeset -f has incorrect exit status"

function foobar
{
	(return 0)
}
> /tmp/shtests$$.1
{
foobar
if	[ -r /tmp/shtests$$.1 ]
then	rm -r /tmp/shtests$$.1
else	err_exit 'return within subshell inside function error'
fi
}
abc() print hi
if	[[ $(abc) != hi ]]
then	err_exit 'abc() print hi not working'
fi
( unset -f abc )
if	[[ $(abc 2>/dev/null) != hi ]]
then	err_exit 'abc() print hi not working after subshell unset'
fi
(
	function f
	{
		exit 1
	}
	f
	err_exit 'exit from function not working'
)
unset -f foo
function foo
{
	x=2
	(
		x=3
		cd /tmp
		print bar
	)
	if	[[ $x != 2 ]]
	then	err_exit 'value of x not restored after subshell inside function'
	fi
}
x=1
dir=$PWD
if	[[ $(foo) != bar ]]
then	err_exit 'cd inside nested subshell not working'
fi
if	[[ $PWD != "$dir" ]]
then	err_exit 'cd inside nested subshell changes $PWD'
fi
fun() /bin/echo hello
if	[[ $(fun) != hello ]]
then	err_exit one line functions not working
fi
trap 'rm -f /tmp/script$$' EXIT
cat > /tmp/script$$ <<-\!
	print -r -- "$1"
!
chmod +x /tmp/script$$
function passargs
{
	/tmp/script$$ "$@"
}
if	[[ $(passargs one) != one ]]
then	err_exit 'passing args from functions to scripts not working'
fi
cat > /tmp/script$$ <<-\!
	trap 'exit 0' EXIT
	function foo
	{
		/tmp > /dev/null  2>&1
	}
	foo
!
if	! /tmp/script$$
then	err_exit 'exit trap incorrectly triggered' 
fi
if	! $SHELL -c /tmp/script$$
then	err_exit 'exit trap incorrectly triggered when invoked with -c' 
fi
$SHELL -c "trap 'rm /tmp/script$$' EXIT"
if	[[ -f /tmp/script$$ ]]
then	err_exit 'exit trap not triggered when invoked with -c' 
fi
cat > /tmp/script$$ <<- \EOF
	foobar()
	{
		return
	}
	shift
	foobar
	print -r -- "$1"
EOF
chmod +x /tmp/script$$
if	[[ $( $SHELL /tmp/script$$ arg1 arg2) != arg2 ]]
then	err_exit 'arguments not restored by posix functions'
fi
function foo
{
	print hello
}
(
	function foo
	{
		print bar
	}
	if [[ $(foo) != bar ]]
	then	err_exit 'function definitions inside subshells not working'
	fi
)
if [[ $(foo) != hello ]]
then	err_exit 'function definitions inside subshells not restored'
fi
unset -f foo bar
function bar
{
        print "$y"
}

function foo
{
        typeset x=3
        y=$x bar
}
x=1
if	[[ $(foo) != 3 ]]
then	err_exit 'variable assignment list not using parent scope'
fi
unset -f foo$$
trap "rm -f /tmp/foo$$" EXIT INT
cat > /tmp/foo$$ <<!
function foo$$
{
	print foo
}
!
chmod +x /tmp/foo$$
FPATH=/tmp
autoload foo$$
if	[[ $(foo$$ 2>/dev/null) != foo ]]
then	err_exit 'autoload not working'
fi
unset -f foobar
function foobar
{
	typeset -r x=3
	return 0
}
( foobar ) 2> /dev/null || err_exit "cannot unset readonly variable in function"
if	$SHELL -n 2> /dev/null <<-! 
	abc()
	!
then	err_exit 'abc() without a function body is not a syntax error'
fi
function winpath
{
	usage='q pathname ...' 
	typeset var format=s
	while   getopts  "$usage" var
	do      case $var in
		q)      format=q;;
	        esac
	done
	print done
}
if	[[ $( (winpath --man 2>/dev/null); print ok) != ok ]]
then	err_exit 'getopts --man in functions not working'
fi
if	[[ $( (winpath -z 2>/dev/null); print ok) != ok ]]
then	err_exit 'getopts with bad option in functions not working'
fi
unset -f x
function x
{
        print "$@"
}
typeset -ft x
if      [[ $(x x=y 2>/dev/null) != x=y ]]
then    err_exit 'name=value pair args not passed to traced functions'
fi
function bad
{
	false
}
trap 'val=false' ERR
val=true
bad
if	[[ $val != false ]]
then	err_exit 'set -e not working for functions'
fi
function bad
{
	false
	return 0
}
val=true
bad
if	[[ $val != true ]]
then	err_exit 'set -e not disabled for functions'
fi
bad()
{
	false
	return 0
}
val=true
bad
if	[[ $val != false ]]
then	err_exit 'set -e not inherited for posix functions'
fi
function myexport 
{
	nameref var=$1
	if	(( $# > 1 ))
	then	export	$1=$2
	fi
	if	(( $# > 2 ))
	then	print $(myexport "$1" "$3" )
		return
	fi
	typeset val
	val=$(export | grep "^$1=")
	print ${val#"$1="}
	
}
export dgk=base
if	[[ $(myexport dgk fun) != fun ]]
then	err_exit 'export inside function not working'
fi
val=$(export | grep "^dgk=")
if	[[ ${val#dgk=} != base ]]
then	err_exit 'export not restored after function call'
fi
if	[[ $(myexport dgk fun fun2) != fun2 ]]
then	err_exit 'export inside function not working with recursive function'
fi
val=$(export | grep "^dgk=")
if	[[ ${val#dgk=} != base ]]
then	err_exit 'export not restored after recursive function call'
fi
if	[[ $(dgk=try3 myexport dgk) != try3 ]]
then	err_exit 'name=value not added to export list with function call'
fi
val=$(export | grep "^dgk=")
if	[[ ${val#dgk=} != base ]]
then	err_exit 'export not restored name=value function call'
fi
unset zzz
if	[[ $(myexport zzz fun) != fun ]]
then	err_exit 'export inside function not working for zzz'
fi
if	[[ $(export | grep "zzz=") ]]
then	err_exit 'zzz exported after function call'
fi
unset zzz
typeset -u zzz
function foo
{
	zzz=abc
	print $zzz
}
if	[[ $(foo)$(foo) != ABCABC ]]
then	err_exit 'attributes on unset variables not saved/restored'
fi
function xpd {
	typeset i j=$1
                for i
                        do print i=$i j=$j
                        [[ $i == a ]] && xpd b
                        done
                }
if	[[ $(xpd a c) != $'i=a j=a\ni=b j=b\ni=c j=a' ]]
then	err_exit 'for loop function optimization error'
fi

typeset -A visited
integer level=0
function closure
{
	(( $# > 5 )) && return 1
	((level < 2)) && ((level++))
	typeset tmp r=0
	visited[$1]=1

	for tmp in $level _$level
	do
		[[ ${visited[$tmp]} == 1 ]] && continue
		closure $tmp $* || r=1
	done
	return $r
}
closure 0 || err_exit -u2 'for loop function optimization bug2'
mkdir  /tmp/ksh$$ || err_exit "mkdir /tmp/ksh$$ failed"
cd /tmp/ksh$$ || err_exit "cd /tmp/ksh$$ failed"
print 'false' > try
chmod +x try
cat > tst <<- EOF
	function ignore
	{
		./try
		return 0
	}
	trap "print error; exit 1" ERR
	ignore
EOF
if	[[ $($SHELL < tst)  == error ]]
then	err_exit 'ERR trap not cleared'
fi
FPATH=/tmp/ksh$$
print ': This does nothing' > /tmp/ksh$$/foobar
chmod +x /tmp/ksh$$/foobar
unset -f  foobar
{ foobar;} 2> /dev/null
if	[[ $? != 126 ]]
then	err_exit 'function file without function definition processes wrong error'
fi
print 'set a b c' > dotscript 
[[ $(PATH=$PATH: $SHELL -c '. dotscript;print $#') == 3 ]] || err_exit 'positional parameters not preserved with . script without arguments'
cd ~- || err_exit "cd back failed"
cd /; rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed"
function errcheck
{
	trap 'print ERR; return 1' ERR
	false
	print ok
}
err=$(errcheck)
[[ $err == ERR ]] || err_exit 'trap on ERR not working in a function'
x="$(
	function foobar
	{
		print ok
	}
	typeset -f foobar
)"
eval "$x"  || err_exit 'typeset -f generates syntax error'
[[ $(foobar) != ok ]] && err_exit 'typeset -f not generating function'
unset -f a b c
a()
{
        b
        b
        print ${.sh.fun}
}
b() { : ;}
[[ $(a) == a ]] || err_exit '.sh.fun not set correctly in a function'
exit $((Errors))

