1*4887Schin########################################################################
2*4887Schin#                                                                      #
3*4887Schin#               This software is part of the ast package               #
4*4887Schin#           Copyright (c) 1982-2007 AT&T Knowledge Ventures            #
5*4887Schin#                      and is licensed under the                       #
6*4887Schin#                  Common Public License, Version 1.0                  #
7*4887Schin#                      by AT&T Knowledge Ventures                      #
8*4887Schin#                                                                      #
9*4887Schin#                A copy of the License is available at                 #
10*4887Schin#            http://www.opensource.org/licenses/cpl1.0.txt             #
11*4887Schin#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
12*4887Schin#                                                                      #
13*4887Schin#              Information and Software Systems Research               #
14*4887Schin#                            AT&T Research                             #
15*4887Schin#                           Florham Park NJ                            #
16*4887Schin#                                                                      #
17*4887Schin#                  David Korn <dgk@research.att.com>                   #
18*4887Schin#                                                                      #
19*4887Schin########################################################################
20*4887Schinfunction err_exit
21*4887Schin{
22*4887Schin	print -u2 -n "\t"
23*4887Schin	print -u2 -r ${Command}[$1]: "${@:2}"
24*4887Schin	let Errors+=1
25*4887Schin}
26*4887Schinalias err_exit='err_exit $LINENO'
27*4887Schin
28*4887SchinCommand=${0##*/}
29*4887Schininteger Errors=0
30*4887Schinfunction checkref
31*4887Schin{
32*4887Schin	nameref foo=$1 bar=$2
33*4887Schin	if	[[ $foo !=  $bar ]]
34*4887Schin	then	err_exit "foo=$foo != bar=$bar"
35*4887Schin	fi
36*4887Schin	foo=hello
37*4887Schin	if	[[ $foo !=  $bar ]]
38*4887Schin	then	err_exit "foo=$foo != bar=$bar"
39*4887Schin	fi
40*4887Schin	foo.child=child
41*4887Schin	if	[[ ${foo.child} !=  ${bar.child} ]]
42*4887Schin	then	err_exit "foo.child=${foo.child} != bar=${bar.child}"
43*4887Schin	fi
44*4887Schin}
45*4887Schin
46*4887Schinname=first
47*4887Schincheckref name name
48*4887Schinname.child=second
49*4887Schincheckref name name
50*4887Schin.foo=top
51*4887Schin.foo.bar=next
52*4887Schincheckref .foo.bar .foo.bar
53*4887Schinif	[[ ${.foo.bar} !=  hello ]]
54*4887Schinthen	err_exit ".foo.bar=${.foo.bar} != hello"
55*4887Schinfi
56*4887Schinif	[[ ${.foo.bar.child} !=  child ]]
57*4887Schinthen	err_exit ".foo.bar.child=${.foo.bar.child} != child"
58*4887Schinfi
59*4887Schinfunction func1
60*4887Schin{
61*4887Schin        nameref color=$1
62*4887Schin        func2 color
63*4887Schin}
64*4887Schin
65*4887Schinfunction func2
66*4887Schin{
67*4887Schin        nameref color=$1
68*4887Schin        set -s -- ${!color[@]}
69*4887Schin	print -r -- "$@"
70*4887Schin}
71*4887Schin
72*4887Schintypeset -A color
73*4887Schincolor[apple]=red
74*4887Schincolor[grape]=purple
75*4887Schincolor[banana]=yellow
76*4887Schinif	[[ $(func1 color) != 'apple banana grape' ]]
77*4887Schinthen	err_exit "nameref or nameref not working"
78*4887Schinfi
79*4887Schinnameref x=.foo.bar
80*4887Schinif	[[ ${!x} != .foo.bar ]]
81*4887Schinthen	err_exit "${!x} not working"
82*4887Schinfi
83*4887Schintypeset +n x $(typeset +n)
84*4887Schinunset x
85*4887Schinnameref x=.foo.bar
86*4887Schinfunction x.set
87*4887Schin{
88*4887Schin	[[ ${.sh.value} ]] && print hello
89*4887Schin}
90*4887Schinif	[[ $(.foo.bar.set) != $(x.set) ]]
91*4887Schinthen	err_exit "function references  not working"
92*4887Schinfi
93*4887Schinif	[[ $(typeset +n) != x ]]
94*4887Schinthen	err_exit "typeset +n doesn't list names of reference variables"
95*4887Schinfi
96*4887Schinif	[[ $(typeset -n) != x=.foo.bar ]]
97*4887Schinthen	err_exit "typeset +n doesn't list values of reference variables"
98*4887Schinfi
99*4887Schinfile=/tmp/shtest$$
100*4887Schintypeset +n foo bar 2> /dev/null
101*4887Schinunset foo bar
102*4887Schinexport bar=foo
103*4887Schinnameref foo=bar
104*4887Schinif	[[ $foo != foo ]]
105*4887Schinthen	err_exit "value of nameref foo !=  $foo"
106*4887Schinfi
107*4887Schintrap "rm -f $file" EXIT INT
108*4887Schincat > $file <<\!
109*4887Schinprint -r -- $foo
110*4887Schin!
111*4887Schinchmod +x "$file"
112*4887Schiny=$( $file)
113*4887Schinif	[[ $y != '' ]]
114*4887Schinthen	err_exit "reference variable not cleared"
115*4887Schinfi
116*4887Schin{
117*4887Schin	command nameref xx=yy
118*4887Schin	command nameref yy=xx
119*4887Schin} 2> /dev/null && err_exit "self reference not detected"
120*4887Schintypeset +n foo bar
121*4887Schinunset foo bar
122*4887Schinset foo
123*4887Schinnameref bar=$1
124*4887Schinfoo=hello
125*4887Schinif	[[ $bar !=  hello ]]
126*4887Schinthen	err_exit 'nameref of positional paramters outside of function not working'
127*4887Schinfi
128*4887Schinunset foo bar
129*4887Schinbar=123
130*4887Schinfunction foobar
131*4887Schin{
132*4887Schin	typeset -n foo=bar
133*4887Schin	typeset -n foo=bar
134*4887Schin}
135*4887Schinfoobar 2> /dev/null || err_exit 'nameref not unsetting previous reference'
136*4887Schin(
137*4887Schin	nameref short=verylong
138*4887Schin	short=( A=a B=b )
139*4887Schin	if	[[ ${verylong.A} != a ]]
140*4887Schin	then	err_exit 'nameref short to longname compound assignment error'
141*4887Schin	fi
142*4887Schin) 2> /dev/null|| err_exit 'nameref short to longname compound assignment error'
143*4887Schinunset x
144*4887Schinif	[[	$(var1=1 var2=2
145*4887Schin		for i in var1 var2
146*4887Schin		do	nameref x=$i
147*4887Schin			print $x
148*4887Schin		done) != $'1\n2' ]]
149*4887Schinthen	err_exit 'for loop nameref optimization error'
150*4887Schinfi
151*4887Schinif	[[	$(typeset -A var1 var2
152*4887Schin		var1[sub1]=1 var2[sub2]=1
153*4887Schin		for i in var1 var2
154*4887Schin		do
155*4887Schin		        typeset -n array=$i
156*4887Schin		        print ${!array[*]}
157*4887Schin		done) != $'sub1\nsub2' ]]
158*4887Schinthen 	err_exit 'for loop nameref optimization test2 error'
159*4887Schinfi
160*4887Schin
161*4887Schinunset -n x foo bar
162*4887Schinif	[[ $(nameref x=foo;for x in foo bar;do print ${!x};done) != $'foo\nbar' ]]
163*4887Schinthen	err_exit 'for loop optimization with namerefs not working'
164*4887Schinfi
165*4887Schinif	[[ $(
166*4887Schin	p=(x=(r=3) y=(r=4))
167*4887Schin	for i in x y
168*4887Schin	do	nameref x=p.$i
169*4887Schin		print ${x.r}
170*4887Schin	done
171*4887Schin) != $'3\n4' ]]
172*4887Schinthen	err_exit 'nameref optimization error'
173*4887Schinfi
174*4887Schin[[ $(
175*4887Schinunset x y var
176*4887Schinvar=(foo=bar)
177*4887Schinfor i in y var
178*4887Schindo	typeset -n x=$i
179*4887Schin	if	[[ ${!x.@} ]]
180*4887Schin	then	print ok
181*4887Schin	fi
182*4887Schin	typeset +n x
183*4887Schindone) != ok ]] && err_exit 'invalid for loop optimization of name references'
184*4887Schinfunction setval # name value
185*4887Schin{
186*4887Schin        nameref arg=$1
187*4887Schin	nameref var=arg.bar
188*4887Schin	var=$2
189*4887Schin}
190*4887Schinfoo=( integer bar=0)
191*4887Schinsetval foo 5
192*4887Schin(( foo.bar == 5)) || err_exit 'nested nameref not working'
193*4887Schinfunction selfref
194*4887Schin{
195*4887Schin        typeset -n ps=$1
196*4887Schin        print -r -- "${ps}"
197*4887Schin}
198*4887Schinps=(a=1 b=2)
199*4887Schin[[ $(selfref ps) == *a=1* ]] ||  err_exit 'local nameref cannot reference global variable of the same name'
200*4887Schinfunction subref
201*4887Schin{
202*4887Schin	typeset -n foo=$1
203*4887Schin	print -r -- ${foo.a}
204*4887Schin}
205*4887Schin[[ $(subref ps) == 1 ]] ||  err_exit 'local nameref cannot reference global variable child'
206*4887Schin
207*4887Schinfunction local
208*4887Schin{
209*4887Schin	typeset ps=(typeset -i a=3 b=4)
210*4887Schin	[[ $(subref ps) == 3 ]] ||  err_exit 'local nameref cannot reference caller compound variable'
211*4887Schin}
212*4887Schinlocal
213*4887Schinunset -f local
214*4887Schinfunction local
215*4887Schin{
216*4887Schin	qs=(integer  a=3; integer b=4)
217*4887Schin}
218*4887Schinlocal 2> /dev/null || err_exit 'function local has non-zero exit status'
219*4887Schin[[ ${qs.a} == 3 ]] || err_exit 'function cannot set compound global variable'
220*4887Schinunset fun i
221*4887Schinfoo=(x=hi)
222*4887Schinfunction fun
223*4887Schin{
224*4887Schin        nameref i=$1
225*4887Schin        print -r -- "${i.x}"
226*4887Schin}
227*4887Schini=foo
228*4887Schin[[ $(fun $i) == hi ]] || err_exit 'nameref for compound variable with in function name of caller fails'
229*4887Schinexit $((Errors))
230