|
From: | Grisha Levit |
Subject: | nameref/subscript fixes for unset builtin |
Date: | Tue, 31 May 2016 23:40:40 -0400 |
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 v
declare -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 v
declare -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 n
declare -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
[Prev in Thread] | Current Thread | [Next in Thread] |