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