# arith-p.sh: test of arithmetic expansion for any POSIX-compliant shell

posix="true"
setup -d

# POSIX does not specify how the result of an arithmetic expansion should be
# formatted. We assume the result is always formatted by 'printf "%ld"'.

test_oE -e 0 'single constant'
echoraw $((0)) $((1)) $((100)) $((020)) $((0x7F))
__IN__
0 1 100 16 127
__OUT__

test_oE -e 0 'single variable'
zero=0 one=1 hundred=100 plus_one=+1 minus_one=-1
echoraw $((zero)) $((one)) $((hundred)) $((plus_one)) $((minus_one))
__IN__
0 1 100 1 -1
__OUT__

test_oE -e 0 'unset variable is considered 0 (direct)'
unset x
echoraw $((x))
__IN__
0
__OUT__

test_oE -e 0 'unary sign operators'
echoraw $((+1)) $((-1)) $((-+-2))
__IN__
1 -1 2
__OUT__

test_oE -e 0 'unary negation operators'
echoraw $((~0)) $((~1)) $((~2)) $((~-1)) $((~-2))
echoraw $((!0)) $((!1)) $((!2)) $((!-1)) $((!-2))
__IN__
-1 -2 -3 0 1
1 0 0 0 0
__OUT__

test_oE -e 0 'multiplicative operators'
echoraw $((0 * 0)) $((1*0)) $((0*1)) $((1*1)) $((2*3)) $((-5*7))
echoraw $((0 / 1)) $((6/2)) $((-12/3)) $((35/-5)) $((-121/-11))
echoraw $((0 % 1)) $((1%1)) $((1%2)) $((47%7))
__IN__
0 0 0 1 6 -35
0 3 -4 -7 11
0 0 1 5
__OUT__

test_oE -e 0 'additive operators'
echoraw $((0 + 0)) $((0+1)) $((2+3)) $((5+-7)) $((-7+13)) $((-1+-2))
echoraw $((0 - 0)) $((0-1)) $((3-2)) $((5- -7)) $((-7-13)) $((-1- -2))
__IN__
0 1 5 -2 6 -3
0 -1 1 12 -20 1
__OUT__

test_oE -e 0 'shift operators'
echoraw $((0 << 0)) $((3<<2)) $((5<<3)) # undefined: $((-2<<3))
echoraw $((0 >> 0)) $((15>>2)) $((43>>3)) $((-14>>3))
__IN__
0 12 40
0 3 5 -2
__OUT__

test_oE -e 0 'relational operators'
echoraw $((0 < 0)) $((0 <= 0)) $((0 > 0)) $((0 >= 0))
echoraw $((-1< -1)) $((-1< 0)) $((-1< 1)) \
        $(( 0< -1)) $(( 0< 0)) $(( 0< 1)) \
        $(( 1< -1)) $(( 1< 0)) $(( 1< 1))
echoraw $((-1<=-1)) $((-1<=0)) $((-1<=1)) \
        $(( 0<=-1)) $(( 0<=0)) $(( 0<=1)) \
        $(( 1<=-1)) $(( 1<=0)) $(( 1<=1))
echoraw $((-1> -1)) $((-1> 0)) $((-1> 1)) \
        $(( 0> -1)) $(( 0> 0)) $(( 0> 1)) \
        $(( 1> -1)) $(( 1> 0)) $(( 1> 1))
echoraw $((-1>=-1)) $((-1>=0)) $((-1>=1)) \
        $(( 0>=-1)) $(( 0>=0)) $(( 0>=1)) \
        $(( 1>=-1)) $(( 1>=0)) $(( 1>=1))
__IN__
0 1 0 1
0 1 1 0 0 1 0 0 0
1 1 1 0 1 1 0 0 1
0 0 0 1 0 0 1 1 0
1 0 0 1 1 0 1 1 1
__OUT__

test_oE -e 0 'equality operators'
echoraw $((0 == 0)) $((1==0)) $((0==1)) $((1==1)) $((3==3)) $((2==3))
echoraw $((0 != 0)) $((1!=0)) $((0!=1)) $((1!=1)) $((3!=3)) $((2!=3))
__IN__
1 0 0 1 1 0
0 1 1 0 0 1
__OUT__

test_oE -e 0 'bitwise operators'
echoraw $((0 & 0)) $((3&5)) $((-13&5)) $((3&-11)) $((-13&-11))
echoraw $((0 ^ 0)) $((3^5)) $((-13^5)) $((3^-11)) $((-13^-11))
echoraw $((0 | 0)) $((3|5)) $((-13|5)) $((3|-11)) $((-13|-11))
__IN__
0 1 1 1 -15
0 6 -10 -10 6
0 7 -9 -9 -9
__OUT__

