From: Chet Ramey Date: Tue, 10 Jul 2012 13:38:15 +0000 (-0400) Subject: 20120705 commit rest of changes for nameref variables X-Git-Tag: bash-4.3-alpha~56 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=87c1f4ece2c31d663fb72933b883267a76c2cd68;p=thirdparty%2Fbash.git 20120705 commit rest of changes for nameref variables --- diff --git a/builtins/set.def b/builtins/set.def index b69e63236..421105be5 100644 --- a/builtins/set.def +++ b/builtins/set.def @@ -1,7 +1,7 @@ This file is set.def, from which is created set.c. It implements the "set" and "unset" builtins in Bash. -Copyright (C) 1987-2011 Free Software Foundation, Inc. +Copyright (C) 1987-2012 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -724,7 +724,7 @@ set_builtin (list) $BUILTIN unset $FUNCTION unset_builtin -$SHORT_DOC unset [-f] [-v] [name ...] +$SHORT_DOC unset [-f] [-v] [-n] [name ...] Unset values and attributes of shell variables and functions. For each NAME, remove the corresponding variable or function. @@ -732,6 +732,8 @@ For each NAME, remove the corresponding variable or function. Options: -f treat each NAME as a shell function -v treat each NAME as a shell variable + -n treat each NAME as a name reference and unset the variable itself + rather than the variable it references Without options, unset first tries to unset a variable, and if that fails, tries to unset a function. @@ -748,13 +750,13 @@ int unset_builtin (list) WORD_LIST *list; { - int unset_function, unset_variable, unset_array, opt, any_failed; + int unset_function, unset_variable, unset_array, opt, nameref, any_failed; char *name; - unset_function = unset_variable = unset_array = any_failed = 0; + unset_function = unset_variable = unset_array = nameref = any_failed = 0; reset_internal_getopt (); - while ((opt = internal_getopt (list, "fv")) != -1) + while ((opt = internal_getopt (list, "fnv")) != -1) { switch (opt) { @@ -764,6 +766,9 @@ unset_builtin (list) case 'v': unset_variable = 1; break; + case 'n': + nameref = 1; + break; default: builtin_usage (); return (EX_USAGE); @@ -777,6 +782,8 @@ unset_builtin (list) builtin_error (_("cannot simultaneously unset a function and a variable")); return (EXECUTION_FAILURE); } + else if (unset_function && nameref) + nameref = 0; while (list) { @@ -810,7 +817,8 @@ unset_builtin (list) } /* Only search for functions here if -f supplied. */ - var = unset_function ? find_function (name) : find_variable (name); + var = unset_function ? find_function (name) + : (nameref ? find_variable_last_nameref (name) : find_variable (name)); /* Some variables (but not functions yet) cannot be unset, period. */ if (var && unset_function == 0 && non_unsettable_p (var)) @@ -837,7 +845,6 @@ unset_builtin (list) NEXT_VARIABLE (); } - /* Unless the -f option is supplied, the name refers to a variable. */ #if defined (ARRAY_VARS) if (var && unset_array) diff --git a/doc/bash.1 b/doc/bash.1 index 3cdcc07a9..8af3319ff 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -5,12 +5,12 @@ .\" Case Western Reserve University .\" chet@po.cwru.edu .\" -.\" Last Change: Sun May 27 20:28:33 EDT 2012 +.\" Last Change: Thu Jul 5 11:10:13 EDT 2012 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2012 May 27" "GNU Bash 4.2" +.TH BASH 1 "2012 July 5" "GNU Bash 4.2" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -1235,6 +1235,39 @@ appended to the array beginning at one greater than the array's maximum index associative array. When applied to a string-valued variable, \fIvalue\fP is expanded and appended to the variable's value. +.PP +A variable can be assigned the \fInameref\fP attribute using the +\fB\-n\fP option to the \fBdeclare\fP or \fBlocal\fP builtin commands +(see the descriptions of \fBdeclare\fP and \fBlocal\fP below) +to create a \fInameref\fP, or a reference to another variable. +This allows variables to be manipulated indirectly. +Whenever the nameref variable is referenced or assigned to, the operation +is actually performed on the variable specified by the nameref variable's +value. +A nameref is commonly used within shell functions to refer to a variable +whose name is passed as an argument to the function. +For instance, if a variable name is passed to a shell function as its first +argument, running +.sp .5 +.RS +.if t \f(CWdeclare -n ref=$1\fP +.if n declare -n ref=$1 +.RE +.sp .5 +inside the function creates a nameref variable \fBref\fP whose value is +the variable name passed as the first argument. +References and assignments to \fBref\fP are treated as references and +assignments to the variable whose name was passed as \fB$1\fP. +If the control variable in a \fBfor\fP loop has the nameref attribute, +the list of words can be a list of shell variables, and a name reference +will be established for each word in the list, in turn, when the loop is +executed. +Array variables cannot be given the \fB\-n\fP attribute. +However, nameref variables can reference array variables and subscripted +array variables. +Namerefs can be unset using the \fB\-n\fP option to the \fBunset\fP builtin. +Otherwise, if \fBunset\fP is executed with the name of a nameref variable +as an argument, the variable referenced by the nameref variable will be unset. .SS Positional Parameters .PP A @@ -7279,10 +7312,10 @@ is greater than the number of enclosing loops, the last enclosing loop (the ``top-level'' loop) is resumed. The return value is 0 unless \fIn\fP is not greater than or equal to 1. .TP -\fBdeclare\fP [\fB\-aAfFgilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] +\fBdeclare\fP [\fB\-aAfFgilnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] .PD 0 .TP -\fBtypeset\fP [\fB\-aAfFgilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] +\fBtypeset\fP [\fB\-aAfFgilnrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...] .PD Declare variables and/or give them attributes. If no \fIname\fPs are given then display the values of variables. @@ -7346,6 +7379,15 @@ When the variable is assigned a value, all upper-case characters are converted to lower-case. The upper-case attribute is disabled. .TP +.B \-n +Give each \fIname\fP the \fInameref\fP attribute, making +it a name reference to another variable. +That other variable is defined by the value of \fIname\fP. +All references and assignments to \fIname\fP, except for changing the +\fB\-n\fP attribute itself, are performed on the variable referenced by +\fIname\fP's value. +The \fB\-n\fP attribute cannot be applied to array variables. +.TP .B \-r Make \fIname\fPs readonly. These names cannot then be assigned values by subsequent assignment statements or unset. @@ -9868,7 +9910,7 @@ value is true unless a supplied .I name is not a defined alias. .TP -\fBunset\fP [\-\fBfv\fP] [\fIname\fP ...] +\fBunset\fP [\-\fBfv\fP] [\-\fBn\fP] [\fIname\fP ...] For each .IR name , remove the corresponding variable or function. @@ -9884,6 +9926,12 @@ is specified, each .I name refers to a shell function, and the function definition is removed. +If the +.B \-n +option is supplied, and \fIname\fP is a variable with the \fInameref\fP +attribute, \fIname\fP will be unset rather than the variable it +references. +\fB\-n\fP has no effect if the \fB\-f\fP option is supplied. If no options are supplied, each \fIname\fP refers to a variable; if there is no variable by that name, any function with that name is unset. diff --git a/doc/bashref.texi b/doc/bashref.texi index 8e3fbe65e..5eee0936e 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -1473,6 +1473,39 @@ in an associative array. When applied to a string-valued variable, @var{value} is expanded and appended to the variable's value. +A variable can be assigned the @var{nameref} attribute using the +@option{-n} option to the \fBdeclare\fP or \fBlocal\fP builtin commands +(@pxref{Bash Builtins}) +to create a @var{nameref}, or a reference to another variable. +This allows variables to be manipulated indirectly. +Whenever the nameref variable is referenced or assigned to, the operation +is actually performed on the variable specified by the nameref variable's +value. +A nameref is commonly used within shell functions to refer to a variable +whose name is passed as an argument to the function. +For instance, if a variable name is passed to a shell function as its first +argument, running +@example +declare -n ref=$1 +@end example +@noindent +inside the function creates a nameref variable @var{ref} whose value is +the variable name passed as the first argument. +References and assignments to @var{ref} are treated as references and +assignments to the variable whose name was passed as @code{$1}. + +If the control variable in a @code{for} loop has the nameref attribute, +the list of words can be a list of shell variables, and a name reference +will be established for each word in the list, in turn, when the loop is +executed. +Array variables cannot be given the @option{-n} attribute. +However, nameref variables can reference array variables and subscripted +array variables. +Namerefs can be unset using the @option{-n} option to the @code{unset} builtin +(@pxref{Bourne Shell Builtins}). +Otherwise, if @code{unset} is executed with the name of a nameref variable +as an argument, the variable referenced by the nameref variable will be unset. + @node Positional Parameters @subsection Positional Parameters @cindex parameters, positional @@ -3616,7 +3649,7 @@ results in permissions of @code{755}. @item unset @btindex unset @example -unset [-fv] [@var{name}] +unset [-fnv] [@var{name}] @end example Remove each variable or function @var{name}. @@ -3624,6 +3657,10 @@ If the @option{-v} option is given, each @var{name} refers to a shell variable and that variable is remvoved. If the @option{-f} option is given, the @var{name}s refer to shell functions, and the function definition is removed. +If the @option{-n} option is supplied, and @var{name} is a variable with +the @var{nameref} attribute, @var{name} will be unset rather than the +variable it references. +@option{-n} has no effect if the @option{-f} option is supplied. If no options are supplied, each @var{name} refers to a variable; if there is no variable by that name, any function with that name is unset. @@ -3812,7 +3849,7 @@ zero if @var{command} is found, and non-zero if not. @item declare @btindex declare @example -declare [-aAfFgilrtux] [-p] [@var{name}[=@var{value}] @dots{}] +declare [-aAfFgilnrtux] [-p] [@var{name}[=@var{value}] @dots{}] @end example Declare variables and give them attributes. If no @var{name}s @@ -3864,6 +3901,15 @@ When the variable is assigned a value, all upper-case characters are converted to lower-case. The upper-case attribute is disabled. +@item -n +Give each @var{name} the @var{nameref} attribute, making +it a name reference to another variable. +That other variable is defined by the value of @var{name}. +All references and assignments to @var{name}, except for changing the +@option{-n} attribute itself, are performed on the variable referenced by +@var{name}'s value. +The @option{-n} attribute cannot be applied to array variables. + @item -r Make @var{name}s readonly. These names cannot then be assigned values by subsequent assignment statements or unset. @@ -4303,7 +4349,7 @@ if any are not found. @item typeset @btindex typeset @example -typeset [-afFgrxilrtux] [-p] [@var{name}[=@var{value}] @dots{}] +typeset [-afFgrxilnrtux] [-p] [@var{name}[=@var{value}] @dots{}] @end example The @code{typeset} command is supplied for compatibility with the Korn diff --git a/variables.c b/variables.c index cd50db4ef..b3350d9a8 100644 --- a/variables.c +++ b/variables.c @@ -2958,7 +2958,7 @@ dispose_variable (var) } /* Unset the shell variable referenced by NAME. Unsetting a nameref variable - unsets both the variable and the variable it resolves to. */ + unsets the variable it resolves to but leaves the nameref alone. */ int unbind_variable (name) const char *name; @@ -2969,13 +2969,23 @@ unbind_variable (name) v = var_lookup (name, shell_variables); nv = (v && nameref_p (v)) ? find_variable_nameref (v) : (SHELL_VAR *)NULL; - r = nv ? makunbound (nv->name, shell_variables) : 0; - if (r == 0) - r = makunbound (name, shell_variables); - + r = nv ? makunbound (nv->name, shell_variables) : makunbound (name, shell_variables); return r; } +/* Unbind NAME, where NAME is assumed to be a nameref variable */ +int +unbind_nameref (name) + const char *name; +{ + SHELL_VAR *v; + + v = var_lookup (name, shell_variables); + if (v && nameref_p (v)) + return makunbound (name, shell_variables); + return 0; +} + /* Unset the shell function named NAME. */ int unbind_func (name) @@ -3073,6 +3083,8 @@ makunbound (name, vc) else if (assoc_p (old_var)) assoc_dispose (assoc_cell (old_var)); #endif + else if (nameref_p (old_var)) + FREE (nameref_cell (old_var)); else FREE (value_cell (old_var)); /* Reset the attributes. Preserve the export attribute if the variable