From a078e04c3d9163541cce590c3fd00f243fe77613 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 9 Jul 2018 10:35:17 -0400 Subject: [PATCH] commit bash-20180628 snapshot --- CWRU/CWRU.chlog | 53 ++++++++++++++++++++++++++++++++++- MANIFEST | 1 + bashhist.c | 23 +++++++++++++-- configure | 31 +++++++++++--------- configure.ac | 33 +++++++++++++--------- general.h | 7 +++++ lib/readline/doc/hstech.texi | 22 +++++++++++++-- lib/readline/doc/hsuser.texi | 18 +++++++++--- lib/readline/doc/version.texi | 12 ++++---- lib/readline/histexpand.c | 45 +++++++++++++++++++++++++++-- lib/readline/history.h | 2 ++ parse.y | 11 ++++---- tests/histexp.right | 15 ++++++++++ tests/histexp.tests | 1 + tests/histexp6.sub | 23 +++++++++++++++ 15 files changed, 246 insertions(+), 51 deletions(-) create mode 100644 tests/histexp6.sub diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 69a8ffce..665bb883 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -3424,7 +3424,7 @@ lib/readline/bind.c takes a length parameter; otherwise equivalent to rl_function_of_keyseq. lib/readline/readline.h - - rl_function_of_keyseq_len: add extern declration for new function + - rl_function_of_keyseq_len: add extern declaration for new function lib/readline/doc/rltech.texi - rl_function_of_keyseq_len: document new function interface @@ -3873,3 +3873,54 @@ variables.c function) without enabling debugging mode and not having initialized the variable previously (using a simple semaphore), create the variables + + 6/25 + ---- +configure.ac + - opt_bash_malloc: bash malloc no longer disabled for systems that + require eight-bit alignment; the bash malloc has had this for a + long time + + 7/4 + --- +bashline.c + - pre_process_line: if command-oriented history is enabled, and the + line being expanded is the second or later in a multi-line command, + and we know the command is being saved as the current history entry, + decrease history_length before calling history_expand so references + like !! refer to the previous history entry as usual + +lib/readline/histexpand.c + - history_quoting_state: new variable, can be set by calling + application before calling history_expand to note that the string + being expanded is part of a quoted string. Can be set to a single + quote, a double quote, or 0 (no quoting) + - history_expand: look at history_quoting_state and honor the + single-quote setting by not expanding any initial portion of the + line before the closing single quote. This allows history expansions + to be performed on a line containing a closing single quote if they + appear after the single quote + +lib/readline/history.h + - history_quoting_state: extern declaration + +bashhist.c + - bash_history_inhibit_expansion: if history_quoting_state indicates + that this string is single-quoted, skip over the single-quoted + portion and determine whether or not the portion after the + quoted string needs to be inhibited from history expansion + +parse.y + - shell_getc: set history_quoting_state based on the contents of the + current delimiter before calling pre_process_line + + 7/6 + --- +lib/readline/doc/hsuser.texi + - describe the default behavior of backslash and single and double + quotes + +lib/readline/doc/hstech.texi + - history_quoting_state: describe effect of setting this variable + - history_quotes_inihibit_expansion: expand the description to include + the default quoting behavior that setting this variable enables diff --git a/MANIFEST b/MANIFEST index cde3410f..61f7cbf1 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1074,6 +1074,7 @@ tests/histexp2.sub f tests/histexp3.sub f tests/histexp4.sub f tests/histexp5.sub f +tests/histexp6.sub f tests/histexp.right f tests/history.tests f tests/history.right f diff --git a/bashhist.c b/bashhist.c index 1672f139..7912cce3 100644 --- a/bashhist.c +++ b/bashhist.c @@ -213,7 +213,7 @@ bash_history_inhibit_expansion (string, i) char *string; int i; { - int t; + int t, si; char hx[2]; hx[0] = history_expansion_char; @@ -236,9 +236,20 @@ bash_history_inhibit_expansion (string, i) return (1); #endif + si = 0; + /* If we're supposed to be in single-quoted string, skip over the + single-quoted part and then look at what's left. */ + if (history_quoting_state == '\'') + { + si = skip_to_delim (string, 0, "'", SD_NOJMP|SD_HISTEXP); + if (string[si] == 0 || si >= i) + return (1); + si++; + } + /* Make sure the history expansion should not be skipped by quoting or command/process substitution. */ - else if ((t = skip_to_histexp (string, 0, hx, SD_NOJMP|SD_HISTEXP)) > 0) + if ((t = skip_to_histexp (string, si, hx, SD_NOJMP|SD_HISTEXP)) > 0) { /* Skip instances of history expansion appearing on the line before this one. */ @@ -549,7 +560,15 @@ pre_process_line (line, print_changes, addit) add that line to the history if ADDIT is non-zero. */ if (!history_expansion_inhibited && history_expansion && history_expansion_p (line)) { + /* If we are expanding the second or later line of a multi-line + command, decrease history_length so references to history expansions + in these lines refer to the previous history entry and not the + current command. */ + if (history_length > 0 && command_oriented_history && current_command_first_line_saved && current_command_line_count > 1) + history_length--; expanded = history_expand (line, &history_value); + if (history_length >= 0 && command_oriented_history && current_command_first_line_saved && current_command_line_count > 1) + history_length++; if (expanded) { diff --git a/configure b/configure index 4ad952b6..73c1ce1a 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac for Bash 5.0, version 4.092. +# From configure.ac for Bash 5.0, version 4.094. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for bash 5.0-alpha. # @@ -2847,33 +2847,38 @@ opt_with_installed_readline=no #htmldir= case "${host_cpu}-${host_os}" in +# mostly obsolete platforms alpha*-*) opt_bash_malloc=no ;; # alpha running osf/1 or linux *[Cc]ray*-*) opt_bash_malloc=no ;; # Crays *-osf1*) opt_bash_malloc=no ;; # other osf/1 machines +*-dgux*) opt_bash_malloc=no ;; # DG/UX machines sparc-svr4*) opt_bash_malloc=no ;; # sparc SVR4, SVR4.2 -sparc-netbsd*) opt_bash_malloc=no ;; # needs 8-byte alignment -mips-irix6*) opt_bash_malloc=no ;; # needs 8-byte alignment m68k-sysv) opt_bash_malloc=no ;; # fixes file descriptor leak in closedir +*-bsdi2.1|*-bsdi3.?) opt_bash_malloc=no ; : ${CC:=shlicc2} ;; # for loadable builtins +*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft +*-beos*) opt_bash_malloc=no ;; # they say it's suitable +# These need additional investigation sparc-linux*) opt_bash_malloc=no ;; # sparc running linux; requires ELF -#*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here -#*-freebsd*) opt_bash_malloc=no ;; # they claim it's better; I disagree -*-openbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment -*-mirbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment *-aix*) opt_bash_malloc=no ;; # AIX machines +*-cygwin*) opt_bash_malloc=no ;; # Cygnus's CYGWIN environment +# Mach-derived systems have a ton of extra malloc functions and lack sbrk(2) *-nextstep*) opt_bash_malloc=no ;; # NeXT machines running NeXTstep *-openstep*) opt_bash_malloc=no ;; # i386/Sparc/HP machines running Openstep *-macos*) opt_bash_malloc=no ;; # Apple MacOS X *-rhapsody*) opt_bash_malloc=no ;; # Apple Rhapsody (MacOS X) *-darwin*) opt_bash_malloc=no ;; # Apple Darwin (MacOS X) -*-dgux*) opt_bash_malloc=no ;; # DG/UX machines -*-qnx*) opt_bash_malloc=no ;; # QNX 4.2, QNX [67].x *-machten4) opt_bash_malloc=no ;; # MachTen 4.x -*-bsdi2.1|*-bsdi3.?) opt_bash_malloc=no ; : ${CC:=shlicc2} ;; # for loadable builtins -*-beos*) opt_bash_malloc=no ;; # they say it's suitable -*-cygwin*) opt_bash_malloc=no ;; # Cygnus's CYGWIN environment -*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft +# Niche or non-mainstream-shell-user systems +*-qnx*) opt_bash_malloc=no ;; # QNX 4.2, QNX [67].x *-nsk*) opt_bash_malloc=no ;; # HP NonStop *-haiku*) opt_bash_malloc=no ;; # Haiku OS +# Deprecated -- bash malloc is suitable +#sparc-netbsd*) opt_bash_malloc=no ;; # needs 8-byte alignment +#mips-irix6*) opt_bash_malloc=no ;; # needs 8-byte alignment +#*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here +#*-freebsd*) opt_bash_malloc=no ;; # they claim it's better; I disagree +#*-openbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment +#*-mirbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment esac # memory scrambling on free() diff --git a/configure.ac b/configure.ac index d3287d98..005dddc3 100644 --- a/configure.ac +++ b/configure.ac @@ -5,7 +5,7 @@ dnl report bugs to chet@po.cwru.edu dnl dnl Process this file with autoconf to produce a configure script. -# Copyright (C) 1987-2016 Free Software Foundation, Inc. +# Copyright (C) 1987-2018 Free Software Foundation, Inc. # # This program is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script. # You should have received a copy of the GNU General Public License # along with this program. If not, see . -AC_REVISION([for Bash 5.0, version 4.092])dnl +AC_REVISION([for Bash 5.0, version 4.094])dnl define(bashvers, 5.0) define(relstatus, alpha) @@ -63,33 +63,38 @@ dnl some systems should be configured without the bash malloc by default dnl and some need a special compiler or loader dnl look in the NOTES file for more case "${host_cpu}-${host_os}" in +# mostly obsolete platforms alpha*-*) opt_bash_malloc=no ;; # alpha running osf/1 or linux *[[Cc]]ray*-*) opt_bash_malloc=no ;; # Crays *-osf1*) opt_bash_malloc=no ;; # other osf/1 machines +*-dgux*) opt_bash_malloc=no ;; # DG/UX machines sparc-svr4*) opt_bash_malloc=no ;; # sparc SVR4, SVR4.2 -sparc-netbsd*) opt_bash_malloc=no ;; # needs 8-byte alignment -mips-irix6*) opt_bash_malloc=no ;; # needs 8-byte alignment m68k-sysv) opt_bash_malloc=no ;; # fixes file descriptor leak in closedir +*-bsdi2.1|*-bsdi3.?) opt_bash_malloc=no ; : ${CC:=shlicc2} ;; # for loadable builtins +*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft +*-beos*) opt_bash_malloc=no ;; # they say it's suitable +# These need additional investigation sparc-linux*) opt_bash_malloc=no ;; # sparc running linux; requires ELF -#*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here -#*-freebsd*) opt_bash_malloc=no ;; # they claim it's better; I disagree -*-openbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment -*-mirbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment *-aix*) opt_bash_malloc=no ;; # AIX machines +*-cygwin*) opt_bash_malloc=no ;; # Cygnus's CYGWIN environment +# Mach-derived systems have a ton of extra malloc functions and lack sbrk(2) *-nextstep*) opt_bash_malloc=no ;; # NeXT machines running NeXTstep *-openstep*) opt_bash_malloc=no ;; # i386/Sparc/HP machines running Openstep *-macos*) opt_bash_malloc=no ;; # Apple MacOS X *-rhapsody*) opt_bash_malloc=no ;; # Apple Rhapsody (MacOS X) *-darwin*) opt_bash_malloc=no ;; # Apple Darwin (MacOS X) -*-dgux*) opt_bash_malloc=no ;; # DG/UX machines -*-qnx*) opt_bash_malloc=no ;; # QNX 4.2, QNX [67].x *-machten4) opt_bash_malloc=no ;; # MachTen 4.x -*-bsdi2.1|*-bsdi3.?) opt_bash_malloc=no ; : ${CC:=shlicc2} ;; # for loadable builtins -*-beos*) opt_bash_malloc=no ;; # they say it's suitable -*-cygwin*) opt_bash_malloc=no ;; # Cygnus's CYGWIN environment -*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft +# Niche or non-mainstream-shell-user systems +*-qnx*) opt_bash_malloc=no ;; # QNX 4.2, QNX [67].x *-nsk*) opt_bash_malloc=no ;; # HP NonStop *-haiku*) opt_bash_malloc=no ;; # Haiku OS +# Deprecated -- bash malloc is suitable +#sparc-netbsd*) opt_bash_malloc=no ;; # needs 8-byte alignment +#mips-irix6*) opt_bash_malloc=no ;; # needs 8-byte alignment +#*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here +#*-freebsd*) opt_bash_malloc=no ;; # they claim it's better; I disagree +#*-openbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment +#*-mirbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment esac # memory scrambling on free() diff --git a/general.h b/general.h index 14cbe833..d89eec8e 100644 --- a/general.h +++ b/general.h @@ -110,6 +110,13 @@ extern char *strcpy __P((char *, const char *)); ((TYPE_WIDTH (t) - TYPE_SIGNED (t)) * 302 / 1000 \ + 1 + TYPE_SIGNED (t)) +/* Updated version adapted from gnulib/intprops.h, not used right now. + Changes the approximation of log10(2) from 302/1000 to 146/485. */ +#if 0 +#define INT_STRLEN_BOUND(t) \ + (INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - TYPE_SIGNED (t)) + TYPE_SIGNED(t)) +#endif + /* Bound on buffer size needed to represent an integer type or expression T, including the terminating null. */ #define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) diff --git a/lib/readline/doc/hstech.texi b/lib/readline/doc/hstech.texi index d28bd485..dbc21c14 100644 --- a/lib/readline/doc/hstech.texi +++ b/lib/readline/doc/hstech.texi @@ -403,7 +403,7 @@ to the ``normal'' terminating characters. Return an array of tokens parsed out of @var{string}, much as the shell might. The tokens are split on the characters in the @var{history_word_delimiters} variable, -and shell quoting conventions are obeyed. +and shell quoting conventions are obeyed as described below. @end deftypefun @deftypefun {char *} history_arg_extract (int first, int last, const char *string) @@ -476,8 +476,24 @@ carriage return, and @samp{=}. @end deftypevar @deftypevar int history_quotes_inhibit_expansion -If non-zero, double-quoted words are not scanned for the history expansion -character or the history comment character. The default value is 0. +If non-zero, the history expansion code implements shell-like quoting: +single-quoted words are not scanned for the history expansion +character or the history comment character, and double-quoted words may +have history expansion performed, since single quotes are not special +within double quotes. +The default value is 0. +@end deftypevar + +@deftypevar int history_quoting_state +An application may set this variable to indicate that the current line +being expanded is subject to existing quoting. If set to @samp{'}, the +history expansion function will assume that the line is single-quoted and +inhibit expansion until it reads an unquoted closing single quote; if set +to @samp{"}, history expansion will assume the line is double quoted until +it reads an unquoted closing double quote. If set to zero, the default, +the history expansion function will assume the line is not quoted and +treat quote characters within the line as described above. +This is only effective if @var{history_quotes_inhibit_expansion} is set. @end deftypevar @deftypevar {rl_linebuf_func_t *} history_inhibit_expansion_function diff --git a/lib/readline/doc/hsuser.texi b/lib/readline/doc/hsuser.texi index d21f65d0..521ccc70 100644 --- a/lib/readline/doc/hsuser.texi +++ b/lib/readline/doc/hsuser.texi @@ -262,8 +262,8 @@ fix errors in previous commands quickly. @ifset BashFeatures History expansion is performed immediately after a complete line is read, before the shell breaks it into words, and is performed -on each line individually without taking quoting on previous lines into -account. +on each line individually. Bash attempts to inform the history +expansion functions about quoting still in effect from previous lines. @end ifset History expansion takes place in two parts. The first is to determine @@ -277,9 +277,19 @@ that Bash does, so that several words surrounded by quotes are considered one word. History expansions are introduced by the appearance of the history expansion character, which is @samp{!} by default. + +History expansion implements shell-like quoting conventions: +a backslash can be used to remove the special handling for the next character; +single quotes enclose verbatim sequences of characters, and can be used to +inhibit history expansion; +and characters enclosed within double quotes may be subject to history +expansion, since backslash can escape the history expansion character, +but single quotes may not, since they are not treated specially within +double quotes. + @ifset BashFeatures -Only @samp{\} and @samp{'} may be used to escape the history expansion -character, but the history expansion character is +When using the shell, only @samp{\} and @samp{'} may be used to escape the +history expansion character, but the history expansion character is also treated as quoted if it immediately precedes the closing double quote in a double-quoted string. @end ifset diff --git a/lib/readline/doc/version.texi b/lib/readline/doc/version.texi index 9fefcfae..79f41917 100644 --- a/lib/readline/doc/version.texi +++ b/lib/readline/doc/version.texi @@ -1,10 +1,10 @@ @ignore -Copyright (C) 1988-2017 Free Software Foundation, Inc. +Copyright (C) 1988-2018 Free Software Foundation, Inc. @end ignore -@set EDITION 7.0 -@set VERSION 7.0 -@set UPDATED 28 December 2017 -@set UPDATED-MONTH December 2017 +@set EDITION 8.0 +@set VERSION 8.0 +@set UPDATED 6 July 2018 +@set UPDATED-MONTH July 2018 -@set LASTCHANGE Thu Dec 28 14:44:16 EST 2017 +@set LASTCHANGE Fri Jul 6 16:25:22 MDT 2018 diff --git a/lib/readline/histexpand.c b/lib/readline/histexpand.c index 34007796..92b996f9 100644 --- a/lib/readline/histexpand.c +++ b/lib/readline/histexpand.c @@ -1,6 +1,6 @@ /* histexpand.c -- history expansion. */ -/* Copyright (C) 1989-2017 Free Software Foundation, Inc. +/* Copyright (C) 1989-2018 Free Software Foundation, Inc. This file contains the GNU History Library (History), a set of routines for managing the text of previously typed lines. @@ -107,6 +107,8 @@ char *history_word_delimiters = HISTORY_WORD_DELIMITERS; particular history expansion should be performed. */ rl_linebuf_func_t *history_inhibit_expansion_function; +int history_quoting_state = 0; + /* **************************************************************** */ /* */ /* History Expansion */ @@ -961,7 +963,22 @@ history_expand (char *hstring, char **output) /* `!' followed by one of the characters in history_no_expand_chars is NOT an expansion. */ - for (i = dquote = squote = 0; string[i]; i++) + dquote = history_quoting_state == '"'; + squote = history_quoting_state == '\''; + + /* If the calling application tells us we are already reading a + single-quoted string, consume the rest of the string right now + and then go on. */ + i = 0; + if (squote && history_quotes_inhibit_expansion) + { + hist_string_extract_single_quoted (string, &i, 0); + squote = 0; + if (string[i]) + i++; + } + + for ( ; string[i]; i++) { #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) @@ -1049,7 +1066,29 @@ history_expand (char *hstring, char **output) } /* Extract and perform the substitution. */ - for (passc = dquote = squote = i = j = 0; i < l; i++) + dquote = history_quoting_state == '"'; + squote = history_quoting_state == '\''; + + /* If the calling application tells us we are already reading a + single-quoted string, consume the rest of the string right now + and then go on. */ + i = j = 0; + if (squote && history_quotes_inhibit_expansion) + { + int c; + + hist_string_extract_single_quoted (string, &i, 0); + squote = 0; + for (c = 0; c < i; c++) + ADD_CHAR (string[c]); + if (string[i]) + { + ADD_CHAR (string[i]); + i++; + } + } + + for (passc = 0; i < l; i++) { int qc, tchar = string[i]; diff --git a/lib/readline/history.h b/lib/readline/history.h index fceb99ca..cc3de29a 100644 --- a/lib/readline/history.h +++ b/lib/readline/history.h @@ -261,7 +261,9 @@ extern char *history_word_delimiters; extern char history_comment_char; extern char *history_no_expand_chars; extern char *history_search_delimiter_chars; + extern int history_quotes_inhibit_expansion; +extern int history_quoting_state; extern int history_write_timestamps; diff --git a/parse.y b/parse.y index 6457782b..8496e2d1 100644 --- a/parse.y +++ b/parse.y @@ -2414,20 +2414,21 @@ shell_getc (remove_quoted_newline) { char *expansions; # if defined (BANG_HISTORY) - int old_hist; - /* If the current delimiter is a single quote, we should not be performing history expansion, even if we're on a different line from the original single quote. */ - old_hist = history_expansion_inhibited; if (current_delimiter (dstack) == '\'') - history_expansion_inhibited = 1; + history_quoting_state = '\''; + else if (current_delimiter (dstack) == '"') + history_quoting_state = '"'; + else + history_quoting_state = 0; # endif /* Calling with a third argument of 1 allows remember_on_history to determine whether or not the line is saved to the history list */ expansions = pre_process_line (shell_input_line, 1, 1); # if defined (BANG_HISTORY) - history_expansion_inhibited = old_hist; + history_quoting_state = 0; # endif if (expansions != shell_input_line) { diff --git a/tests/histexp.right b/tests/histexp.right index 11ed7330..1eeb39fb 100644 --- a/tests/histexp.right +++ b/tests/histexp.right @@ -223,3 +223,18 @@ echo +(/one|/two|/three)/Step1 *(/tmp|/dev|/usr)/Step1 echo *(/tmp|/dev|/usr)/Step1 *(/tmp|/dev|/usr)/Step1 +one + echo echo one +echo one +echo one +echo one + 1 set -o histexpand + 2 echo one + 3 for f in a b c; do echo echo one; done +two + echo echo two +echo two +echo two +echo two + 1 echo two + 2 for f in a b c; do echo echo two; done diff --git a/tests/histexp.tests b/tests/histexp.tests index 22c90a76..5ae925e1 100644 --- a/tests/histexp.tests +++ b/tests/histexp.tests @@ -141,3 +141,4 @@ ${THIS_SH} ./histexp2.sub ${THIS_SH} ./histexp3.sub ${THIS_SH} ./histexp4.sub ${THIS_SH} ./histexp5.sub +${THIS_SH} ./histexp6.sub diff --git a/tests/histexp6.sub b/tests/histexp6.sub new file mode 100644 index 00000000..b95b460a --- /dev/null +++ b/tests/histexp6.sub @@ -0,0 +1,23 @@ +HISTFILE=$TMPDIR/bashhist-$$ + +set -o history +set -o histexpand + +echo one + +for f in a b c; do + echo !! +done + +history +history -c + +echo two +for f in a b c; do + echo !-1 +done + +history + +set +o history +rm -f $HISTFILE