# Tests for named references %prep # Required in order to declare an unset hash for substitution test setopt TYPESET_TO_UNSET : ${ZTST_continue::=1} %test typeset -n ptr typeset -n 0:minimal declaration >ptr typeset -n ptr= typeset -n 0:nameref placeholder >ptr='' typeset -n ptr ptr=var typeset -n 0:assign nameref placeholder >ptr=var unset ptr typeset -n ptr typeset -n ptr=var typeset -n 0:assign placeholder with new typeset >ptr=var typeset -n ptr1 typeset -n ptr2=ptr1 typeset -n 0:chain ending in placeholder >ptr1 >ptr2=ptr1 typeset ptr=var typeset -n ptr typeset -n 0:convert scalar to nameref >ptr=var typeset -n ptr=var typeset +n ptr typeset -p ptr 0:remove nameref attribute >typeset ptr=var typeset -n ptr=gvar () { local ptr typeset -p ptr } typeset -p ptr 0:Local non-reference hides outside reference >typeset ptr >typeset -n ptr=gvar typeset -n ptr typeset -t ptr typeset -p ptr 0:change type of a placeholder F:Other type changes are fatal errors, should this also be? >typeset -n ptr='' *?*ptr: can't change type of a named reference typeset -n ptr=var typeset -t ptr typeset -p ptr var 0:change type of referenced var >typeset -n ptr=var >typeset -t var typeset var unset var typeset -n ptr=var typeset -t ptr typeset -p ptr var 0:change type of unset referenced var F:regression - at one time this incorrectly applied the tag to "ptr" F:note this causes "var" to become set >typeset -n ptr=var >typeset -t var typeset -n ptr=var[2] typeset -t ptr 1:change type of referenced array element *?*var\[2\]: can't change type via subscript reference typeset -n ptr[1]=var 1:illegal nameref name *?*reference variable cannot be an array typeset var=value typeset -n ptr=var print $ptr 0:basic nameref expansion, no braces >value typeset var=value typeset -n ptr=var print ${ptr} 0:basic nameref expansion, braces >value typeset var=(val1 val2) typeset -n ptr=var print $ptr 0:nameref array expansion >val1 val2 typeset -A var=(val1 val2) typeset -n ptr=var print ${(kv)ptr} 0:nameref hash expansion >val1 val2 typeset -n ptr=var typeset var=value typeset -p ptr var ptr=newvalue typeset -p ptr var 0:assign existing scalar via nameref >typeset -n ptr=var >typeset var=value >typeset -n ptr=var >typeset var=newvalue typeset -n ptr=var typeset var=value unset ptr typeset -p var 0:unset via nameref typeset -n ptr=var typeset var=value unset -n ptr typeset -p var ptr 0:unset of the nameref itself F:If earlier tests change, might get "no such variable" here >typeset var=value typeset -n ptr=var typeset var=value typeset -p ptr var typeset ptr=newvalue typeset -p ptr var 0:typeset existing scalar via nameref >typeset -n ptr=var >typeset var=value >typeset -n ptr=var >typeset var=newvalue typeset -n ptr=var ptr=value typeset -p var ptr 0:assign new scalar via nameref >typeset -g var=value >typeset -n ptr=var unset var typeset -n ptr=var typeset var=(val1 val2) typeset -p ptr var ptr=(new1 new2) typeset -p ptr var 0:assign existing array via nameref >typeset -n ptr=var >typeset -a var=( val1 val2 ) >typeset -n ptr=var >typeset -a var=( new1 new2 ) typeset -p ptr ptr1 ptr2 var 1:check state of paramtab ONE F:unexpected side-effects of previous tests *?*no such variable: ptr *?*no such variable: ptr1 *?*no such variable: ptr2 *?*no such variable: var typeset -n ptr=var ptr=(val1 val2) typeset -p var ptr 0:assign new array via nameref >typeset -g -a var=( val1 val2 ) >typeset -n ptr=var unset var typeset -n ptr2=var typeset -n ptr1=ptr2 typeset var=value typeset -p ptr1 ptr2 var print $ptr1 0:indirect nameref expansion >typeset -n ptr1=ptr2 >typeset -n ptr2=var >typeset var=value >value typeset -p ptr1 ptr2 var 1:check state of paramtab TWO F:unexpected side-effects of previous tests *?*no such variable: ptr1 *?*no such variable: ptr2 *?*no such variable: var typeset var typeset -n ptr2=var typeset -n ptr1=ptr2 typeset ptr1=newvalue typeset -p ptr1 ptr2 var 0:typeset existing parameter indirectly >typeset -n ptr1=ptr2 >typeset -n ptr2=var >typeset var=newvalue typeset var=value typeset -n ptr2=var typeset -n ptr1=ptr2 unset ptr1 typeset -p ptr1 ptr2 var 0:unset parameter indirectly >typeset -n ptr1=ptr2 >typeset -n ptr2=var typeset -n ptr2=var typeset -n ptr1=ptr2 typeset ptr1=newvalue typeset -p ptr1 ptr2 var 0:typeset new parameter indirectly >typeset -n ptr1=ptr2 >typeset -n ptr2=var >typeset var=newvalue unset var typeset -n ptr2=var typeset -n ptr1=ptr2 typeset var=value typeset -p ptr1 ptr2 var ptr1=newvalue typeset -p ptr1 ptr2 var 0:assign new parameter indirectly >typeset -n ptr1=ptr2 >typeset -n ptr2=var >typeset var=value >typeset -n ptr1=ptr2 >typeset -n ptr2=var >typeset var=newvalue typeset -p ptr1 ptr2 var 1:check state of paramtab THREE F:unexpected side-effects of previous tests *?*no such variable: ptr1 *?*no such variable: ptr2 *?*no such variable: var typeset -a var typeset -n ptr2=var typeset -n ptr1=ptr2 typeset ptr1=(val1 val2) typeset -p ptr1 ptr2 var 0:typeset existing array indirectly >typeset -n ptr1=ptr2 >typeset -n ptr2=var >typeset -a var=( val1 val2 ) typeset -n ptr2=var typeset -n ptr1=ptr2 typeset ptr1=(val1 val2) typeset -p ptr1 ptr2 var 0:typeset new array indirectly >typeset -n ptr1=ptr2 >typeset -n ptr2=var >typeset -a var=( val1 val2 ) typeset -p ptr1 ptr2 1:check state of paramtab FOUR F:unexpected side-effects of previous tests *?*no such variable: ptr1 *?*no such variable: ptr2 unset var typeset -n ptr2=var typeset -n ptr1=ptr2 ptr1=(val1 val2) typeset -p ptr1 ptr2 var 0:assign new array indirectly >typeset -n ptr1=ptr2 >typeset -n ptr2=var >typeset -g -a var=( val1 val2 ) typeset -n ptr1=ptr2 typeset -n ptr2=ptr1 1:direct nameref loop not allowed *?*invalid self reference unset var typeset -gn ptr1=var typeset -p ptr1 0:global reference to unset var >typeset -g -n ptr1=var unset -n ptr1 typeset -gn ptr1 typeset -p ptr1 ptr1=ptr1 1:global direct reference >typeset -g -n ptr1 *?*invalid self reference typeset -n ptr1=ptr2 typeset -n ptr2=ptr3 typeset -n ptr3=ptr1 1:indirect nameref loop not allowed *?*invalid self reference typeset -n ptr1 ptr2 ptr1=ptr2 ptr2=ptr1 1:looping assignment not allowed *?*invalid self reference unset -n ptr2 typeset -n ptr2='path[2]' print -r -- $ptr2 0q:nameref to array element, no braces >${path[2]} unset -n ptr2 typeset -n ptr2='path[2]' print -r -- ${ptr2} 0q:nameref to array element, with braces >${path[2]} unset -n ptr1 typeset -A hash=(x MISS y HIT) typeset -n ptr1='hash[y]' print -r -- $ptr1 0:nameref to hash element, no braces >HIT unset -n ptr1 typeset -A hash=(x MISS y HIT) typeset -n ptr1='hash[y]' print -r -- ${ptr1} 0:nameref to hash element, with braces >HIT unset -n ptr2 typeset -a ary=(1 2) typeset -n ptr2='ary[2]' ptr2=TWO typeset -p ary 0:assign array element by nameref >typeset -a ary=( 1 TWO ) unset -n ptr2 typeset -n ptr2='ary[2]' ptr2=TWO typeset -p ary 0f:create array element by nameref F:ksh93 does not implement this either >typeset -a ary=( '' TWO ) unset -n ptr1 typeset -A hash=(x MISS y MISS) typeset -n ptr1='hash[y]' ptr1=HIT typeset -p hash 0:assign to hash element by nameref >typeset -A hash=( [x]=MISS [y]=HIT ) unset -n ptr1 typeset -A hash typeset -n ptr1='hash[y]' ptr1=HIT typeset -p hash 0f:create hash by element nameref F:ksh93 does not implement this either >typeset -A hash=( [y]=HIT ) unset -n ptr1 typeset -n ptr1='not[2]good' 1:invalid nameref *?*invalid variable name: not\[2\]good unset -n ptr1 unset hash typeset -A hash typeset -n ptr1='hash[y]' print ${ptr1::=HIT} typeset -p ptr1 hash 0f:create hash by element substitution >HIT >typeset -n ptr1='hash[y]' >typeset -A hash=( [y]=HIT ) unset -n ptr unset gval typeset -n ptr=gval gval=global () { local gval=local; print $ptr; typeset -p ptr gval } 0:up-reference part 1 >global >typeset -g -n ptr=gval >typeset gval=local typeset -p ptr ptr1 ptr2 val 1:check state of paramtab FIVE F:unexpected side-effects of previous tests *?*no such variable: ptr *?*no such variable: ptr1 *?*no such variable: ptr2 *?*no such variable: val unset gval typeset -n ptr1=gval typeset gval () { typeset gval=local; ptr1=global } typeset -p ptr1 gval 0:up-reference assignment part 1 F:All tests run inside a function, so "typeset gval" creates a local; F:if that were omitted, ptr1= assignment would create a true global F:and the output below would change to "typeset -g gval=global" >typeset -n ptr1=gval >typeset gval=global typeset -p ptr ptr1 ptr2 val gval 1:check state of paramtab SIX F:unexpected side-effects of previous tests *?*no such variable: ptr *?*no such variable: ptr1 *?*no such variable: ptr2 *?*no such variable: val *?*no such variable: gval typeset gval=global () { typeset -n ptr=gval local gval=local print $ptr } typeset -p ptr gval 1:up-reference part 2 >global *?*no such variable: ptr >typeset gval=global typeset -n ptr=gval () { local lval=local typeset -n ptr=lval ptr=LOCAL typeset -p lval gval ptr } typeset -p ptr 0:localized namerefs hide global namerefs *?*no such variable: gval >typeset lval=LOCAL >typeset -n ptr=lval >typeset -n ptr=gval typeset -A var=(myself outside) () { typeset -n myself=var[myself] local -h var print -r -- $myself typeset -p var } 0:up-reference part 3, hidden global >outside >typeset -h var () { typeset notdef unset notdef () { typeset -n ptr=notdef ptr=(DEFINED) } typeset -p notdef } 0:up-reference part 4, unset local and type change >typeset -a notdef=( DEFINED ) () { typeset -n ptr1=ptr2 typeset -n ptr2 typeset -p ptr1 ptr2 typeset val=LOCAL () { ptr1=val typeset -n printf "%s=%s\n" ptr1 "$ptr1" ptr2 "$ptr2" } typeset -p ptr1 ptr2 } typeset -p ptr2 1:up-reference part 5, stacked namerefs, end not in scope >typeset -n ptr1=ptr2 >typeset -n ptr2 >ptr1=ptr2 >ptr2=val >ptr1=LOCAL >ptr2=LOCAL >typeset -n ptr1=ptr2 >typeset -n ptr2=val *?*no such variable: ptr2 typeset ptr2 () { typeset -n ptr1=ptr2 typeset -n ptr2 typeset -p ptr1 ptr2 typeset val=LOCAL () { ptr1=val typeset -n printf "%s=%s\n" ptr1 "$ptr1" ptr2 "$ptr2" } typeset -p ptr1 ptr2 } typeset -p ptr2 0:up-reference part 6, stacked namerefs, end is in scope F:Same test, should part 5 output look like this? >typeset -n ptr1=ptr2 >typeset -n ptr2 >ptr1=ptr2 >ptr2 >ptr1=val >ptr2= >typeset -n ptr1=ptr2 >typeset -n ptr2 >typeset ptr2=val () { () { local var typeset -nu ptr1=var ptr1=outer && print -u2 assignment expected to fail typeset -n ptr2=var ptr2=inner typeset -n printf "%s=%s\n" ptr1 "$ptr1" ptr2 "$ptr2" } typeset -p var } typeset -p var 1:up-reference part 7, upscope namerefs, end not in scope >ptr1=var >ptr2=var >ptr1= >ptr2=inner *?*typeset*: no such variable: var *?*typeset*: no such variable: var typeset var () { () { local var typeset -nu ptr1=var ptr1=outer || print -u2 assignment expected to succeed typeset -n ptr2=var ptr2=inner typeset -n printf "%s=%s\n" ptr1 "$ptr1" ptr2 "$ptr2" } typeset -p var } typeset -p var 0:up-reference part 8, upscope namerefs, end in scope >ptr1=var >ptr2=var >ptr1=outer >ptr2=inner >typeset -g var=outer >typeset var=outer if zmodload zsh/parameter; then () { zmodload -u zsh/parameter typeset -n myself=parameters[myself] local -h parameters print -r -- $myself typeset -p parameters } else ZTST_skip='Cannot zmodload zsh/parameter, skipping autoload test' fi 0:up-reference part 9, autoloading with hidden special >nameref-local-nameref-local >typeset -h parameters if [[ $options[typesettounset] != on ]]; then ZTST_skip='Ignoring zmodload bug that resets TYPESET_TO_UNSET' setopt typesettounset fi 0:options reloaded F:Checking for a bug in zmodload that affects later tests typeset ptr2=var2 typeset var2=GLOBAL () { typeset -n ptr1=ptr2 typeset ptr2=var1 typeset var1=VAR1 typeset var2=VAR2 print -r -- ${(P)ptr1} } 0:Order of evaluation with ${(P)...} >VAR2 ary=(one two three four) typeset -n ptr=ary print -r ${(j.:.)ptr//o/0} 0:expansion flags and string replacement >0ne:tw0:three:f0ur var=value typeset -n ptr=var myscalar=ptr echo ${(P)myscalar} 0:named references with (P), as ${(P)name_of_nameref} >value var=value myscalar=var typeset -n ptr=myscalar echo ${(P)ptr} 0:named references with (P), as ${(P)nameref} >value ary=( 'bry[1]' 'bry[2]' ) bry=( lorem ipsum ) typeset -n ptr='ary[2]' print -r -- ${ptr} print -r -- ${(P)ptr} 0:named references with (P), array element to array element >bry[2] >ipsum unset -n ref unset var typeset -n ref=var typeset var=GLOBAL () { typeset -n ref=$1 print -r $ref ref=RESET typeset -p ref var } ref typeset -p ref var 0:local reference points to same-name global reference, part 1 >GLOBAL >typeset -n ref=ref >typeset -g var=RESET >typeset -n ref=var >typeset var=RESET unset -n ref unset var typeset -n ref=var () { typeset -n ref=$1 print -r $ref ref=RESET typeset -p ref var } ref typeset -p ref var 0:local reference points to same-name global reference, part 2 > >typeset -n ref=ref >typeset -g var=RESET >typeset -n ref=var >typeset -g var=RESET unset -n ref unset one typeset -n ref typeset one=ONE for ref in one ref two; do print -r $ref; done 1:for-loop variable is a reference, part 1 >ONE *?*ref: invalid self reference unset -n ref unset one typeset -n ref () { typeset one=ONE for ref in one ref two; do print -r ${(t)ref}; done } 1:for-loop variable is a reference, part 2 >scalar-local *?*ref: invalid self reference unset -n ref unset one var typeset -n ref=var () { typeset one=ONE typeset -n ref=ref for ref in one ref two; do typeset -p ref print -r $ref done typeset -p ref } typeset -p ref 0:for-loop variable is a reference, part 3 >typeset -n ref=one >ONE >typeset -n ref=ref > >typeset -n ref=two > >typeset -n ref=two >typeset -n ref=var typeset -g .K01.scalar='RW' typeset -gA .K01.assoc=(x y) typeset -ga .K01.array=(z) typeset -gi .K01.integer=0 typeset -gE .K01.double=0.0 typeset -gF .K01.float=0.0 typeset -gr .K01.readonly='RO' typeset -n gref for gref in ARGC .K01.{scalar,assoc,array,integer,double,float,readonly} do { unset gref } always { TRY_BLOCK_ERROR=0 } done typeset -p .K01.{scalar,assoc,array,integer,double,float,readonly} unset .K01.{scalar,assoc,array,integer,double,float} 0:unset various types via nameref, including a readonly special >typeset -g .K01.scalar >typeset -g -A .K01.assoc >typeset -g -a .K01.array >typeset -g -i .K01.integer >typeset -g -E .K01.double >typeset -g -F .K01.float >typeset -g -r .K01.readonly=RO *?*read-only variable: ARGC *?*read-only variable: .K01.readonly unset -n ref unset one typeset -n ref () { setopt localoptions warn_nested_var typeset one=ONE for ref in one two; do print -r ${(t)ref}; done typeset -n ref for ref in one two; do print -r ${(t)ref}; done } 0:for-loop variable is a reference, part 4, warnings >scalar-local > >scalar-local > *?*reference ref*to local variable one unset -n ref typeset -n ref () { setopt localoptions warn_nested_var typeset inner ref=inner } typeset -p ref 0:Global variable is a reference, warning >typeset -n ref=inner *?*reference ref*to local variable inner typeset -n ptr='ary[$(echo 2)]' typeset -a ary=(one two three) print $ptr 1:attempt deferred command substitution in subscript F:runs in `setopt noexec` so $(...) returns nothing *?*bad math expression: empty string unset -n ref typeset -n ref=GLOBAL () { typeset -gn ref=RESET } typeset -p ref 0:reset global reference within function >typeset -n ref=RESET unset -n ref typeset -rn ref=RO typeset -p ref (typeset -n ref=RW) print status: $? expected: 1 typeset +r -n ref typeset -p ref typeset -r +n ref typeset -p ref (typeset -rn ref) print status: $? expected: 1 typeset +r -n ref=RW # Assignment occurs after type change, typeset -p ref RO # so RO=RW here. Potentially confusing. typeset -r -n ref=RX # No type change, so referent changes ... typeset -p ref RO # ... and previous refererent does not. typeset +rn ref=RW # Here ref=RW, again type changed first. typeset -p ref 0:add and remove readonly attribute with references >typeset -rn ref=RO *?*: ref: read-only reference >status: 1 expected: 1 >typeset -n ref=RO >typeset -r ref=RO *?*: ref: read-only variable >status: 1 expected: 1 >typeset -n ref=RO >typeset -g RO=RW >typeset -rn ref=RX >typeset -g RO=RW >typeset ref=RW () { typeset -n r1 r2= typeset -p r1 r2 print -- ${(!)r1-unset} print -- ${+r1} typeset -p r1 } 0:unset nameref remains unset when resolved F:relies on global TYPESET_TO_UNSET in %prep >typeset -n r1 >typeset -n r2='' >unset >0 >typeset -n r1 bar=xx typeset -n foo=bar () { typeset -n foo; foo=zz foo=zz || print -u2 foo: assignment failed print $bar $zz } () { typeset -n foo; foo=zz; local zz; foo=zz; print $bar $zz } 0:regression: local nameref may not in-scope a global parameter F:previously this could create an infinite recursion and crash >xx >xx zz *?*foo: assignment failed typeset -nm foo=bar 1:create nameref by pattern match not allowed *?*typeset:1: invalid reference # # The following tests are run in interactive mode, using PS1 as an # assignable special with side-effects. This crashed at one time. # # Note bypassing TYPESET_TO_UNSET here $ZTST_testdir/../Src/zsh -fis <<<$' typeset -n p=PS1 () { typeset -p p local p typeset -p p p=xx typeset -p p } ' 0:regression: assign to local that shadows global named reference >typeset -g -n p=PS1 >typeset p='' >typeset p=xx *?* # Note bypassing TYPESET_TO_UNSET here $ZTST_testdir/../Src/zsh -fis <<<$' () { typeset p=PS1 typeset -n p p=zz } typeset -p PS1 ' 0:regression - converting a string into a named reference >typeset PS1=zz *?* %clean