From 6110f1bc2b3e4a6d07bb0f152c39237ea957d116 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Sat, 6 Feb 2021 18:28:36 -0500 Subject: [PATCH] commit bash-20210203 snapshot --- CWRU/CWRU.chlog | 32 ++++++++++++++++++++++++++++++++ array.h | 11 ++++++++++- bashhist.c | 6 ++++-- doc/bash.1 | 3 ++- doc/bashref.texi | 3 ++- lib/readline/histexpand.c | 27 +++++++++++++++++++++++++-- tests/extglob6.sub | 2 ++ variables.c | 10 ++++------ 8 files changed, 81 insertions(+), 13 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 71cca9c9..308bb7ca 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -9504,3 +9504,35 @@ parse.y statement body, make sure to save any alias that's currently being expanded. Restore the alias after the compound assignment is parsed. Reported back in 11/2020 by Alex fxmbsw7 Ratchev + + 2/4 + --- +lib/readline/histexpand.c + - history_expand_internal: when calling the history_inhibit_expansion + function, make sure to call it using the string as we've expanded it + to that point (RESULT), adding the expansion and next characters + temporarily, since we make expansion decisions based on what we've + accumulated, not what we started with. This makes things like + echo abc!$!$ work, where before the second `!' inhibited expansion + because bash_history_inhibit_expansion mistakenly took it as the + second character in a `$!' word expansion. Fixes bug reported back + in 10/2020 by Paul Fox + +array.h + - array_pop: instead of calling array_dispose_element from this macro, + just call array_shift with the AS_DISPOSE flag + + 2/5 + --- +bashhist.c + - shell_comment: move condition to return 0 if the delimiter stack is + not empty or the shell is parsing a here document into the function + itself, don't have the callers check so the check is in one place. + Fixes bug reported by Oguz + +array.h,variables.c + - ARRAY_ELEMENT_REPLACE: convenience define for modifying an array + element's value + +variables.c + - pop_args: a couple of code simplifications diff --git a/array.h b/array.h index a5e01e27..3bc76953 100644 --- a/array.h +++ b/array.h @@ -106,11 +106,14 @@ extern ARRAY *array_from_string PARAMS((char *, char *)); #define set_element_value(ae, val) ((ae)->value = (val)) +#define set_max_index(a, i) ((a)->max_index = (i)) +#define set_num_elements(a, n) ((a)->num_elements = (n)) + /* Convenience */ #define array_push(a,v) \ do { array_rshift ((a), 1, (v)); } while (0) #define array_pop(a) \ - do { array_dispose_element (array_shift ((a), 1, 0)); } while (0) + do { array_shift ((a), 1, AS_DISPOSE); } while (0) #define GET_ARRAY_FROM_VAR(n, v, a) \ do { \ @@ -118,6 +121,12 @@ extern ARRAY *array_from_string PARAMS((char *, char *)); (a) = ((v) && array_p ((v))) ? array_cell (v) : (ARRAY *)0; \ } while (0) +#define ARRAY_ELEMENT_REPLACE(ae, v) \ + do { \ + free ((ae)->value); \ + (ae)->value = (v); \ + } while (0) + #define ALL_ELEMENT_SUB(c) ((c) == '@' || (c) == '*') /* In eval.c, but uses ARRAY * */ diff --git a/bashhist.c b/bashhist.c index 2a05a53f..adbd90f9 100644 --- a/bashhist.c +++ b/bashhist.c @@ -653,6 +653,8 @@ shell_comment (line) char *p; int n; + if (dstack.delimiter_depth != 0 || (parser_state & PST_HEREDOC)) + return 0; if (line == 0) return 0; for (p = line; p && *p && whitespace (*p); p++) @@ -757,7 +759,7 @@ maybe_add_history (line) int is_comment; hist_last_line_added = 0; - is_comment = (parser_state & PST_HEREDOC) ? 0 : shell_comment (line); + is_comment = shell_comment (line); /* Don't use the value of history_control to affect the second and subsequent lines of a multi-line command (old code did @@ -874,7 +876,7 @@ bash_add_history (line) add_it = 1; if (command_oriented_history && current_command_line_count > 1) { - is_comment = (parser_state & PST_HEREDOC) ? 0 : shell_comment (line); + is_comment = shell_comment (line); /* The second and subsequent lines of a here document have the trailing newline preserved. We don't want to add extra newlines here, but we diff --git a/doc/bash.1 b/doc/bash.1 index fbb347f1..d3dd3084 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -596,7 +596,8 @@ See for a description of a subshell environment. If the \fBlastpipe\fP option is enabled using the \fBshopt\fP builtin (see the description of \fBshopt\fP below), -the last element of a pipeline may be run by the shell process. +the last element of a pipeline may be run by the shell process +when job control is not active. .SS Lists A \fIlist\fP is a sequence of one or more pipelines separated by one of the operators diff --git a/doc/bashref.texi b/doc/bashref.texi index 9aecfac4..cceef130 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -695,7 +695,8 @@ Each command in a pipeline is executed in its own subshell, which is a separate process (@pxref{Command Execution Environment}). If the @code{lastpipe} option is enabled using the @code{shopt} builtin (@pxref{The Shopt Builtin}), -the last element of a pipeline may be run by the shell process. +the last element of a pipeline may be run by the shell process +when job control is not active. The exit status of a pipeline is the exit status of the last command in the diff --git a/lib/readline/histexpand.c b/lib/readline/histexpand.c index 34506da9..8ab68091 100644 --- a/lib/readline/histexpand.c +++ b/lib/readline/histexpand.c @@ -1207,13 +1207,36 @@ history_expand (char *hstring, char **output) characters in history_no_expand_chars, then it is not a candidate for expansion of any kind. */ if (cc == 0 || member (cc, history_no_expand_chars) || - (dquote && cc == '"') || - (history_inhibit_expansion_function && (*history_inhibit_expansion_function) (string, i))) + (dquote && cc == '"')) { ADD_CHAR (string[i]); break; } + /* If the application has defined a function to determine whether + or not a history expansion should be performed, call it here. */ + /* We check against what we've expanded so far, with the current + expansion appended, because that seems to be what csh does. We + decide to expand based on what we have to this point, not what + we started with. */ + if (history_inhibit_expansion_function) + { + int save_j, temp; + + save_j = j; + ADD_CHAR (string[i]); + ADD_CHAR (cc); + + temp = (*history_inhibit_expansion_function) (result, save_j); + if (temp) + { + result[--j] = '\0'; /* `unadd' cc, leaving ADD_CHAR(string[i]) */ + break; + } + else + result[j = save_j] = '\0'; + } + #if defined (NO_BANG_HASH_MODIFIERS) /* There is something that is listed as a `word specifier' in csh documentation which means `the expanded text to this point'. diff --git a/tests/extglob6.sub b/tests/extglob6.sub index a5f3e6b2..5e2aafbe 100644 --- a/tests/extglob6.sub +++ b/tests/extglob6.sub @@ -21,6 +21,8 @@ cd $DIR touch a .b +LC_COLLATE=C # fix sort order + echo @(?|.?) echo @(.?|?) echo ? .? diff --git a/variables.c b/variables.c index 623d6e4a..ebff0138 100644 --- a/variables.c +++ b/variables.c @@ -5676,7 +5676,7 @@ pop_args () GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a); GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a); - ce = array_shift (bash_argc_a, 1, 0); + ce = array_unshift_element (bash_argc_a); if (ce == 0 || legal_number (element_value (ce), &i) == 0) i = 0; @@ -6286,8 +6286,7 @@ set_pipestatus_array (ps, nproc) if (array_num_elements (a) == nproc && nproc == 1) { ae = element_forw (a->head); - free (element_value (ae)); - set_element_value (ae, itos (ps[0])); + ARRAY_ELEMENT_REPLACE (ae, itos (ps[0])); } else if (array_num_elements (a) <= nproc) { @@ -6296,8 +6295,7 @@ set_pipestatus_array (ps, nproc) for (i = 0; i < array_num_elements (a); i++) { ae = element_forw (ae); - free (element_value (ae)); - set_element_value (ae, itos (ps[i])); + ARRAY_ELEMENT_REPLACE (ae, itos (ps[i])); } /* add any more */ for ( ; i < nproc; i++) @@ -6310,7 +6308,7 @@ set_pipestatus_array (ps, nproc) { /* deleting elements. it's faster to rebuild the array. */ array_flush (a); - for (i = 0; ps[i] != -1; i++) + for (i = 0; i < nproc; i++) { t = inttostr (ps[i], tbuf, sizeof (tbuf)); array_insert (a, i, t);