From 6a3116f58c876ca58a786f0ddff578ecf126588e Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Thu, 29 Aug 2019 11:20:15 -0400 Subject: [PATCH] Bash-5.0 patch 10: changes to posix-mode assignment statements preceding functions and special builtins --- patchlevel.h | 2 +- tests/varenv.right | 6 +++--- variables.c | 38 ++++++++++++++++++++++++++------------ 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/patchlevel.h b/patchlevel.h index 02f1d606..8002af70 100644 --- a/patchlevel.h +++ b/patchlevel.h @@ -25,6 +25,6 @@ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh looks for to find the patch level (for the sccs version string). */ -#define PATCHLEVEL 9 +#define PATCHLEVEL 10 #endif /* _PATCHLEVEL_H_ */ diff --git a/tests/varenv.right b/tests/varenv.right index 159a8773..ca7d4cf1 100644 --- a/tests/varenv.right +++ b/tests/varenv.right @@ -146,9 +146,9 @@ declare -x foo="abc" inside: declare -x var="value" outside: declare -- var="one" inside: declare -x var="value" -outside: declare -x var="value" -inside: declare -- var="local" -outside: declare -x var="global" +outside: declare -- var="outside" +inside: declare -x var="global" +outside: declare -- var="outside" foo= environment foo= foo=foo environment foo=foo foo=foo environment foo=foo diff --git a/variables.c b/variables.c index 610629ab..af3fd04a 100644 --- a/variables.c +++ b/variables.c @@ -4460,9 +4460,9 @@ char **tempvar_list; int tvlist_ind; /* Take a variable from an assignment statement preceding a posix special - builtin (including `return') and create a global variable from it. This - is called from merge_temporary_env, which is only called when in posix - mode. */ + builtin (including `return') and create a variable from it as if a + standalone assignment statement had been performed. This is called from + merge_temporary_env, which is only called when in posix mode. */ static void push_posix_temp_var (data) PTR_T data; @@ -4472,16 +4472,27 @@ push_posix_temp_var (data) var = (SHELL_VAR *)data; - binding_table = global_variables->table; - if (binding_table == 0) - binding_table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS); + /* Just like do_assignment_internal(). This makes assignments preceding + special builtins act like standalone assignment statements when in + posix mode, satisfying the posix requirement that this affect the + "current execution environment." */ + v = bind_variable (var->name, value_cell (var), ASS_FORCE|ASS_NOLONGJMP); - v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP); + /* If this modifies an existing local variable, v->context will be non-zero. + If it comes back with v->context == 0, we bound at the global context. + Set binding_table appropriately. It doesn't matter whether it's correct + if the variable is local, only that it's not global_variables->table */ + binding_table = v->context ? shell_variables->table : global_variables->table; /* global variables are no longer temporary and don't need propagating. */ - var->attributes &= ~(att_tempvar|att_propagate); + if (binding_table == global_variables->table) + var->attributes &= ~(att_tempvar|att_propagate); + if (v) - v->attributes |= var->attributes; + { + v->attributes |= var->attributes; + v->attributes &= ~att_tempvar; /* not a temp var now */ + } if (find_special_var (var->name) >= 0) tempvar_list[tvlist_ind++] = savestring (var->name); @@ -4575,14 +4586,17 @@ dispose_temporary_env (pushf) sh_free_func_t *pushf; { int i; + HASH_TABLE *disposer; tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1); tempvar_list[tvlist_ind = 0] = 0; - - hash_flush (temporary_env, pushf); - hash_dispose (temporary_env); + + disposer = temporary_env; temporary_env = (HASH_TABLE *)NULL; + hash_flush (disposer, pushf); + hash_dispose (disposer); + tempvar_list[tvlist_ind] = 0; array_needs_making = 1; -- 2.21.0