diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index d7257c93..09fbe6dd 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -10358,3 +10358,96 @@ arrayfunc.c builtins/printf.def - printf_builtin: if LIST_OPTFLAGS includes W_ARRAYREF, set VA_NOEXPAND in VFLAGS + + 5/17 + ---- + +lib/readline/complete.c + - compute_lcd_of_matches: move a couple of strlen calls out of a loop + in calls to mbrtowc; performance improvement only. Report and fix + from sparrowhawk996@gmail.com + +lib/readline/bind.c + - rl_trim_arg_from_keyseq: take a key sequence and its length and + return the index into the key sequence following any initial numeric + argument. Return -1 if there is no numeric argument (the caller is + expected to make sure) or if the key sequence consists *only* of + the numeric argument. The caller should use the remainder of the + key sequence to look up the desired key binding. + +lib/readline/readline.h + - rl_trim_arg_from_keyseq: extern declaration + +bashline.c + - bash_execute_unix_command: if the argument count is > 1 or we have + an explicit argument, call rl_trim_arg_from_keyseq to get past the + numeric argument and deal with the rest of the key sequence. We still + need a way to pass it to the invoked program or function. From + a report from Jesper Nygards + + 5/18 + ---- + +bashline.c + - bash_execute_unix_command: if the user supplied a numeric argument + when invoking bash_execute_unix_command, pass it to the command in + the READLINE_ARGUMENT variable + +lib/readline/readline.[ch] + - _rl_del_executing_keyseq: convenience function to `delete' the last + character added to the executing key sequence. Intended to be used + before calling rl_execute_next or similar functions that push input + back to be re-read + +doc/{bash.1,bashref.texi} + - READLINE_ARGUMENT: documented new variable available for commands + defined using `bind -x' keybindings + +lib/readline/doc/rltech.texi + - rl_trim_arg_from_keyseq: documented new function + + 5/19 + ---- + +builtins/evalstring.c + - should_suppress_fork: suppress the fork if we're in a process + substitution subshell, in addition to being a simple command + without redirections. From a report back in 10/2020 from + Hyunho Cho + +bashline.c + - command_word_completion_function: if we're trying to complete an + absolute program (one containing a slash), don't run strcmp or + strcasecmp on the return value from rl_filename_completion_function, + since that duplicates work the filename completion function already + does. From a report back in 1/2021 by awa54@cdak.net + + 5/22 + ---- +parse.y + - CHECK_FOR_RESERVED_WORD: if we are returning an ESAC and unsetting + PST_CASESTMT, decrement esacs_needed_count + +parse.y,shell.h + - sh_parser_state_t: save and restore esacs_needed_count and + expecting_in_token in the shell parser state struct and + save_parser_state/restore_parser_state + +print_cmd.c + - print_simple_command: don't bother to call command_print_word_list + with an empty list + - print_simple_command: don't print a space before a redirection list + if there weren't any command words to print + + 5/24 + ---- + +lib/sh/input_avail.c + - nchars_avail: make sure SET and OSET are declared on systems with + select(2). Reported by Larkin Nickle + +parse.y + - cond_term: if we read a `!' toggle CMD_INVERT_RETURN instead of + setting it unconditionally. Report and patch from + Vincent Menegaux via + https://savannah.gnu.org/patch/?10070 diff --git a/bashline.c b/bashline.c index 87fbfdda..8cb03259 100644 --- a/bashline.c +++ b/bashline.c @@ -2301,10 +2301,16 @@ globword: if (absolute_program (hint)) { +#if 0 if (igncase == 0) match = strncmp (val, hint, hint_len) == 0; else match = strncasecmp (val, hint, hint_len) == 0; +#else + /* Why duplicate the comparison rl_filename_completion_function + already performs? */ + match = 1; +#endif /* If we performed tilde expansion, restore the original filename. */ @@ -4371,12 +4377,28 @@ bash_execute_unix_command (count, key) SHELL_VAR *v; char ibuf[INT_STRLEN_BOUND(int) + 1]; Keymap cmd_xmap; + const char *kseq; + size_t kslen; + + kseq = rl_executing_keyseq; + kslen = rl_key_sequence_length; + + /* If we have a numeric argument, chop it off the front of the key sequence */ + if (count > 1 || rl_explicit_arg) + { + i = rl_trim_arg_from_keyseq (rl_executing_keyseq, rl_key_sequence_length, rl_get_keymap ()); + if (i > 0) + { + kseq = rl_executing_keyseq + i; + kslen = rl_key_sequence_length - i; + } + } /* First, we need to find the right command to execute. This is tricky, because we might have already indirected into another keymap, so we have to walk cmd_xmap using the entire key sequence. */ cmd_xmap = get_cmd_xmap_from_keymap (rl_get_keymap ()); - cmd = (char *)rl_function_of_keyseq_len (rl_executing_keyseq, rl_key_sequence_length, cmd_xmap, &type); + cmd = (char *)rl_function_of_keyseq_len (kseq, kslen, cmd_xmap, &type); if (type == ISKMAP && (type = ((Keymap) cmd)[ANYOTHERKEY].type) == ISMACR) cmd = (char*)((Keymap) cmd)[ANYOTHERKEY].function; @@ -4413,6 +4435,14 @@ bash_execute_unix_command (count, key) v = bind_int_variable ("READLINE_MARK", value, 0); if (v) VSETATTR (v, att_exported); + + if (count > 1 || rl_explicit_arg) + { + value = inttostr (count, ibuf, sizeof (ibuf)); + v = bind_int_variable ("READLINE_ARGUMENT", value, 0); + if (v) + VSETATTR (v, att_exported); + } array_needs_making = 1; save_parser_state (&ps); @@ -4435,6 +4465,7 @@ bash_execute_unix_command (count, key) check_unbind_variable ("READLINE_LINE"); check_unbind_variable ("READLINE_POINT"); check_unbind_variable ("READLINE_MARK"); + check_unbind_variable ("READLINE_ARGUMENT"); array_needs_making = 1; /* and restore the readline buffer and display after command execution. */ diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 18928a17..fcffb3d5 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -88,20 +88,18 @@ int should_suppress_fork (command) COMMAND *command; { -#if 0 /* TAG: bash-5.2 */ int subshell; subshell = subshell_environment & SUBSHELL_PROCSUB; /* salt to taste */ -#endif return (startup_state == 2 && parse_and_execute_level == 1 && - running_trap == 0 && *bash_input.location.string == '\0' && parser_expanding_alias () == 0 && + running_trap == 0 && command->type == cm_simple && signal_is_trapped (EXIT_TRAP) == 0 && signal_is_trapped (ERROR_TRAP) == 0 && any_signals_trapped () < 0 && -#if 0 /* TAG: bash-5.2 */ +#if 1 /* TAG: bash-5.2 */ (subshell || (command->redirects == 0 && command->value.Simple->redirects == 0)) && #else command->redirects == 0 && command->value.Simple->redirects == 0 && @@ -575,9 +573,9 @@ parse_string (string, from_file, flags, endp) code = should_jump_to_top_level = 0; oglobal = global_command; - ostring = string; with_input_from_string (string, from_file); + ostring = bash_input.location.string; while (*(bash_input.location.string)) /* XXX - parser_expanding_alias () ? */ { command = (COMMAND *)NULL; diff --git a/builtins/wait.def b/builtins/wait.def index 6ec628d9..ab1e88bc 100644 --- a/builtins/wait.def +++ b/builtins/wait.def @@ -152,7 +152,7 @@ wait_builtin (list) int arrayflags; #if 0 - arrayflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0; + arrayflags = assoc_expand_once ? VA_NOEXPAND : 0; if (assoc_expand_once && (list_optflags & W_ARRAYREF)) arrayflags |= VA_ONEWORD|VA_NOEXPAND; #else diff --git a/doc/bash.1 b/doc/bash.1 index a5dee515..b4f798c9 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -711,11 +711,12 @@ the conditional expression \fIexpression\fP. Expressions are composed of the primaries described below under .SM .BR "CONDITIONAL EXPRESSIONS" . -Word splitting and pathname expansion are not performed on the words -between the \fB[[\fP and \fB]]\fP; tilde expansion, -parameter and variable expansion, -arithmetic expansion, command substitution, process -substitution, and quote removal are performed. +The words between the \fB[[\fP and \fB]]\fP do not undergo word splitting +and filename expansion. +The shell performs tilde expansion, parameter and +variable expansion, arithmetic expansion, command substitution, process +substitution, and quote removal on those words +(as if the words were enclosed in double quotes). Conditional operators such as \fB\-f\fP must be unquoted to be recognized as primaries. .if t .sp 0.5 @@ -1953,6 +1954,16 @@ If is unset, it loses its special properties, even if it is subsequently reset. .TP +.B READLINE_ARGUMENT +Any numeric argument given to a Readline command that was defined using +.if t \f(CWbind -x\fP +.if n "bind -x" +(see +.SM +.B "SHELL BUILTIN COMMANDS" +below) +when it was invoked. +.TP .B READLINE_LINE The contents of the .B readline @@ -5048,6 +5059,9 @@ while they execute. All builtins return an exit status of 2 to indicate incorrect usage, generally invalid options or missing arguments. .PP +The exit status of the last command is available in the special +parameter $?. +.PP \fBBash\fP itself returns the exit status of the last command executed, unless a syntax error occurs, in which case it exits with a non-zero value. See also the \fBexit\fP builtin @@ -7478,7 +7492,8 @@ does not contain a slash, filenames in .SM .B PATH are used to find the directory containing -.IR filename . +.IR filename , +but \fIfilename\fP does not need to be executable. The file searched for in .SM .B PATH @@ -7498,12 +7513,12 @@ is not searched. If any \fIarguments\fP are supplied, they become the positional parameters when \fIfilename\fP is executed. Otherwise the positional parameters are unchanged. -If the \fB\-T\fP option is enabled, \fBsource\fP inherits any trap on +If the \fB\-T\fP option is enabled, \fB.\fP inherits any trap on \fBDEBUG\fP; if it is not, any \fBDEBUG\fP trap string is saved and -restored around the call to \fBsource\fP, and \fBsource\fP unsets the +restored around the call to \fB.\fP, and \fB.\fP unsets the \fBDEBUG\fP trap while it executes. If \fB\-T\fP is not set, and the sourced file changes -the \fBDEBUG\fP trap, the new value is retained when \fBsource\fP completes. +the \fBDEBUG\fP trap, the new value is retained when \fB.\fP completes. The return status is the status of the last command exited within the script (0 if no commands are executed), and false if .I filename @@ -7633,6 +7648,11 @@ and .B READLINE_MARK variables to the current location of the insertion point and the saved insertion point (the mark), respectively. +The shell assigns any numeric argument the user supplied to the +.SM +.B READLINE_ARGUMENT +variable. +If there was no argument, that variable is not set. If the executed command changes the value of any of .SM .BR READLINE_LINE , @@ -10360,7 +10380,7 @@ number of positional parameters. .TP 8 .B sourcepath If set, the -\fBsource\fP (\fB.\fP) builtin uses the value of +\fB.\fP (\fBsource\fP) builtin uses the value of .SM .B PATH to find the directory containing the file supplied as an argument. diff --git a/doc/bashref.texi b/doc/bashref.texi index a21b9e12..ffe22644 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -1145,10 +1145,12 @@ Return a status of 0 or 1 depending on the evaluation of the conditional expression @var{expression}. Expressions are composed of the primaries described below in @ref{Bash Conditional Expressions}. -Word splitting and filename expansion are not performed on the words -between the @code{[[} and @code{]]}; tilde expansion, parameter and +The words between the @code{[[} and @code{]]} do not undergo word splitting +and filename expansion. +The shell performs tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process -substitution, and quote removal are performed. +substitution, and quote removal on those words +(as if the words were enclosed in double quotes). Conditional operators such as @samp{-f} must be unquoted to be recognized as primaries. @@ -1813,7 +1815,8 @@ If @var{value} is not given, the variable is assigned the null string. All @var{value}s undergo tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote -removal (detailed below). If the variable has its @code{integer} +removal (@pxref{Shell Parameter Expansion}). +If the variable has its @code{integer} attribute set, then @var{value} is evaluated as an arithmetic expression even if the @code{$((@dots{}))} expansion is not used (@pxref{Arithmetic Expansion}). @@ -3491,6 +3494,9 @@ conditional and list constructs. All builtins return an exit status of 2 to indicate incorrect usage, generally invalid options or missing arguments. +The exit status of the last command is available in the special +parameter $? (@pxref{Special Parameters}). + @node Signals @subsection Signals @cindex signal handling @@ -3677,18 +3683,19 @@ The return status is zero. Read and execute commands from the @var{filename} argument in the current shell context. If @var{filename} does not contain a slash, -the @env{PATH} variable is used to find @var{filename}. +the @env{PATH} variable is used to find @var{filename}, +but @var{filename} does not need to be executable. When Bash is not in @sc{posix} mode, the current directory is searched if @var{filename} is not found in @env{$PATH}. If any @var{arguments} are supplied, they become the positional parameters when @var{filename} is executed. Otherwise the positional parameters are unchanged. -If the @option{-T} option is enabled, @code{source} inherits any trap on +If the @option{-T} option is enabled, @code{.} inherits any trap on @code{DEBUG}; if it is not, any @code{DEBUG} trap string is saved and -restored around the call to @code{source}, and @code{source} unsets the +restored around the call to @code{.}, and @code{.} unsets the @code{DEBUG} trap while it executes. If @option{-T} is not set, and the sourced file changes -the @code{DEBUG} trap, the new value is retained when @code{source} completes. +the @code{DEBUG} trap, the new value is retained when @code{.} completes. The return status is the exit status of the last command executed, or zero if no commands are executed. If @var{filename} is not found, or cannot be read, the return status is non-zero. @@ -4325,6 +4332,9 @@ When @var{shell-command} is executed, the shell sets the buffer and the @code{READLINE_POINT} and @code{READLINE_MARK} variables to the current location of the insertion point and the saved insertion point (the @var{mark}), respectively. +The shell assigns any numeric argument the user supplied to the +@code{READLINE_ARGUMENT} variable. +If there was no argument, that variable is not set. If the executed command changes the value of any of @code{READLINE_LINE}, @code{READLINE_POINT}, or @code{READLINE_MARK}, those new values will be reflected in the editing state. @@ -5745,7 +5755,7 @@ builtin prints an error message when the shift count exceeds the number of positional parameters. @item sourcepath -If set, the @code{source} builtin uses the value of @env{PATH} +If set, the @code{.} (@code{source}) builtin uses the value of @env{PATH} to find the directory containing the file supplied as an argument. This option is enabled by default. @@ -6547,6 +6557,11 @@ If @env{RANDOM} is unset, it loses its special properties, even if it is subsequently reset. +@item READLINE_ARGUMENT +Any numeric argument given to a Readline command that was defined using +@samp{bind -x} (@pxref{Bash Builtins} +when it was invoked. + @item READLINE_LINE The contents of the Readline line buffer, for use with @samp{bind -x} (@pxref{Bash Builtins}). diff --git a/doc/version.texi b/doc/version.texi index 13969e8a..6a81da85 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,10 +2,10 @@ Copyright (C) 1988-2021 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Mon May 10 10:12:46 EDT 2021 +@set LASTCHANGE Tue May 18 11:34:00 EDT 2021 @set EDITION 5.1 @set VERSION 5.1 -@set UPDATED 10 May 2021 +@set UPDATED 18 May 2021 @set UPDATED-MONTH May 2021 diff --git a/execute_cmd.c b/execute_cmd.c index 26cf2cb1..54924d3f 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -1477,6 +1477,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) /* If a command is asynchronous in a subshell (like ( foo ) & or the special case of an asynchronous GROUP command where the + the subshell bit is turned on down in case cm_group: below), turn off `asynchronous', so that two subshells aren't spawned. XXX - asynchronous used to be set to 0 in this block, but that @@ -1621,7 +1622,9 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) default_buffered_input = -1; #endif -#if 0 /* TAG: bash-5.2 */ +#if 0 + /* We can't optimize if one of the commands executed by the subshell sets + an exit trap. */ if (user_subshell && command->type == cm_subshell) optimize_subshell_command (command->value.Subshell->command); #endif diff --git a/lib/readline/bind.c b/lib/readline/bind.c index f43baf45..fdd61e9b 100644 --- a/lib/readline/bind.c +++ b/lib/readline/bind.c @@ -880,6 +880,75 @@ rl_function_of_keyseq_len (const char *keyseq, size_t len, Keymap map, int *type return _rl_function_of_keyseq_internal (keyseq, len, map, type); } +/* Assuming there is a numeric argument at the beginning of KEYSEQ (the + caller is responsible for checking), return the index of the portion of + the key sequence following the numeric argument. If there's no numeric + argument (?), or if KEYSEQ consists solely of a numeric argument (?), + return -1. */ +int +rl_trim_arg_from_keyseq (const char *keyseq, size_t len, Keymap map) +{ + register int i, parsing_digits; + unsigned char ic; + + if (map == 0) + map = _rl_keymap; + + /* The digits following the initial one (e.g., the binding to digit-argument) + or the optional `-' in a binding to digit-argument or universal-argument + are not added to rl_executing_keyseq. This is basically everything read by + rl_digit_loop. The parsing_digits logic is here in case they ever are. */ + for (i = parsing_digits = 0; keyseq && i < len; i++) + { + ic = keyseq[i]; + + if (parsing_digits) + { + if (_rl_digit_p (ic) == 0) + return (i); + continue; + } + + if (map[ic].type == ISKMAP) + { + if (i + 1 == len) + return -1; + map = FUNCTION_TO_KEYMAP (map, ic); + continue; + } + if (map[ic].type == ISFUNC) + { + if (map[ic].function != rl_digit_argument && map[ic].function != rl_universal_argument) + return -1; + + /* We don't bother with a keyseq that is only a numeric argument */ + if (i + 1 == len) + return -1; + + parsing_digits = 1; + + /* This logic should be identical to rl_digit_loop */ + /* We accept M-- as equivalent to M--1, C-u- as equivalent to C-u-1 + but set parsing_digits to 2 to note that we saw `-' */ + if (map[ic].function == rl_universal_argument && (i + 1 == '-')) + { + i++; + parsing_digits = 2; + continue; + } + if (map[ic].function == rl_digit_argument && ic == '-') + { + parsing_digits = 2; + continue; + } + } + } + + /* If we're still parsing digits by the time we get here, we don't allow a + key sequence that consists solely of a numeric argument */ + return -1; +} + /* The last key bindings file read. */ static char *last_readline_init_file = (char *)NULL; diff --git a/lib/readline/doc/rltech.texi b/lib/readline/doc/rltech.texi index 0baf588d..d234dd8b 100644 --- a/lib/readline/doc/rltech.texi +++ b/lib/readline/doc/rltech.texi @@ -885,6 +885,15 @@ It takes a "translated" key sequence and should be used if the key sequence can include NUL. @end deftypefun +@deftypefun {int} rl_trim_arg_from_keyseq (const char *keyseq, size_t len, Keymap map) +If there is a numeric argument at the beginning of @var{keyseq}, possibly +including digits, return the index of the first character in @var{keyseq} +following the numeric argument. +This can be used to skip over the numeric argument (which is available as +@code{rl_numeric_arg} while traversing the key sequence that invoked the +current command. +@end deftypefun + @deftypefun {char **} rl_invoking_keyseqs (rl_command_func_t *function) Return an array of strings representing the key sequences used to invoke @var{function} in the current keymap. diff --git a/lib/readline/doc/version.texi b/lib/readline/doc/version.texi index cd0998e8..e90b1e62 100644 --- a/lib/readline/doc/version.texi +++ b/lib/readline/doc/version.texi @@ -4,7 +4,7 @@ Copyright (C) 1988-2021 Free Software Foundation, Inc. @set EDITION 8.1 @set VERSION 8.1 -@set UPDATED 28 April 2021 -@set UPDATED-MONTH April 2021 +@set UPDATED 18 May 2021 +@set UPDATED-MONTH May 2021 -@set LASTCHANGE Wed Apr 28 14:30:42 EDT 2021 +@set LASTCHANGE Tue May 18 11:44:17 EDT 2021 diff --git a/lib/readline/readline.c b/lib/readline/readline.c index 4002fe51..a048d58b 100644 --- a/lib/readline/readline.c +++ b/lib/readline/readline.c @@ -1549,3 +1549,12 @@ _rl_add_executing_keyseq (int key) RESIZE_KEYSEQ_BUFFER (); rl_executing_keyseq[rl_key_sequence_length++] = key; } + +/* `delete' the last character added to the executing key sequence. Use this + before calling rl_execute_next to avoid keys being added twice. */ +void +_rl_del_executing_keyseq (void) +{ + if (rl_key_sequence_length > 0) + rl_key_sequence_length--; +} diff --git a/lib/readline/readline.h b/lib/readline/readline.h index 30684c06..124f57b1 100644 --- a/lib/readline/readline.h +++ b/lib/readline/readline.h @@ -336,6 +336,7 @@ extern char *rl_untranslate_keyseq (int); extern rl_command_func_t *rl_named_function (const char *); extern rl_command_func_t *rl_function_of_keyseq (const char *, Keymap, int *); extern rl_command_func_t *rl_function_of_keyseq_len (const char *, size_t, Keymap, int *); +extern int rl_trim_arg_from_keyseq (const char *, size_t, Keymap); extern void rl_list_funmap_names (void); extern char **rl_invoking_keyseqs_in_map (rl_command_func_t *, Keymap); diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index 86a29127..bda34119 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -379,6 +379,7 @@ extern void _rl_init_executing_keyseq (void); extern void _rl_term_executing_keyseq (void); extern void _rl_end_executing_keyseq (void); extern void _rl_add_executing_keyseq (int); +extern void _rl_del_executing_keyseq (void); /* rltty.c */ extern int _rl_disable_tty_signals (void); diff --git a/lib/sh/input_avail.c b/lib/sh/input_avail.c index 695165fd..2ac44616 100644 --- a/lib/sh/input_avail.c +++ b/lib/sh/input_avail.c @@ -110,7 +110,7 @@ nchars_avail (fd, nchars) #if defined(HAVE_SELECT) fd_set readfds, exceptfds; #endif -#if defined (HAVE_PSELECT) +#if defined (HAVE_PSELECT) || defined (HAVE_SELECT) sigset_t set, oset; #endif diff --git a/parse.y b/parse.y index 7cc00b31..759a08c8 100644 --- a/parse.y +++ b/parse.y @@ -2910,9 +2910,10 @@ static int open_brace_count; break; /* Posix grammar rule 4 */ \ if ((parser_state & PST_CASEPAT) && last_read_token == '(' && word_token_alist[i].token == ESAC) /*)*/ \ break; /* phantom Posix grammar rule 4 */ \ - if (word_token_alist[i].token == ESAC) \ + if (word_token_alist[i].token == ESAC) { \ parser_state &= ~(PST_CASEPAT|PST_CASESTMT); \ - else if (word_token_alist[i].token == CASE) \ + esacs_needed_count--; \ + } else if (word_token_alist[i].token == CASE) \ parser_state |= PST_CASESTMT; \ else if (word_token_alist[i].token == COND_END) \ parser_state &= ~(PST_CONDCMD|PST_CONDEXPR); \ @@ -4902,7 +4903,7 @@ cond_term () dispose_word (yylval.word); /* not needed */ term = cond_term (); if (term) - term->flags |= CMD_INVERT_RETURN; + term->flags ^= CMD_INVERT_RETURN; } else if (tok == WORD && yylval.word->word[0] == '-' && yylval.word->word[1] && yylval.word->word[2] == 0 && test_unop (yylval.word->word)) { @@ -6795,6 +6796,9 @@ save_parser_state (ps) ps->need_here_doc = need_here_doc; ps->here_doc_first_line = here_doc_first_line; + ps->esacs_needed = esacs_needed_count; + ps->expecting_in = expecting_in_token; + if (need_here_doc == 0) ps->redir_stack[0] = 0; else @@ -6857,6 +6861,9 @@ restore_parser_state (ps) need_here_doc = ps->need_here_doc; here_doc_first_line = ps->here_doc_first_line; + esacs_needed_count = ps->esacs_needed; + expecting_in_token = ps->expecting_in; + #if 0 for (i = 0; i < HEREDOC_MAX; i++) redir_stack[i] = ps->redir_stack[i]; diff --git a/parser.h b/parser.h index 59bddaca..f4804d7a 100644 --- a/parser.h +++ b/parser.h @@ -48,6 +48,7 @@ #define PST_REDIRLIST 0x080000 /* parsing a list of redirections preceding a simple command name */ #define PST_COMMENT 0x100000 /* parsing a shell comment; used by aliases */ #define PST_ENDALIAS 0x200000 /* just finished expanding and consuming an alias */ +#define PST_NOEXPAND 0x400000 /* don't expand anything in read_token_word; for command substitution */ /* Definition of the delimiter stack. Needed by parse.y and bashhist.c. */ struct dstack { diff --git a/print_cmd.c b/print_cmd.c index 3c8c2d8f..3c890b22 100644 --- a/print_cmd.c +++ b/print_cmd.c @@ -956,11 +956,13 @@ void print_simple_command (simple_command) SIMPLE_COM *simple_command; { - command_print_word_list (simple_command->words, " "); + if (simple_command->words) + command_print_word_list (simple_command->words, " "); if (simple_command->redirects) { - cprintf (" "); + if (simple_command->words) + cprintf (" "); print_redirection_list (simple_command->redirects); } } diff --git a/redir.c b/redir.c index 815c1431..7a762bea 100644 --- a/redir.c +++ b/redir.c @@ -807,8 +807,18 @@ do_redirection_internal (redirect, flags, fnp) continue. */ redirectee_word = redirection_expand (redirectee); +#if 0 + /* TAG:bash-5.2 */ /* XXX - what to do with [N]<&$w- where w is unset or null? ksh93 - closes N. */ + turns it into [N]<&- or [N]>&- and closes N. */ + if ((ri == r_move_input_word || ri == r_move_output_word) && redirectee_word == 0) + { + sd = redirect->redirector; + rd.dest = 0; + new_redirect = make_redirection (sd, r_close_this, rd, 0); + } + else +#endif if (redirectee_word == 0) return (AMBIGUOUS_REDIRECT); else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0') diff --git a/shell.h b/shell.h index 06efc946..af3d7da3 100644 --- a/shell.h +++ b/shell.h @@ -205,6 +205,9 @@ typedef struct _sh_parser_state_t int need_here_doc; int here_doc_first_line; + int esacs_needed; + int expecting_in; + /* structures affecting the parser */ void *pushed_strings; REDIRECT *redir_stack[HEREDOC_MAX]; diff --git a/tests/comsub-eof.right b/tests/comsub-eof.right index 42677985..55261512 100644 --- a/tests/comsub-eof.right +++ b/tests/comsub-eof.right @@ -1,5 +1,5 @@ -./comsub-eof0.sub: line 1: unexpected EOF while looking for matching `)' -./comsub-eof0.sub: line 5: syntax error: unexpected end of file +./comsub-eof0.sub: line 3: unexpected EOF while looking for matching `)' +./comsub-eof0.sub: line 7: syntax error: unexpected end of file hi ./comsub-eof2.sub: line 2: warning: here-document at line 1 delimited by end-of-file (wanted `EOF') hi @@ -11,5 +11,7 @@ contents hi ./comsub-eof5.sub: line 13: warning: here-document at line 11 delimited by end-of-file (wanted `EOF') hi +./comsub-eof5.sub: line 19: warning: here-document at line 17 delimited by end-of-file (wanted `)') +./comsub-eof5.sub: line 15: unexpected EOF while looking for matching `)' ./comsub-eof6.sub: line 1: unexpected EOF while looking for matching `)' diff --git a/tests/comsub-eof0.sub b/tests/comsub-eof0.sub index 7b0775fb..7490faab 100644 --- a/tests/comsub-eof0.sub +++ b/tests/comsub-eof0.sub @@ -1,3 +1,5 @@ +# it's only the space before the paren that makes this an error +# when I fix it, it will show up here foo=$(cat < argv[1] = <'A^IB'> argv[1] = argv[1] = <$'a\tb\tc'> + AD +E hello' world hello world! hello' world! diff --git a/tests/nquote.tests b/tests/nquote.tests index 958f5c75..c3b86e31 100644 --- a/tests/nquote.tests +++ b/tests/nquote.tests @@ -132,6 +132,9 @@ recho "$( args $'A\tB' )" recho $'a\tb\tc' recho "$'a\tb\tc'" +# tests for $'...' being expanded in command substitution, and when +echo "$(echo $'\t\t\101\104\n\105')" + ${THIS_SH} ./nquote1.sub ${THIS_SH} ./nquote2.sub ${THIS_SH} ./nquote3.sub diff --git a/tests/printf2.sub b/tests/printf2.sub index 45c48d4c..94a2bb10 100644 --- a/tests/printf2.sub +++ b/tests/printf2.sub @@ -1,6 +1,12 @@ unset LC_ALL LC_CTYPE -export LANG=en_US.UTF-8 +export LANG=C +case $(printf %d\\n \'A) in +65) ;; +*) echo "printf2.sub: character conversion failed" >&2 ;; +esac + +export LANG=en_US.UTF-8 case $(printf %d\\n \'À) in 192) exit 0;; *) echo "printf2.sub: multibyte character conversion failed" >&2 ; exit 2 ;;