# Tests for named references %prep # Required in order to declare an unset hash for substitution test setopt TYPESET_TO_UNSET : ${ZTST_continue::=1} # The following test allows to assess what different types of named # references refer to during their lifetime depending on where they # were initialized and whether they were defined with or without the # "-u" flag. # # The first parameter determines whether the named references are # defined with or without the flag "-u". # # The second parameter determines where the named references are # initialized. In all cases the named references are defined at the # start of function "g". With value "0" they are initialized at the # same place (in the same statement). With the other values, the # initialization is delayed until later, the greater the value and the # later the initialization. function e() { local s=$0 a=($0); f "$@"; } function f() { local s=$0 a=($0); g "$@"; } function g() { if (($2)); then local -n $1 rs ra rs1 ra1; else local -n $1 rs=s ra=a rs1="s[1]" ra1="a[1]"; fi; if (($2 == 1)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi; echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; local s=$0 a=($0); if (($2 == 2)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi; echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; h "$@"; echo "$0:3: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; } function h() { if (($2 == 3)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi; echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; local s=$0 a=($0); if (($2 == 4)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi; echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; i "$@"; echo "$0:3: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; # Check that re-entering the same scope doesn't undo scope exit k "$@" } function i() { if (($2 == 5)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi; echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; local s=$0 a=($0); if (($2 == 6)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi; echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; j "$@"; echo "$0:3: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; k "$@"; } function j() { echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; local s=$0 a=($0); echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1"; } functions -c j k local s=T a=(T); function f1() { typeset var=$0; typeset -n ref1 ref2; typeset -n ref3=ref2; function f2() { typeset ref2=XX; function f3() { typeset var=$0; function f4() { typeset var=$0; ref1=var; ref3=var; # Initializes ref2 to var echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; } f4; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; function g4() { typeset var=$0; function g5() { typeset var=$0; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; } g5; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; } g4; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; } f3; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; } f2; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; function h2() { typeset var=$0; function h3() { typeset var=$0; function h4() { typeset var=$0; function h5() { typeset var=$0; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; } h5; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; } h4; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; } h3; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; } h2; echo "$0: ref1=$ref1 ref2=$ref2 ref3=$ref3"; } %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 typeset ptr1=not-a-ref () { typeset -n ptr1=ptr1 () { typeset -n ptr1=ptr1 echo $ptr1 } } 0:regression: not a self reference (test 1) >not-a-ref typeset -n ptr1 typeset -n ptr2=ptr1 () { typeset ptr2=no-a-ref typeset -n ptr1=ptr2 } 0:regression: not a self reference (test 2) 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 name reference: 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 ( inner() { local -n var="${1:?}"; var=(alpha beta gamma); } outer() { local -a foo=(outer); inner foo; typeset -p foo; } foo=3 ; { outer foo } always { typeset -p foo } ) 0:up-reference part 10, assignment to enclosing scope, types match >typeset -a foo=( alpha beta gamma ) >typeset -g foo=3 ( inner() { local -n var="${1:?}"; var=(alpha beta gamma); } outer() { local foo=outer; inner foo; typeset -p foo; } foo=3 ; { outer foo } always { typeset -p foo } ) 0:up-reference part 11, assignment to enclosing scope, type mismatch >typeset -a foo=( alpha beta gamma ) >typeset -g foo=3 ( inner() { local -n var="${1:?}"; unset var; var=(alpha beta gamma); } outer() { local foo=outer; inner foo; typeset -p foo; } foo=3 ; { outer foo } always { typeset -p foo } ) 0:up-reference part 12, assignment to enclosing scope, unset by reference >typeset -a foo=( alpha beta gamma ) >typeset -g foo=3 ( inner() { local "${1:?}"; local -nu var="$1"; var=(alpha beta gamma); } outer() { local -a foo=(outer); inner foo; typeset -p foo; } foo=3 ; { outer foo } always { typeset -p foo } ) 0:up-reference part 13, assignment to enclosing scope, skip local >typeset -a foo=( alpha beta gamma ) >typeset -g foo=3 ( inner() { local "${1:?}"; local -nu var="$1"; typeset -g var=(alpha beta gamma); } outer() { local -a foo=(outer); inner foo; typeset -p foo; } foo=3 ; { outer foo } always { typeset -p foo } ) 0f:up-reference part 14, typeset -g to enclosing scope, skip local F:typeset cannot bypass a name in the local scope, even via nameref >typeset -a foo=( alpha beta gamma ) >typeset -g foo=3 () { # scope with no parameters () { local -nu upref=$1 local var=at_upref print -- $upref } var } 0:up-reference part 15, non-existent parameter in outer scope # no output expected > 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 var1 typeset -n ref=var1 () { typeset -n ref=var2 ref=RESET typeset -p ref var2 } typeset -p ref var2 0:local reference hides same-name global reference >typeset -n ref=var2 >typeset -g var2=RESET >typeset -n ref=var1 >typeset -g var2=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 typeset -p bar zz } # prior to workers/53676 the assignment failed unset zz () { typeset -n foo; foo=zz; local zz; foo=zz; typeset -p bar zz } 0:regression: local nameref may not in-scope a global parameter F:previously this could create an infinite recursion and crash >typeset -g bar=xx >typeset -g zz=zz >typeset -g bar=xx >typeset zz=zz typeset -nm foo=bar 1:create nameref by pattern match not allowed *?*typeset:1: -m not allowed with -n e -u 0 0:assignment at different scope than declaration, -u 0 >g:1: rs=f - ra=f - rs1=f - ra1=f >g:2: rs=f - ra=f - rs1=f - ra1=f >h:1: rs=f - ra=f - rs1=f - ra1=f >h:2: rs=f - ra=f - rs1=f - ra1=f >i:1: rs=f - ra=f - rs1=f - ra1=f >i:2: rs=f - ra=f - rs1=f - ra1=f >j:1: rs=f - ra=f - rs1=f - ra1=f >j:2: rs=f - ra=f - rs1=f - ra1=f >i:3: rs=f - ra=f - rs1=f - ra1=f >k:1: rs=f - ra=f - rs1=f - ra1=f >k:2: rs=f - ra=f - rs1=f - ra1=f >h:3: rs=f - ra=f - rs1=f - ra1=f >k:1: rs=f - ra=f - rs1=f - ra1=f >k:2: rs=f - ra=f - rs1=f - ra1=f >g:3: rs=f - ra=f - rs1=f - ra1=f e '' 0 0:assignment at different scope than declaration, '' 0 >g:1: rs=f - ra=f - rs1=f - ra1=f >g:2: rs=f - ra=f - rs1=f - ra1=f >h:1: rs=f - ra=f - rs1=f - ra1=f >h:2: rs=f - ra=f - rs1=f - ra1=f >i:1: rs=f - ra=f - rs1=f - ra1=f >i:2: rs=f - ra=f - rs1=f - ra1=f >j:1: rs=f - ra=f - rs1=f - ra1=f >j:2: rs=f - ra=f - rs1=f - ra1=f >i:3: rs=f - ra=f - rs1=f - ra1=f >k:1: rs=f - ra=f - rs1=f - ra1=f >k:2: rs=f - ra=f - rs1=f - ra1=f >h:3: rs=f - ra=f - rs1=f - ra1=f >k:1: rs=f - ra=f - rs1=f - ra1=f >k:2: rs=f - ra=f - rs1=f - ra1=f >g:3: rs=f - ra=f - rs1=f - ra1=f e -u 2 0:assignment at different scope than declaration, -u 2 >g:1: rs= - ra= - rs1= - ra1= >g:2: rs=f - ra=f - rs1=f - ra1=f >h:1: rs=f - ra=f - rs1=f - ra1=f >h:2: rs=f - ra=f - rs1=f - ra1=f >i:1: rs=f - ra=f - rs1=f - ra1=f >i:2: rs=f - ra=f - rs1=f - ra1=f >j:1: rs=f - ra=f - rs1=f - ra1=f >j:2: rs=f - ra=f - rs1=f - ra1=f >i:3: rs=f - ra=f - rs1=f - ra1=f >k:1: rs=f - ra=f - rs1=f - ra1=f >k:2: rs=f - ra=f - rs1=f - ra1=f >h:3: rs=f - ra=f - rs1=f - ra1=f >k:1: rs=f - ra=f - rs1=f - ra1=f >k:2: rs=f - ra=f - rs1=f - ra1=f >g:3: rs=f - ra=f - rs1=f - ra1=f e -u 6 0:assignment at different scope than declaration, -u 6 >g:1: rs= - ra= - rs1= - ra1= >g:2: rs= - ra= - rs1= - ra1= >h:1: rs= - ra= - rs1= - ra1= >h:2: rs= - ra= - rs1= - ra1= >i:1: rs= - ra= - rs1= - ra1= >i:2: rs=f - ra=f - rs1=f - ra1=f >j:1: rs=f - ra=f - rs1=f - ra1=f >j:2: rs=f - ra=f - rs1=f - ra1=f >i:3: rs=f - ra=f - rs1=f - ra1=f >k:1: rs=f - ra=f - rs1=f - ra1=f >k:2: rs=f - ra=f - rs1=f - ra1=f >h:3: rs=f - ra=f - rs1=f - ra1=f >k:1: rs=f - ra=f - rs1=f - ra1=f >k:2: rs=f - ra=f - rs1=f - ra1=f >g:3: rs=f - ra=f - rs1=f - ra1=f e '' 6 0:assignment at different scope than declaration, '' 6 >g:1: rs= - ra= - rs1= - ra1= >g:2: rs= - ra= - rs1= - ra1= >h:1: rs= - ra= - rs1= - ra1= >h:2: rs= - ra= - rs1= - ra1= >i:1: rs= - ra= - rs1= - ra1= >i:2: rs=i - ra=i - rs1=i - ra1=i >j:1: rs=i - ra=i - rs1=i - ra1=i >j:2: rs=i - ra=i - rs1=i - ra1=i >i:3: rs=i - ra=i - rs1=i - ra1=i >k:1: rs=i - ra=i - rs1=i - ra1=i >k:2: rs=i - ra=i - rs1=i - ra1=i >h:3: rs=h - ra=h - rs1=h - ra1=h >k:1: rs=h - ra=h - rs1=h - ra1=h >k:2: rs=h - ra=h - rs1=h - ra1=h >g:3: rs=g - ra=g - rs1=g - ra1=g f1 0:Transitive references with scoping changes >f4: ref1=f4 ref2=XX ref3=f4 >f3: ref1=f3 ref2=XX ref3=f3 >g5: ref1=f3 ref2=XX ref3=g4 >g4: ref1=f3 ref2=XX ref3=g4 >f3: ref1=f3 ref2=XX ref3=f3 >f2: ref1=f1 ref2=XX ref3=f1 >f1: ref1=f1 ref2=f1 ref3=f1 >h5: ref1=f1 ref2=f1 ref3=f1 >h4: ref1=f1 ref2=f1 ref3=f1 >h3: ref1=f1 ref2=f1 ref3=f1 >h2: ref1=f1 ref2=f1 ref3=f1 >f1: ref1=f1 ref2=f1 ref3=f1 # # The following two tests are linked, do not separate # edgelocal() ( local -n x=$1; typeset -p x; print -r $x ) edgeupper() ( local -nu x=$1; typeset -p x; print -r $x ) for edge in argv ARGC \@ \* \# 0 1 01 \! \? - _ do edgelocal $edge edgelocal "$edge""[1]" edgeupper $edge done 0:references to builtin specials F:Subscripting on 1 01 ! ? - should print first character but do not >typeset -n x=argv >argv >typeset -n x='argv[1]' >argv[1] >typeset -n x=ARGC >1 >typeset -n x='ARGC[1]' >1 >typeset -n x=0 >edgelocal >typeset -n x='0[1]' >e >typeset -n x=1 > >typeset -n x='1[1]' > >typeset -n x=01 > >typeset -n x='01[1]' > >typeset -n x=! >0 >typeset -n x='![1]' > >typeset -un x=! >0 >typeset -n x='?' >0 >typeset -n x='?[1]' > >typeset -un x='?' >0 >typeset -n x=- >569X >typeset -n x='-[1]' > >typeset -un x=- >569X >typeset -n x=_ >x >typeset -n x='_[1]' >x >typeset -un x=_ >x ?edgeupper: invalid name reference: argv ?edgeupper: invalid name reference: ARGC ?edgelocal: invalid name reference: @ ?edgelocal: invalid name reference: @[1] ?edgeupper: invalid name reference: @ ?edgelocal: invalid name reference: * ?edgelocal: invalid name reference: *[1] ?edgeupper: invalid name reference: * ?edgelocal: invalid name reference: # ?edgelocal: invalid name reference: #[1] ?edgeupper: invalid name reference: # ?edgeupper: invalid name reference: 0 ?edgeupper: invalid name reference: 1 ?edgeupper: invalid name reference: 01 edgelocal \$ edgelocal '$[1]' edgeupper \$ unfunction edgelocal edgeupper 0qf:references to $$ F:$$[1] reference should print the first digit of $$ but prints nothing >typeset -n x='$' >$$ >typeset -n x='\$[1]' >$$[1] >$$ # # 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 *?* unset var1 var2 typeset -n ref1=var1 () { typeset -n ref2=ref1 typeset -n ref1=var2 typeset -i ref2=42 typeset -p ref1 ref2 var1 var2 } 1:typeset reference chain to not-yet-defined variable including a hidden reference ?(anon):typeset:4: no such variable: var2 >typeset -n ref1=var2 >typeset -n ref2=ref1 >typeset -i var1=42 typeset -n ref1 typeset -n ref2=ref1 () { typeset -n ref3=ref2 typeset ref2=foo ref1=ref3 } 1:self reference chain including a hidden reference ?(anon):3: ref3: invalid self reference zmodload -u zsh/random echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*} typeset -n ref=SRANDOM echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*} echo v=${ref/<->/integer} zmodload -u zsh/random echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*} echo v=${ref/<->/integer} 0:Referring and dereferring an autoload variable loads it (direct) >z=SRANDOM (zsh/random) >z= >v=integer >z=SRANDOM (zsh/random) >v=integer zmodload -u zsh/random echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*} typeset -n ref=SRANDOM[1,20] echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*} echo v=${ref/<->/integer} zmodload -u zsh/random echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*} echo v=${ref/<->/integer} 0:Referring and dereferring an autoload variable loads it (subscript) >z=SRANDOM (zsh/random) >z= >v=integer >z=SRANDOM (zsh/random) >v=integer typeset -n ref=SRANDOM echo v=${ref/<->/integer} zmodload -u zsh/random echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*} typeset -h SRANDOM=local-variable echo v=${ref/<->/integer} echo NOT REACHED 1:Dereferring an autoload variable fails to load it if its hidden (direct) >v=integer >z=SRANDOM (zsh/random) ?(eval):6: Can't add module parameter `SRANDOM': local parameter exists ?(eval):zsh/random:6: error when adding parameter `SRANDOM' ?(eval):6: autoloading module zsh/random failed to define parameter: SRANDOM typeset -n ref=SRANDOM[1,20] echo v=${ref/<->/integer} zmodload -u zsh/random echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*} typeset -h SRANDOM=local-variable echo v=${ref/<->/integer} echo NOT REACHED 1:Dereferring an autoload variable fails to load it if its hidden (subscript) >v=integer >z=SRANDOM (zsh/random) ?(eval):6: Can't add module parameter `SRANDOM': local parameter exists ?(eval):zsh/random:6: error when adding parameter `SRANDOM' ?(eval):6: autoloading module zsh/random failed to define parameter: SRANDOM () { typeset var1=var1 typeset var2=var2 typeset -n ref1=var1 echo "ref1=$ref1"; () { typeset -n ref1=var2 typeset -n ref2=ref1 echo "ref1=$ref1"; echo "ref2=$ref2"; } } 0:regression: don't follow references when computing base scope - part 1 >ref1=var1 >ref1=var2 >ref2=var2 () { typeset var1=var1 typeset -n ref1=var1 echo ref1=$ref1; () { typeset var2=var2 typeset -n ref1 typeset -n ref2=ref1 ref1=var2 echo ref1=$ref1; echo ref2=$ref2; } } 0:regression: don't follow references when computing base scope - part 2 >ref1=var1 >ref1=var2 >ref2=var2 typeset -n ref1 typeset -n ref2=ref1; () { typeset ref2=foo ref1=ref2 } echo reached echo $ref1 echo NOT REACHED 1:expansion of incidental reference loop triggers error >reached *?*: ref1: invalid self reference typeset -n ref1 typeset -n ref2=ref1; () { typeset ref2=foo ref1=ref2 } echo reached ref1=foo echo NOT REACHED 1:assignment to incidental reference loop triggers error >reached *?*: ref1: invalid self reference typeset -n ref1 typeset -n ref2=ref1; () { typeset ref2=foo ref1=ref2 } echo reached typeset -n ref3=ref1 echo NOT REACHED 1:reference to incidental reference loop triggers error >reached *?*: ref1: invalid self reference typeset -A -g VAR0=(aa AA) typeset -n -g REF0=VAR0 typeset -A -g var0=(aa AA) typeset -A var1=(aa AA) () { typeset -A var2=(aa AA) typeset -n ref0=var0 ref1=var1 ref2=var2 # Test initial association typeset -pm VAR0 var\? REF0=(zz ZZ); ref0=(zz ZZ); ref1=(zz ZZ); ref2=(zz ZZ); typeset -pm VAR0 var\? # Test change from association to string REF0=foo; ref0=foo; ref1=foo; ref2=foo; typeset -pm VAR0 var\? REF0=bar; ref0=bar; ref1=bar; ref2=bar; typeset -pm VAR0 var\? # Test change from string to array REF0=(aa AA); ref0=(aa AA); ref1=(aa AA); ref2=(aa AA); typeset -pm VAR0 var\? REF0=(zz ZZ); ref0=(zz ZZ); ref1=(zz ZZ); ref2=(zz ZZ); typeset -pm VAR0 var\? # Test change from array to string REF0=foo; ref0=foo; ref1=foo; ref2=foo; typeset -pm VAR0 var\? } 0:type changes via assignments to references >typeset -g -A VAR0=( [aa]=AA ) >typeset -g -A var0=( [aa]=AA ) >typeset -g -A var1=( [aa]=AA ) >typeset -A var2=( [aa]=AA ) >typeset -g -A VAR0=( [zz]=ZZ ) >typeset -g -A var0=( [zz]=ZZ ) >typeset -g -A var1=( [zz]=ZZ ) >typeset -A var2=( [zz]=ZZ ) >typeset -g VAR0=foo >typeset -g var0=foo >typeset -g var1=foo >typeset var2=foo >typeset -g VAR0=bar >typeset -g var0=bar >typeset -g var1=bar >typeset var2=bar >typeset -g -a VAR0=( aa AA ) >typeset -g -a var0=( aa AA ) >typeset -g -a var1=( aa AA ) >typeset -a var2=( aa AA ) >typeset -g -a VAR0=( zz ZZ ) >typeset -g -a var0=( zz ZZ ) >typeset -g -a var1=( zz ZZ ) >typeset -a var2=( zz ZZ ) >typeset -g VAR0=foo >typeset -g var0=foo >typeset -g var1=foo >typeset var2=foo typeset -A -g ass0=(aa AA) typeset -A ass1=(aa AA) typeset -a -g arr0=(aa AA) typeset -a arr1=(aa AA) typeset -g str0=foo typeset str1=foo () { typeset -n Ass0=ass0 Ass1=ass1 Arr0=arr0 Arr1=arr1 Str0=str0 Str1=str1 typeset ass0 ass1 arr0 arr1 str0 str1 { Ass0=foo } always { TRY_BLOCK_ERROR=0 }; echo $? { Ass1=foo } always { TRY_BLOCK_ERROR=0 }; echo $? { Arr0=foo } always { TRY_BLOCK_ERROR=0 }; echo $? { Arr1=foo } always { TRY_BLOCK_ERROR=0 }; echo $? { Str0=(x) } always { TRY_BLOCK_ERROR=0 }; echo $? { Str1=(x) } always { TRY_BLOCK_ERROR=0 }; echo $? } typeset -p ass0 ass1 arr0 arr1 str0 str1 0:can't change type of hidden variables via assignments to references >1 >1 >1 >1 >1 >1 >typeset -g -A ass0=( [aa]=AA ) >typeset -A ass1=( [aa]=AA ) >typeset -g -a arr0=( aa AA ) >typeset -a arr1=( aa AA ) >typeset -g str0=foo >typeset str1=foo ?(anon):3: can't change type of hidden variable: ass0 ?(anon):4: can't change type of hidden variable: ass1 ?(anon):5: can't change type of hidden variable: arr0 ?(anon):6: can't change type of hidden variable: arr1 ?(anon):7: can't change type of hidden variable: str0 ?(anon):8: can't change type of hidden variable: str1 typeset -A ass=(aa AA) typeset -a arr=(aa AA) typeset -i int=42 typeset str=foo typeset -n Ass=ass Arr=arr Int=int Str=str { typeset Ass=foo } always { TRY_BLOCK_ERROR=0 }; echo $? { typeset Arr=foo } always { TRY_BLOCK_ERROR=0 }; echo $? { typeset Int=(aa AA) } always { TRY_BLOCK_ERROR=0 }; echo $? { typeset Str=(aa AA) } always { TRY_BLOCK_ERROR=0 }; echo $? typeset -p ass arr int str 0:type changes via plain typeset to references F:converting from association/array to string should work here too >1 >1 >0 >0 >typeset -A ass=( [aa]=AA ) >typeset -a arr=( aa AA ) >typeset -a int=( aa AA ) >typeset -a str=( aa AA ) ?(eval):typeset:6: ass: inconsistent type for assignment ?(eval):typeset:7: arr: inconsistent type for assignment typeset var typeset -n ref=var # Change type to string unset var; typeset var=fubar; typeset ref=barfu; typeset -p var unset var; typeset -i var=12345; typeset +i ref=barfu; typeset -p var unset var; typeset -a var=(a A); typeset +a ref=barfu; typeset -p var unset var; typeset -A var=(a A); typeset +A ref=barfu; typeset -p var # Change type to integer unset var; typeset var=fubar; typeset -i ref=56789; typeset -p var unset var; typeset -i var=12345; typeset -i ref=56789; typeset -p var unset var; typeset -a var=(a A); typeset -i ref=56789; typeset -p var unset var; typeset -A var=(a A); typeset -i ref=56789; typeset -p var # Change type to array unset var; typeset var=fubar; typeset -a ref=(z Z); typeset -p var unset var; typeset -i var=12345; typeset -a ref=(z Z); typeset -p var unset var; typeset -a var=(a A); typeset -a ref=(z Z); typeset -p var unset var; typeset -A var=(a A); typeset -a ref=(z Z); typeset -p var # Change type to association unset var; typeset var=fubar; typeset -A ref=(z Z); typeset -p var unset var; typeset -i var=12345; typeset -A ref=(z Z); typeset -p var unset var; typeset -a var=(a A); typeset -A ref=(z Z); typeset -p var unset var; typeset -A var=(a A); typeset -A ref=(z Z); typeset -p var 0:type changes via typed typeset to references >typeset var=barfu >typeset var=barfu >typeset var=barfu >typeset var=barfu >typeset -i var=56789 >typeset -i var=56789 >typeset -i var=56789 >typeset -i var=56789 >typeset -a var=( z Z ) >typeset -a var=( z Z ) >typeset -a var=( z Z ) >typeset -a var=( z Z ) >typeset -A var=( [z]=Z ) >typeset -A var=( [z]=Z ) >typeset -A var=( [z]=Z ) >typeset -A var=( [z]=Z ) %clean