test_oE -e 0 'logical operators'
echoraw $((0 && 0)) $((3&&0)) $((0&&-5)) $((3&&-5))
echoraw $((0 || 0)) $((3||0)) $((0||-5)) $((3||-5))
echoraw $((0 ? 0 : 0)) $((0?1:2)) $((1?2:3)) $((-1?2:3))
__IN__
0 0 0 1
0 1 1 1
0 2 2 2
__OUT__

test_oE -e 0 'conditional evaluation of && operator operand'
a=0
echoraw $((1&&(a=5)))
echoraw $((0&&(a=-5)))
echoraw $a
__IN__
1
0
5
__OUT__

test_oE -e 0 'conditional evaluation of || operator operand'
a=0
echoraw $((0||(a=5)))
echoraw $((1||(a=-5)))
echoraw $a
__IN__
1
1
5
__OUT__

test_oE -e 0 'conditional evaluation of ?: operator operand'
a=0 b=0
echoraw $((1?(a=5):(b=-5)))
echoraw $a $b
a=0 b=0
echoraw $((0?(a=-5):(b=5)))
echoraw $a $b
__IN__
5
5 0
5
0 5
__OUT__

test_oE -e 0 'assignment operators'
a=0 b=2 c=15 d=46 e=3 f=3 g=7 h=30 i=3 j=3 k=3
echoraw $((a=5)) $((b*=3)) $((c/=3)) $((d%=7)) $((e+=5)) $((f-=5)) \
    $((g<<=2)) $((h>>=2)) $((i&=5)) $((j^=5)) $((k|=5))
echoraw $a $b $c $d $e $f $g $h $i $j $k
__IN__
5 6 5 4 8 -2 28 7 1 6 7
5 6 5 4 8 -2 28 7 1 6 7
__OUT__

test_O -d -e n 'assigning to read-only variable'
readonly a=3
echoraw $((a=5))
echoraw not reached
__IN__

test_oE -e 0 'unset variable is considered 0 (assignment)'
unset x
echoraw $((a=x)) && echoraw $a
__IN__
0
0
__OUT__

test_oE 'operator precedence: unary and multiplicatives'
echoraw $((!0*3)) $((~-1*3)) $((!1/2)) $((!1%1))
__IN__
3 0 0 0
__OUT__

test_oE 'operator precedence: multiplicatives'
echoraw -          -           $((2*1%2))
echoraw $((2/2*3)) $((12/6/2)) $((6/3%2))
echoraw $((7%4*2)) $((8%12/2)) $((7%2%3))
__IN__
- - 0
3 1 0
6 4 1
__OUT__

test_oE 'operator precedence: multiplicatives and additives'
echoraw $((2*3+1)) $((2*3-1)) $((1/1+1)) $((5%1+1))
echoraw $((1+2*3)) $((9-2*3)) $((2+0/2)) $((1+5%1))
__IN__
7 5 2 1
7 3 2 1
__OUT__

test_oE 'operator precedence: additives'
echoraw $((2-1+3)) $((3-2-1))
__IN__
4 0
__OUT__

test_oE 'operator precedence: additives and shifts'
echoraw $((1+1<<2)) $((3-1<<2)) $((8+8>>2)) $((8-4>>2))
echoraw $((1<<1+1)) $((2<<1-1)) $((8>>1+1)) $((8>>1-1))
__IN__
8 8 4 1
4 2 2 8
__OUT__

test_oE 'operator precedence: shifts'
echoraw $((1<<2<<1)) $((1<<3>>1)) $((8>>2<<1)) $((8>>2>>1))
__IN__
8 4 4 1
__OUT__

test_oE 'operator precedence: shifts and relationals'
echoraw $((1<<1<0)) $((2>>1<=0)) $((1<<1>2)) $((2>>1>=2))
echoraw $((0<2>>1)) $((1<=1<<1)) $((1>1>>1)) $((1>=1<<1))
__IN__
0 0 0 0
1 1 1 0
__OUT__

test_oE 'operator precedence: relationals'
echoraw $((1< 2< 2)) $((0< 1<=2)) $((1< 2> 0)) $((1< 2>=0))
echoraw $((1<=2< 2)) $((0<=0<=0)) $((1<=2> 1)) $((1<=2>=2))
echoraw $((0> 0< 1)) $((0> 0<=1)) $((1> 2> 2)) $((1> 2>=0))
echoraw $((0>=0< 0)) $((0>=0<=1)) $((1>=2> 1)) $((1>=2>=2))
__IN__
1 1 1 1
1 0 0 0
1 1 0 1
0 1 0 0
__OUT__

