From 7910c04f143976600f0699f606818b38fe25b55e Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Fri, 24 Apr 2020 18:07:42 -0400 Subject: [PATCH] commit bash-20200422 snapshot --- CWRU/CWRU.chlog | 44 +++++++++++++++++++++++++++++++++++++ doc/bashref.texi | 7 ++++++ examples/loadables/lcut.c | 21 +----------------- expr.c | 2 ++ jobs.c | 10 +++++++-- lib/readline/isearch.c | 17 +++++++++++++++ lib/readline/kill.c | 2 +- lib/readline/search.c | 46 ++++++++++++++++++++++++++++++++++----- parse.y | 14 +++++++++--- tests/comsub-posix.right | 4 ++++ tests/comsub-posix.tests | 15 +++++++++++++ tests/comsub-posix4.sub | 24 ++++++++++++++++++++ 12 files changed, 175 insertions(+), 31 deletions(-) create mode 100644 tests/comsub-posix4.sub diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index fbd09a271..262763b6e 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -8141,3 +8141,47 @@ lib/readline/isearch.c - _rl_isearch_dispatch: do translation for keys that map to rl_do_lowercase_version like we do when dispatching while reading a key sequence + + 4/23 + ---- +lib/readline/isearch.c + - _rl_isearch_dispatch: if bracketed paste mode is enabled and there are + enough characters waiting in the terminal's input queue, try to read + the bracketed paste prefix and jump straight to the opcode execution + if we read it. Otherwise, just go on with the ESC. Inspired by report + from + +parse.y + - parse_comsub: posix-mode shells don't allow a closing right paren to + delimit a pending here-document -- it requires the newline + +doc/bashref.texi + - POSIX mode: updated posix mode description with the new here-document + delimiter requirement + +lib/readline/search.c + - _rl_nsearch_dispatch: if bracketed paste mode is enabled, and we read + an ESC, try to see if we have a bracketed paste op and insert the + pasted next. If we don't, go on with the ESC + - _rl_nsearch_dosearch: experimental code to highlight the search string + when displaying the line found in the history. Only done when we are + not searching for a pattern, since we don't have information on the + end of the matching portion of the line. Experimental because it + changes where we put point and mark if searching is successful + +expr.c + - expr_streval: if find_variable for the case where the string is not + an array reference doesn't find anything, see if we can find + something by using find_variable_last_nameref and use the value + from there in the call to expr_streval, kind of using the expression + recursion to complement the nameref recursion. Report from + Daniel Molina + + 4/24 + ---- +jobs.c + - {start,stop}_pipeline: don't reset pipeline_pgrp to 0 if it's already + the same as shell_pgrp, since we don't want to reset it in the middle + of a shell started to run a command or process substitution (after + forking a child to run one command, but before forking another, for + instance). Reported by Rob Landley diff --git a/doc/bashref.texi b/doc/bashref.texi index 2014440e7..b4ed2330a 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -7786,6 +7786,13 @@ not have to appear as matched pairs. The parser does not recognize @code{time} as a reserved word if the next token begins with a @samp{-}. +@ignore +@item +When parsing @code{$()} command substitutions containing here-documents, +the parser does not allow a here-document to be delimited by the closing +right parenthesis. The newline after the here-document delimiter is required. +@end ignore + @item The @samp{!} character does not introduce history expansion within a double-quoted string, even if the @code{histexpand} option is enabled. diff --git a/examples/loadables/lcut.c b/examples/loadables/lcut.c index 4dfc09142..18d5f375d 100644 --- a/examples/loadables/lcut.c +++ b/examples/loadables/lcut.c @@ -454,7 +454,7 @@ cut_internal (which, list) return (EXECUTION_FAILURE); } - if (list == 0) + if (list == 0 && which == 0) { builtin_error ("string argument required"); return (EX_USAGE); @@ -505,9 +505,6 @@ cut_internal (which, list) op.npos = npos; op.poslist = poslist; - /* we can eventually implement cut as a builtin with a cutfile() function - that opens cutstring as a filename (or `-' for stdin) and runs cutline - on every line in the file. */ if (which == 0) rval = cutline (v, cutstring, &op); @@ -521,22 +518,6 @@ lcut_builtin (list) return (cut_internal (0, list)); } -/* Called when builtin is enabled and loaded from the shared object. If this - function returns 0, the load fails. */ -int -lcut_builtin_load (name) - char *name; -{ - return (1); -} - -/* Called when builtin is disabled. */ -void -lcut_builtin_unload (name) - char *name; -{ -} - char *lcut_doc[] = { "Extract selected fields from a string.", "", diff --git a/expr.c b/expr.c index b323d3efe..66c04afd1 100644 --- a/expr.c +++ b/expr.c @@ -1168,6 +1168,8 @@ expr_streval (tok, e, lvalue) #else v = find_variable (tok); #endif + if (v == 0 && e != ']') + v = find_variable_last_nameref (tok, 0); if ((v == 0 || invisible_p (v)) && unbound_vars_is_error) { diff --git a/jobs.c b/jobs.c index b791900de..f98e2e60c 100644 --- a/jobs.c +++ b/jobs.c @@ -519,7 +519,12 @@ start_pipeline () if (the_pipeline) { cleanup_the_pipeline (); - pipeline_pgrp = 0; + /* If job_control == 0, pipeline_pgrp will always be equal to shell_pgrp; + if job_control != 0, pipeline_pgrp == shell_pgrp for command and + process substitution, in which case we want it to be the same as + shell_pgrp for the lifetime of this shell instance. */ + if (pipeline_pgrp != shell_pgrp) + pipeline_pgrp = 0; #if defined (PGRP_PIPE) sh_closepipe (pgrp_pipe); #endif @@ -632,7 +637,8 @@ stop_pipeline (async, deferred) the_pipeline = (PROCESS *)NULL; newjob->pgrp = pipeline_pgrp; - pipeline_pgrp = 0; + if (pipeline_pgrp != shell_pgrp) + pipeline_pgrp = 0; newjob->flags = 0; if (pipefail_opt) diff --git a/lib/readline/isearch.c b/lib/readline/isearch.c index 026c2d7c3..201a37bbc 100644 --- a/lib/readline/isearch.c +++ b/lib/readline/isearch.c @@ -355,6 +355,22 @@ _rl_isearch_dispatch (_rl_search_cxt *cxt, int c) _rl_add_executing_keyseq (c); + /* XXX - experimental code to allow users to bracketed-paste into the search + string even when ESC is one of the isearch-terminators. Not perfect yet. */ + if (_rl_enable_bracketed_paste && c == ESC && strchr (cxt->search_terminators, c) && (n = _rl_nchars_available ()) > (2*BRACK_PASTE_SLEN-1)) + { + j = _rl_read_bracketed_paste_prefix (c); + if (j == 1) + { + cxt->lastc = -7; /* bracketed paste, see below */ + goto opcode_dispatch; + } + else if (_rl_pushed_input_available ()) /* eat extra char we pushed back */ + c = cxt->lastc = rl_read_key (); + else + c = cxt->lastc; /* last ditch */ + } + /* If we are moving into a new keymap, modify cxt->keymap and go on. This can be a problem if c == ESC and we want to terminate the incremental search, so we check */ @@ -531,6 +547,7 @@ add_character: _rl_init_executing_keyseq (); +opcode_dispatch: /* Now dispatch on the character. `Opcodes' affect the search string or state. Other characters are added to the string. */ switch (cxt->lastc) diff --git a/lib/readline/kill.c b/lib/readline/kill.c index e65e988ec..5366445e2 100644 --- a/lib/readline/kill.c +++ b/lib/readline/kill.c @@ -1,6 +1,6 @@ /* kill.c -- kill ring management. */ -/* Copyright (C) 1994-2019 Free Software Foundation, Inc. +/* Copyright (C) 1994-2020 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. diff --git a/lib/readline/search.c b/lib/readline/search.c index d3920d4b6..ab65a3752 100644 --- a/lib/readline/search.c +++ b/lib/readline/search.c @@ -1,6 +1,6 @@ /* search.c - code for non-incremental searching in emacs and vi modes. */ -/* Copyright (C) 1992-2017 Free Software Foundation, Inc. +/* Copyright (C) 1992-2020 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. @@ -159,7 +159,7 @@ noninc_search_from_pos (char *string, int pos, int dir, int flags, int *ncp) static int noninc_dosearch (char *string, int dir, int flags) { - int oldpos, pos; + int oldpos, pos, ind; HIST_ENTRY *entry; if (string == 0 || *string == '\0' || noninc_history_pos < 0) @@ -168,7 +168,7 @@ noninc_dosearch (char *string, int dir, int flags) return 0; } - pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, (int *)0); + pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, &ind); if (pos == -1) { /* Search failed, current history position unchanged. */ @@ -192,8 +192,19 @@ noninc_dosearch (char *string, int dir, int flags) make_history_line_current (entry); - rl_point = 0; - rl_mark = rl_end; + if (_rl_enable_bracketed_paste && ((flags & SF_PATTERN) == 0) && ind > 0 && ind < rl_end) + { + rl_point = ind; + rl_mark = ind + strlen (string); + if (rl_mark > rl_end) + rl_mark = rl_end; /* can't happen? */ + rl_activate_mark (); + } + else + { + rl_point = 0; + rl_mark = rl_end; + } rl_clear_message (); return 1; @@ -268,6 +279,8 @@ _rl_nsearch_abort (_rl_search_cxt *cxt) static int _rl_nsearch_dispatch (_rl_search_cxt *cxt, int c) { + int n; + if (c < 0) c = CTRL ('C'); @@ -301,6 +314,28 @@ _rl_nsearch_dispatch (_rl_search_cxt *cxt, int c) _rl_nsearch_abort (cxt); return -1; + case ESC: + /* XXX - experimental code to allow users to bracketed-paste into the + search string. Similar code is in isearch.c:_rl_isearch_dispatch(). + The difference here is that the bracketed paste sometimes doesn't + paste everything, so checking for the prefix and the suffix in the + input queue doesn't work well. We just have to check to see if the + number of chars in the input queue is enough for the bracketed paste + prefix and hope for the best. */ + if (_rl_enable_bracketed_paste && ((n = _rl_nchars_available ()) >= (BRACK_PASTE_SLEN-1))) + { + if (_rl_read_bracketed_paste_prefix (c) == 1) + rl_bracketed_paste_begin (1, c); + else + { + c = rl_read_key (); /* get the ESC that got pushed back */ + _rl_insert_char (1, c); + } + } + else + _rl_insert_char (1, c); + break; + default: #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) @@ -312,6 +347,7 @@ _rl_nsearch_dispatch (_rl_search_cxt *cxt, int c) } (*rl_redisplay_function) (); + rl_deactivate_mark (); return 1; } diff --git a/parse.y b/parse.y index 0892ef142..c5d9b93cd 100644 --- a/parse.y +++ b/parse.y @@ -3987,8 +3987,9 @@ eof_error: if (ch == '\n' && SHOULD_PROMPT ()) prompt_again (); - /* XXX -- possibly allow here doc to be delimited by ending right - paren. */ + /* XXX -- we currently allow here doc to be delimited by ending right + paren in default mode and posix mode. To change posix mode, change + the #if 1 to #if 0 below */ if ((tflags & LEX_INHEREDOC) && ch == close && count == 1) { int tind; @@ -3996,7 +3997,14 @@ eof_error: tind = lex_firstind; while ((tflags & LEX_STRIPDOC) && ret[tind] == '\t') tind++; - if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen)) +#if 1 + if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen)) +#else + /* Posix-mode shells require the newline after the here-document + delimiter. */ + if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen) && + posixly_correct == 0) +#endif { tflags &= ~(LEX_STRIPDOC|LEX_INHEREDOC|LEX_QUOTEDDOC); /*itrace("parse_comsub:%d: found here doc end `%*s'", line_number, hdlen, ret + tind);*/ diff --git a/tests/comsub-posix.right b/tests/comsub-posix.right index 2290aa6dc..9aebb8482 100644 --- a/tests/comsub-posix.right +++ b/tests/comsub-posix.right @@ -3,6 +3,7 @@ abmnopyz ab +abcd abcd sh_352.26ax sh_352.26ay @@ -47,11 +48,14 @@ after 5 after 6 x x +x quoted ) comment here-doc with ) +here-doc with \() here-doc terminated with a parenthesis ' # or a single back- or doublequote +line terminated with a backslash ./comsub-posix1.sub: command substitution: line 2: syntax error near unexpected token `)' ./comsub-posix1.sub: command substitution: line 2: ` if x; then echo foo )' after diff --git a/tests/comsub-posix.tests b/tests/comsub-posix.tests index 2922a9c56..4fe1dfaa1 100644 --- a/tests/comsub-posix.tests +++ b/tests/comsub-posix.tests @@ -27,6 +27,7 @@ echo $( ) echo $() echo ab$()cd +echo ab$( )cd echo $(case a in (a) echo sh_352.26ax; esac ) echo $(case a in (a) echo sh_352.26ay; esac) @@ -180,6 +181,10 @@ echo $( case x in x) echo x;; esac ) +echo $( + case x in x) echo x;; esac # followed by a comment +) + echo $( case x in (x) echo x;; esac ) @@ -198,6 +203,12 @@ cat <<\eof eof ) +echo $( + cat <<\eof + here-doc with \() +eof +) + echo $( cat <<\) here-doc terminated with a parenthesis @@ -210,6 +221,10 @@ cat <<\eof eof ) +echo $( + echo line terminated with a backslash # \ +) + ${THIS_SH} ./comsub-posix1.sub ${THIS_SH} ./comsub-posix2.sub diff --git a/tests/comsub-posix4.sub b/tests/comsub-posix4.sub new file mode 100644 index 000000000..edd247652 --- /dev/null +++ b/tests/comsub-posix4.sub @@ -0,0 +1,24 @@ +: ${THIS_SH:=./bash} +set -o posix + +# tests from Sven Mascheck that check whether a here-doc in a command +# substitution can be terminated by EOF (the closing paren) +# +# currently unused + +# Example D.3 # should fail with unterminated here-doc +${THIS_SH} -o posix -c 'echo $( + cat <<\eof + D.3: here-doc with ) +eof)' + +# Example D.4 +# the first EOF has a trailing blank +# the third EOF is the correct one +echo $(cat <<'EOF' + D.4 error-prone use of here-doc terminator +EOF +EOF) +EOF +) +echo after here-document -- 2.47.2