278 lines
9.0 KiB
Diff
278 lines
9.0 KiB
Diff
From 4e4cebb6dcf4522243b5b9e87918789aea8f73a1 Mon Sep 17 00:00:00 2001
|
|
From: Chet Ramey <chet.ramey@case.edu>
|
|
Date: Tue, 20 Jun 2023 11:10:39 -0400
|
|
Subject: [PATCH] fix for nofork comsub command printing; fix for crash caused
|
|
by tempvar assignment converted to an array in a function
|
|
|
|
Conflict:code context adaptation and delete modify in CWRU.chlog
|
|
Reference:https://git.savannah.gnu.org/cgit/bash.git/commit/?id=4e4cebb6dcf4522243b5b9e87918789aea8f73a1
|
|
---
|
|
arrayfunc.c | 13 ++++++++++
|
|
arrayfunc.h | 2 ++
|
|
builtins/declare.def | 14 ++++++++---
|
|
print_cmd.c | 12 +++++----
|
|
shell.h | 2 ++
|
|
subst.h | 1 +
|
|
variables.c | 60 ++++++++++++++++++++++++++++++--------------
|
|
7 files changed, 76 insertions(+), 28 deletions(-)
|
|
|
|
diff --git a/arrayfunc.c b/arrayfunc.c
|
|
index 58d0222..687b7ab 100644
|
|
--- a/arrayfunc.c
|
|
+++ b/arrayfunc.c
|
|
@@ -147,6 +147,19 @@ convert_var_to_assoc (var)
|
|
return var;
|
|
}
|
|
|
|
+/* Copy the array (ARRAY *) or assoc (HASH_TABLE *) from variable V1 to V2,
|
|
+ and return V2. */
|
|
+SHELL_VAR *
|
|
+arrayvar_copyval (SHELL_VAR *v1, SHELL_VAR *v2)
|
|
+{
|
|
+ FREE (value_cell (v2));
|
|
+ if (array_p (v1))
|
|
+ var_setarray (v2, array_copy (array_cell (v1)));
|
|
+ else if (assoc_p (v1))
|
|
+ var_setassoc (v2, assoc_copy (assoc_cell (v1)));
|
|
+ return v2;
|
|
+}
|
|
+
|
|
char *
|
|
make_array_variable_value (entry, ind, key, value, flags)
|
|
SHELL_VAR *entry;
|
|
diff --git a/arrayfunc.h b/arrayfunc.h
|
|
index 838e76d..ec455fa 100644
|
|
--- a/arrayfunc.h
|
|
+++ b/arrayfunc.h
|
|
@@ -47,6 +47,8 @@ extern int array_expand_once;
|
|
extern SHELL_VAR *convert_var_to_array PARAMS((SHELL_VAR *));
|
|
extern SHELL_VAR *convert_var_to_assoc PARAMS((SHELL_VAR *));
|
|
|
|
+extern SHELL_VAR *arrayvar_copyval (SHELL_VAR *, SHELL_VAR *);
|
|
+
|
|
extern char *make_array_variable_value PARAMS((SHELL_VAR *, arrayind_t, char *, char *, int));
|
|
|
|
extern SHELL_VAR *bind_array_variable PARAMS((char *, arrayind_t, char *, int));
|
|
diff --git a/builtins/declare.def b/builtins/declare.def
|
|
index 21e4516..13f20de 100644
|
|
--- a/builtins/declare.def
|
|
+++ b/builtins/declare.def
|
|
@@ -952,20 +952,26 @@ restart_new_var_name:
|
|
if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
|
|
{
|
|
SHELL_VAR *tv;
|
|
- char *tvalue;
|
|
|
|
tv = find_tempenv_variable (var->name);
|
|
if (tv)
|
|
{
|
|
- tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
|
|
- tv = bind_variable (var->name, tvalue, 0);
|
|
+ /* We don't bother with modifying the temporary env because
|
|
+ we're already using it. */
|
|
+ tv = bind_variable (name_cell (var), value_cell (var), ASS_NOTEMPENV);
|
|
+
|
|
if (tv)
|
|
{
|
|
+#if defined (ARRAY_VARS)
|
|
+ /* copy array value if array variable */
|
|
+ if ((array_p (var) || assoc_p (var)))
|
|
+ arrayvar_copyval (var, tv);
|
|
+#endif
|
|
+ /* then copy attributes */
|
|
tv->attributes |= var->attributes & ~att_tempvar;
|
|
if (tv->context > 0)
|
|
VSETATTR (tv, att_propagate);
|
|
}
|
|
- free (tvalue);
|
|
}
|
|
VSETATTR (var, att_propagate);
|
|
}
|
|
diff --git a/print_cmd.c b/print_cmd.c
|
|
index 3c8c2d8..d497418 100644
|
|
--- a/print_cmd.c
|
|
+++ b/print_cmd.c
|
|
@@ -666,7 +666,7 @@ print_group_command (group_command)
|
|
group_command_nesting++;
|
|
cprintf ("{ ");
|
|
|
|
- if (inside_function_def == 0)
|
|
+ if (inside_function_def == 0 /* && pretty_print_mode == 0 */)
|
|
skip_this_indent++;
|
|
else
|
|
{
|
|
@@ -680,7 +680,7 @@ print_group_command (group_command)
|
|
make_command_string_internal (group_command->command);
|
|
PRINT_DEFERRED_HEREDOCS ("");
|
|
|
|
- if (inside_function_def)
|
|
+ if (inside_function_def /* || pretty_print_mode */)
|
|
{
|
|
cprintf ("\n");
|
|
indentation -= indentation_amount;
|
|
@@ -1459,9 +1459,11 @@ indent (amount)
|
|
static void
|
|
semicolon ()
|
|
{
|
|
- if (command_string_index > 0 &&
|
|
- (the_printed_command[command_string_index - 1] == '&' ||
|
|
- the_printed_command[command_string_index - 1] == '\n'))
|
|
+ if ((command_string_index > 0 &&
|
|
+ the_printed_command[command_string_index - 1] == '\n') ||
|
|
+ (command_string_index > 1 &&
|
|
+ the_printed_command[command_string_index - 1] == '&' &&
|
|
+ the_printed_command[command_string_index - 2] == ' '))
|
|
return;
|
|
cprintf (";");
|
|
}
|
|
diff --git a/shell.h b/shell.h
|
|
index 91b31ac..ebc2a26 100644
|
|
--- a/shell.h
|
|
+++ b/shell.h
|
|
@@ -106,6 +106,8 @@ extern int indirection_level;
|
|
extern int shell_compatibility_level;
|
|
extern int running_under_emacs;
|
|
|
|
+extern int pretty_print_mode;
|
|
+
|
|
extern int posixly_correct;
|
|
extern int no_line_editing;
|
|
|
|
diff --git a/subst.h b/subst.h
|
|
index 1347651..a5a5fae 100644
|
|
--- a/subst.h
|
|
+++ b/subst.h
|
|
@@ -55,6 +55,7 @@
|
|
#define ASS_NOEVAL 0x0100 /* don't evaluate value as expression */
|
|
#define ASS_NOLONGJMP 0x0200 /* don't longjmp on fatal assignment error */
|
|
#define ASS_NOINVIS 0x0400 /* don't resolve local invisible variables */
|
|
+#define ASS_NOTEMPENV 0x2000 /* don't assign into temporary environment */
|
|
|
|
/* Flags for the string extraction functions. */
|
|
#define SX_NOALLOC 0x0001 /* just skip; don't return substring */
|
|
diff --git a/variables.c b/variables.c
|
|
index 73f157f..2529afb 100644
|
|
--- a/variables.c
|
|
+++ b/variables.c
|
|
@@ -266,6 +266,8 @@ static SHELL_VAR *new_shell_variable PARAMS((const char *));
|
|
static SHELL_VAR *make_new_variable PARAMS((const char *, HASH_TABLE *));
|
|
static SHELL_VAR *bind_variable_internal PARAMS((const char *, char *, HASH_TABLE *, int, int));
|
|
|
|
+static void init_shell_variable (SHELL_VAR *);
|
|
+
|
|
static void dispose_variable_value PARAMS((SHELL_VAR *));
|
|
static void free_variable_hash_data PARAMS((PTR_T));
|
|
|
|
@@ -2702,6 +2704,21 @@ make_local_variable (name, flags)
|
|
new_var = make_new_variable (name, vc->table);
|
|
else
|
|
{
|
|
+#if 0
|
|
+ /* This handles the case where a variable is found in both the temporary
|
|
+ environment *and* declared as a local variable. If we want to avoid
|
|
+ multiple entries with the same name in VC->table (that might mess up
|
|
+ unset), we need to use the existing variable entry and destroy the
|
|
+ current value. Currently disabled because it doesn't matter -- the
|
|
+ right things happen. */
|
|
+ new_var = 0;
|
|
+ if (was_tmpvar && (new_var = hash_lookup (name, vc->table)))
|
|
+ {
|
|
+ dispose_variable_value (new_var);
|
|
+ init_variable (new_var);
|
|
+ }
|
|
+ if (new_var == 0)
|
|
+#endif
|
|
new_var = make_new_variable (name, vc->table);
|
|
|
|
/* If we found this variable in one of the temporary environments,
|
|
@@ -2761,16 +2778,9 @@ set_local_var_flags:
|
|
return (new_var);
|
|
}
|
|
|
|
-/* Create a new shell variable with name NAME. */
|
|
-static SHELL_VAR *
|
|
-new_shell_variable (name)
|
|
- const char *name;
|
|
+static void
|
|
+init_variable (SHELL_VAR *entry)
|
|
{
|
|
- SHELL_VAR *entry;
|
|
-
|
|
- entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
|
|
-
|
|
- entry->name = savestring (name);
|
|
var_setvalue (entry, (char *)NULL);
|
|
CLEAR_EXPORTSTR (entry);
|
|
|
|
@@ -2783,7 +2793,18 @@ new_shell_variable (name)
|
|
make_local_variable has the responsibility of changing the
|
|
variable context. */
|
|
entry->context = 0;
|
|
+}
|
|
+
|
|
+/* Create a new shell variable with name NAME. */
|
|
+static SHELL_VAR *
|
|
+new_shell_variable (const char *name)
|
|
+{
|
|
+ SHELL_VAR *entry;
|
|
|
|
+ entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
|
|
+
|
|
+ entry->name = savestring (name);
|
|
+ init_variable (entry);
|
|
return (entry);
|
|
}
|
|
|
|
@@ -3265,8 +3286,9 @@ bind_variable (name, value, flags)
|
|
and, if found, modify the value there before modifying it in the
|
|
shell_variables table. This allows sourced scripts to modify values
|
|
given to them in a temporary environment while modifying the variable
|
|
- value that the caller sees. */
|
|
- if (temporary_env && value) /* XXX - can value be null here? */
|
|
+ value that the caller sees. The caller can inhibit this by setting
|
|
+ ASS_NOTEMPENV in FLAGS. */
|
|
+ if (temporary_env && value && (flags & ASS_NOTEMPENV) == 0) /* XXX - can value be null here? */
|
|
bind_tempenv_variable (name, value);
|
|
|
|
/* XXX -- handle local variables here. */
|
|
@@ -4581,6 +4603,11 @@ push_temp_var (data)
|
|
|
|
v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
|
|
|
|
+#if defined (ARRAY_VARS)
|
|
+ if (v && (array_p (var) || assoc_p (var)))
|
|
+ arrayvar_copyval (var, v);
|
|
+#endif
|
|
+
|
|
/* XXX - should we set the context here? It shouldn't matter because of how
|
|
assign_in_env works, but we do it anyway. */
|
|
if (v)
|
|
@@ -5245,6 +5272,7 @@ push_posix_tempvar_internal (var, isbltin)
|
|
set_current_options (value_cell (var));
|
|
set_shellopts ();
|
|
}
|
|
+
|
|
/* This takes variable assignments preceding special builtins that can execute
|
|
multiple commands (source, eval, etc.) and performs the equivalent of
|
|
an assignment statement to modify the closest enclosing variable (the
|
|
@@ -5286,14 +5314,8 @@ push_posix_tempvar_internal (var, isbltin)
|
|
|
|
#if defined (ARRAY_VARS)
|
|
if (v && (array_p (var) || assoc_p (var)))
|
|
- {
|
|
- FREE (value_cell (v));
|
|
- if (array_p (var))
|
|
- var_setarray (v, array_copy (array_cell (var)));
|
|
- else
|
|
- var_setassoc (v, assoc_copy (assoc_cell (var)));
|
|
- }
|
|
-#endif
|
|
+ arrayvar_copyval (var, v);
|
|
+#endif
|
|
|
|
dispose_variable (var);
|
|
}
|
|
--
|
|
2.33.0
|
|
|