mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
$ arch/*/bin/ksh -xc 'typeset -a a=(1 2 3); \ (typeset -A a; typeset -p a); typeset -p a' typeset -A a=() typeset -a a=(1 2 3) The associative array in the subshell is empty, so the conversion failed. So far, I have been unsuccessful at fixing this in the array and/or virtual subshell code (a patch that fixes it there would still be more than welcome). As usual, real subshells work correctly, so this commit adds another forking workaround. The use case is rare and specific enough that I have no performance concerns. src/cmd/ksh93/bltins/typeset.c: setall(): - Fork a virtual subshell if we're actually converting a variable to an associative array, i.e.: the NV_ARRAY (-A, associative array) attribute was passed, there are no assignments (sh.envlist is NULL), and the variable is not unset. src/cmd/ksh93/tests/arith.sh: - Fix the "Array subscript quoting test" tests that should not have been passing and that correctly failed after this fix; they used 'typeset -A' without an assignment in a subshell, assuming it was unset in the parent shell, which it wasn't. Resolves: https://github.com/ksh93/ksh/issues/409
987 lines
33 KiB
Bash
Executable file
987 lines
33 KiB
Bash
Executable file
########################################################################
|
|
# #
|
|
# This software is part of the ast package #
|
|
# Copyright (c) 1982-2012 AT&T Intellectual Property #
|
|
# Copyright (c) 2020-2022 Contributors to ksh 93u+m #
|
|
# and is licensed under the #
|
|
# Eclipse Public License, Version 1.0 #
|
|
# by AT&T Intellectual Property #
|
|
# #
|
|
# A copy of the License is available at #
|
|
# http://www.eclipse.org/org/documents/epl-v10.html #
|
|
# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
|
|
# #
|
|
# Information and Software Systems Research #
|
|
# AT&T Research #
|
|
# Florham Park NJ #
|
|
# #
|
|
# David Korn <dgk@research.att.com> #
|
|
# #
|
|
########################################################################
|
|
|
|
. "${SHTESTS_COMMON:-${0%/*}/_common}"
|
|
|
|
integer hasposix=0
|
|
(set -o posix) 2>/dev/null && ((hasposix++)) # not using [[ -o ?posix ]] as it's broken on 93v-
|
|
|
|
trap '' FPE # NOTE: osf.alpha requires this (no ieee math)
|
|
|
|
integer x=1 y=2 z=3
|
|
if (( 2+2 != 4 ))
|
|
then err_exit 2+2!=4
|
|
fi
|
|
if ((x+y!=z))
|
|
then err_exit x+y!=z
|
|
fi
|
|
if (($x+$y!=$z))
|
|
then err_exit $x+$y!=$z
|
|
fi
|
|
if (((x|y)!=z))
|
|
then err_exit "(x|y)!=z"
|
|
fi
|
|
if ((y >= z))
|
|
then err_exit "y>=z"
|
|
fi
|
|
if ((y+3 != z+2))
|
|
then err_exit "y+3!=z+2"
|
|
fi
|
|
if ((y<<2 != 1<<3))
|
|
then err_exit "y<<2!=1<<3"
|
|
fi
|
|
if ((133%10 != 3))
|
|
then err_exit "133%10!=3"
|
|
if (( 2.5 != 2.5 ))
|
|
then err_exit 2.5!=2.5
|
|
fi
|
|
fi
|
|
d=0
|
|
((d || 1)) || err_exit 'd=0; ((d||1))'
|
|
if (( d++!=0))
|
|
then err_exit "d++!=0"
|
|
fi
|
|
if (( --d!=0))
|
|
then err_exit "--d!=0"
|
|
fi
|
|
if (( (d++,6)!=6 && d!=1))
|
|
then err_exit '(d++,6)!=6 && d!=1'
|
|
fi
|
|
d=0
|
|
if (( (1?2+1:3*4+d++)!=3 || d!=0))
|
|
then err_exit '(1?2+1:3*4+d++) !=3'
|
|
fi
|
|
for ((i=0; i < 20; i++))
|
|
do :
|
|
done
|
|
if (( i != 20))
|
|
then err_exit 'for (( expr)) failed'
|
|
fi
|
|
for ((i=0; i < 20; i++)); do : ; done
|
|
if (( i != 20))
|
|
then err_exit 'for (( expr));... failed'
|
|
fi
|
|
for ((i=0; i < 20; i++)) do : ; done
|
|
if (( i != 20))
|
|
then err_exit 'for (( expr))... failed'
|
|
fi
|
|
if (( (i?0:1) ))
|
|
then err_exit '(( (i?0:1) )) failed'
|
|
fi
|
|
if (( (1 || 1 && 0) != 1 ))
|
|
then err_exit '( (1 || 1 && 0) != 1) failed'
|
|
fi
|
|
if (( (_=1)+(_x=0)-_ ))
|
|
then err_exit '(_=1)+(_x=0)-_ failed'
|
|
fi
|
|
if (( (3^6) != 5))
|
|
then err_exit '((3^6) != 5) failed'
|
|
fi
|
|
integer x=1
|
|
if (( (x=-x) != -1 ))
|
|
then err_exit '(x=-x) != -1 failed'
|
|
fi
|
|
i=2
|
|
if (( 1$(($i))3 != 123 ))
|
|
then err_exit ' 1$(($i))3 failed'
|
|
fi
|
|
((pi=4*atan(1.)))
|
|
point=(
|
|
float x
|
|
float y
|
|
)
|
|
(( point.x = cos(pi/6), point.y = sin(pi/6) ))
|
|
if (( point.x*point.x + point.y*point.y > 1.01 ))
|
|
then err_exit 'cos*cos +sin*sin > 1.01'
|
|
fi
|
|
if (( point.x*point.x + point.y*point.y < .99 ))
|
|
then err_exit 'cos*cos +sin*sin < .99'
|
|
fi
|
|
if [[ $((y=x=1.5)) != 1 ]]
|
|
then err_exit 'typecast not working in arithmetic evaluation'
|
|
fi
|
|
typeset -E x=1.5
|
|
( ((x++)) ) 2>/dev/null
|
|
if [[ $? == 0 ]]
|
|
then err_exit 'postincrement of floating point allowed'
|
|
fi
|
|
( ((++x)) ) 2>/dev/null
|
|
if [[ $? == 0 ]]
|
|
then err_exit 'preincrement of floating point allowed'
|
|
fi
|
|
x=1.5
|
|
( ((x%1.1)) ) 2>/dev/null
|
|
if [[ $? == 0 ]]
|
|
then err_exit 'floating point allowed with % operator'
|
|
fi
|
|
x=.125
|
|
if [[ $(( 4 * x/2 )) != 0.25 ]]
|
|
then err_exit '(( 4 * x/2 )) is not 0.25, with x=.125'
|
|
fi
|
|
if [[ $(( pow(2,3) )) != 8 ]]
|
|
then err_exit '$(( pow(2,3) )) != 8'
|
|
fi
|
|
( [[ $(( pow(2,(3)) )) == 8 ]] ) 2> /dev/null
|
|
if (( $? ))
|
|
then err_exit '$(( pow(2,(3)) )) != 8'
|
|
fi
|
|
unset x
|
|
integer x=1; integer x=1
|
|
if [[ $x != 1 ]]
|
|
then err_exit 'two consecutive integer x=1 not working'
|
|
fi
|
|
unset z
|
|
{ z=$(typeset -RZ2 z2; (( z2 = 8 )); print $z2) ;} 2>/dev/null
|
|
if [[ $z != "08" ]]
|
|
then err_exit "typeset -RZ2 leading 0 decimal not working [z=$z]"
|
|
fi
|
|
{ z=$(typeset -RZ3 z3; (( z3 = 8 )); print $z3) ;} 2>/dev/null
|
|
if [[ $z != "008" ]]
|
|
then err_exit "typeset -RZ3 leading 0 decimal not working [z=$z]"
|
|
fi
|
|
unset z
|
|
typeset -Z3 z=010
|
|
(( z=z+1))
|
|
if [[ $z != 011 ]]
|
|
then err_exit "leading 0's in -Z not treated as decimal"
|
|
fi
|
|
unset x
|
|
integer x=0
|
|
if [[ $((x+=1)) != 1 ]] || ((x!=1))
|
|
then err_exit "+= not working"
|
|
x=1
|
|
fi
|
|
x=1
|
|
if [[ $((x*=5)) != 5 ]] || ((x!=5))
|
|
then err_exit "*= not working"
|
|
x=5
|
|
fi
|
|
if [[ $((x%=4)) != 1 ]] || ((x!=1))
|
|
then err_exit "%= not working"
|
|
x=1
|
|
fi
|
|
if [[ $((x|=6)) != 7 ]] || ((x!=7))
|
|
then err_exit "|= not working"
|
|
x=7
|
|
fi
|
|
if [[ $((x&=5)) != 5 ]] || ((x!=5))
|
|
then err_exit "&= not working"
|
|
x=5
|
|
fi
|
|
function newscope
|
|
{
|
|
float x=1.5
|
|
(( x += 1 ))
|
|
print -r -- $x
|
|
}
|
|
if [[ $(newscope) != 2.5 ]]
|
|
then err_exit "arithmetic using wrong scope"
|
|
fi
|
|
unset x
|
|
integer y[3]=9 y[4]=2 i=3
|
|
(( x = y[3] + y[4] ))
|
|
if [[ $x != 11 ]]
|
|
then err_exit "constant indexed array arithmetic failure"
|
|
fi
|
|
(( x = $empty y[3] + y[4] ))
|
|
if [[ $x != 11 ]]
|
|
then err_exit "empty constant indexed array arithmetic failure"
|
|
fi
|
|
(( x = y[i] + y[i+1] ))
|
|
if [[ $x != 11 ]]
|
|
then err_exit "variable subscript indexed array arithmetic failure"
|
|
fi
|
|
integer a[5]=3 a[2]=4
|
|
(( x = y[a[5]] + y[a[2]] ))
|
|
if [[ $x != 11 ]]
|
|
then err_exit "nested subscript indexed array arithmetic failure"
|
|
fi
|
|
unset y
|
|
typeset -Ai y
|
|
y[three]=9 y[four]=2
|
|
three=four
|
|
four=three
|
|
(( x = y[three] + y[four] ))
|
|
if [[ $x != 11 ]]
|
|
then err_exit "constant associative array arithmetic failure"
|
|
fi
|
|
(( x = y[$three] + y[$four] ))
|
|
if [[ $x != 11 ]]
|
|
then err_exit "variable subscript associative array arithmetic failure"
|
|
fi
|
|
$SHELL -nc '((a = 1))' 2> /dev/null || err_exit "sh -n fails with arithmetic"
|
|
$SHELL -nc '((a.b++))' 2> /dev/null || err_exit "sh -n fails with arithmetic2"
|
|
unset z
|
|
float z=7.5
|
|
if { (( z%2 != 1));} 2> /dev/null
|
|
then err_exit '% not working on floating point'
|
|
fi
|
|
chr=(a ' ' '=' '\r' '\n' '\\' '\"' '$' "\\'" '[' ']' '(' ')' '<' '\xab' '\040' '`' '{' '}' '*' '\E')
|
|
if (('a' == 97))
|
|
then val=(97 32 61 13 10 92 34 36 39 91 93 40 41 60 171 32 96 123 125 42 27)
|
|
else val=(129 64 126 13 21 224 127 91 125 173 189 77 93 76 171 32 121 192 208 92 39 21)
|
|
fi
|
|
q=0
|
|
for ((i=0; i < ${#chr[@]}; i++))
|
|
do if (( '${chr[i]}' != ${val[i]} ))
|
|
then err_exit "(( '${chr[i]}' != ${val[i]} ))"
|
|
fi
|
|
if [[ $(( '${chr[i]}' )) != ${val[i]} ]]
|
|
then err_exit "(( '${chr[i]}' )) != ${val[i]}"
|
|
fi
|
|
if [[ $(( L'${chr[i]}' )) != ${val[i]} ]]
|
|
then err_exit "(( '${chr[i]}' )) != ${val[i]}"
|
|
fi
|
|
if eval '((' "'${chr[i]}'" != ${val[i]} '))'
|
|
then err_exit "eval (( '${chr[i]}' != ${val[i]} ))"
|
|
fi
|
|
if eval '((' "'${chr[i]}'" != ${val[i]} ' + $q ))'
|
|
then err_exit "eval (( '${chr[i]}' != ${val[i]} ))"
|
|
fi
|
|
done
|
|
unset x
|
|
typeset -ui x=4294967293
|
|
[[ $x != 4294967293 ]] && err_exit "unsigned integers not working"
|
|
x=32767
|
|
x=x+1
|
|
[[ $x != 32768 ]] && err_exit "unsigned integer addition not working"
|
|
unset x
|
|
float x=99999999999999999999999999
|
|
if (( x < 1e20 ))
|
|
then err_exit 'large integer constants not working'
|
|
fi
|
|
unset x y
|
|
function foobar
|
|
{
|
|
nameref x=$1
|
|
(( x +=1 ))
|
|
print $x
|
|
}
|
|
x=0 y=4
|
|
if [[ $(foobar y) != 5 ]]
|
|
then err_exit 'name references in arithmetic statements in functions broken'
|
|
fi
|
|
if (( 2**3 != pow(2,3) ))
|
|
then err_exit '2**3 not working'
|
|
fi
|
|
if (( 2**3*2 != pow(2,3)*2 ))
|
|
then err_exit '2**3*2 not working'
|
|
fi
|
|
if (( 4**3**2 != pow(4,pow(3,2)) ))
|
|
then err_exit '4**3**2 not working'
|
|
fi
|
|
if (( (4**3)**2 != pow(pow(4,3),2) ))
|
|
then err_exit '(4**3)**2 not working'
|
|
fi
|
|
if (( 1**Inf != pow(1,Inf) ))
|
|
then err_exit '1**Inf not working'
|
|
fi
|
|
if (( 1**NaN != pow(1,NaN) ))
|
|
then err_exit '1**NaN not working'
|
|
fi
|
|
typeset -Z3 x=11
|
|
typeset -i x
|
|
if (( x != 11 ))
|
|
then err_exit '-Z3 not treated as decimal'
|
|
fi
|
|
unset x
|
|
typeset -ui x=-1
|
|
(( x >= 0 )) || err_exit 'unsigned integer not working'
|
|
(( $x >= 0 )) || err_exit 'unsigned integer not working as $x'
|
|
unset x
|
|
typeset -ui42 x=50
|
|
if [[ $x != 42#18 ]]
|
|
then err_exit 'display of unsigned integers in non-decimal bases wrong'
|
|
fi
|
|
$SHELL -c 'i=0;(( ofiles[i] != -1 && (ofiles[i] < mins || mins == -1) ));exit 0' 2> /dev/null || err_exit 'lexical error with arithmetic expression'
|
|
$SHELL -c '(( +1 == 1))' 2> /dev/null || err_exit 'unary + not working'
|
|
typeset -E20 val=123.01234567890
|
|
[[ $val == 123.0123456789 ]] || err_exit "rounding error val=$val"
|
|
if [[ $(print x$((10))=foo) != x10=foo ]]
|
|
then err_exit 'parsing error with x$((10))=foo'
|
|
fi
|
|
$SHELL -c 'typeset x$((10))=foo' 2> /dev/null || err_exit 'typeset x$((10)) parse error'
|
|
unset x
|
|
x=$(( exp(log(2.0)) ))
|
|
(( x > 1.999 && x < 2.001 )) || err_exit 'composite functions not working'
|
|
unset x y n
|
|
typeset -Z8 x=0 y=0
|
|
integer n
|
|
for (( n=0; n < 20; n++ ))
|
|
do let "x = $x+1"
|
|
(( y = $y+1 ))
|
|
done
|
|
(( x == n )) || err_exit 'let with zero filled fields not working'
|
|
(( y == n )) || err_exit '((...)) with zero filled fields not working'
|
|
typeset -RZ3 x=10
|
|
[[ $(($x)) == 10 && $((1$x)) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros'
|
|
unset y
|
|
[[ $(let y=$x;print $y) == 10 && $(let y=1$x;print $y) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros with let'
|
|
unset i ip ipx
|
|
typeset -i hex=( 172 30 18 1)
|
|
typeset -ui ip=0 ipx=0
|
|
integer i
|
|
for ((i=0; i < 4; i++))
|
|
do (( ip = (ip<<8) | hex[i]))
|
|
done
|
|
for ((i=0; i < 4; i++))
|
|
do (( ipx = ip % 256 ))
|
|
(( ip /= 256 ))
|
|
(( ipx != hex[3-i] )) && err_exit "hex digit $((3-i)) not correct"
|
|
done
|
|
unset x
|
|
x=010
|
|
(( x == 10 )) || err_exit 'leading zeros in x treated as octal arithmetic with ((x))'
|
|
(( $x == 10 )) || err_exit 'leading zeros in x treated as octal arithmetic with (($x))'
|
|
if ((hasposix))
|
|
then set --posix
|
|
((x == 8)) || err_exit 'posix: leading zeros in x not treated as octal arithmetic with ((x))'
|
|
(($x == 8)) || err_exit 'posix: leading zeros in x not treated as octal arithmetic with (($x))'
|
|
set --noposix
|
|
fi
|
|
unset x
|
|
typeset -Z x=010
|
|
(( x == 10 )) || err_exit 'leading zeros not ignored for arithmetic'
|
|
(( $x == 10 )) || err_exit 'leading zeros not ignored for arithmetic with $x'
|
|
typeset -i i=x
|
|
(( i == 10 )) || err_exit 'leading zeros not ignored for arithmetic assignment'
|
|
(( ${x:0:1} == 0 )) || err_exit 'leading zero should not be stripped for x:a:b'
|
|
c010=3
|
|
(( c$x == 3 )) || err_exit 'leading zero with variable should not be stripped'
|
|
[[ $( ($SHELL -c '((++1))' 2>&1) 2>/dev/null ) == *++1:* ]] || err_exit "((++1)) not generating error message"
|
|
i=2
|
|
(( "22" == 22 )) || err_exit "double quoted constants fail"
|
|
(( "2$i" == 22 )) || err_exit "double quoted variables fail"
|
|
(( "18+$i+2" == 22 )) || err_exit "double quoted expressions fail"
|
|
# 04-04-28 bug fix
|
|
unset i; typeset -i i=01-2
|
|
(( i == -1 )) || err_exit "01-2 is not -1"
|
|
|
|
cat > $tmp/script <<-\!
|
|
tests=$*
|
|
typeset -A blop
|
|
function blop.get
|
|
{
|
|
.sh.value=777
|
|
}
|
|
function mkobj
|
|
{
|
|
nameref obj=$1
|
|
obj=()
|
|
[[ $tests == *1* ]] && {
|
|
(( obj.foo = 1 ))
|
|
(( obj.bar = 2 ))
|
|
(( obj.baz = obj.foo + obj.bar )) # ok
|
|
echo $obj
|
|
}
|
|
[[ $tests == *2* ]] && {
|
|
(( obj.faz = faz = obj.foo + obj.bar )) # ok
|
|
echo $obj
|
|
}
|
|
[[ $tests == *3* ]] && {
|
|
# case 3, 'active' variable involved, w/ intermediate variable
|
|
(( obj.foz = foz = ${blop[1]} )) # coredump
|
|
echo $obj
|
|
}
|
|
[[ $tests == *4* ]] && {
|
|
# case 4, 'active' variable, in two steps
|
|
(( foz = ${blop[1]} )) # ok
|
|
(( obj.foz = foz )) # ok
|
|
echo $obj
|
|
}
|
|
[[ $tests == *5* ]] && {
|
|
# case 5, 'active' variable involved, w/o intermediate variable
|
|
(( obj.fuz = ${blop[1]} )) # coredump
|
|
echo $obj
|
|
}
|
|
[[ $tests == *6* ]] && {
|
|
echo $(( obj.baz = obj.foo + obj.bar )) # coredump
|
|
}
|
|
[[ $tests == *7* ]] && {
|
|
echo $(( obj.foo + obj.bar )) # coredump
|
|
}
|
|
}
|
|
mkobj bla
|
|
!
|
|
chmod +x $tmp/script
|
|
[[ $($tmp/script 1) != '( bar=2 baz=3 foo=1 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
|
|
[[ $($tmp/script 2) != '( faz=0 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
|
|
[[ $($tmp/script 3) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
|
|
[[ $($tmp/script 4) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
|
|
[[ $($tmp/script 5) != '( fuz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
|
|
[[ $($tmp/script 6) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
|
|
[[ $($tmp/script 7) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
|
|
unset foo
|
|
typeset -F1 foo=123456789.19
|
|
[[ $foo == 123456789.2 ]] || err_exit 'typeset -F1 not working correctly'
|
|
|
|
# divide by zero
|
|
|
|
for expr in '1/(1/2)' '8%(1/2)' '8%(1.0/2)'
|
|
do [[ $( ( $SHELL -c "( (($expr)) ) || print ok" ) 2>/dev/null ) == ok ]] || err_exit "divide by zero not trapped: $expr"
|
|
done
|
|
|
|
for expr in '1/(1.0/2)' '1/(1/2.0)'
|
|
do [[ $( ( $SHELL -c "( print -r -- \$(($expr)) )" ) 2>/dev/null ) == 2 ]] || err_exit "invalid value for: $expr"
|
|
done
|
|
[[ $((5||0)) == 1 ]] || err_exit '$((5||0))'" == $((5||0)) should be 1"
|
|
$SHELL -c 'integer x=3 y=2; (( (y += x += 2) == 7 && x==5))' 2> /dev/null || err_exit '((y += x += 2)) not working'
|
|
$SHELL -c 'b=0; [[ $((b?a=1:b=9)) == 9 ]]' 2> /dev/null || err_exit 'b?a=1:b=9 not working'
|
|
unset x
|
|
(( x = 4*atan(1.0) ))
|
|
[[ $x == "$((x))" ]] || err_exit '$x !- $((x)) when x is pi'
|
|
$SHELL -c "[[ ${x//./} == {14,100}(\d) ]]" 2> /dev/null || err_exit 'pi has less than 14 significant places'
|
|
if (( Inf+1 == Inf ))
|
|
then set \
|
|
Inf inf \
|
|
-Inf -inf \
|
|
Nan nan \
|
|
-Nan -nan \
|
|
1.0/0.0 inf
|
|
while (( $# >= 2 ))
|
|
do x=$(printf "%g\n" $(($1)))
|
|
[[ $x == $2 ]] || err_exit "printf '%g\\n' \$(($1)) failed -- expected $2, got $x"
|
|
x=$(printf "%g\n" $1)
|
|
[[ $x == $2 ]] || err_exit "printf '%g\\n' $1 failed -- expected $2, got $x"
|
|
x=$(printf -- $(($1)))
|
|
[[ $x == $2 ]] || err_exit "print -- \$(($1)) failed -- expected $2, got $x"
|
|
shift 2
|
|
done
|
|
(( 1.0/0.0 == Inf )) || err_exit '1.0/0.0 != Inf'
|
|
[[ $(print -- $((0.0/0.0))) == ?(-)nan ]] || err_exit '0.0/0.0 != NaN'
|
|
(( Inf*Inf == Inf )) || err_exit 'Inf*Inf != Inf'
|
|
(( NaN != NaN )) || err_exit 'NaN == NaN'
|
|
(( -5*Inf == -Inf )) || err_exit '-5*Inf != -Inf'
|
|
[[ $(print -- $((sqrt(-1.0)))) == ?(-)nan ]]|| err_exit 'sqrt(-1.0) != NaN'
|
|
(( pow(1.0,-Inf) == 1.0 )) || err_exit 'pow(1.0,-Inf) != 1.0'
|
|
(( pow(-Inf,0.0) == 1.0 )) || err_exit 'pow(-Inf,0.0) != 1.0'
|
|
(( pow(1.0,Inf) == 1.0 )) || err_exit 'pow(1.0,Inf) != 1.0'
|
|
(( pow(Inf,0.0) == 1.0 )) || err_exit 'pow(Inf,0.0) != 1.0'
|
|
(( pow(1.0,NaN) == 1.0 )) || err_exit 'pow(1.0,NaN) != 1.0'
|
|
(( pow(Nan,0.0) == 1.0 )) || err_exit 'pow(Nan,0.0) != 1.0'
|
|
[[ $(print -- $((NaN/Inf))) == ?(-)nan ]] || err_exit 'NaN/Inf != NaN'
|
|
(( 4.0/Inf == 0.0 )) || err_exit '4.0/Inf != 0.0'
|
|
else err_exit 'Inf and NaN not working'
|
|
fi
|
|
unset x y n r
|
|
n=14.555
|
|
float x=$n y
|
|
y=$(printf "%a" x)
|
|
r=$y
|
|
[[ $r == $n ]] || err_exit "output of printf %a not self preserving -- expected $x, got $y"
|
|
unset x y r
|
|
float x=-0 y=-0.0
|
|
r=-0
|
|
[[ $((-0)) == 0 ]] || err_exit '$((-0)) should be 0'
|
|
[[ $(( -1*0)) == 0 ]] || err_exit '$(( -1*0)) should be 0'
|
|
[[ $(( -1.0*0)) == -0 ]] || err_exit '$(( -1.0*0)) should be -0'
|
|
[[ $(printf "%g %g %g\n" x $x $((x)) ) == '-0 -0 -0' ]] || err_exit '%g of x $x $((x)) for x=-0 should all be -0'
|
|
[[ $(printf "%g %g %g\n" y $x $((y)) ) == '-0 -0 -0' ]] || err_exit '%g of y $y $((y)) for y=-0.0 should all be -0'
|
|
$SHELL -c '(( x=));:' 2> /dev/null && err_exit '((x=)) should be an error'
|
|
$SHELL -c '(( x+=));:' 2> /dev/null && err_exit '((x+=)) should be an error'
|
|
$SHELL -c '(( x=+));:' 2> /dev/null && err_exit '((x=+)) should be an error'
|
|
$SHELL -c 'x=();x.arr[0]=(z=3); ((x.arr[0].z=2))' 2> /dev/null || err_exit '(((x.arr[0].z=2)) should not be an error'
|
|
|
|
float t
|
|
typeset a b r
|
|
v="-0.0 0.0 +0.0 -1.0 1.0 +1.0"
|
|
for a in $v
|
|
do for b in $v
|
|
do (( r = copysign(a,b) ))
|
|
(( t = copysign(a,b) ))
|
|
[[ $r == $t ]] || err_exit $(printf "float t=copysign(%3.1f,%3.1f) => %3.1f -- expected %3.1f\n" a b t r)
|
|
done
|
|
done
|
|
|
|
typeset -l y y_ascii
|
|
(( y=sin(90) ))
|
|
y_ascii=$y
|
|
(( y == y_ascii )) || err_exit "no match,\n\t$(printf "%a\n" y)\n!=\n\t$(printf "%a\n" y_ascii)"
|
|
|
|
( $SHELL <<- \EOF
|
|
p=5
|
|
t[p]=6
|
|
while (( t[p] != 0 )) ; do
|
|
((
|
|
p+=1 ,
|
|
t[p]+=2 ,
|
|
p+=3 ,
|
|
t[p]+=5 ,
|
|
p+=1 ,
|
|
t[p]+=2 ,
|
|
p+=1 ,
|
|
t[p]+=1 ,
|
|
p-=6 ,
|
|
t[p]-=1
|
|
))
|
|
:
|
|
done
|
|
EOF) 2> /dev/null || err_exit 'error with comma expression'
|
|
|
|
N=(89551 89557)
|
|
i=0 j=1
|
|
[[ $(printf "%d" N[j]-N[i]) == 6 ]] || err_exit 'printf %d N[i]-N[j] failed'
|
|
[[ $((N[j]-N[i])) == 6 ]] || err_exit '$((N[j]-N[i])) incorrect'
|
|
|
|
unset a x
|
|
x=0
|
|
((a[++x]++))
|
|
((x==1)) || err_exit "((a[++x]++)) should only increment x once (expected '1', got '$x')"
|
|
((a[1]==1)) || err_exit "a[1] not incremented (expected '1', got '${a[1]}')"
|
|
unset a
|
|
x=0
|
|
((a[x++]++))
|
|
((x==1)) || err_exit "((a[x++]++)) should only increment x once (expected '1', got '$x')"
|
|
((a[0]==1)) || err_exit "a[0] not incremented (expected '1', got '${a[0]}')"
|
|
unset a
|
|
x=0
|
|
((a[x+=2]+=1))
|
|
((x==2)) || err_exit "((a[x+=2]++)) should result in x==2 (expected '2', got '$x')"
|
|
((a[2]==1)) || err_exit "a[0] not 1 (expected '1', got '${a[2]}')"
|
|
|
|
unset a i
|
|
typeset -a a
|
|
i=1
|
|
(( a[i]=1 ))
|
|
(( a[0] == 0 )) || err_exit 'a[0] not 0'
|
|
(( a[1] == 1 )) || err_exit 'a[1] not 1'
|
|
|
|
unset a
|
|
typeset -i a
|
|
for ((i=0;i<1000;i++))
|
|
do ((a[RANDOM%2]++))
|
|
done
|
|
(( (a[0]+a[1])==1000)) || err_exit '(a[0]+a[1])!=1000'
|
|
|
|
(( 4.**3/10 == 6.4 )) || err_exit '4.**3/10!=6.4'
|
|
(( (.5+3)/7 == .5 )) || err_exit '(.5+3)/7!==.5'
|
|
|
|
function .sh.math.mysin x
|
|
{
|
|
((.sh.value = x - x**3/6. + x**5/120.-x**7/5040. + x**9/362880.))
|
|
}
|
|
|
|
(( abs(sin(.5)-mysin(.5)) < 1e-6 )) || err_exit 'mysin() not close to sin()'
|
|
|
|
$SHELL 2> /dev/null <<- \EOF || err_exit "arithmetic functions defined and referenced in compound command not working"
|
|
{
|
|
function .sh.math.mysin x
|
|
{
|
|
((.sh.value = x-x**3/6. + x**5/120.-x**7/5040. + x**9/362880.))
|
|
}
|
|
(( abs(sin(.5)-mysin(.5)) < 1e-6 ))
|
|
exit 0
|
|
}
|
|
EOF
|
|
|
|
|
|
|
|
function .sh.math.max x y z
|
|
{
|
|
.sh.value=x
|
|
(( y > x )) && .sh.value=y
|
|
(( z > .sh.value )) && .sh.value=z
|
|
}
|
|
(( max(max(3,8,5),7,5)==8)) || err_exit 'max(max(3,8,5),7,5)!=8'
|
|
(( max(max(3,8,5),7,9)==9)) || err_exit 'max(max(3,8,9),7,5)!=9'
|
|
(( max(6,max(3,9,5),7)==9 )) || err_exit 'max(6,max(3,8,5),7)!=9'
|
|
(( max(6,7, max(3,8,5))==8 )) || err_exit 'max(6,7,max(3,8,5))!=8'
|
|
|
|
enum color_t=(red green blue yellow)
|
|
color_t shirt pants=blue
|
|
(( pants == blue )) || err_exit 'pants should be blue'
|
|
(( shirt == red )) || err_exit 'pants should be red'
|
|
(( shirt != green )) || err_exit 'shirt should not be green'
|
|
(( pants != shirt )) || err_exit 'pants should be the same as shirt'
|
|
(( pants = yellow ))
|
|
(( pants == yellow )) || err_exit 'pants should be yellow'
|
|
|
|
unset z
|
|
integer -a z=( [1]=90 )
|
|
function x
|
|
{
|
|
nameref nz=$1
|
|
float x y
|
|
float x=$((log10(nz))) y=$((log10($nz)))
|
|
(( abs(x-y) < 1e-10 )) || err_exit '$nz and nz differs in arithmetic expression when nz is reference to array instance'
|
|
}
|
|
x z[1]
|
|
|
|
unset x
|
|
float x
|
|
x=$( ($SHELL -c 'print -- $(( asinh(acosh(atanh(sin(cos(tan(atan(acos(asin(tanh(cosh(sinh(asinh(acosh(atanh(sin(cos(tan(atan(acos(asin(tanh(cosh(sinh(.5)))))))))))))))))))))))) )) ';:) 2> /dev/null)
|
|
(( abs(x-.5) < 1.e-10 )) || err_exit 'bug in composite function evaluation'
|
|
|
|
unset x
|
|
typeset -X x=16
|
|
{ (( $x == 16 )) ;} 2> /dev/null || err_exit 'expansions of hexfloat not working in arithmetic expansions'
|
|
|
|
unset foo
|
|
function foobar
|
|
{
|
|
(( foo = 8))
|
|
}
|
|
typeset -i foo
|
|
foobar
|
|
(( foo == 8 )) || err_exit 'arithmetic assignment binding to the wrong scope'
|
|
|
|
(( tgamma(4)/12 )) || err_exit 'floating point attribute for functions not preserved'
|
|
|
|
unset F
|
|
function f
|
|
{
|
|
((F=1))
|
|
}
|
|
f
|
|
[[ $F == 1 ]] || err_exit 'scoping bug with arithmetic expression'
|
|
|
|
F=1
|
|
function f
|
|
{
|
|
typeset F
|
|
((F=2))
|
|
}
|
|
[[ $F == 1 ]] || err_exit 'scoping bug2 with arithmetic expression'
|
|
|
|
unset play foo x z
|
|
typeset -A play
|
|
x=foo
|
|
play[$x]=(x=2)
|
|
for ((i=0; i < 2; i++))
|
|
do (( play[$x].y , z++ ))
|
|
done
|
|
(( z==2 )) || err_exit 'unset compound array variable error with for loop optimization'
|
|
|
|
[[ $($SHELL 2> /dev/null -c 'print -- $(( ldexp(1, 4) ))' ) == 16 ]] || err_exit 'function ldexp not implement or not working correctly'
|
|
|
|
|
|
$SHELL 2> /dev/null -c 'str="0x1.df768ed398ee1e01329a130627ae0000p-1";typeset -l -E x;((x=str))' || err_exit '((x=var)) fails for hexfloat with var beginning with 0x1.nnn'
|
|
|
|
x=(3 6 12)
|
|
(( x[2] /= x[0]))
|
|
(( x[2] == 4 )) || err_exit '(( x[2] /= x[0])) fails for indexed array'
|
|
|
|
x=([0]=3 [1]=6 [2]=12)
|
|
(( x[2] /= x[0]))
|
|
(( x[2] == 4 )) || err_exit '(( x[2] /= x[0])) fails for associative array'
|
|
|
|
got=$($SHELL 2> /dev/null -c 'compound -a x;compound -a x[0].y; integer -a x[0].y[0].z; (( x[0].y[0].z[2]=3 )); typeset -p x')
|
|
exp='typeset -C -a x=((typeset -C -a y=( [0]=(typeset -a -l -i z=([2]=3);));))'
|
|
[[ $got == "$exp" ]] || err_exit '(( x[0].y[0].z[2]=3 )) not working'
|
|
|
|
unset x
|
|
let x=010
|
|
[[ $x == 10 ]] || err_exit 'let treating 010 as octal'
|
|
(set -o letoctal; let x=010; [[ $x == 8 ]]) || err_exit 'let not treating 010 as octal with letoctal on'
|
|
if [[ -o ?posix ]]
|
|
then (set -o posix; let x=010; [[ $x == 8 ]]) || err_exit 'let not treating 010 as octal with posix on'
|
|
fi
|
|
|
|
float z=0
|
|
integer aa=2 a=1
|
|
typeset -A A
|
|
A[a]=(typeset -A AA)
|
|
A[a].AA[aa]=1
|
|
(( z= A[a].AA[aa]++ ))
|
|
(( z == 1 )) || err_exit "z should be '1' but is '$z' for associative array of associative array arithmetic"
|
|
[[ ${A[a].AA[aa]} == 2 ]] || err_exit "\${A[a].AA[aa]} should be '2' but is '${A[a].AA[aa]}'" \
|
|
'after ++ operation for associative array of associative array arithmetic'
|
|
unset A[a]
|
|
|
|
A[a]=(typeset -a AA)
|
|
A[a].AA[aa]=1
|
|
(( z += A[a].AA[aa++]++ ))
|
|
(( z == 2 )) || err_exit "z should be '2' but is '$z' for associative array of indexed array arithmetic"
|
|
(( aa == 3 )) || err_exit "subscript aa should be '3' but is '$aa' after ++"
|
|
[[ ${A[a].AA[aa-1]} == 2 ]] || err_exit "\${A[a].AA[aa]} should be '2' but is '${A[a].AA[aa]}'" \
|
|
'after ++ operation for associative array of indexed array arithmetic'
|
|
unset A
|
|
|
|
typeset -a A
|
|
A[a]=(typeset -A AA)
|
|
A[a].AA[aa]=1
|
|
(( z += A[a].AA[aa]++ ))
|
|
(( z == 3 )) || err_exit "z should be '3' but is '$z' for indexed array of associative array arithmetic"
|
|
[[ ${A[a].AA[aa]} == 2 ]] || err_exit "\${A[a].AA[aa]} should be '2' but is '${A[a].AA[aa]}'" \
|
|
'after ++ operation for indexed array of associative array arithmetic'
|
|
unset A[a]
|
|
|
|
A[a]=(typeset -a AA)
|
|
A[a].AA[aa]=1
|
|
(( z += A[a++].AA[aa++]++ ))
|
|
(( z == 4 )) || err_exit "z should be '4' but is '$z' for indexed array of indexed array arithmetic"
|
|
[[ ${A[a-1].AA[aa-1]} == 2 ]] || err_exit "\${A[a].AA[aa]} should be '2' but is '${A[a].AA[aa]}'" \
|
|
'after ++ operation for indexed array of indexed array arithmetic'
|
|
(( aa == 4 )) || err_exit "subscript aa should be '4' but is '$aa' after ++"
|
|
(( a == 2 )) || err_exit "subscript a should be '2' but is '$a' after ++"
|
|
unset A
|
|
|
|
unset r x
|
|
integer x
|
|
r=020
|
|
(($r == 20)) || err_exit 'leading 0 treated as octal inside ((...))'
|
|
x=$(($r))
|
|
((x == 20)) || err_exit 'leading 0 treated as octal inside $((...))'
|
|
x=$r
|
|
((x == 20)) || err_exit 'leading 0 treated as octal outside ((...))'
|
|
print -- -020 | read x
|
|
((x == -20)) || err_exit 'numbers with leading -0 treated as octal outside ((...))'
|
|
print -- -8#20 | read x
|
|
((x == -16)) || err_exit 'numbers with leading -8# should be treated as octal'
|
|
if ((hasposix))
|
|
then set --posix
|
|
(($r == 16)) || err_exit 'posix: leading 0 not treated as octal inside ((...))'
|
|
x=$(($r))
|
|
(( x == 16 )) || err_exit 'posix: leading 0 not treated as octal inside $((...))'
|
|
x=$r
|
|
((x == 16)) || err_exit 'posix: leading 0 not as octal outside ((...))'
|
|
print -- -020 | read x
|
|
((x == -16)) || err_exit 'posix: numbers with leading -0 should be treated as octal outside ((...))'
|
|
set --noposix
|
|
fi
|
|
|
|
unset x
|
|
x=0x1
|
|
let "$x==1" || err_exit 'hex constants not working with let'
|
|
(( $x == 1 )) || err_exit 'arithmetic with $x, where $x is hex constant not working'
|
|
for i in 1
|
|
do (($x == 1)) || err_exit 'arithmetic in for loop with $x, where $x is hex constant not working'
|
|
done
|
|
x=010
|
|
let "$x==10" || err_exit 'arithmetic with $x where $x is 010 should be decimal in let'
|
|
(( 9.$x == 9.01 )) || err_exit 'arithmetic with 9.$x where x=010 should be 9.01'
|
|
(( 9$x == 9010 )) || err_exit 'arithmetic with 9$x where x=010 should be 9010'
|
|
x010=99
|
|
((x$x == 99 )) || err_exit 'arithmetic with x$x where x=010 should be $x010'
|
|
(( 3+$x == 13 )) || err_exit '3+$x where x=010 should be 13 in ((...))'
|
|
if ((hasposix))
|
|
then set --posix
|
|
(( 3+$x == 11 )) || err_exit 'posix: 3+$x where x=010 should be 11 in ((...))'
|
|
set --noposix
|
|
fi
|
|
let "(3+$x)==13" || err_exit 'let should not recognize leading 0 as octal'
|
|
unset x
|
|
typeset -RZ3 x=10
|
|
(( $x == 10 )) || err_exit 'leading 0 in -RZ should not create octal constant with ((...))'
|
|
let "$x==10" || err_exit 'leading 0 in -RZ should not create octal constant with let'
|
|
|
|
unset v x
|
|
x=0x1.0000000000000000000000000000p+6
|
|
v=$(printf $'%.28a\n' 64)
|
|
[[ $v == "$x" ]] || err_exit "'printf %.28a 64' failed -- expected '$x', got '$v'"
|
|
|
|
# ======
|
|
# Redirections with ((...)) should not cause a syntax error
|
|
(eval '((1)) >/dev/null') 2>/dev/null || err_exit 'redirections with ((...)) yield a syntax error'
|
|
|
|
# ======
|
|
# Arbitrary command execution vulnerability in array subscripts in arithmetic expressions
|
|
# https://github.com/ksh93/ksh/issues/152
|
|
unset a
|
|
|
|
exp='array_test_1: 1$(echo INJECTION >&2): arithmetic syntax error'
|
|
got=$(set +x; var='1$(echo INJECTION >&2)' "$SHELL" -c 'typeset -a a; ((a[$var]++)); typeset -p a' array_test_1 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 1A: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; var='1$(echo INJECTION >&2)' "$SHELL" -c 'typeset -a a; ((a["$var"]++)); typeset -p a' array_test_1 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 1B: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
|
|
exp='typeset -A a=(['\''1$(echo INJECTION >&2)'\'']=1)'
|
|
got=$(set +x; { var='1$(echo INJECTION >&2)'; typeset -A a; ((a[$var]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 2A: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var='1$(echo INJECTION >&2)'; typeset -A a; ((a["$var"]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 2B: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
|
|
exp='typeset -A a=(['\''$0`echo INJECTION >&2`'\'']=1)'
|
|
got=$(set +x; { var='$0`echo INJECTION >&2`'; typeset -A a; ((a[$var]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 3A: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var='$0`echo INJECTION >&2`'; typeset -A a; ((a["$var"]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 3B: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
|
|
exp='typeset -A a=(['\''x\]+b\[$(echo INJECTION >&2)'\'']=1)'
|
|
got=$(set +x; { var="x\]+b\[\$(echo INJECTION >&2)"; typeset -A a; ((a[$var]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 4A: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var="x\]+b\[\$(echo INJECTION >&2)"; typeset -A a; ((a["$var"]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 4B: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
|
|
exp='typeset -A a=(['\''$var'\'']=1)'
|
|
got=$(set +x; { var='$0$(echo INJECTION >&2)'; typeset -A a; ((a[\$var]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5A: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var='1`echo INJECTION >&2`'; typeset -A a; ((a["\$var"]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5B: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var=''; typeset -A a; ((a[\$var]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5C: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var='\'; typeset -A a; ((a[\$var]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5D: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var=']'; typeset -A a; ((a[\$var]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5E: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var='x]foo'; typeset -A a; ((a[\$var]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5F: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var=''; typeset -A a; let 'a[$var]++'; typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5G: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var='\'; typeset -A a; let 'a[$var]++'; typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5H: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var=']'; typeset -A a; let 'a[$var]++'; typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5I: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var='x]foo'; typeset -A a; let 'a[$var]++'; typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5J: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var='1$(echo INJECTION >&2)'; typeset -A a; ((a["\$var"]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5K: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var="x\]+b\[\$(echo INJECTION >&2)"; typeset -A a; ((a[\$var]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5L: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
got=$(set +x; { var="x\]+b\[\$(uname>&2)"; typeset -A a; ((a["\$var"]++)); typeset -p a; } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "Array subscript quoting test 5M: expected $(printf %q "$exp"), got $(printf %q "$got")"
|
|
|
|
# ======
|
|
# Arithmetic recursion level was not reset on encountering readonly error in combination with a recursive arithmetic expression.
|
|
# (arithmetic array subscripts inside arithmetic expressions are one example of such recursion)
|
|
# https://github.com/ksh93/ksh/pull/239#discussion_r606874442
|
|
srcdir=${SHTESTS_COMMON%/tests/*}
|
|
integer maxlevel=$(grep $'^#define MAXLEVEL\t' "$srcdir/sh/streval.c" | sed 's/.*MAXLEVEL//')
|
|
if ((!maxlevel))
|
|
then err_exit "could not get maximum arithmetic recursion level from source code; update this test"
|
|
maxlevel=1024
|
|
fi
|
|
integer loopcount=maxlevel+10
|
|
got=$(
|
|
typeset -r -A -i ro_arr=([a]=10 [b]=20 [c]=30)
|
|
set +x
|
|
for ((i=0; i<loopcount; i++)); do
|
|
let "ro_arr[i+1] += 5"
|
|
done 2>&1
|
|
)
|
|
[[ $got == *recursion* ]] && err_exit "recursion level not reset on readonly error (main shell)"
|
|
got=$(
|
|
typeset -r -A -i ro_arr=([a]=10 [b]=20 [c]=30)
|
|
set +x
|
|
for ((i=0; i<loopcount; i++)); do
|
|
( ((ro_arr[i+1] += 5)) )
|
|
done 2>&1
|
|
)
|
|
[[ $got == *recursion* ]] && err_exit "recursion level not reset on readonly error (subshell)"
|
|
|
|
# ======
|
|
# Some math function tests and only error if function exits
|
|
unset got
|
|
got=0
|
|
if ( (( exp10(3) )) ) 2> /dev/null
|
|
then
|
|
(( (got=exp10(3)) == 1000 )) || err_exit "exp10(3) != 1000, got '$got'"
|
|
fi
|
|
got=0
|
|
if ( (( int(6.89) )) ) 2> /dev/null
|
|
then
|
|
(( (got=int(6.89)) == 6 )) || err_exit "int(6.89) != 6, got '$got'"
|
|
fi
|
|
got=0
|
|
if ( (( int(-6.89) )) ) 2> /dev/null
|
|
then
|
|
(( (got=int(-6.89)) == -6 )) || err_exit "int(-6.89) != -6, got '$got'"
|
|
fi
|
|
float got=-1
|
|
if ( (( float(2./3) )) ) 2> /dev/null
|
|
then
|
|
(( (got=float(2./3)) == 2./3 )) || err_exit "float(2./3) != 2./3, got '$got'"
|
|
fi
|
|
unset got
|
|
|
|
# ======
|
|
# https://github.com/ksh93/ksh/issues/326
|
|
((hasposix)) && for m in u d i o x X
|
|
do
|
|
set --posix
|
|
case $m in
|
|
o) exp="10;21;32;" ;;
|
|
x) exp="8;11;1a;" ;;
|
|
X) exp="8;11;1A;" ;;
|
|
*) exp="8;17;26;" ;;
|
|
esac
|
|
got=${ printf "%$m;" 010 021 032; }
|
|
[[ $got == "$exp" ]] || err_exit "posix: printf %$m does not recognize octal arguments" \
|
|
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
|
set --noposix
|
|
done
|
|
|
|
# ======
|
|
# BUG_ARITHNAN: In ksh <= 93u+m 2021-11-15 and zsh 5.6 - 5.8, the case-insensitive
|
|
# floating point constants Inf and NaN are recognised in arithmetic evaluation,
|
|
# overriding any variables with the names Inf, NaN, INF, nan, etc.
|
|
if ((hasposix))
|
|
then set --posix
|
|
Inf=42 NaN=13
|
|
inf=421 nan=137
|
|
INF=429 NAN=937
|
|
typeset -l v=$((Inf)),$((NaN)),$((inf)),$((nan)),$((INF)),$((NAN))
|
|
case $v in
|
|
( inf,nan,inf,nan,inf,nan )
|
|
err_exit "posix: arith: inf/nan override variables" ;;
|
|
( "$Inf,$NaN,$inf,$nan,$INF,$NAN" )
|
|
: mustNotHave BUG_ARITHNAN ;;
|
|
( * )
|
|
err_exit "posix: arith: weird inf/nan problem: $(printf %q "$v")" ;;
|
|
esac
|
|
unset -v Inf NaN inf nan INF NAN v
|
|
set --noposix
|
|
fi
|
|
|
|
# ======
|
|
# https://github.com/ksh93/ksh/issues/334#issuecomment-968603087
|
|
exp=21
|
|
got=$(typeset -Z x=0x15; set +x; { echo $((x)); } 2>&1)
|
|
[[ $got == "$exp" ]] || err_exit "typeset -Z corrupts hexadecimal number in arithmetic context" \
|
|
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
|
|
|
# ======
|
|
# Test for 'set -u' backported from ksh93v- 2013-09-26
|
|
unset IFS i
|
|
set -u
|
|
float -a ar
|
|
function f
|
|
{
|
|
integer i=0 ar_i=0
|
|
for (( i=0 ; i < 3 ; i++ ))
|
|
do (( ar[ar_i++]=i))
|
|
done
|
|
printf "%q\n" "${ar[*]}"
|
|
}
|
|
[[ $(f) == "'0 1 2'" ]] || err_exit '0 value for variable in arithmetic expression inside function with set -u fails'
|
|
set +u
|
|
|
|
# Test for unset x.NOT_KNOWN floating point variable (backported
|
|
# from ksh93v- 2013-09-13).
|
|
unset x
|
|
float x
|
|
((x.NOT_KNOWN == 0)) || err_exit 'x.NOT_KNOWN is unknown and should have value 0'
|
|
|
|
# Test for a bug with short integers that causes core dumps
|
|
# (backported from ksh93v- 2013-08-07).
|
|
"$SHELL" <<- \EOF || err_exit 'detected short integer bug that causes core dumps'
|
|
typeset -s -i -a t
|
|
typeset -s -i p
|
|
(( p=2**17 )) # tape start position
|
|
(( t[p]+=13))
|
|
while (( t[p] != 0 ))
|
|
do ((t[p]-=1 , p+=1))
|
|
done
|
|
exit 0
|
|
EOF
|
|
|
|
# ======
|
|
exit $((Errors<125?Errors:125))
|