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