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