The patch below addresses the following three issues: ------------------------------
Doing unset -n n[0] actually unsets the target variable
$ v=(0 1); declare -n n=v
$ unset -n n[0]
$ declare -p n vdeclare -n n="v"
bash: declare: v: not found
------------------------------
Unsetting namerefs that are array references does not work
$ v=(0 1); declare -n n=v[1]
$ unset n
$ declare -p n vdeclare -n n="v[1]"declare -a v=([0]="0" [1]="1")
------------------------------
Same as with no options, unset -n will search for functions if it doesn’t
find a variable. If the nameref is invisble, it will unset any function
with the same name instead of the nameref.
While this might meet the posix requirement of “if neither -f nor -v…” I
suspect it would make more sense to follow the behavior as specified in the
bash docs
Without options, unset first tries to unset a variable, and if that fails,
tries to unset a function.
$ unset -n n; declare -n n; n() { :; }
$ unset -n n
$ declare -p n; declare -F ndeclare -n n
------------------------------
It’s also the case that if a function has a name that is also a valid array
reference, unset with no options will not find it and unset -f must be
used, but this seems reasonable.
------------------------------
diff --git a/builtins/set.def b/builtins/set.def
index 8f74f0e..c563fe7 100644--- a/builtins/set.def+++ b/builtins/set.def
@@ -808,7 +808,7 @@ unset_builtin (list)
{
int unset_function, unset_variable, unset_array, opt, nameref, any_failed;
int global_unset_func, global_unset_var;- char *name;+ char *name, *tname;
unset_function = unset_variable = unset_array = nameref = any_failed = 0;
global_unset_func = global_unset_var = 0;
@@ -859,7 +859,7 @@ unset_builtin (list)
#if defined (ARRAY_VARS)
unset_array = 0;- if (!unset_function &&
valid_array_reference (name, 0))+ if (!unset_function && nameref
== 0 && valid_array_reference (name, 0))
{
t = strchr (name, '[');
*t++ = '\0';
@@ -897,7 +897,7 @@ unset_builtin (list)
find a function after unsuccessfully searching for a variable,
note that we're acting on a function now as if -f were
supplied. The readonly check below takes care of it. */-
if (var == 0 && unset_variable == 0 && unset_function == 0)+ if
(var == 0 && unset_variable == 0 && unset_function == 0 && nameref ==
0)
{
if (var = find_function (name))
unset_function = 1;
@@ -932,7 +932,20 @@ unset_builtin (list)
if (var == 0 && nameref == 0 && unset_function == 0)
{
var = find_variable_last_nameref (name, 0);- tem =
(var && nameref_p (var)) ? unbind_variable (nameref_cell (var)) :
unbind_variable (name);+ if (var && nameref_p (var))+#if defined
(ARRAY_VARS)+ if (valid_array_reference (nameref_cell (var),
0))+ {+ tname = savestring(nameref_cell (var));+
var = array_variable_part(tname, &t, 0);+ if (var)+
tem = unbind_array_element (array_variable_part (tname, &t,
0), t);+ }+ else+#endif /* ARRAY_VARS */+ tem =
unbind_variable (nameref_cell (var));+ else+ tem =
unbind_variable (name);
}
else
tem = unset_function ? unbind_func (name) : (nameref ?
unbind_nameref (name) : unbind_variable (name));
@@ -941,7 +954,7 @@ unset_builtin (list)
is specified, the name refers to a variable; if a variable by
that name does not exist, a function by that name, if any,
shall be unset.'' */- if (tem == -1 && unset_function ==
0 && unset_variable == 0)+ if (tem == -1 && unset_function == 0
&& unset_variable == 0 && nameref == 0)
tem = unbind_func (name);
name = list->word->word; /* reset above for namerefs */
unset_nameref_subscripts.patch
Description: Binary data
