1######################################################################## 2# # 3# This software is part of the ast package # 4# Copyright (c) 1982-2010 AT&T Intellectual Property # 5# and is licensed under the # 6# Common Public License, Version 1.0 # 7# by AT&T Intellectual Property # 8# # 9# A copy of the License is available at # 10# http://www.opensource.org/licenses/cpl1.0.txt # 11# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # 12# # 13# Information and Software Systems Research # 14# AT&T Research # 15# Florham Park NJ # 16# # 17# David Korn <dgk@research.att.com> # 18# # 19######################################################################## 20function err_exit 21{ 22 print -u2 -n "\t" 23 print -u2 -r ${Command}[$1]: "${@:2}" 24 let Errors+=1 25} 26alias err_exit='err_exit $LINENO' 27 28Command=${0##*/} 29integer Errors=0 30 31tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; } 32trap "cd /; rm -rf $tmp" EXIT 33 34function checkref 35{ 36 nameref foo=$1 bar=$2 37 if [[ $foo != $bar ]] 38 then err_exit "foo=$foo != bar=$bar" 39 fi 40 foo=hello 41 if [[ $foo != $bar ]] 42 then err_exit "foo=$foo != bar=$bar" 43 fi 44 foo.child=child 45 if [[ ${foo.child} != ${bar.child} ]] 46 then err_exit "foo.child=${foo.child} != bar=${bar.child}" 47 fi 48} 49 50name=first 51checkref name name 52name.child=second 53checkref name name 54.foo=top 55.foo.bar=next 56checkref .foo.bar .foo.bar 57if [[ ${.foo.bar} != hello ]] 58then err_exit ".foo.bar=${.foo.bar} != hello" 59fi 60if [[ ${.foo.bar.child} != child ]] 61then err_exit ".foo.bar.child=${.foo.bar.child} != child" 62fi 63function func1 64{ 65 nameref color=$1 66 func2 color 67} 68 69function func2 70{ 71 nameref color=$1 72 set -s -- ${!color[@]} 73 print -r -- "$@" 74} 75 76typeset -A color 77color[apple]=red 78color[grape]=purple 79color[banana]=yellow 80if [[ $(func1 color) != 'apple banana grape' ]] 81then err_exit "nameref or nameref not working" 82fi 83nameref x=.foo.bar 84if [[ ${!x} != .foo.bar ]] 85then err_exit "${!x} not working" 86fi 87typeset +n x $(typeset +n) 88unset x 89nameref x=.foo.bar 90function x.set 91{ 92 [[ ${.sh.value} ]] && print hello 93} 94if [[ $(.foo.bar.set) != $(x.set) ]] 95then err_exit "function references not working" 96fi 97if [[ $(typeset +n) != x ]] 98then err_exit "typeset +n doesn't list names of reference variables" 99fi 100if [[ $(typeset -n) != x=.foo.bar ]] 101then err_exit "typeset +n doesn't list values of reference variables" 102fi 103file=$tmp/test 104typeset +n foo bar 2> /dev/null 105unset foo bar 106export bar=foo 107nameref foo=bar 108if [[ $foo != foo ]] 109then err_exit "value of nameref foo != $foo" 110fi 111cat > $file <<\! 112print -r -- $foo 113! 114chmod +x "$file" 115y=$( $file) 116if [[ $y != '' ]] 117then err_exit "reference variable not cleared" 118fi 119{ 120 command nameref xx=yy 121 command nameref yy=xx 122} 2> /dev/null && err_exit "self reference not detected" 123typeset +n foo bar 124unset foo bar 125set foo 126nameref bar=$1 127foo=hello 128if [[ $bar != hello ]] 129then err_exit 'nameref of positional paramters outside of function not working' 130fi 131unset foo bar 132bar=123 133function foobar 134{ 135 typeset -n foo=bar 136 typeset -n foo=bar 137} 138foobar 2> /dev/null || err_exit 'nameref not unsetting previous reference' 139( 140 nameref short=verylong 141 short=( A=a B=b ) 142 if [[ ${verylong.A} != a ]] 143 then err_exit 'nameref short to longname compound assignment error' 144 fi 145) 2> /dev/null|| err_exit 'nameref short to longname compound assignment error' 146unset x 147if [[ $(var1=1 var2=2 148 for i in var1 var2 149 do nameref x=$i 150 print $x 151 done) != $'1\n2' ]] 152then err_exit 'for loop nameref optimization error' 153fi 154if [[ $(typeset -A var1 var2 155 var1[sub1]=1 var2[sub2]=1 156 for i in var1 var2 157 do 158 typeset -n array=$i 159 print ${!array[*]} 160 done) != $'sub1\nsub2' ]] 161then err_exit 'for loop nameref optimization test2 error' 162fi 163 164unset -n x foo bar 165if [[ $(nameref x=foo;for x in foo bar;do print ${!x};done) != $'foo\nbar' ]] 166then err_exit 'for loop optimization with namerefs not working' 167fi 168if [[ $( 169 p=(x=(r=3) y=(r=4)) 170 for i in x y 171 do nameref x=p.$i 172 print ${x.r} 173 done 174) != $'3\n4' ]] 175then err_exit 'nameref optimization error' 176fi 177[[ $( 178unset x y var 179var=(foo=bar) 180for i in y var 181do typeset -n x=$i 182 if [[ ${!x.@} ]] 183 then print ok 184 fi 185 typeset +n x 186done) != ok ]] && err_exit 'invalid for loop optimization of name references' 187function setval # name value 188{ 189 nameref arg=$1 190 nameref var=arg.bar 191 var=$2 192} 193foo=( integer bar=0) 194setval foo 5 195(( foo.bar == 5)) || err_exit 'nested nameref not working' 196function selfref 197{ 198 typeset -n ps=$1 199 print -r -- "${ps}" 200} 201ps=(a=1 b=2) 202[[ $(selfref ps) == *a=1* ]] || err_exit 'local nameref cannot reference global variable of the same name' 203function subref 204{ 205 typeset -n foo=$1 206 print -r -- ${foo.a} 207} 208[[ $(subref ps) == 1 ]] || err_exit 'local nameref cannot reference global variable child' 209 210function local 211{ 212 typeset ps=(typeset -i a=3 b=4) 213 [[ $(subref ps) == 3 ]] || err_exit 'local nameref cannot reference caller compound variable' 214} 215local 216unset -f local 217function local 218{ 219 qs=(integer a=3; integer b=4) 220} 221local 2> /dev/null || err_exit 'function local has non-zero exit status' 222[[ ${qs.a} == 3 ]] || err_exit 'function cannot set compound global variable' 223unset fun i 224foo=(x=hi) 225function fun 226{ 227 nameref i=$1 228 print -r -- "${i.x}" 229} 230i=foo 231[[ $(fun $i) == hi ]] || err_exit 'nameref for compound variable with in function name of caller fails' 232unset -n foo bar 233typeset -A foo 234foo[x.y]=(x=3 y=4) 235nameref bar=foo[x.y] 236[[ ${bar.x} == 3 ]] || err_exit 'nameref to subscript containing . fails' 237[[ ${!bar} == 'foo[x.y]' ]] || err_exit '${!var} not correct for nameref to an array instance' 238typeset +n bar 239nameref bar=foo 240[[ ${!bar} == foo ]] || err_exit '${!var} not correct for nameref to array variable' 241$SHELL -c 'function bar { nameref x=foo[++];};typeset -A foo;bar' 2> /dev/null ||err_exit 'nameref of associative array tries to evaluate subscript' 242i=$($SHELL -c 'nameref foo=bar; bar[2]=(x=3 y=4); nameref x=foo[2].y;print -r -- $x' 2> /dev/null) 243[[ $i == 4 ]] || err_exit 'creating reference from subscripted variable whose name is a reference failed' 244[[ $($SHELL 2> /dev/null <<- '+++EOF' 245 function bar 246 { 247 nameref x=$1 248 print -r -- "$x" 249 } 250 function foo 251 { 252 typeset var=( foo=hello) 253 bar var 254 } 255 foo 256+++EOF 257) == *foo=hello* ]] || err_exit 'unable to display compound variable from name reference of local variable' 258#set -x 259for c in '=' '[' ']' '\' "'" '"' '<' '=' '(' 260do [[ $($SHELL 2> /dev/null <<- ++EOF++ 261 x;i=\\$c;typeset -A a; a[\$i]=foo;typeset -n x=a[\$i]; print "\$x" 262 ++EOF++ 263) != foo ]] && err_exit 'nameref x=[$c] '"not working for c=$c" 264done 265unset -n foo x 266unset foo x 267typeset -A foo 268nameref x=foo[xyz] 269foo[xyz]=ok 270[[ $x == ok ]] || err_exit 'nameref to unset subscript not working' 271function function2 272{ 273 nameref v=$1 274 v.x=19 v.y=20 275} 276function function1 277{ 278 typeset compound_var=() 279 function2 compound_var 280 printf "x=%d, y=%d\n" compound_var.x compound_var.y 281} 282x="$(function1)" 283[[ "$x" != 'x=19, y=20' ]] && err_exit "expected 'x=19, y=20', got '${x}'" 284typeset +n bar 285unset foo bar 286[[ $(function a 287{ 288 for i in foo bar 289 do typeset -n v=$i 290 print $v 291 done | cat 292} 293foo=1 bar=2;a) == $'1\n2' ]] 2> /dev/null || err_exit 'nameref in pipeline broken' 294function a 295{ 296 typeset -n v=vars.data._1 297 print "${v.a} ${v.b}" 298} 299vars=(data=()) 300vars.data._1.a=a.1 301vars.data._1.b=b.1 302[[ $(a) == 'a.1 b.1' ]] || err_exit 'nameref choosing wrong scope -- ' 303typeset +n bam zip foo 304unset bam zip foo 305typeset -A foo 306foo[2]=bar 307typeset -n bam=foo[2] 308typeset -n zip=bam 309[[ $zip == bar ]] || err_exit 'nameref to another nameref to array element fails' 310[[ -R zip ]] || err_exit '[[ -R zip ]] should detect that zip is a reference' 311[[ -R bam ]] || err_exit '[[ -R bam ]] should detect that bam is a reference' 312[[ -R zip ]] || err_exit '[[ -v zip ]] should detect that zip is set' 313[[ -v bam ]] || err_exit '[[ -v bam ]] should detect that bam is set' 314[[ -R 123 ]] && err_exit '[[ -R 123 ]] should detect that 123 is not a reference' 315[[ -v 123 ]] && err_exit '[[ -v 123 ]] should detect that 123 is not set' 316 317unset ref x 318typeset -n ref 319x=3 320function foobar 321{ 322 typeset xxx=3 323 ref=xxx 324 return 0 325} 326foobar 2> /dev/null && err_exit 'invalid reference should cause foobar to fail' 327[[ -v ref ]] && err_exit '$ref should be unset' 328ref=x 329[[ $ref == 3 ]] || err_exit "\$ref is $ref, it should be 3" 330function foobar 331{ 332 typeset fvar=() 333 typeset -n ref=fvar.foo 334 ref=ok 335 print -r $ref 336} 337[[ $(foobar) == ok ]] 2> /dev/null || err_exit 'nameref in function not creating variable in proper scope' 338function foobar 339{ 340 nameref doc=docs 341 nameref bar=doc.num 342 [[ $bar == 2 ]] || err_exit 'nameref scoping error' 343} 344 345docs=(num=2) 346foobar 347 348typeset +n x y 349unset x y 350typeset -A x 351x[a]=(b=c) 352typeset -n y=x[a] 353[[ ${!y.@} == 'x[a].b' ]] || err_exit 'reference to array element not expanded with ${!y.@}' 354 355typeset +n v 356v=() 357k=a.b.c/d 358command typeset -n n=v.${k//['./']/_} 2> /dev/null || err_exit 'patterns with quotes not handled correctly with name reference assignment' 359 360typeset _n sp 361nameref sp=addrsp 362sp[14]=( size=1 ) 363[[ -v sp[19] ]] && err_exit '[[ -v sp[19] ]] where sp is a nameref should not be set' 364 365exit $((Errors)) 366