mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-05-17 09:21:04 +02:00
51403: Tests and documentation for 51402, clean up some other tests.
This commit is contained in:
parent
3eed6f70cd
commit
acb15e3cc9
7 changed files with 218 additions and 18 deletions
|
@ -1,5 +1,9 @@
|
|||
2023-02-12 Bart Schaefer <schaefer@zsh.org>
|
||||
|
||||
* 51403: Doc/Zsh/builtins.yo, Doc/Zsh/expn.yo, Doc/Zsh/func.yo,
|
||||
Doc/Zsh/grammar.yo, Doc/Zsh/params.yo, Test/K01nameref.ztst:
|
||||
Tests and documentation for 51402, clean up some other tests.
|
||||
|
||||
* 51402: Src/builtin.c, Src/loop.c, Src/params.c, Src/zsh.h:
|
||||
Add ksh/bash features (unset -n, for ref), readonly refs,
|
||||
better error checking and messages, code injection safety,
|
||||
|
|
|
@ -2041,12 +2041,13 @@ cindex(named reference)
|
|||
cindex(reference, named)
|
||||
The flag tt(-n) creates a em(named reference) to another parameter.
|
||||
The second parameter need not exist at the time the reference is
|
||||
created. No attributes except tt(-g) may be used in conjunction with
|
||||
created. Only tt(-g) and tt(-r) may be used in conjunction with
|
||||
tt(-n). The var(name) so created may not be an array element nor use
|
||||
a subscript, but the var(value) assigned may be any valid parameter
|
||||
name syntax, even a subscripted array element (including an associative
|
||||
array element) or an array slice, which is evaluated when the named
|
||||
reference is expanded.
|
||||
reference is expanded. It is an error for a named reference to refer
|
||||
to itself, even indirectly through a chain of references.
|
||||
See ifzman(zmanref(zshexpn))ifnzman(noderef(Parameter Expansion)) and
|
||||
ifzman(zmanref(zshparam))ifnzman(noderef(Parameters)) for details of the
|
||||
behavior of named references.
|
||||
|
@ -2443,7 +2444,7 @@ with the command `tt(zmodload -F zsh/rlimits b:unlimit)'.
|
|||
)
|
||||
findex(unset)
|
||||
cindex(parameters, unsetting)
|
||||
item(tt(unset) [ tt(-fmv) ] var(name) ...)(
|
||||
item(tt(unset) [ tt(-fmv) ] [ tt(-n) ] var(name) ...)(
|
||||
Each named parameter is unset.
|
||||
Local parameters remain local even if unset; they appear unset within scope,
|
||||
but the previous value will still reappear when the scope ends.
|
||||
|
@ -2457,10 +2458,13 @@ be quoted) and all parameters with matching names are unset. Note that this
|
|||
cannot be used when unsetting associative array elements, as the subscript
|
||||
will be treated as part of the pattern.
|
||||
|
||||
The tt(-v) flag specifies that var(name) refers to parameters. This is the
|
||||
default behaviour.
|
||||
The tt(-v) flag specifies that var(name) refers to parameters. This is
|
||||
the default behaviour. If the tt(-n) option is supplied, and
|
||||
var(name) is a a named reference, var(name) will be unset rather than
|
||||
the variable it references.
|
||||
|
||||
tt(unset -f) is equivalent to tt(unfunction).
|
||||
tt(unset -f) is equivalent to tt(unfunction). The tt(-n) option has
|
||||
no effect with tt(-f).
|
||||
)
|
||||
findex(unsetopt)
|
||||
cindex(options, unsetting)
|
||||
|
|
|
@ -1581,7 +1581,10 @@ is interpreted at the time tt(${)var(pname)tt(}) is expanded. Any
|
|||
form of subscript is allowed, including those that select individual
|
||||
elements, substrings of scalar strings, or multiple elements as with
|
||||
array slices or the `tt((i))', `tt((I))', `tt((r))', `tt((R))' and
|
||||
`tt((w))' subscript flags.
|
||||
`tt((w))' subscript flags. However, the subscript is evaluated with
|
||||
the tt(NO_EXEC) option in effect, so command substitution and other
|
||||
similar constructs produce no output, although are not syntactically
|
||||
excluded.
|
||||
|
||||
When var(rname) is an array (but not an array element or slice), the
|
||||
named reference may also be used in substitutions requiring an
|
||||
|
|
|
@ -13,6 +13,40 @@ Functions are executed like commands with the arguments
|
|||
passed as positional parameters.
|
||||
(See noderef(Command Execution).)
|
||||
|
||||
Parameters declared by any of the `tt(typeset)' family of commands
|
||||
during the execution of a function become em(local) to the function
|
||||
unless the `tt(-g)' option is used. This is the em(scope) of the
|
||||
parameter, which extends dynamically to any other functions called by
|
||||
the declaring function. In most cases, local parameters take the
|
||||
place of any other parameter having the same name that was assigned or
|
||||
declared in an earlier function scope.
|
||||
(See noderef(Local Parameters).)
|
||||
|
||||
A named parameter declared with the `tt(-n)' option to any of the
|
||||
`tt(typeset)' commands becomes a reference to a parameter in scope at
|
||||
the time of assignment to the named reference, which may be at a
|
||||
different call level than the declaring function. For this reason,
|
||||
it is good practice to declare a named reference as soon as the
|
||||
referent parameter is in scope, and as early as possible in the
|
||||
function if the reference is to a parameter in a calling scope.
|
||||
|
||||
A typical use of named references is to pass the name
|
||||
of the referent as a positional parameter. For example,
|
||||
ifzman()
|
||||
example(pop+LPAR()RPAR() {
|
||||
local -n ref=$1
|
||||
local last=$ref[$#ref]
|
||||
ref[$#ref]=LPAR()RPAR()
|
||||
print -r -- $last
|
||||
}
|
||||
array=LPAR() a list of five values RPAR()
|
||||
pop array)
|
||||
|
||||
prints the word `tt(values)' and shortens `tt($array)' to
|
||||
`tt(LPAR() a list of five RPAR())'. There are no local parameters in
|
||||
tt(pop) at the time `tt(ref=$1)' is assigned, so `tt(ref)' becomes a
|
||||
reference to `tt(array)' in the caller.
|
||||
|
||||
Functions execute in the same process as the caller and
|
||||
share all files
|
||||
and present working directory with the
|
||||
|
|
|
@ -187,6 +187,9 @@ Expand the list of var(word)s, and set the parameter
|
|||
var(name) to each of them in turn, executing var(list)
|
||||
each time. If the `tt(in) var(word)' is omitted,
|
||||
use the positional parameters instead of the var(word)s.
|
||||
If any var(name) has been declared as a named reference,
|
||||
the corresponding var(word) is treated as the name of a
|
||||
parameter and var(name) is made a reference to that.
|
||||
|
||||
The var(term) consists of one or more newline or tt(;)
|
||||
which terminate the var(word)s, and are optional when the
|
||||
|
|
|
@ -656,8 +656,8 @@ When a em(named reference) is created with `tt(typeset -n)', all uses
|
|||
of var(pname) in assignments and expansions instead assign to or
|
||||
expand var(rname). This also applies to `tt(unset )var(pname)' and to
|
||||
most subsequent uses of `tt(typeset)' with the exception of
|
||||
`tt(typeset -n)' and `tt(typeset +n)', so to remove a named reference
|
||||
it is necessary to use one of:
|
||||
`tt(typeset -n)' and `tt(typeset +n)', so to remove a named reference,
|
||||
use either `tt(unset -n )var(pname)' or one of:
|
||||
ifzman()
|
||||
example(tt(typeset -n )var(pname)
|
||||
tt(typeset +n )var(pname))
|
||||
|
|
|
@ -23,6 +23,12 @@
|
|||
ptr=var
|
||||
typeset -n
|
||||
0:assign nameref placeholder
|
||||
>ptr=var
|
||||
|
||||
typeset ptr=var
|
||||
typeset -n ptr
|
||||
typeset -n
|
||||
0:convert scalar to nameref
|
||||
>ptr=var
|
||||
|
||||
typeset -n ptr=var
|
||||
|
@ -46,6 +52,11 @@ F:Other type changes are fatal errors, should this also be?
|
|||
>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
|
||||
|
@ -91,6 +102,14 @@ F:Other type changes are fatal errors, should this also be?
|
|||
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
|
||||
|
@ -105,11 +124,11 @@ F:Other type changes are fatal errors, should this also be?
|
|||
typeset -n ptr=var
|
||||
ptr=value
|
||||
typeset -p var ptr
|
||||
unset var # for next test
|
||||
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
|
||||
|
@ -132,11 +151,11 @@ F:unexpected side-effects of previous tests
|
|||
typeset -n ptr=var
|
||||
ptr=(val1 val2)
|
||||
typeset -p var ptr
|
||||
unset var # for next test
|
||||
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
|
||||
|
@ -178,12 +197,12 @@ F:unexpected side-effects of previous tests
|
|||
typeset -n ptr1=ptr2
|
||||
typeset ptr1=newvalue
|
||||
typeset -p ptr1 ptr2 var
|
||||
unset var # for next test
|
||||
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
|
||||
|
@ -219,19 +238,18 @@ F:unexpected side-effects of previous tests
|
|||
typeset -n ptr1=ptr2
|
||||
typeset ptr1=(val1 val2)
|
||||
typeset -p ptr1 ptr2 var
|
||||
unset var # for next test
|
||||
0:typeset new array indirectly
|
||||
>typeset -n ptr1=ptr2
|
||||
>typeset -n ptr2=var
|
||||
>typeset -a var=( val1 val2 )
|
||||
|
||||
typeset -p ptr1 ptr2 var
|
||||
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
|
||||
*?*no such variable: var
|
||||
|
||||
unset var
|
||||
typeset -n ptr2=var
|
||||
typeset -n ptr1=ptr2
|
||||
ptr1=(val1 val2)
|
||||
|
@ -244,6 +262,20 @@ F:unexpected side-effects of previous tests
|
|||
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
|
||||
|
@ -252,28 +284,39 @@ F:unexpected side-effects of previous tests
|
|||
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
|
||||
|
@ -281,6 +324,7 @@ F:unexpected side-effects of previous tests
|
|||
0:assign array element by nameref
|
||||
>typeset -a ary=( 1 TWO )
|
||||
|
||||
unset -n ptr2
|
||||
typeset -n ptr2='ary[2]'
|
||||
ptr2=TWO
|
||||
typeset -p ary
|
||||
|
@ -288,6 +332,7 @@ F:unexpected side-effects of previous tests
|
|||
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
|
||||
|
@ -295,6 +340,7 @@ F:ksh93 does not implement this either
|
|||
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
|
||||
|
@ -303,10 +349,13 @@ F:ksh93 does not implement this either
|
|||
F:ksh93 does not implement this either
|
||||
>typeset -A hash=( [y]=HIT )
|
||||
|
||||
unset -n ptr1
|
||||
typeset -n ptr1='not good'
|
||||
1:invalid nameref
|
||||
*?*invalid variable name: not good
|
||||
|
||||
unset -n ptr1
|
||||
unset hash
|
||||
typeset -A hash
|
||||
typeset -n ptr1='hash[y]'
|
||||
print ${ptr1::=HIT}
|
||||
|
@ -316,24 +365,25 @@ F:ksh93 does not implement this either
|
|||
>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 }
|
||||
unset gval # for next test
|
||||
0:up-reference part 1
|
||||
>global
|
||||
>typeset -g -n ptr=gval
|
||||
>typeset gval=local
|
||||
|
||||
typeset -p ptr ptr1 ptr2 val gval
|
||||
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
|
||||
*?*no such variable: gval
|
||||
|
||||
unset gval
|
||||
typeset -n ptr1=gval
|
||||
typeset gval
|
||||
() { typeset gval=local; ptr1=global }
|
||||
|
@ -509,4 +559,106 @@ F:Same test, should part 5 output look like this?
|
|||
>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
|
||||
|
||||
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
|
||||
>
|
||||
*?*ref: global reference to local variable: one
|
||||
|
||||
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
|
||||
|
||||
%clean
|
||||
|
|
Loading…
Reference in a new issue