xref: /titanic_51/usr/src/lib/libshell/common/tests/nameref.sh (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin########################################################################
2da2e3ebdSchin#                                                                      #
3da2e3ebdSchin#               This software is part of the ast package               #
4*3e14f97fSRoger A. Faulkner#          Copyright (c) 1982-2010 AT&T Intellectual Property          #
5da2e3ebdSchin#                      and is licensed under the                       #
6da2e3ebdSchin#                  Common Public License, Version 1.0                  #
77c2fbfb3SApril Chin#                    by AT&T Intellectual Property                     #
8da2e3ebdSchin#                                                                      #
9da2e3ebdSchin#                A copy of the License is available at                 #
10da2e3ebdSchin#            http://www.opensource.org/licenses/cpl1.0.txt             #
11da2e3ebdSchin#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
12da2e3ebdSchin#                                                                      #
13da2e3ebdSchin#              Information and Software Systems Research               #
14da2e3ebdSchin#                            AT&T Research                             #
15da2e3ebdSchin#                           Florham Park NJ                            #
16da2e3ebdSchin#                                                                      #
17da2e3ebdSchin#                  David Korn <dgk@research.att.com>                   #
18da2e3ebdSchin#                                                                      #
19da2e3ebdSchin########################################################################
20da2e3ebdSchinfunction err_exit
21da2e3ebdSchin{
22da2e3ebdSchin	print -u2 -n "\t"
23da2e3ebdSchin	print -u2 -r ${Command}[$1]: "${@:2}"
24da2e3ebdSchin	let Errors+=1
25da2e3ebdSchin}
26da2e3ebdSchinalias err_exit='err_exit $LINENO'
27da2e3ebdSchin
28da2e3ebdSchinCommand=${0##*/}
29da2e3ebdSchininteger Errors=0
3034f9b3eeSRoland Mainz
3134f9b3eeSRoland Mainztmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
3234f9b3eeSRoland Mainztrap "cd /; rm -rf $tmp" EXIT
3334f9b3eeSRoland Mainz
34da2e3ebdSchinfunction checkref
35da2e3ebdSchin{
36da2e3ebdSchin	nameref foo=$1 bar=$2
37da2e3ebdSchin	if	[[ $foo !=  $bar ]]
38da2e3ebdSchin	then	err_exit "foo=$foo != bar=$bar"
39da2e3ebdSchin	fi
40da2e3ebdSchin	foo=hello
41da2e3ebdSchin	if	[[ $foo !=  $bar ]]
42da2e3ebdSchin	then	err_exit "foo=$foo != bar=$bar"
43da2e3ebdSchin	fi
44da2e3ebdSchin	foo.child=child
45da2e3ebdSchin	if	[[ ${foo.child} !=  ${bar.child} ]]
46da2e3ebdSchin	then	err_exit "foo.child=${foo.child} != bar=${bar.child}"
47da2e3ebdSchin	fi
48da2e3ebdSchin}
49da2e3ebdSchin
50da2e3ebdSchinname=first
51da2e3ebdSchincheckref name name
52da2e3ebdSchinname.child=second
53da2e3ebdSchincheckref name name
54da2e3ebdSchin.foo=top
55da2e3ebdSchin.foo.bar=next
56da2e3ebdSchincheckref .foo.bar .foo.bar
57da2e3ebdSchinif	[[ ${.foo.bar} !=  hello ]]
58da2e3ebdSchinthen	err_exit ".foo.bar=${.foo.bar} != hello"
59da2e3ebdSchinfi
60da2e3ebdSchinif	[[ ${.foo.bar.child} !=  child ]]
61da2e3ebdSchinthen	err_exit ".foo.bar.child=${.foo.bar.child} != child"
62da2e3ebdSchinfi
63da2e3ebdSchinfunction func1
64da2e3ebdSchin{
65da2e3ebdSchin        nameref color=$1
66da2e3ebdSchin        func2 color
67da2e3ebdSchin}
68da2e3ebdSchin
69da2e3ebdSchinfunction func2
70da2e3ebdSchin{
71da2e3ebdSchin        nameref color=$1
72da2e3ebdSchin        set -s -- ${!color[@]}
73da2e3ebdSchin	print -r -- "$@"
74da2e3ebdSchin}
75da2e3ebdSchin
76da2e3ebdSchintypeset -A color
77da2e3ebdSchincolor[apple]=red
78da2e3ebdSchincolor[grape]=purple
79da2e3ebdSchincolor[banana]=yellow
80da2e3ebdSchinif	[[ $(func1 color) != 'apple banana grape' ]]
81da2e3ebdSchinthen	err_exit "nameref or nameref not working"
82da2e3ebdSchinfi
83da2e3ebdSchinnameref x=.foo.bar
84da2e3ebdSchinif	[[ ${!x} != .foo.bar ]]
85da2e3ebdSchinthen	err_exit "${!x} not working"
86da2e3ebdSchinfi
87da2e3ebdSchintypeset +n x $(typeset +n)
88da2e3ebdSchinunset x
89da2e3ebdSchinnameref x=.foo.bar
90da2e3ebdSchinfunction x.set
91da2e3ebdSchin{
92da2e3ebdSchin	[[ ${.sh.value} ]] && print hello
93da2e3ebdSchin}
94da2e3ebdSchinif	[[ $(.foo.bar.set) != $(x.set) ]]
95da2e3ebdSchinthen	err_exit "function references  not working"
96da2e3ebdSchinfi
97da2e3ebdSchinif	[[ $(typeset +n) != x ]]
98da2e3ebdSchinthen	err_exit "typeset +n doesn't list names of reference variables"
99da2e3ebdSchinfi
100da2e3ebdSchinif	[[ $(typeset -n) != x=.foo.bar ]]
101da2e3ebdSchinthen	err_exit "typeset +n doesn't list values of reference variables"
102da2e3ebdSchinfi
10334f9b3eeSRoland Mainzfile=$tmp/test
104da2e3ebdSchintypeset +n foo bar 2> /dev/null
105da2e3ebdSchinunset foo bar
106da2e3ebdSchinexport bar=foo
107da2e3ebdSchinnameref foo=bar
108da2e3ebdSchinif	[[ $foo != foo ]]
109da2e3ebdSchinthen	err_exit "value of nameref foo !=  $foo"
110da2e3ebdSchinfi
111da2e3ebdSchincat > $file <<\!
112da2e3ebdSchinprint -r -- $foo
113da2e3ebdSchin!
114da2e3ebdSchinchmod +x "$file"
115da2e3ebdSchiny=$( $file)
116da2e3ebdSchinif	[[ $y != '' ]]
117da2e3ebdSchinthen	err_exit "reference variable not cleared"
118da2e3ebdSchinfi
119da2e3ebdSchin{
120da2e3ebdSchin	command nameref xx=yy
121da2e3ebdSchin	command nameref yy=xx
122da2e3ebdSchin} 2> /dev/null && err_exit "self reference not detected"
123da2e3ebdSchintypeset +n foo bar
124da2e3ebdSchinunset foo bar
125da2e3ebdSchinset foo
126da2e3ebdSchinnameref bar=$1
127da2e3ebdSchinfoo=hello
128da2e3ebdSchinif	[[ $bar !=  hello ]]
129da2e3ebdSchinthen	err_exit 'nameref of positional paramters outside of function not working'
130da2e3ebdSchinfi
131da2e3ebdSchinunset foo bar
132da2e3ebdSchinbar=123
133da2e3ebdSchinfunction foobar
134da2e3ebdSchin{
135da2e3ebdSchin	typeset -n foo=bar
136da2e3ebdSchin	typeset -n foo=bar
137da2e3ebdSchin}
138da2e3ebdSchinfoobar 2> /dev/null || err_exit 'nameref not unsetting previous reference'
139da2e3ebdSchin(
140da2e3ebdSchin	nameref short=verylong
141da2e3ebdSchin	short=( A=a B=b )
142da2e3ebdSchin	if	[[ ${verylong.A} != a ]]
143da2e3ebdSchin	then	err_exit 'nameref short to longname compound assignment error'
144da2e3ebdSchin	fi
145da2e3ebdSchin) 2> /dev/null|| err_exit 'nameref short to longname compound assignment error'
146da2e3ebdSchinunset x
147da2e3ebdSchinif	[[	$(var1=1 var2=2
148da2e3ebdSchin		for i in var1 var2
149da2e3ebdSchin		do	nameref x=$i
150da2e3ebdSchin			print $x
151da2e3ebdSchin		done) != $'1\n2' ]]
152da2e3ebdSchinthen	err_exit 'for loop nameref optimization error'
153da2e3ebdSchinfi
154da2e3ebdSchinif	[[	$(typeset -A var1 var2
155da2e3ebdSchin		var1[sub1]=1 var2[sub2]=1
156da2e3ebdSchin		for i in var1 var2
157da2e3ebdSchin		do
158da2e3ebdSchin		        typeset -n array=$i
159da2e3ebdSchin		        print ${!array[*]}
160da2e3ebdSchin		done) != $'sub1\nsub2' ]]
161da2e3ebdSchinthen 	err_exit 'for loop nameref optimization test2 error'
162da2e3ebdSchinfi
163da2e3ebdSchin
164da2e3ebdSchinunset -n x foo bar
165da2e3ebdSchinif	[[ $(nameref x=foo;for x in foo bar;do print ${!x};done) != $'foo\nbar' ]]
166da2e3ebdSchinthen	err_exit 'for loop optimization with namerefs not working'
167da2e3ebdSchinfi
168da2e3ebdSchinif	[[ $(
169da2e3ebdSchin	p=(x=(r=3) y=(r=4))
170da2e3ebdSchin	for i in x y
171da2e3ebdSchin	do	nameref x=p.$i
172da2e3ebdSchin		print ${x.r}
173da2e3ebdSchin	done
174da2e3ebdSchin) != $'3\n4' ]]
175da2e3ebdSchinthen	err_exit 'nameref optimization error'
176da2e3ebdSchinfi
177da2e3ebdSchin[[ $(
178da2e3ebdSchinunset x y var
179da2e3ebdSchinvar=(foo=bar)
180da2e3ebdSchinfor i in y var
181da2e3ebdSchindo	typeset -n x=$i
182da2e3ebdSchin	if	[[ ${!x.@} ]]
183da2e3ebdSchin	then	print ok
184da2e3ebdSchin	fi
185da2e3ebdSchin	typeset +n x
186da2e3ebdSchindone) != ok ]] && err_exit 'invalid for loop optimization of name references'
187da2e3ebdSchinfunction setval # name value
188da2e3ebdSchin{
189da2e3ebdSchin        nameref arg=$1
190da2e3ebdSchin	nameref var=arg.bar
191da2e3ebdSchin	var=$2
192da2e3ebdSchin}
193da2e3ebdSchinfoo=( integer bar=0)
194da2e3ebdSchinsetval foo 5
195da2e3ebdSchin(( foo.bar == 5)) || err_exit 'nested nameref not working'
196da2e3ebdSchinfunction selfref
197da2e3ebdSchin{
198da2e3ebdSchin        typeset -n ps=$1
199da2e3ebdSchin        print -r -- "${ps}"
200da2e3ebdSchin}
201da2e3ebdSchinps=(a=1 b=2)
202da2e3ebdSchin[[ $(selfref ps) == *a=1* ]] ||  err_exit 'local nameref cannot reference global variable of the same name'
203da2e3ebdSchinfunction subref
204da2e3ebdSchin{
205da2e3ebdSchin	typeset -n foo=$1
206da2e3ebdSchin	print -r -- ${foo.a}
207da2e3ebdSchin}
208da2e3ebdSchin[[ $(subref ps) == 1 ]] ||  err_exit 'local nameref cannot reference global variable child'
209da2e3ebdSchin
210da2e3ebdSchinfunction local
211da2e3ebdSchin{
212da2e3ebdSchin	typeset ps=(typeset -i a=3 b=4)
213da2e3ebdSchin	[[ $(subref ps) == 3 ]] ||  err_exit 'local nameref cannot reference caller compound variable'
214da2e3ebdSchin}
215da2e3ebdSchinlocal
216da2e3ebdSchinunset -f local
217da2e3ebdSchinfunction local
218da2e3ebdSchin{
219da2e3ebdSchin	qs=(integer  a=3; integer b=4)
220da2e3ebdSchin}
221da2e3ebdSchinlocal 2> /dev/null || err_exit 'function local has non-zero exit status'
222da2e3ebdSchin[[ ${qs.a} == 3 ]] || err_exit 'function cannot set compound global variable'
223da2e3ebdSchinunset fun i
224da2e3ebdSchinfoo=(x=hi)
225da2e3ebdSchinfunction fun
226da2e3ebdSchin{
227da2e3ebdSchin        nameref i=$1
228da2e3ebdSchin        print -r -- "${i.x}"
229da2e3ebdSchin}
230da2e3ebdSchini=foo
231da2e3ebdSchin[[ $(fun $i) == hi ]] || err_exit 'nameref for compound variable with in function name of caller fails'
2327c2fbfb3SApril Chinunset -n foo bar
2337c2fbfb3SApril Chintypeset -A foo
2347c2fbfb3SApril Chinfoo[x.y]=(x=3 y=4)
2357c2fbfb3SApril Chinnameref bar=foo[x.y]
2367c2fbfb3SApril Chin[[ ${bar.x} == 3 ]] || err_exit 'nameref to subscript containing . fails'
2377c2fbfb3SApril Chin[[ ${!bar} == 'foo[x.y]' ]] || err_exit '${!var} not correct for nameref to an array instance'
2387c2fbfb3SApril Chintypeset +n bar
2397c2fbfb3SApril Chinnameref bar=foo
2407c2fbfb3SApril Chin[[ ${!bar} == foo ]] || err_exit '${!var} not correct for nameref to array variable'
2417c2fbfb3SApril Chin$SHELL -c 'function bar { nameref x=foo[++];};typeset -A foo;bar' 2> /dev/null ||err_exit 'nameref of associative array tries to evaluate subscript'
2427c2fbfb3SApril Chini=$($SHELL -c 'nameref foo=bar; bar[2]=(x=3 y=4); nameref x=foo[2].y;print -r -- $x' 2> /dev/null)
2437c2fbfb3SApril Chin[[ $i == 4 ]] || err_exit 'creating reference from subscripted variable whose name is a reference failed'
2447c2fbfb3SApril Chin[[ $($SHELL 2> /dev/null <<- '+++EOF'
2457c2fbfb3SApril Chin	function bar
2467c2fbfb3SApril Chin	{
2477c2fbfb3SApril Chin	 	nameref x=$1
2487c2fbfb3SApril Chin	 	print -r -- "$x"
2497c2fbfb3SApril Chin	}
2507c2fbfb3SApril Chin	function foo
2517c2fbfb3SApril Chin	{
2527c2fbfb3SApril Chin	 	typeset var=( foo=hello)
2537c2fbfb3SApril Chin	 	bar var
2547c2fbfb3SApril Chin	}
2557c2fbfb3SApril Chin	foo
2567c2fbfb3SApril Chin+++EOF
2577c2fbfb3SApril Chin) ==  *foo=hello* ]] || err_exit 'unable to display compound variable from name reference of local variable'
2587c2fbfb3SApril Chin#set -x
2597c2fbfb3SApril Chinfor c in '=' '[' ']' '\' "'" '"' '<' '=' '('
2607c2fbfb3SApril Chindo	[[ $($SHELL 2> /dev/null <<- ++EOF++
2617c2fbfb3SApril Chin	x;i=\\$c;typeset -A a; a[\$i]=foo;typeset -n x=a[\$i]; print "\$x"
2627c2fbfb3SApril Chin	++EOF++
2637c2fbfb3SApril Chin) != foo ]] && err_exit 'nameref x=[$c] '"not working for c=$c"
2647c2fbfb3SApril Chindone
2657c2fbfb3SApril Chinunset -n foo x
2667c2fbfb3SApril Chinunset foo x
2677c2fbfb3SApril Chintypeset -A foo
2687c2fbfb3SApril Chinnameref x=foo[xyz]
2697c2fbfb3SApril Chinfoo[xyz]=ok
2707c2fbfb3SApril Chin[[ $x == ok ]] || err_exit 'nameref to unset subscript not working'
2717c2fbfb3SApril Chinfunction function2
2727c2fbfb3SApril Chin{
2737c2fbfb3SApril Chin	nameref v=$1
2747c2fbfb3SApril Chin	v.x=19 v.y=20
2757c2fbfb3SApril Chin}
2767c2fbfb3SApril Chinfunction function1
2777c2fbfb3SApril Chin{
2787c2fbfb3SApril Chin	typeset compound_var=()
2797c2fbfb3SApril Chin	function2 compound_var
2807c2fbfb3SApril Chin	printf "x=%d, y=%d\n" compound_var.x compound_var.y
2817c2fbfb3SApril Chin}
2827c2fbfb3SApril Chinx="$(function1)"
2837c2fbfb3SApril Chin[[ "$x" != 'x=19, y=20' ]] && err_exit "expected 'x=19, y=20', got '${x}'"
2847c2fbfb3SApril Chintypeset +n bar
2857c2fbfb3SApril Chinunset foo bar
2867c2fbfb3SApril Chin[[ $(function a
2877c2fbfb3SApril Chin{
2887c2fbfb3SApril Chin	for i in  foo bar
2897c2fbfb3SApril Chin	do	typeset -n v=$i
2907c2fbfb3SApril Chin		print $v
2917c2fbfb3SApril Chin	done | cat
2927c2fbfb3SApril Chin}
2937c2fbfb3SApril Chinfoo=1 bar=2;a) == $'1\n2' ]] 2> /dev/null || err_exit 'nameref in pipeline broken'
2947c2fbfb3SApril Chinfunction a
2957c2fbfb3SApril Chin{
2967c2fbfb3SApril Chin	typeset -n v=vars.data._1
2977c2fbfb3SApril Chin	print "${v.a} ${v.b}"
2987c2fbfb3SApril Chin}
2997c2fbfb3SApril Chinvars=(data=())
3007c2fbfb3SApril Chinvars.data._1.a=a.1
3017c2fbfb3SApril Chinvars.data._1.b=b.1
3027c2fbfb3SApril Chin[[ $(a) == 'a.1 b.1' ]] || err_exit 'nameref choosing wrong scope -- '
30334f9b3eeSRoland Mainztypeset +n bam zip foo
30434f9b3eeSRoland Mainzunset bam zip foo
30534f9b3eeSRoland Mainztypeset -A foo
30634f9b3eeSRoland Mainzfoo[2]=bar
30734f9b3eeSRoland Mainztypeset -n bam=foo[2]
30834f9b3eeSRoland Mainztypeset -n zip=bam
30934f9b3eeSRoland Mainz[[ $zip == bar ]] || err_exit 'nameref to another nameref to array element fails'
31034f9b3eeSRoland Mainz[[ -R zip ]] || err_exit '[[ -R zip ]] should detect that zip is a reference'
31134f9b3eeSRoland Mainz[[ -R bam ]] || err_exit '[[ -R bam ]] should detect that bam is a reference'
31234f9b3eeSRoland Mainz[[ -R zip ]] || err_exit '[[ -v zip ]] should detect that zip is set'
31334f9b3eeSRoland Mainz[[ -v bam ]] || err_exit '[[ -v bam ]] should detect that bam is set'
31434f9b3eeSRoland Mainz[[ -R 123 ]] && err_exit '[[ -R 123 ]] should detect that 123 is not a reference'
31534f9b3eeSRoland Mainz[[ -v 123 ]] && err_exit '[[ -v 123 ]] should detect that 123 is not set'
31634f9b3eeSRoland Mainz
31734f9b3eeSRoland Mainzunset ref x
31834f9b3eeSRoland Mainztypeset -n ref
31934f9b3eeSRoland Mainzx=3
32034f9b3eeSRoland Mainzfunction foobar
32134f9b3eeSRoland Mainz{
32234f9b3eeSRoland Mainz	typeset xxx=3
32334f9b3eeSRoland Mainz	ref=xxx
32434f9b3eeSRoland Mainz	return 0
32534f9b3eeSRoland Mainz}
32634f9b3eeSRoland Mainzfoobar 2> /dev/null && err_exit 'invalid reference should cause foobar to fail'
32734f9b3eeSRoland Mainz[[ -v ref ]] && err_exit '$ref should be unset'
32834f9b3eeSRoland Mainzref=x
32934f9b3eeSRoland Mainz[[ $ref == 3 ]] || err_exit "\$ref is $ref, it should be 3"
33034f9b3eeSRoland Mainzfunction foobar
33134f9b3eeSRoland Mainz{
33234f9b3eeSRoland Mainz        typeset fvar=()
33334f9b3eeSRoland Mainz        typeset -n ref=fvar.foo
33434f9b3eeSRoland Mainz        ref=ok
33534f9b3eeSRoland Mainz        print -r $ref
33634f9b3eeSRoland Mainz}
33734f9b3eeSRoland Mainz[[ $(foobar) ==  ok ]] 2> /dev/null  || err_exit 'nameref in function not creating variable in proper scope'
33834f9b3eeSRoland Mainzfunction foobar
33934f9b3eeSRoland Mainz{
34034f9b3eeSRoland Mainz        nameref doc=docs
34134f9b3eeSRoland Mainz        nameref bar=doc.num
34234f9b3eeSRoland Mainz	[[ $bar == 2 ]] || err_exit 'nameref scoping error'
34334f9b3eeSRoland Mainz}
34434f9b3eeSRoland Mainz
34534f9b3eeSRoland Mainzdocs=(num=2)
34634f9b3eeSRoland Mainzfoobar
34734f9b3eeSRoland Mainz
34834f9b3eeSRoland Mainztypeset +n x y
34934f9b3eeSRoland Mainzunset x y
35034f9b3eeSRoland Mainztypeset -A x
35134f9b3eeSRoland Mainzx[a]=(b=c)
35234f9b3eeSRoland Mainztypeset -n y=x[a]
35334f9b3eeSRoland Mainz[[ ${!y.@} == 'x[a].b' ]] || err_exit 'reference to array element not expanded with ${!y.@}'
35434f9b3eeSRoland Mainz
35534f9b3eeSRoland Mainztypeset +n v
35634f9b3eeSRoland Mainzv=()
35734f9b3eeSRoland Mainzk=a.b.c/d
35834f9b3eeSRoland Mainzcommand typeset -n n=v.${k//['./']/_} 2> /dev/null || err_exit 'patterns with quotes not handled correctly with name reference assignment'
35934f9b3eeSRoland Mainz
36034f9b3eeSRoland Mainztypeset _n sp
36134f9b3eeSRoland Mainznameref sp=addrsp
36234f9b3eeSRoland Mainzsp[14]=( size=1 )
36334f9b3eeSRoland Mainz[[ -v sp[19] ]]  && err_exit '[[ -v sp[19] ]] where sp is a nameref should not be set'
36434f9b3eeSRoland Mainz
365da2e3ebdSchinexit $((Errors))
366