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 <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 i=\\$c;typeset -A a; a[\$i]=foo;typeset -n x=a[\$i]; print "\$x" 262 ++EOF++ 263) != foo ]] && err_exit 'nameref x=a[$c] '"not working for c=$c" 264done 265for c in '=' '[' ']' '\' "'" '"' '<' '=' '(' 266do [[ $($SHELL 2> /dev/null <<- ++EOF++ 267 i=\\$c;typeset -A a; a[\$i]=foo;b=a[\$i];typeset -n x=\$b; print "\$x" 268 ++EOF++ 269) != foo ]] && err_exit 'nameref x=$b with b=a[$c] '"not working for c=$c" 270done 271 272unset -n foo x 273unset foo x 274typeset -A foo 275nameref x=foo[xyz] 276foo[xyz]=ok 277[[ $x == ok ]] || err_exit 'nameref to unset subscript not working' 278function function2 279{ 280 nameref v=$1 281 v.x=19 v.y=20 282} 283function function1 284{ 285 typeset compound_var=() 286 function2 compound_var 287 printf "x=%d, y=%d\n" compound_var.x compound_var.y 288} 289x="$(function1)" 290[[ "$x" != 'x=19, y=20' ]] && err_exit "expected 'x=19, y=20', got '${x}'" 291typeset +n bar 292unset foo bar 293[[ $(function a 294{ 295 for i in foo bar 296 do typeset -n v=$i 297 print $v 298 done | cat 299} 300foo=1 bar=2;a) == $'1\n2' ]] 2> /dev/null || err_exit 'nameref in pipeline broken' 301function a 302{ 303 typeset -n v=vars.data._1 304 print "${v.a} ${v.b}" 305} 306vars=(data=()) 307vars.data._1.a=a.1 308vars.data._1.b=b.1 309[[ $(a) == 'a.1 b.1' ]] || err_exit 'nameref choosing wrong scope -- ' 310typeset +n bam zip foo 311unset bam zip foo 312typeset -A foo 313foo[2]=bar 314typeset -n bam=foo[2] 315typeset -n zip=bam 316[[ $zip == bar ]] || err_exit 'nameref to another nameref to array element fails' 317[[ -R zip ]] || err_exit '[[ -R zip ]] should detect that zip is a reference' 318[[ -R bam ]] || err_exit '[[ -R bam ]] should detect that bam is a reference' 319[[ -R zip ]] || err_exit '[[ -v zip ]] should detect that zip is set' 320[[ -v bam ]] || err_exit '[[ -v bam ]] should detect that bam is set' 321[[ -R 123 ]] && err_exit '[[ -R 123 ]] should detect that 123 is not a reference' 322[[ -v 123 ]] && err_exit '[[ -v 123 ]] should detect that 123 is not set' 323 324unset ref x 325typeset -n ref 326x=3 327function foobar 328{ 329 typeset xxx=3 330 ref=xxx 331 return 0 332} 333foobar 2> /dev/null && err_exit 'invalid reference should cause foobar to fail' 334[[ -v ref ]] && err_exit '$ref should be unset' 335ref=x 336[[ $ref == 3 ]] || err_exit "\$ref is $ref, it should be 3" 337function foobar 338{ 339 typeset fvar=() 340 typeset -n ref=fvar.foo 341 ref=ok 342 print -r $ref 343} 344[[ $(foobar) == ok ]] 2> /dev/null || err_exit 'nameref in function not creating variable in proper scope' 345function foobar 346{ 347 nameref doc=docs 348 nameref bar=doc.num 349 [[ $bar == 2 ]] || err_exit 'nameref scoping error' 350} 351 352docs=(num=2) 353foobar 354 355typeset +n x y 356unset x y 357typeset -A x 358x[a]=(b=c) 359typeset -n y=x[a] 360[[ ${!y.@} == 'x[a].b' ]] || err_exit 'reference to array element not expanded with ${!y.@}' 361 362typeset +n v 363v=() 364k=a.b.c/d 365command typeset -n n=v.${k//['./']/_} 2> /dev/null || err_exit 'patterns with quotes not handled correctly with name reference assignment' 366 367typeset _n sp 368nameref sp=addrsp 369sp[14]=( size=1 ) 370[[ -v sp[19] ]] && err_exit '[[ -v sp[19] ]] where sp is a nameref should not be set' 371 372function fun2 373{ 374 nameref var=$1 375 var.foo=bar 376} 377 378function fun1 379{ 380 compound -S container 381 fun2 container 382 [[ $container == *foo=bar* ]] || err_exit 'name references to static compound variables in parent scope not working' 383} 384fun1 385 386function fun2 387{ 388 nameref var=$1 389 var.foo=bar 390} 391 392typeset -T container_t=( 393 typeset foo 394) 395 396function fun1 397{ 398 container_t -S container 399 fun2 container 400 [[ $container == *foo=bar* ]] || err_exit 'name references to static type variables in parent scope not working' 401} 402fun1 403 404function fun2 405{ 406 nameref var=$1 407 nameref node=var.foo 408 node=bar 409} 410function fun3 411{ 412 fun2 container #2> /dev/null 413} 414compound container 415fun3 416[[ $container == *foo=bar* ]] || err_exit 'name reference to a name reference variable in a function not working' 417 418typeset -A x=( [a]=1 ) 419nameref c=x[h] 420[[ -v x[h] ]] && err_exit 'creating reference to non-existant associative array element causes element to get added' 421 422unset a 423function x 424{ 425 nameref a=a 426 (( $# > 0 )) && typeset -A a 427 a[a b]=${1-99} # this was cauing a syntax on the second call 428} 429x 7 430x 2> /dev/null 431[[ ${a[a b]} == 99 ]] || err_exit 'nameref not handling subscript correctly' 432 433nameref sizes=baz 434typeset -A -i sizes 435sizes[bar]=1 436[[ ${sizes[*]} == 1 ]] || err_exit 'adding -Ai attribute to name referenced variable not working' 437 438$SHELL 2> /dev/null -c 'nameref foo=bar; typeset -A foo; (( (x=foo[a])==0 ))' || err_exit 'references inside arithmetic expressions not working' 439: 440 441unset ar z 442integer -a ar 443nameref z=ar[0] 444(( z[2]=3)) 445[[ ${ar[0][2]} == 3 ]] || err_exit "\${ar[0][2]} is '${ar[0][2]}' but should be 3" 446(( ar[0][2] == 3 )) || err_exit "ar[0][2] is '${ar[0][2]}' but should be 3" 447 448unset c x 449typeset +n c x 450compound c=( typeset -a x ) 451nameref x=c.x 452x[4]=1 453[[ ${ typeset -p c.x ;} == *-C* ]] && err_exit 'c.x should not have -C attributes' 454 455{ $SHELL 2> /dev/null <<- \EOF 456 typeset -T xxx_t=( 457 float x=1 y=2 458 typeset name=abc 459 ) 460 xxx_t x 461 nameref r=x.y 462 [[ $r == 2 ]] || exit 1 463 unset x 464 [[ ${!r} == .deleted ]] || exit 2 465EOF 466} 2> /dev/null #|| print -u2 bad 467exitval=$? 468if [[ $(kill -l $exitval) == SEGV ]] 469then print -u2 'name reference to unset type instance causes segmentation violation' 470else if((exitval)) 471 then print -u2 'name reference to unset type instance not redirected to .deleted' 472 fi 473fi 474 475typeset +n nr 476unset c nr 477compound c 478compound -A c.a 479nameref nr=c.a[hello] 480[[ ${!nr} == "c.a[hello]" ]] || err_exit 'name reference nr to unset associative array instance does not expand ${!nr} correctly.' 481 482typeset +n nr 483compound -a c.b 484nameref nr=c.b[2] 485[[ ${!nr} == "c.b[2]" ]] || err_exit 'name reference nr to unset indexed array instance does not expand ${!nr} correctly.' 486 487typeset +n a b 488unset a b 489typeset -n a=ls[0] b=ls[1] 490read line << \! 4913 4 492! 493set -A ls -- $line 494[[ $a == 3 ]] || err_exit 'name reference to ls[0] when ls is not an array fails' 495 496$SHELL 2> /dev/null <<-\EOF || err_exit 'nameref to array element fails' 497 set -o errexit 498 function bf { 499 nameref treename=$1 500 nodepath="treename" ; 501 nameref x="$nodepath" 502 compound -A x.nodes 503 nameref node=treename.nodes[4] 504 node=() 505 typeset +p node.elements 506 } 507 compound c 508 bf c 509EOF 510 511function add_compound 512{ 513 nameref arr=$1 514 arr[34]+=( float val=1.1 ) 515} 516compound -a rootcpv 517nameref mycpv=rootcpv[4][8][16][32][64] 518compound -a mycpv.myindexedcompoundarray 519add_compound mycpv.myindexedcompoundarray 520(( mycpv.myindexedcompoundarray[34].val == 1.1 )) || err_exit 'nameref scoping error' 521 522function add_file_to_tree 523{ 524 nameref node=$1 525 compound -A node.elements 526 node.elements[/]=(filepath=foobar) 527} 528function main 529{ 530 compound filetree 531 add_file_to_tree filetree 532} 533main 2> /dev/null 534[[ $? == 0 ]] || err_exit 'nameref binding to calling function compound variable failed' 535 536unset l 537typeset -a -C l 538printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4][6] 539exp=$(print -v l) 540unset l 541typeset -a -C l 542nameref l4=l[4] 543printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4[6] 544[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working' 545unset l 546typeset -a -C l 547nameref l46=l[4][6] 548printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l46 549[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l46=l[4][6] not working' 550 551exp=$'(\n\t[4]=(\n\t\ttypeset -a ar=(\n\t\t\t1\n\t\t\t2\n\t\t)\n\t\tb=1\n\t)\n)' 552unset l 553typeset +n l4 554typeset -a -C l 555nameref l4=l[4] 556printf "( typeset -a ar=( 1\n2\n) b=1 )\n" | read -C l4 557[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working with indexed array read' 558 559unset l 560typeset +n l4 561typeset -A -C l 562nameref l4=l[4] 563printf "( typeset -a ar=( 1\n2\n) b=1 )\n" | read -C l4 564[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working with associative array read' 565 566exp=$'(\n\t[9]=(\n\t\tfish=4\n\t)\n)' 567function add_eval 568{ 569 nameref pos=$1 570 source /dev/stdin <<<"$2" 571 typeset -m pos=addvar 572} 573function do_local_plain 574{ 575 compound -A local_tree 576 add_eval local_tree[9].fish "typeset -i addvar=4" 577 [[ $(print -v local_tree) == "$exp" ]] || err_exit 'do_local_plain failed' 578} 579function do_global_throughnameref 580{ 581 nameref tr=global_tree 582 add_eval tr[9].fish "typeset -i addvar=4" 583 [[ $(print -v tr) == "$exp" ]] || err_exit 'do_global_throughnameref failed' 584} 585function do_local_throughnameref 586{ 587 compound -A local_tree 588 nameref tr=local_tree 589 add_eval tr[9].fish "typeset -i addvar=4" 590 [[ $(print -v tr) == "$exp" ]] || err_exit 'do_local_throughnameref failed' 591} 592compound -A global_tree 593do_global_throughnameref 594do_local_throughnameref 595do_local_plain 596 597unset ar 598compound -a ar 599function read_c 600{ 601 nameref v=$1 602 read -C v 603} 604print "( typeset -i x=36 ) " | read_c ar[5][9][2] 605exp=$'(\n\t[5]=(\n\t\t[9]=(\n\t\t\t[2]=(\n\t\t\t\ttypeset -i x=36\n\t\t\t)\n\t\t)\n\t)\n)' 606[[ $(print -v ar) == "$exp" ]] || err_exit 'read into nameref of global array instance from within a function fails' 607 608function read_c 609{ 610 nameref v=$1 611 read -C v 612} 613function main 614{ 615 compound -a ar 616 nameref nar=ar 617 print "( typeset -i x=36 ) " | read_c nar[5][9][2] 618 exp=$'(\n\t[5]=(\n\t\t[9]=(\n\t\t\t[2]=(\n\t\t\t\ttypeset -i x=36\n\t\t\t)\n\t\t)\n\t)\n)' 619 [[ $(print -v nar) == "$exp" ]] || err_exit 'read from a nameref variable from calling scope fails' 620} 621main 622 623function rf2 624{ 625 nameref val=$1 626 read -C val 627} 628function rf 629{ 630 nameref val=$1 631 rf2 val 632} 633function main 634{ 635 compound c 636 typeset -A -C c.l 637 nameref l4=c.l[4] 638 printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | rf l4 639 exp=$'(\n\ttypeset -C -A l=(\n\t\t[4]=(\n\t\t\ttypeset -a ar=(\n\t\t\t\t1\n\t\t\t\t2\n\t\t\t\t3\n\t\t\t)\n\t\t\tb=1\n\t\t)\n\t)\n)' 640 [[ $(print -v c) == "$exp" ]] || err_exit 'read -C with nameref to array element fails' 641} 642main 643 644# bug reported by ek 645cfg=( alarms=(type=3)) 646function a 647{ 648 typeset -n y=$1 649 print -- ${y.type} 650} 651function b 652{ 653 a $1 654} 655[[ $(a cfg.alarms) == 3 ]] || err_exit "nameref scoping error in function" 656[[ $(b cfg.alarms) == 3 ]] || err_exit "nameref scoping error in nested function" 657 658function yy 659{ 660 nameref n=$1 661 n=( z=4 ) 662} 663yy foo 664unset foo 665[[ $foo ]] && err_exit 'unset after creating via nameref in function not working' 666 667unset arr 668typeset -a arr=( ( 1 2 3 ) ( 4 5 6 ) ( 7 8 9 )) 669typeset -n ref=arr[1] 670[[ $ref == 4 ]] || err_exit '$ref should be 4' 671[[ ${ref[@]} == '4 5 6' ]] || err_exit '${ref[@]} should be "4 5 6"' 672[[ $ref == "${arr[1]}" ]] || err_exit '$ref shuld be ${arr[1]}' 673[[ ${ref[@]} == "${arr[1][@]}" ]] || err_exit '${ref[@]} should be ${arr[1][@]}' 674 675function fun2 676{ 677 nameref var=$1.foo 678 var=$2 679} 680function fun1 681{ 682 xxx=$1 683 fun2 $xxx bam 684} 685args=(bar=yes) 686fun1 args 687[[ $args == *foo=bam* ]] || err_exit 'nameref does not bind to correct scope' 688 689typeset +n ref 690unset ref ar 691typeset -a arr=( 1 2 3 ) 692typeset -n ref='arr[2]' 693[[ $(typeset -p ref) == *'arr[2]'* ]] || err_exit 'typeset -p ref when ref is a reference to an index array element is wrong' 694 695$SHELL 2> /dev/null -c 'function x { nameref lv=gg ; compound -A lv.c=( [4]=( x=1 )) ; } ; compound gg ; x' || err_exit 'compound array assignment with nameref in a function failed' 696 697exit $((Errors<125?Errors:125)) 698