Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ksh93/tests/variables.sh
1810 views
1
########################################################################
2
# #
3
# This software is part of the ast package #
4
# Copyright (c) 1982-2012 AT&T Intellectual Property #
5
# and is licensed under the #
6
# Eclipse Public License, Version 1.0 #
7
# by AT&T Intellectual Property #
8
# #
9
# A copy of the License is available at #
10
# http://www.eclipse.org/org/documents/epl-v10.html #
11
# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
12
# #
13
# Information and Software Systems Research #
14
# AT&T Research #
15
# Florham Park NJ #
16
# #
17
# David Korn <[email protected]> #
18
# #
19
########################################################################
20
function err_exit
21
{
22
print -u2 -n "\t"
23
print -u2 -r ${Command}[$1]: "${@:2}"
24
let Errors+=1
25
}
26
alias err_exit='err_exit $LINENO'
27
28
Command=${0##*/}
29
integer Errors=0
30
31
tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
32
trap "cd /; rm -rf $tmp" EXIT
33
34
[[ ${.sh.version} == "$KSH_VERSION" ]] || err_exit '.sh.version != KSH_VERSION'
35
unset ss
36
[[ ${@ss} ]] && err_exit '${@ss} should be empty string when ss is unset'
37
[[ ${!ss} == ss ]] || err_exit '${!ss} should be ss when ss is unset'
38
[[ ${#ss} == 0 ]] || err_exit '${#ss} should be 0 when ss is unset'
39
# RANDOM
40
if (( RANDOM==RANDOM || $RANDOM==$RANDOM ))
41
then err_exit RANDOM variable not working
42
fi
43
# SECONDS
44
sleep 3
45
if (( SECONDS < 2 ))
46
then err_exit SECONDS variable not working
47
fi
48
# _
49
set abc def
50
if [[ $_ != def ]]
51
then err_exit _ variable not working
52
fi
53
# ERRNO
54
#set abc def
55
#rm -f foobar#
56
#ERRNO=
57
#2> /dev/null < foobar#
58
#if (( ERRNO == 0 ))
59
#then err_exit ERRNO variable not working
60
#fi
61
# PWD
62
if [[ ! $PWD -ef . ]]
63
then err_exit PWD variable failed, not equivalent to .
64
fi
65
# PPID
66
exp=$$
67
got=${ $SHELL -c 'print $PPID'; }
68
if [[ ${ $SHELL -c 'print $PPID'; } != $$ ]]
69
then err_exit "PPID variable failed -- expected '$exp', got '$got'"
70
fi
71
# OLDPWD
72
old=$PWD
73
cd /
74
if [[ $OLDPWD != $old ]]
75
then err_exit "OLDPWD variable failed -- expected '$old', got '$OLDPWD'"
76
fi
77
cd $old || err_exit cd failed
78
# REPLY
79
read <<-!
80
foobar
81
!
82
if [[ $REPLY != foobar ]]
83
then err_exit REPLY variable not working
84
fi
85
integer save=$LINENO
86
# LINENO
87
LINENO=10
88
#
89
# These lines intentionally left blank
90
#
91
if (( LINENO != 13))
92
then err_exit LINENO variable not working
93
fi
94
LINENO=save+10
95
IFS=:
96
x=a::b::c
97
if [[ $x != a::b::c ]]
98
then err_exit "word splitting on constants"
99
fi
100
set -- $x
101
if [[ $# != 5 ]]
102
then err_exit ":: doesn't separate null arguments "
103
fi
104
set x
105
if x$1=0 2> /dev/null
106
then err_exit "x\$1=value treated as an assignment"
107
fi
108
# check for attributes across subshells
109
typeset -i x=3
110
y=1/0
111
if ( x=y ) 2> /dev/null
112
then err_exit "attributes not passed to subshells"
113
fi
114
unset x
115
function x.set
116
{
117
nameref foo=${.sh.name}.save
118
foo=${.sh.value}
119
.sh.value=$0
120
}
121
x=bar
122
if [[ $x != x.set ]]
123
then err_exit 'x.set does not override assignment'
124
fi
125
x.get()
126
{
127
nameref foo=${.sh.name}.save
128
.sh.value=$foo
129
}
130
131
if [[ $x != bar ]]
132
then err_exit 'x.get does not work correctly'
133
fi
134
typeset +n foo
135
unset foo
136
foo=bar
137
(
138
unset foo
139
set +u
140
if [[ $foo != '' ]]
141
then err_exit '$foo not null after unset in subsehll'
142
fi
143
)
144
if [[ $foo != bar ]]
145
then err_exit 'unset foo in subshell produces side effect '
146
fi
147
unset foo
148
if [[ $( { : ${foo?hi there} ; } 2>&1) != *'hi there' ]]
149
then err_exit '${foo?hi there} with foo unset does not print hi there on 2'
150
fi
151
x=$0
152
set foobar
153
if [[ ${@:0} != "$x foobar" ]]
154
then err_exit '${@:0} not expanding correctly'
155
fi
156
set --
157
if [[ ${*:0:1} != "$0" ]]
158
then err_exit '${@:0} not expanding correctly'
159
fi
160
ACCESS=0
161
function COUNT.set
162
{
163
(( ACCESS++ ))
164
}
165
COUNT=0
166
(( COUNT++ ))
167
if (( COUNT != 1 || ACCESS!=2 ))
168
then err_exit " set discipline failure COUNT=$COUNT ACCESS=$ACCESS"
169
fi
170
LANG=C > /dev/null 2>&1
171
if [[ $LANG != C ]]
172
then err_exit "C locale not working"
173
fi
174
unset RANDOM
175
unset -n foo
176
foo=junk
177
function foo.get
178
{
179
.sh.value=stuff
180
unset -f foo.get
181
}
182
if [[ $foo != stuff ]]
183
then err_exit "foo.get discipline not working"
184
fi
185
if [[ $foo != junk ]]
186
then err_exit "foo.get discipline not working after unset"
187
fi
188
# special variables
189
set -- 1 2 3 4 5 6 7 8 9 10
190
sleep 1000 &
191
if [[ $(print -r -- ${#10}) != 2 ]]
192
then err_exit '${#10}, where ${10}=10 not working'
193
fi
194
for i in @ '*' ! '#' - '?' '$'
195
do false
196
eval foo='$'$i bar='$'{$i}
197
if [[ ${foo} != "${bar}" ]]
198
then err_exit "\$$i not equal to \${$i}"
199
fi
200
command eval bar='$'{$i%?} 2> /dev/null || err_exit "\${$i%?} gives syntax error"
201
if [[ $i != [@*] && ${foo%?} != "$bar" ]]
202
then err_exit "\${$i%?} not correct"
203
fi
204
command eval bar='$'{$i#?} 2> /dev/null || err_exit "\${$i#?} gives syntax error"
205
if [[ $i != [@*] && ${foo#?} != "$bar" ]]
206
then err_exit "\${$i#?} not correct"
207
fi
208
command eval foo='$'{$i} bar='$'{#$i} || err_exit "\${#$i} gives synta
209
x error"
210
if [[ $i != @([@*]) && ${#foo} != "$bar" ]]
211
then err_exit "\${#$i} not correct"
212
fi
213
done
214
kill $!
215
unset x
216
CDPATH=/
217
x=$(cd ${tmp#/})
218
if [[ $x != $tmp ]]
219
then err_exit 'CDPATH does not display new directory'
220
fi
221
CDPATH=/:
222
x=$(cd ${tmp%/*}; cd ${tmp##*/})
223
if [[ $x ]]
224
then err_exit 'CDPATH displays new directory when not used'
225
fi
226
x=$(cd ${tmp#/})
227
if [[ $x != $tmp ]]
228
then err_exit "CDPATH ${tmp#/} does not display new directory"
229
fi
230
TMOUT=100
231
(TMOUT=20)
232
if (( TMOUT !=100 ))
233
then err_exit 'setting TMOUT in subshell affects parent'
234
fi
235
unset y
236
function setdisc # var
237
{
238
eval function $1.get'
239
{
240
.sh.value=good
241
}
242
'
243
}
244
y=bad
245
setdisc y
246
if [[ $y != good ]]
247
then err_exit 'setdisc function not working'
248
fi
249
integer x=$LINENO
250
: $'\
251
'
252
if (( LINENO != x+3 ))
253
then err_exit '\<newline> gets linenumber count wrong'
254
fi
255
set --
256
set -- "${@-}"
257
if (( $# !=1 ))
258
then err_exit '"${@-}" not expanding to null string'
259
fi
260
for i in : % + / 3b '**' '***' '@@' '{' '[' '}' !! '*a' '$foo'
261
do (eval : \${"$i"} 2> /dev/null) && err_exit "\${$i} not an syntax error"
262
done
263
unset IFS
264
( IFS=' ' ; read -r a b c <<-!
265
x y z
266
!
267
if [[ $b ]]
268
then err_exit 'IFS=" " not causing adjacent space to be null string'
269
fi
270
)
271
read -r a b c <<-!
272
x y z
273
!
274
if [[ $b != y ]]
275
then err_exit 'IFS not restored after subshell'
276
fi
277
278
# The next part generates 3428 IFS set/read tests.
279
280
unset IFS x
281
function split
282
{
283
i=$1 s=$2 r=$3
284
IFS=': '
285
set -- $i
286
IFS=' '
287
g="[$#]"
288
while :
289
do case $# in
290
0) break ;;
291
esac
292
g="$g($1)"
293
shift
294
done
295
case "$g" in
296
"$s") ;;
297
*) err_exit "IFS=': '; set -- '$i'; expected '$s' got '$g'" ;;
298
esac
299
print "$i" | IFS=": " read arg rem; g="($arg)($rem)"
300
case "$g" in
301
"$r") ;;
302
*) err_exit "IFS=': '; read '$i'; expected '$r' got '$g'" ;;
303
esac
304
}
305
for str in \
306
'-' \
307
'a' \
308
'- -' \
309
'- a' \
310
'a -' \
311
'a b' \
312
'- - -' \
313
'- - a' \
314
'- a -' \
315
'- a b' \
316
'a - -' \
317
'a - b' \
318
'a b -' \
319
'a b c'
320
do
321
IFS=' '
322
set x $str
323
shift
324
case $# in
325
0) continue ;;
326
esac
327
f1=$1
328
case $f1 in
329
'-') f1='' ;;
330
esac
331
shift
332
case $# in
333
0) for d0 in '' ' '
334
do
335
for d1 in '' ' ' ':' ' :' ': ' ' : '
336
do
337
case $f1$d1 in
338
'') split "$d0$f1$d1" "[0]" "()()" ;;
339
' ') ;;
340
*) split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;;
341
esac
342
done
343
done
344
continue
345
;;
346
esac
347
f2=$1
348
case $f2 in
349
'-') f2='' ;;
350
esac
351
shift
352
case $# in
353
0) for d0 in '' ' '
354
do
355
for d1 in ' ' ':' ' :' ': ' ' : '
356
do
357
case ' ' in
358
$f1$d1|$d1$f2) continue ;;
359
esac
360
for d2 in '' ' ' ':' ' :' ': ' ' : '
361
do
362
case $f2$d2 in
363
'') split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;;
364
' ') ;;
365
*) split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;;
366
esac
367
done
368
done
369
done
370
continue
371
;;
372
esac
373
f3=$1
374
case $f3 in
375
'-') f3='' ;;
376
esac
377
shift
378
case $# in
379
0) for d0 in '' ' '
380
do
381
for d1 in ':' ' :' ': ' ' : '
382
do
383
case ' ' in
384
$f1$d1|$d1$f2) continue ;;
385
esac
386
for d2 in ' ' ':' ' :' ': ' ' : '
387
do
388
case $f2$d2 in
389
' ') continue ;;
390
esac
391
case ' ' in
392
$f2$d2|$d2$f3) continue ;;
393
esac
394
for d3 in '' ' ' ':' ' :' ': ' ' : '
395
do
396
case $f3$d3 in
397
'') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;;
398
' ') ;;
399
*) x=$f2$d2$f3$d3
400
x=${x#' '}
401
x=${x%' '}
402
split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)"
403
;;
404
esac
405
done
406
done
407
done
408
done
409
continue
410
;;
411
esac
412
done
413
unset IFS
414
415
if [[ $( (print ${12345:?}) 2>&1) != *12345* ]]
416
then err_exit 'incorrect error message with ${12345?}'
417
fi
418
unset foobar
419
if [[ $( (print ${foobar:?}) 2>&1) != *foobar* ]]
420
then err_exit 'incorrect error message with ${foobar?}'
421
fi
422
unset bar
423
if [[ $( (print ${bar:?bam}) 2>&1) != *bar*bam* ]]
424
then err_exit 'incorrect error message with ${foobar?}'
425
fi
426
{ $SHELL -c '
427
function foo
428
{
429
typeset SECONDS=0
430
sleep 1.5
431
print $SECONDS
432
433
}
434
x=$(foo)
435
(( x >1 && x < 2 ))
436
'
437
} 2> /dev/null || err_exit 'SECONDS not working in function'
438
cat > $tmp/script <<-\!
439
posixfun()
440
{
441
unset x
442
nameref x=$1
443
print -r -- "$x"
444
}
445
function fun
446
{
447
nameref x=$1
448
print -r -- "$x"
449
}
450
if [[ $1 ]]
451
then file=${.sh.file}
452
else print -r -- "${.sh.file}"
453
fi
454
!
455
chmod +x $tmp/script
456
. $tmp/script 1
457
[[ $file == $tmp/script ]] || err_exit ".sh.file not working for dot scripts"
458
[[ $($SHELL $tmp/script) == $tmp/script ]] || err_exit ".sh.file not working for scripts"
459
[[ $(posixfun .sh.file) == $tmp/script ]] || err_exit ".sh.file not working for posix functions"
460
[[ $(fun .sh.file) == $tmp/script ]] || err_exit ".sh.file not working for functions"
461
[[ $(posixfun .sh.fun) == posixfun ]] || err_exit ".sh.fun not working for posix functions"
462
[[ $(fun .sh.fun) == fun ]] || err_exit ".sh.fun not working for functions"
463
[[ $(posixfun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for posix functions"
464
[[ $(fun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for functions"
465
(
466
[[ $(posixfun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for posix functions in subshells"
467
[[ $(fun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for functions in subshells"
468
(( .sh.subshell == 1 )) || err_exit ".sh.subshell not working in a subshell"
469
)
470
TIMEFORMAT='this is a test'
471
[[ $({ { time :;} 2>&1;}) == "$TIMEFORMAT" ]] || err_exit 'TIMEFORMAT not working'
472
: ${.sh.version}
473
[[ $(alias integer) == *.sh.* ]] && err_exit '.sh. prefixed to alias name'
474
: ${.sh.version}
475
[[ $(whence rm) == *.sh.* ]] && err_exit '.sh. prefixed to tracked alias name'
476
: ${.sh.version}
477
[[ $(cd /bin;env | grep PWD=) == *.sh.* ]] && err_exit '.sh. prefixed to PWD'
478
# unset discipline bug fix
479
dave=dave
480
function dave.unset
481
{
482
unset dave
483
}
484
unset dave
485
[[ $(typeset +f) == *dave.* ]] && err_exit 'unset discipline not removed'
486
487
x=$(
488
dave=dave
489
function dave.unset
490
{
491
print dave.unset
492
}
493
)
494
[[ $x == dave.unset ]] || err_exit 'unset discipline not called with subset completion'
495
496
print 'print ${VAR}' > $tmp/script
497
unset VAR
498
VAR=new $tmp/script > $tmp/out
499
got=$(<$tmp/out)
500
[[ $got == new ]] || err_exit "previously unset environment variable not passed to script, expected 'new', got '$got'"
501
[[ ! $VAR ]] || err_exit "previously unset environment variable set after script, expected '', got '$VAR'"
502
unset VAR
503
VAR=old
504
VAR=new $tmp/script > $tmp/out
505
got=$(<$tmp/out)
506
[[ $got == new ]] || err_exit "environment variable covering local variable not passed to script, expected 'new', got '$got'"
507
[[ $VAR == old ]] || err_exit "previously set local variable changed after script, expected 'old', got '$VAR'"
508
unset VAR
509
export VAR=old
510
VAR=new $tmp/script > $tmp/out
511
got=$(<$tmp/out)
512
[[ $got == new ]] || err_exit "environment variable covering environment variable not passed to script, expected 'new', got '$got'"
513
[[ $VAR == old ]] || err_exit "previously set environment variable changed after script, expected 'old', got '$VAR'"
514
515
(
516
unset dave
517
function dave.append
518
{
519
.sh.value+=$dave
520
dave=
521
}
522
dave=foo; dave+=bar
523
[[ $dave == barfoo ]] || exit 2
524
) 2> /dev/null
525
case $? in
526
0) ;;
527
1) err_exit 'append discipline not implemented';;
528
*) err_exit 'append discipline not working';;
529
esac
530
.sh.foobar=hello
531
{
532
function .sh.foobar.get
533
{
534
.sh.value=world
535
}
536
} 2> /dev/null || err_exit "cannot add get discipline to .sh.foobar"
537
[[ ${.sh.foobar} == world ]] || err_exit 'get discipline for .sh.foobar not working'
538
x='a|b'
539
IFS='|'
540
set -- $x
541
[[ $2 == b ]] || err_exit '$2 should be b after set'
542
exec 3>&2 2> /dev/null
543
set -x
544
( IFS= ) 2> /dev/null
545
set +x
546
exec 2>&3-
547
set -- $x
548
[[ $2 == b ]] || err_exit '$2 should be b after subshell'
549
: & pid=$!
550
( : & )
551
[[ $pid == $! ]] || err_exit '$! value not preserved across subshells'
552
unset foo
553
typeset -A foo
554
function foo.set
555
{
556
case ${.sh.subscript} in
557
bar) if ((.sh.value > 1 ))
558
then .sh.value=5
559
foo[barrier_hit]=yes
560
fi
561
;;
562
barrier_hit)
563
if [[ ${.sh.value} == yes ]]
564
then foo[barrier_not_hit]=no
565
else foo[barrier_not_hit]=yes
566
fi
567
;;
568
esac
569
}
570
foo[barrier_hit]=no
571
foo[bar]=1
572
(( foo[bar] == 1 )) || err_exit 'foo[bar] should be 1'
573
[[ ${foo[barrier_hit]} == no ]] || err_exit 'foo[barrier_hit] should be no'
574
[[ ${foo[barrier_not_hit]} == yes ]] || err_exit 'foo[barrier_not_hit] should be yes'
575
foo[barrier_hit]=no
576
foo[bar]=2
577
(( foo[bar] == 5 )) || err_exit 'foo[bar] should be 5'
578
[[ ${foo[barrier_hit]} == yes ]] || err_exit 'foo[barrier_hit] should be yes'
579
[[ ${foo[barrier_not_hit]} == no ]] || err_exit 'foo[barrier_not_hit] should be no'
580
unset x
581
typeset -i x
582
function x.set
583
{
584
typeset sub=${.sh.subscript}
585
(( sub > 0 )) && (( x[sub-1]= x[sub-1] + .sh.value ))
586
}
587
x[0]=0 x[1]=1 x[2]=2 x[3]=3
588
[[ ${x[@]} == '12 8 5 3' ]] || err_exit 'set discipline for indexed array not working correctly'
589
float seconds
590
((SECONDS=3*4))
591
seconds=SECONDS
592
(( seconds < 12 || seconds > 12.1 )) && err_exit "SECONDS is $seconds and should be close to 12"
593
unset a
594
function a.set
595
{
596
print -r -- "${.sh.name}=${.sh.value}"
597
}
598
[[ $(a=1) == a=1 ]] || err_exit 'set discipline not working in subshell assignment'
599
[[ $(a=1 :) == a=1 ]] || err_exit 'set discipline not working in subshell command'
600
601
[[ ${.sh.subshell} == 0 ]] || err_exit '${.sh.subshell} should be 0'
602
(
603
[[ ${.sh.subshell} == 1 ]] || err_exit '${.sh.subshell} should be 1'
604
(
605
[[ ${.sh.subshell} == 2 ]] || err_exit '${.sh.subshell} should be 2'
606
)
607
)
608
609
set -- {1..32768}
610
(( $# == 32768 )) || err_exit "\$# failed -- expected 32768, got $#"
611
set --
612
613
unset r v x
614
path=$PATH
615
x=foo
616
for v in EDITOR VISUAL OPTIND CDPATH FPATH PATH ENV LINENO RANDOM SECONDS _
617
do nameref r=$v
618
unset $v
619
if ( $SHELL -c "unset $v; : \$$v" ) 2>/dev/null
620
then [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'"
621
r=$x
622
[[ $r == $x ]] || err_exit "$v=$x failed -- expected '$x', got '$r'"
623
else err_exit "unset $v; : \$$v failed"
624
fi
625
done
626
627
x=x
628
for v in LC_ALL LC_CTYPE LC_MESSAGES LC_COLLATE LC_NUMERIC
629
do nameref r=$v
630
unset $v
631
[[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'"
632
d=$($SHELL -c "$v=$x" 2>&1)
633
[[ $d ]] || err_exit "$v=$x failed -- expected locale diagnostic"
634
{ g=$( r=$x; print -- $r ); } 2>/dev/null
635
[[ $g == '' ]] || err_exit "$v=$x failed -- expected '', got '$g'"
636
{ g=$( r=C; r=$x; print -- $r ); } 2>/dev/null
637
[[ $g == 'C' ]] || err_exit "$v=C; $v=$x failed -- expected 'C', got '$g'"
638
done
639
PATH=$path
640
641
cd $tmp
642
643
print print -n zzz > zzz
644
chmod +x zzz
645
exp='aaazzz'
646
got=$($SHELL -c 'unset SHLVL; print -n aaa; ./zzz' 2>&1) >/dev/null 2>&1
647
[[ $got == "$exp" ]] || err_exit "unset SHLVL causes script failure -- expected '$exp', got '$got'"
648
649
mkdir glean
650
for cmd in date ok
651
do exp="$cmd ok"
652
rm -f $cmd
653
print print $exp > glean/$cmd
654
chmod +x glean/$cmd
655
got=$(CDPATH=:.. $SHELL -c "PATH=:/bin:/usr/bin; date > /dev/null; cd glean && ./$cmd" 2>&1)
656
[[ $got == "$exp" ]] || err_exit "cd with CDPATH after PATH change failed -- expected '$exp', got '$got'"
657
done
658
659
v=LC_CTYPE
660
unset $v
661
[[ -v $v ]] && err_exit "unset $v; [[ -v $v ]] failed"
662
eval $v=C
663
[[ -v $v ]] || err_exit "$v=C; [[ -v $v ]] failed"
664
665
cmd='set --nounset; unset foo; : ${!foo*}'
666
$SHELL -c "$cmd" 2>/dev/null || err_exit "'$cmd' exit status $?, expected 0"
667
668
SHLVL=1
669
level=$($SHELL -c $'$SHELL -c \'print -r "$SHLVL"\'')
670
[[ $level == 3 ]] || err_exit "SHLVL should be 3 not $level"
671
672
[[ $($SHELL -c '{ x=1; : ${x.};print ok;}' 2> /dev/null) == ok ]] || err_exit '${x.} where x is a simple variable causes shell to abort'
673
674
$SHELL -c 'unset .sh' 2> /dev/null
675
[[ $? == 1 ]] || err_exit 'unset .sh should return 1'
676
677
exit $((Errors<125?Errors:125))
678
679