From 7b024db83e0388c43b8e13e4e56144dabfe75c96 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 17 May 2021 12:03:03 -0400 Subject: [PATCH] more minor changes for builtins and array subscript expansion; fix to `wait -n' --- CWRU/CWRU.chlog | 38 ++++++++++++++++++++++++++++++++++++++ arrayfunc.c | 3 ++- builtins/common.c | 13 +++++++++++-- builtins/declare.def | 2 +- builtins/printf.def | 2 +- builtins/read.def | 38 +++++++++++++++++++++++++++++--------- builtins/wait.def | 8 ++++++++ doc/bash.1 | 7 ++++--- doc/bashref.texi | 7 ++++--- jobs.c | 1 + lib/readline/signals.c | 2 +- subst.h | 1 + test.c | 7 ++++--- tests/array.right | 2 +- 14 files changed, 106 insertions(+), 25 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 7916f4e9..d7257c93 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -10320,3 +10320,41 @@ subst.c that are backslash-quoted in subscripts after word expansion. skipsubscript treats them specially, so you have to quote them to do things like `key='"' ; array[$key]=1 ; [[ -v array[$key] ]]' + + 5/16 + ---- + +builtins/wait.def + - wait_builtin: if we longjmp to wait_intr_buf, call unset_waitlist if + we have called set_waitlist (wflags & JWAIT_WAITING). Fixes bug with + wait -n interrupted by a trapped signal (not SIGINT) reported by + Jonas Alfredsson + +jobs.c + - wait_sigint_cleanup: restore the old sigint handler before we longjmp + out by calling restore_sigint_handler() + + 5/17 + ---- +builtins/read.def + - bind_read_variable: now takes an additional argument, flags to pass + to builtin_bind_variable; change callers + - SET_VFLAGS: set vflags and bindflags + - read_builtin: call SET_VFLAGS to set vflags and bindflags from each + word before calling valid_array_reference and bind_read_variable + +builtins/common.c + - builtin_bind_variable: set vflags (for valid_array_reference) and + bindflags (for bind_variable/assign_array_element) separately for + clarity + +arrayfunc.c + - assign_array_element: sanity check: make sure that the suubscript + returned by array_variable_name consumes the entire NAME, otherwise + flag it as a subscript error. This keeps things like + `KEY=' ]'; read assoc[$KEY] <<< hello' from assigning to incomplete + subscripts + +builtins/printf.def + - printf_builtin: if LIST_OPTFLAGS includes W_ARRAYREF, set VA_NOEXPAND + in VFLAGS diff --git a/arrayfunc.c b/arrayfunc.c index 5a826ce1..c2778586 100644 --- a/arrayfunc.c +++ b/arrayfunc.c @@ -344,7 +344,8 @@ assign_array_element (name, value, flags) (ASS_ALLOWALLSUB) we allow it. */ if (((isassoc == 0 || (flags & (ASS_NOEXPAND|ASS_ALLOWALLSUB)) == 0) && (ALL_ELEMENT_SUB (sub[0]) && sub[1] == ']')) || - (sublen <= 1)) + (sublen <= 1) || + (sub[sublen] != '\0')) /* sanity check */ { free (vname); err_badarraysub (name); diff --git a/builtins/common.c b/builtins/common.c index dc7b8d9c..8d37eba4 100644 --- a/builtins/common.c +++ b/builtins/common.c @@ -971,6 +971,7 @@ builtin_help () /* */ /* **************************************************************** */ +/* Assign NAME=VALUE, passing FLAGS to the assignment functions. */ SHELL_VAR * builtin_bind_variable (name, value, flags) char *name; @@ -978,6 +979,7 @@ builtin_bind_variable (name, value, flags) int flags; { SHELL_VAR *v; + int vflags, bindflags; #if defined (ARRAY_VARS) /* Callers are responsible for calling this with array references that have @@ -985,10 +987,17 @@ builtin_bind_variable (name, value, flags) Affected builtins: read, printf To make this really work, needs additional downstream support, starting with assign_array_element and array_variable_name. */ - if (valid_array_reference (name, assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0) == 0) + vflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0; + bindflags = flags | (assoc_expand_once ? ASS_NOEXPAND : 0) | ASS_ALLOWALLSUB; + if (flags & ASS_NOEXPAND) + vflags |= VA_NOEXPAND; + if (flags & ASS_ONEWORD) + vflags |= VA_ONEWORD; + + if (valid_array_reference (name, vflags) == 0) v = bind_variable (name, value, flags); else - v = assign_array_element (name, value, flags | (assoc_expand_once ? ASS_NOEXPAND : 0) | ASS_ALLOWALLSUB); + v = assign_array_element (name, value, bindflags); #else /* !ARRAY_VARS */ v = bind_variable (name, value, flags); #endif /* !ARRAY_VARS */ diff --git a/builtins/declare.def b/builtins/declare.def index 58413853..48797a2c 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -404,7 +404,7 @@ declare_internal (list, local_var) name = savestring (list->word->word); wflags = list->word->flags; #if defined (ARRAY_VARS) - assoc_noexpand = assoc_expand_once && (wflags & W_ASSIGNMENT); + assoc_noexpand = (assoc_expand_once || expand_once_flag) && (wflags & W_ASSIGNMENT); #else assoc_noexpand = 0; #endif diff --git a/builtins/printf.def b/builtins/printf.def index a10fb979..5605bedb 100644 --- a/builtins/printf.def +++ b/builtins/printf.def @@ -269,7 +269,7 @@ printf_builtin (list) #if defined (ARRAY_VARS) arrayflags = assoc_expand_once ? VA_NOEXPAND : 0; if (assoc_expand_once && (list_optflags & W_ARRAYREF)) - arrayflags |= VA_ONEWORD; /* XXX - VA_NOEXPAND? */ + arrayflags |= VA_ONEWORD|VA_NOEXPAND; retval = legal_identifier (vname) || valid_array_reference (vname, arrayflags); #else retval = legal_identifier (vname); diff --git a/builtins/read.def b/builtins/read.def index f670b7fd..1898e600 100644 --- a/builtins/read.def +++ b/builtins/read.def @@ -128,7 +128,7 @@ static void set_eol_delim PARAMS((int)); static void reset_eol_delim PARAMS((char *)); static void set_readline_timeout PARAMS((sh_timer *t, time_t, long)); #endif -static SHELL_VAR *bind_read_variable PARAMS((char *, char *)); +static SHELL_VAR *bind_read_variable PARAMS((char *, char *, int)); #if defined (HANDLE_MULTIBYTE) static int read_mbchar PARAMS((int, char *, int, int, int)); #endif @@ -190,6 +190,20 @@ read_builtin_timeout (fd) : shtimer_select (read_timeout)); } +#if defined (ARRAY_VARS) +#define SET_VFLAGS(wordflags) \ + do { \ + vflags = assoc_expand_once ? VA_NOEXPAND : 0; \ + bindflags = assoc_expand_once ? ASS_NOEXPAND : 0; \ + if (assoc_expand_once && (wordflags & W_ARRAYREF)) \ + vflags |= VA_ONEWORD|VA_NOEXPAND; \ + if (vflags & VA_NOEXPAND) \ + bindflags |= ASS_NOEXPAND; \ + if (vflags & VA_ONEWORD) \ + bindflags |= ASS_ONEWORD; \ + } while (0) +#endif + /* Read the value of the shell variables whose names follow. The reading is done from the current input stream, whatever that may be. Successive words of the input line are assigned @@ -221,6 +235,7 @@ read_builtin (list) WORD_LIST *alist; int vflags; #endif + int bindflags; #if defined (READLINE) char *rlbuf, *itext; int rlind; @@ -362,9 +377,11 @@ read_builtin (list) /* Convenience: check early whether or not the first of possibly several variable names is a valid identifier, and bail early if so. */ #if defined (ARRAY_VARS) - vflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0; + if (list) + SET_VFLAGS (list->word->flags); if (list && legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0) #else + bindflags = 0; if (list && legal_identifier (list->word->word) == 0) #endif { @@ -952,6 +969,7 @@ assign_vars: { varname = list->word->word; #if defined (ARRAY_VARS) + SET_VFLAGS (list->word->flags); if (legal_identifier (varname) == 0 && valid_array_reference (varname, vflags) == 0) #else if (legal_identifier (varname) == 0) @@ -975,16 +993,16 @@ assign_vars: if (t && saw_escape) { t1 = dequote_string (t); - var = bind_read_variable (varname, t1); + var = bind_read_variable (varname, t1, bindflags); free (t1); } else - var = bind_read_variable (varname, t ? t : ""); + var = bind_read_variable (varname, t ? t : "", bindflags); } else { t = (char *)0; - var = bind_read_variable (varname, ""); + var = bind_read_variable (varname, "", bindflags); } FREE (t); @@ -1000,6 +1018,7 @@ assign_vars: /* Now assign the rest of the line to the last variable argument. */ #if defined (ARRAY_VARS) + SET_VFLAGS (list->word->flags); if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0) #else if (legal_identifier (list->word->word) == 0) @@ -1036,11 +1055,11 @@ assign_vars: if (saw_escape && input_string && *input_string) { t = dequote_string (input_string); - var = bind_read_variable (list->word->word, t); + var = bind_read_variable (list->word->word, t, bindflags); free (t); } else - var = bind_read_variable (list->word->word, input_string ? input_string : ""); + var = bind_read_variable (list->word->word, input_string ? input_string : "", bindflags); if (var) { @@ -1057,12 +1076,13 @@ assign_vars: } static SHELL_VAR * -bind_read_variable (name, value) +bind_read_variable (name, value, flags) char *name, *value; + int flags; { SHELL_VAR *v; - v = builtin_bind_variable (name, value, 0); + v = builtin_bind_variable (name, value, flags); return (v == 0 ? v : ((readonly_p (v) || noassign_p (v)) ? (SHELL_VAR *)NULL : v)); } diff --git a/builtins/wait.def b/builtins/wait.def index 6e134fb2..6ec628d9 100644 --- a/builtins/wait.def +++ b/builtins/wait.def @@ -151,7 +151,13 @@ wait_builtin (list) #if defined (ARRAY_VARS) int arrayflags; +#if 0 arrayflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0; + if (assoc_expand_once && (list_optflags & W_ARRAYREF)) + arrayflags |= VA_ONEWORD|VA_NOEXPAND; +#else + arrayflags = 0; /* not yet without builtin_bind_var_to_int support */ +#endif if (legal_identifier (vname) == 0 && valid_array_reference (vname, arrayflags) == 0) #else if (legal_identifier (vname) == 0) @@ -180,6 +186,8 @@ wait_builtin (list) last_command_exit_signal = wait_signal_received; status = 128 + wait_signal_received; wait_sigint_cleanup (); + if (wflags & JWAIT_WAITING) + unset_waitlist (); WAIT_RETURN (status); } diff --git a/doc/bash.1 b/doc/bash.1 index 82dfa1e6..a5dee515 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -2902,7 +2902,7 @@ For example, a\fB{\fPd,c,b\fB}\fPe expands into `ade ace abe'. .PP A sequence expression takes the form \fB{\fP\fIx\fP\fB..\fP\fIy\fP\fB[..\fP\fIincr\fP\fB]}\fP, -where \fIx\fP and \fIy\fP are either integers or single characters, +where \fIx\fP and \fIy\fP are either integers or single letters, and \fIincr\fP, an optional increment, is an integer. When integers are supplied, the expression expands to each number between \fIx\fP and \fIy\fP, inclusive. @@ -2911,10 +2911,11 @@ same width. When either \fIx\fP or \fPy\fP begins with a zero, the shell attempts to force all generated terms to contain the same number of digits, zero-padding where necessary. -When characters are supplied, the expression expands to each character +When letters are supplied, the expression expands to each character lexicographically between \fIx\fP and \fIy\fP, inclusive, using the default C locale. -Note that both \fIx\fP and \fIy\fP must be of the same type. +Note that both \fIx\fP and \fIy\fP must be of the same type +(integer or letter). When the increment is supplied, it is used as the difference between each term. The default increment is 1 or \-1 as appropriate. .PP diff --git a/doc/bashref.texi b/doc/bashref.texi index 9cc8b1ae..a21b9e12 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -2075,7 +2075,7 @@ ade ace abe @end example A sequence expression takes the form @code{@{@var{x}..@var{y}[..@var{incr}]@}}, -where @var{x} and @var{y} are either integers or single characters, +where @var{x} and @var{y} are either integers or letters, and @var{incr}, an optional increment, is an integer. When integers are supplied, the expression expands to each number between @var{x} and @var{y}, inclusive. @@ -2084,10 +2084,11 @@ same width. When either @var{x} or @var{y} begins with a zero, the shell attempts to force all generated terms to contain the same number of digits, zero-padding where necessary. -When characters are supplied, the expression expands to each character +When letters are supplied, the expression expands to each character lexicographically between @var{x} and @var{y}, inclusive, using the default C locale. -Note that both @var{x} and @var{y} must be of the same type. +Note that both @var{x} and @var{y} must be of the same type +(integer or letter). When the increment is supplied, it is used as the difference between each term. The default increment is 1 or -1 as appropriate. diff --git a/jobs.c b/jobs.c index 49a862e1..ffe4bed6 100644 --- a/jobs.c +++ b/jobs.c @@ -2741,6 +2741,7 @@ wait_sigint_cleanup () { queue_sigchld = 0; waiting_for_child = 0; + restore_sigint_handler (); } static void diff --git a/lib/readline/signals.c b/lib/readline/signals.c index 2bbec3ec..83cdc53f 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -64,7 +64,7 @@ /* This typedef is equivalent to the one for Function; it allows us to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ -typedef RETSIGTYPE SigHandler (); +typedef RETSIGTYPE SigHandler (int); #if defined (HAVE_POSIX_SIGNALS) typedef struct sigaction sighandler_cxt; diff --git a/subst.h b/subst.h index bb461bc1..eaa29de9 100644 --- a/subst.h +++ b/subst.h @@ -56,6 +56,7 @@ #define ASS_NOLONGJMP 0x0200 /* don't longjmp on fatal assignment error */ #define ASS_NOINVIS 0x0400 /* don't resolve local invisible variables */ #define ASS_ALLOWALLSUB 0x0800 /* allow * and @ as associative array keys */ +#define ASS_ONEWORD 0x1000 /* don't check array subscripts, assume higher level has done that */ /* Flags for the string extraction functions. */ #define SX_NOALLOC 0x0001 /* just skip; don't return substring */ diff --git a/test.c b/test.c index fdd46c4f..0daf71f6 100644 --- a/test.c +++ b/test.c @@ -525,6 +525,7 @@ unary_test (op, arg, flags) struct stat stat_buf; struct timespec mtime, atime; SHELL_VAR *v; + int aflags; switch (op[1]) { @@ -632,16 +633,16 @@ unary_test (op, arg, flags) case 'v': #if defined (ARRAY_VARS) - if (valid_array_reference (arg, assoc_expand_once ? VA_NOEXPAND : 0)) + aflags = assoc_expand_once ? AV_NOEXPAND : 0; + if (valid_array_reference (arg, aflags)) { char *t; - int rtype, ret, aflags; + int rtype, ret; /* Let's assume that this has already been expanded once. */ /* XXX - TAG:bash-5.2 fix with corresponding fix to execute_cmd.c: execute_cond_node() that passes TEST_ARRAYEXP in FLAGS */ - aflags = assoc_expand_once ? AV_NOEXPAND : 0; #if 0 /* TAG:bash-5.2 */ if (shell_compatibility_level > 51) diff --git a/tests/array.right b/tests/array.right index c2c9a718..c61a27ce 100644 --- a/tests/array.right +++ b/tests/array.right @@ -745,7 +745,7 @@ argv[1] = declare -A A=([$'\t']="2" [" "]="2" ) declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["]"]="2" ["@"]="2" ) declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["]"]="2" ["@"]="2" ) -./array27.sub: line 52: A[]]: bad array subscript +./array27.sub: line 52: read: `A[]]': not a valid identifier declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" ) ./array27.sub: line 60: printf: `A[]]': not a valid identifier declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" )