test_oE 'operator precedence: relationals and equalities'
echoraw $((0<=0==0)) $((0<=0!=1)) $((0==0<=0)) $((0!=2<=1))
echoraw $((1< 0==0)) $((1< 0!=1)) $((0==0< 0)) $((1!=0< 0))
echoraw $((0>=0==0)) $((1>=2!=0)) $((0==0>=0)) $((1!=0>=0))
echoraw $((0> 0==0)) $((0> 0!=1)) $((0==0> 1)) $((1!=0> 1))
__IN__
0 0 0 0
1 1 1 1
0 0 0 0
1 1 1 1
__OUT__

test_oE 'operator precedence: equalities'
echoraw $((0==0==2)) $((0==0!=2)) $((2!=0==0)) $((0!=2!=2))
__IN__
0 1 0 1
__OUT__

test_oE 'operator precedence: equalities and bitwise and'
echoraw $((0==0&0)) $((0&0==0)) $((1!=0&0)) $((0&0!=1))
__IN__
0 0 0 0
__OUT__

test_oE 'operator precedence: bitwise and and xor'
echoraw $((0&0^1)) $((1^0&0))
__IN__
1 1
__OUT__

test_oE 'operator precedence: bitwise xor and or'
echoraw $((1^1|1)) $((1|1^1))
__IN__
1 1
__OUT__

test_oE 'operator precedence: bitwise or and logical and'
echoraw $((1|1&&0)) $((0&&1|1))
__IN__
0 0
__OUT__

test_oE 'operator precedence: logical and and or'
echoraw $((0&&0||1)) $((1||0&&0))
__IN__
1 1
__OUT__

test_oE 'operator precedence: logical or and conditional'
echoraw $((2||0?0:1)) $((1?0:1||1))
__IN__
0 0
__OUT__

test_oE 'operator precedence: conditionals'
echoraw $((4?1:0?2:3))
__IN__
1
__OUT__

test_oE 'operator precedence: assignments in conditionals'
b=5 c=6 d=5 e=0 f=0 g=1 h=8 i=7 j=0 k=0
echoraw $((1?a=2:3)) $((1?b*=2:3)) $((1?c/=2:3)) $((1?d%=2:3)) \
    $((1?e+=2:3)) $((1?f-=2:3)) $((1?g<<=2:3)) $((1?h>>=2:3)) \
    $((1?i&=2:4)) $((1?j^=2:4)) $((1?k|=2:4))
echoraw $a $b $c $d $e $f $g $h $i $j $k
__IN__
2 10 3 1 2 -2 4 2 2 2 2
2 10 3 1 2 -2 4 2 2 2 2
__OUT__

test_oE 'operator precedence: conditionals and assignments'
b=5 c=6 d=5 e=0 f=0 g=1 h=8 i=7 j=0 k=0
echoraw $((a=1?2:3)) $((b*=1?2:3)) $((c/=1?2:3)) $((d%=1?2:3)) \
    $((e+=1?2:3)) $((f-=1?2:3)) $((g<<=1?2:3)) $((h>>=1?2:3)) \
    $((i&=1?2:4)) $((j^=1?2:4)) $((k|=1?2:4))
echoraw $a $b $c $d $e $f $g $h $i $j $k
__IN__
2 10 3 1 2 -2 4 2 2 2 2
2 10 3 1 2 -2 4 2 2 2 2
__OUT__

test_oE 'operator precedence: assignments'
b=5 c=10 d=5 e=10 f=10 g=16 h=2 i=3 j=1 k=2
echoraw $((a=b*=2)) $((c/=d%=3)) $((e+=f-=1)) $((g<<=h>>=1)) $((i&=j^=k|=1))
echoraw $a $b $c $d $e $f $g $h $i $j $k
__IN__
10 5 19 32 2
10 10 5 2 19 9 32 1 2 2 3
__OUT__

test_oE 'parentheses'
echoraw $(((7))) $((-(-3))) $(((1+2)*5)) $((15/(7%4))) $(((0?1:0)?1:(a=2)))
__IN__
7 3 15 5 2
__OUT__

test_oE 'parameter expansion in arithmetic expansion'
a=+123
echoraw $(($a)) $((${a%3})) $(($a-23))
__IN__
123 12 100
__OUT__

test_oE 'command substitution in arithmetic expansion'
echoraw $(($(echo 123))) $((1+$(echo 10)+`echo 100`+1000))
__IN__
123 1111
__OUT__

# Quote removal is tested in arith-y.tst.
#test_oE 'quote removal'
#__IN__
#__OUT__

test_oE 'assignment in parameter expansion in arithmetic expansion'
unset a
echoraw $((${a=1}))
echoraw $a
__IN__
1
1
__OUT__

test_O -d -e n 'malformed arithmetic expansion'
echoraw $((--))
__IN__
