diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 56428a714..64c47346f 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -2037,6 +2037,20 @@ To initialize a parameter var(param) to a command output and mark it readonly, use tt(typeset -r )var(param) or tt(readonly )var(param) after the parameter assignment statement. +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 other attribute flags may be used in conjunction with +tt(-n). The var(name) assigned-to 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 (incuding an associative +array element) or an array slice, which is evaluated when the named +reference is expanded. +See ifzman(zmanref(zshexpn))ifnzman(noderef(Parameter Expansion)) and +ifzman(zmanref(zshparam))ifnzman(noderef(Parameters)) for details of the +behavior of named references. + If no attribute flags are given, and either no var(name) arguments are present or the flag tt(+m) is used, then each parameter name printed is preceded by a list of the attributes of that parameter (tt(array), @@ -2242,9 +2256,9 @@ automatically given the tt(-h) attribute to avoid name clashes. item(tt(-H))( Hide value: specifies that tt(typeset) will not display the value of the parameter when listing parameters; the display for such parameters is -always as if the `tt(PLUS())' flag had been given. Use of the parameter is -in other respects normal, and the option does not apply if the parameter is -specified by name, or by pattern with the tt(-m) option. This is on by +always as if the `tt(PLUS())' flag were given, but use of the parameter is +in other respects normal. This effect does not apply when the parameter is +specified by name or by pattern with the tt(-m) option. This is on by default for the parameters in the tt(zsh/parameter) and tt(zsh/mapfile) modules. Note, however, that unlike the tt(-h) flag this is also useful for non-special parameters. diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index fd5443b20..ff6087cac 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1226,6 +1226,9 @@ for parameters with the `hide' flag (tt(-h)) item(tt(hideval))( for parameters with the `hideval' flag (tt(-H)) ) +item(tt(nameref))( +for named references having an empty value (tt(-n)) +) item(tt(special))( for special parameters defined by the shell ) @@ -1523,6 +1526,77 @@ Include the unmatched portion in the result (the em(R)est). ) enditem() +subsect(Named References) +cindex(named references) +cindex(namerefs) +cindex(reference variables) +cindex(parameters, nameref) +The command +ifzman() +indent(tt(typeset -n )var(pname)tt(=)var(rname)) + +initializes a parameter var(pname) as a reference to a second +parameter var(rname). With the few exceptions described here, when +var(pname) is used in any of the expansion forms described above, the +parameter var(rname) is expanded instead. This is similar to the +action of the `tt((P))' expansion flag, but when var(rname) has itself +been declared a named reference, that third parameter referenced by +var(pname) is also expanded, and so on. With `tt((P))' this must be +done explicitly, so for example +tt(${LPAR()P)tt(RPAR()${LPAR()P)tt(RPAR())var(name)tt(}}). + +Unlike `tt((P))', named references in substitutions that perform +assignment, such as tt(${)var(pname)tt(::=)var(word)tt(}), do not +create new arrays when var(rname) is in the form of an array element +or slice and no such array (or associative array) is presently set. +This includes arrays declared, but not initialized, when the option +tt(TYPESET_TO_UNSET) is in effect. The var(word) is substituted but +no assignment occurs. + +Also unlike `tt((P))' named references always expand parameters at +the scope in which var(rname) existed when `tt(typeset -n)' was +called. This can be used to expand or assign parameters from an +earlier scope even if a local of the same name has been declared at +a later scope. Example: +ifzman() +example(tt(caller=OUTER) +tt(func LPAR()RPAR() {) +tt( print before local: $caller) +tt( typeset -n outer=$1) +tt( local caller=INNER) +tt( print by reference: $outer) +tt( outer=RESULT) +tt(}) +tt(func caller) +tt(print after func: $caller)) + +displays the output +ifzman() +example(tt(before local: OUTER) +tt(by reference: OUTER) +tt(after func: RESULT)) + +When var(rname) includes an array subscript, the subscript expression +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. + +When var(rname) is an array (but not an array element or slice), the +named reference may also be used in substitutions requiring an +var(arrayname), so these are equivalent: +ifzman() +example(tt(${)var(name)tt(:|)var(rname)tt(}) +tt(${)var(name)tt(:|)var(pname)tt(})) + +Expansions of the form `tt(${LPAR()t)tt(RPAR())var(pname)tt(})' expand +the type information of var(rname), unless var(rname) is empty, in which +case `tt(nameref)' is expanded, or when no variable var(rname) exists, +in which case the expansion is empty. + +See also ifzman(zmanref(zshparam))ifnzman(noderef(Parameters)). + subsect(Rules) cindex(parameter expansion rules) cindex(rules, parameter expansion) @@ -1545,12 +1619,16 @@ substitutions; the nested substitution will return either a scalar or an array as determined by the flags, possibly adjusted for quoting. All the following steps take place where applicable at all levels of substitution. -Note that, unless the `tt((P))' flag is present, the flags and any +Note that, unless the `tt((P))' flag or a named reference is present, +the flags and any subscripts apply directly to the value of the nested substitution; for example, the expansion tt(${${foo}}) behaves exactly the same as -tt(${foo}). When the `tt((P))' flag is present in a nested substitution, +tt(${foo}). When a named reference or the `tt((P))' flag is used in a +nested substitution, the other substitution rules are applied to the value em(before) it is interpreted as a name, so tt(${${(P)foo}}) may differ from tt(${(P)foo}). +When both a named reference and the `tt((P))' flag appear, the named +reference is resolved before `tt((P))' is applied. At each nested level of substitution, the substituted words undergo all forms of single-word substitution (i.e. not filename generation), including diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo index 18fd3606e..0e89d65c8 100644 --- a/Doc/Zsh/mod_parameter.yo +++ b/Doc/Zsh/mod_parameter.yo @@ -125,7 +125,7 @@ zmanref(zshexpn) ifnzman(\ noderef(Parameter Expansion) )\ -. The value may also be `tt(undefined)' indicating a parameter that +. The value may also be `tt(undefined)' indicating a parameter that may be autoloaded from a module but has not yet been referenced. Setting or unsetting keys in this array is not possible. ) diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 55009c6de..2dfd5bd14 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -80,6 +80,7 @@ startmenu() menu(Array Parameters) menu(Positional Parameters) menu(Local Parameters) +menu(Named References) menu(Parameters Set By The Shell) menu(Parameters Used By The Shell) endmenu() @@ -592,7 +593,7 @@ array assignment of the form `var(n)tt(=LPAR())var(value) ...tt(RPAR())' is allowed, and has the effect of shifting all the values at positions greater than var(n) by as many positions as necessary to accommodate the new values. -texinode(Local Parameters)(Parameters Set By The Shell)(Positional Parameters)(Parameters) +texinode(Local Parameters)(Named References)(Positional Parameters)(Parameters) sect(Local Parameters) Shell function executions delimit scopes for shell parameters. (Parameters are dynamically scoped.) The tt(typeset) builtin, and its @@ -626,6 +627,49 @@ find the programs in tt(/new/directory) inside a function. Note that the restriction in older versions of zsh that local parameters were never exported has been removed. +cindex(named references) +cindex(references, named) +texinode(Named References)(Parameters Set By The Shell)(Local Parameters)(Parameters) +sect(Named References) +Zsh supports two different mechanisms for indirect parameter referencing: +ifzman() +example(tt(typeset )var(name)tt(=)var(rname) +tt(print -r -- ${LPAR()P)tt(RPAR())var(name)tt(})) +ifzman() +example(tt(typeset -n )var(pname)tt(=)var(rname) +tt(print -r -- ${)var(pname)tt(})) + +The `tt((P))' flag method is older and should be used when a script +needs to be backwards-compatible. This is described fully in +ifzman(zmanref(zshexpn))ifnzman(noderef(Parameter Expansion)). + +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)', so to remove a named reference it is necessary to +use: +ifzman() +example(tt(typeset +n )var(pname) +tt(unset )var(pname)) + +When `tt(typeset -n )var(pname)tt(=)var(rname)' appears in a given +(global or function) scope, `tt(${)var(pname)tt(})' refers to +var(rname) in the scope of the tt(typeset) command. This differs +from ksh93 where the scope used is that of var(rname) even if the +current var(rname) would be found in a surrounding scope. +em(This is a misfeature.) + +An empty reference such as one of +ifzman() +example(tt(typeset -n )var(pname) +tt(typeset -n )var(pname)tt(=) +tt(typeset -n )var(pname)tt(="")) + +acts as a placeholder. The first non-empty assignment to var(pname) +initializes the reference, and subsequently any expansions of, or +assignments to, var(pname) act on the referenced parameter. + texinode(Parameters Set By The Shell)(Parameters Used By The Shell)(Local Parameters)(Parameters) sect(Parameters Set By The Shell) In the parameter lists that follow, the mark `' indicates that the