diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 8a3f06d9..5a145526 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -13348,7 +13348,7 @@ doc/{bash.1,bashref.texi} --- lib/readline/display.c - update_line: completely rewrote the code that handles line wrapping - in the presence of multibyte/double-width characters; punts toa + in the presence of multibyte/double-width characters; punts to a dumb update in cases where the number of screen positions doesn't match - update_line: in one case, where we are deleting characters from the @@ -14458,3 +14458,76 @@ subst.c overflow when allocating large pieces of memory. Report and fix from Siteshwar Vashisht , originally based on http://lists.gnu.org/archive/html/bug-bash/2017-11/msg00047.html + + 11/24 + ----- +lib/readline/bind.c + - rl_empty_keymap: new public function, returns non-zero if there are + no keys bound in the keymap passed as an argument + +lib/readline/readline.h + - rl_empty_keymap: new public extern declaration + +lib/readline/doc/rltech.texi + - rl_empty_keymap: document new function + +lib/readline/bind.c + - rl_generic_bind: keep track of the previous keymap and previous + index in a multi-key key sequence so we can remove an empty terminal + keymap and remove a previous override to ANYOTHERKEY. Right now, + this only works for one previous keymap level. Inspired by a report + from Clark Wang + + 11/25 + ----- +lib/readline/display.c + - _rl_update_final: make sure that computing the length of the visible + bottom line (botline_length) takes any invisible characters in the + prompt into account (woff). This value is used as part of the check + whether or not we want to remove the line-wrapping indicator on + terminals like xterm + - _rl_update_final: when removing the line-wrapping indicator on xterm, + make sure we take invisible characters in the prompt (woff) into + account when computing the character in the rightmost physical + screen position. Fixes cosmetic line-wrapping issue reported by + Egmont Koblinger + + 11/27 + ----- +lib/sh/ufuncs.c + - fsleep: if using select to implement sleep, use restart after + a signal interrupts the select and handle pending signals. If + pselect is available, use that instead and block SIGCHLD while + pselect is executing. + Fixes report from Thiruvadi Rajaraman + + 11/28 + ----- +lib/readline/signals.c + - rl_check_signals: new public function: a wrapper for RL_CHECK_SIGNALS + that can be used by applications that install a wrapper for + rl_getc (rl_getc_function) so they can respond to signals that + arrive while waiting for input in the same way as rl_getc. The app + can use rl_pending_signal() to get the most recently-received + signal. From a discussion about Gnuplot initiated by + Rin Okuyama + +lib/readline/readline.h + - rl_check_signals: new extern declaration + +lib/readline/doc/rltech.texi + - rl_check_signals: document new public function + +variables.c + - set_pwd: test for and force an inherited OLDPWD to be a directory + if OLDPWD_CHECK_DIRECTORY is defined in config-top.h (it is by + default). Issue raised by Mikulas Patocka + +config-top.h + - OLDPWD_CHECK_DIRECTORY: new define, defined to 1 by default + + 11/29 + ----- +Makefile.in + - pathexp.o: add dependencies on libintl.h. Reported by + Ross Burton diff --git a/Makefile.in b/Makefile.in index 3e52403b..3a4d66b0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1293,6 +1293,7 @@ mailcheck.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h make_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h nojobs.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h y.tab.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h +pathexp.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h pcomplete.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h pcomplib.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h print_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h diff --git a/config-top.h b/config-top.h index 1474a5fb..e1f97698 100644 --- a/config-top.h +++ b/config-top.h @@ -165,3 +165,7 @@ /* Define to use libc mktemp/mkstemp instead of replacements in lib/sh/tmpfile.c */ #define USE_MKTEMP #define USE_MKSTEMP + +/* Define to force the value of OLDPWD inherited from the environment to be a + directory */ +#define OLDPWD_CHECK_DIRECTORY 1 diff --git a/lib/readline/bind.c b/lib/readline/bind.c index fef538b1..e1a69031 100644 --- a/lib/readline/bind.c +++ b/lib/readline/bind.c @@ -325,9 +325,10 @@ int rl_generic_bind (int type, const char *keyseq, char *data, Keymap map) { char *keys; - int keys_len; + int keys_len, prevkey; register int i; KEYMAP_ENTRY k; + Keymap prevmap; k.function = 0; @@ -350,12 +351,17 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map) return -1; } + prevmap = map; + prevkey = keys[0]; + /* Bind keys, making new keymaps as necessary. */ for (i = 0; i < keys_len; i++) { unsigned char uc = keys[i]; int ic; + prevkey = ic; + ic = uc; if (ic < 0 || ic >= KEYMAP_SIZE) { @@ -367,7 +373,10 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map) { ic = UNMETA (ic); if (map[ESC].type == ISKMAP) - map = FUNCTION_TO_KEYMAP (map, ESC); + { + prevmap = map; + map = FUNCTION_TO_KEYMAP (map, ESC); + } } if ((i + 1) < keys_len) @@ -386,6 +395,7 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map) map[ic].type = ISKMAP; map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap()); } + prevmap = map; map = FUNCTION_TO_KEYMAP (map, ic); /* The dispatch code will return this function if no matching key sequence is found in the keymap. This (with a little @@ -405,6 +415,7 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map) xfree ((char *)map[ic].function); else if (map[ic].type == ISKMAP) { + prevmap = map; map = FUNCTION_TO_KEYMAP (map, ic); ic = ANYOTHERKEY; /* If we're trying to override a keymap with a null function @@ -421,7 +432,28 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map) } rl_binding_keymap = map; + } + + /* If we unbound a key (type == ISFUNC, data == 0), and the prev keymap + points to the keymap where we unbound the key (sanity check), and the + current binding keymap is empty (rl_empty_keymap() returns non-zero), + and the binding keymap has ANYOTHERKEY set with type == ISFUNC + (overridden function), delete the now-empty keymap, take the previously- + overridden function and remove the override. */ + /* Right now, this only works one level back. */ + if (type == ISFUNC && data == 0 && + prevmap[prevkey].type == ISKMAP && + (FUNCTION_TO_KEYMAP(prevmap, prevkey) == rl_binding_keymap) && + rl_binding_keymap[ANYOTHERKEY].type == ISFUNC && + rl_empty_keymap (rl_binding_keymap)) + { + prevmap[prevkey].type = rl_binding_keymap[ANYOTHERKEY].type; + prevmap[prevkey].function = rl_binding_keymap[ANYOTHERKEY].function; + rl_discard_keymap (rl_binding_keymap); + rl_binding_keymap = prevmap; + } + xfree (keys); return 0; } diff --git a/lib/readline/display.c b/lib/readline/display.c index b90437f1..54566efd 100644 --- a/lib/readline/display.c +++ b/lib/readline/display.c @@ -2938,7 +2938,7 @@ delete_chars (int count) void _rl_update_final (void) { - int full_lines; + int full_lines, woff, botline_length; full_lines = 0; /* If the cursor is the only thing on an otherwise-blank last line, @@ -2950,16 +2950,23 @@ _rl_update_final (void) full_lines = 1; } _rl_move_vert (_rl_vis_botlin); + woff = W_OFFSET(_rl_vis_botlin, wrap_offset); + botline_length = VIS_LLEN(_rl_vis_botlin) - woff; /* If we've wrapped lines, remove the final xterm line-wrap flag. */ - if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth)) + if (full_lines && _rl_term_autowrap && botline_length == _rl_screenwidth) { char *last_line; - last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; + /* LAST_LINE includes invisible characters, so if you want to get the + last character of the first line, you have to take WOFF into account. + This needs to be done for both calls to _rl_move_cursor_relative, + which takes a buffer position as the first argument, and any direct + subscripts of LAST_LINE. */ + last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; /* = VIS_CHARS(_rl_vis_botlin); */ cpos_buffer_position = -1; /* don't know where we are in buffer */ - _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */ + _rl_move_cursor_relative (_rl_screenwidth - 1 + woff, last_line); /* XXX */ _rl_clear_to_eol (0); - putc (last_line[_rl_screenwidth - 1], rl_outstream); + putc (last_line[_rl_screenwidth - 1 + woff], rl_outstream); } _rl_vis_botlin = 0; rl_crlf (); diff --git a/lib/readline/doc/rltech.texi b/lib/readline/doc/rltech.texi index 2754ad27..5e57eaba 100644 --- a/lib/readline/doc/rltech.texi +++ b/lib/readline/doc/rltech.texi @@ -694,6 +694,11 @@ Free all storage associated with @var{keymap}. This calls @code{rl_discard_keymap} to free subordindate keymaps and macros. @end deftypefun +@deftypefun int rl_empty_keymap (Keymap keymap) +Return non-zero if there are no keys bound to functions in @var{keymap}; +zero if there are any keys bound. +@end deftypefun + Readline has several internal keymaps. These functions allow you to change which keymap is active. @@ -1685,6 +1690,19 @@ handlers, depending on the values of @code{rl_catch_signals} and @code{rl_catch_sigwinch}. @end deftypefun +If an application wants to force Readline to handle any signals that +have arrived while it has been executing, @code{rl_check_signals()} +will call Readline's internal signal handler if there are any pending +signals. This is primarily intended for those applications that use +a custom @code{rl_getc_function} (@pxref{Readline Variables}) and wish +to handle signals received while waiting for input. + +@deftypefun void rl_check_signals (void) +If there are any pending signals, call Readline's internal signal handling +functions to process them. @code{rl_pending_signal()} can be used independently +to determine whether or not there are any pending signals. +@end deftypefun + If an application does not wish Readline to catch @code{SIGWINCH}, it may call @code{rl_resize_terminal()} or @code{rl_set_screen_size()} to force Readline to update its idea of the terminal size when a @code{SIGWINCH} diff --git a/lib/readline/doc/version.texi b/lib/readline/doc/version.texi index 364d6791..b6222944 100644 --- a/lib/readline/doc/version.texi +++ b/lib/readline/doc/version.texi @@ -4,7 +4,7 @@ Copyright (C) 1988-2017 Free Software Foundation, Inc. @set EDITION 7.0 @set VERSION 7.0 -@set UPDATED 8 October 2017 -@set UPDATED-MONTH October 2017 +@set UPDATED 28 November 2017 +@set UPDATED-MONTH November 2017 -@set LASTCHANGE Sun Oct 8 11:44:33 EDT 2017 +@set LASTCHANGE Tue Nov 28 10:14:48 PST 2017 diff --git a/lib/readline/keymaps.c b/lib/readline/keymaps.c index 0400668b..4ade30bc 100644 --- a/lib/readline/keymaps.c +++ b/lib/readline/keymaps.c @@ -77,6 +77,21 @@ rl_make_bare_keymap (void) return (keymap); } +/* A convenience function that returns 1 if there are no keys bound to + functions in KEYMAP */ +int +rl_empty_keymap (Keymap keymap) +{ + int i; + + for (i = 0; i < ANYOTHERKEY; i++) + { + if (keymap[i].type != ISFUNC || keymap[i].function) + return 0; + } + return 1; +} + /* Return a new keymap which is a copy of MAP. Just copies pointers, does not copy text of macros or descend into child keymaps. */ Keymap diff --git a/lib/readline/readline.h b/lib/readline/readline.h index 8af4e62f..c847e937 100644 --- a/lib/readline/readline.h +++ b/lib/readline/readline.h @@ -346,6 +346,7 @@ extern int rl_parse_and_bind PARAMS((char *)); /* Functions for manipulating keymaps. */ extern Keymap rl_make_bare_keymap PARAMS((void)); +extern int rl_empty_keymap PARAMS((Keymap)); extern Keymap rl_copy_keymap PARAMS((Keymap)); extern Keymap rl_make_keymap PARAMS((void)); extern void rl_discard_keymap PARAMS((Keymap)); @@ -447,6 +448,7 @@ extern void rl_reset_after_signal PARAMS((void)); extern void rl_free_line_state PARAMS((void)); extern int rl_pending_signal PARAMS((void)); +extern void rl_check_signals PARAMS((void)); extern void rl_echo_signal_char PARAMS((int)); diff --git a/lib/readline/signals.c b/lib/readline/signals.c index add165c5..76c5c473 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -595,6 +595,12 @@ rl_pending_signal (void) { return (_rl_caught_signal); } + +void +rl_check_signals (void) +{ + RL_CHECK_SIGNALS (); +} #endif /* HANDLE_SIGNALS */ /* **************************************************************** */ diff --git a/lib/sh/ufuncs.c b/lib/sh/ufuncs.c index fcd4c044..9a146bb7 100644 --- a/lib/sh/ufuncs.c +++ b/lib/sh/ufuncs.c @@ -37,8 +37,16 @@ #include #endif +#include +#if !defined (errno) +extern int errno; +#endif /* !errno */ + #if defined (HAVE_SELECT) # include "posixselect.h" +# include "quit.h" +# include "trap.h" +# include "stat-time.h" #endif /* A version of `alarm' using setitimer if it's available. */ @@ -84,17 +92,46 @@ falarm (secs, usecs) /* A version of sleep using fractional seconds and select. I'd like to use `usleep', but it's already taken */ -#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) +#if defined (HAVE_TIMEVAL) && (defined (HAVE_SELECT) || defined (HAVE_PSELECT)) int fsleep(sec, usec) unsigned int sec, usec; { + int e, r; +#if defined (HAVE_PSELECT) + sigset_t blocked_sigs; + struct timespec ts; +#else struct timeval tv; +#endif +#if defined (HAVE_PSELECT) + sigemptyset (&blocked_sigs); +# if defined (SIGCHLD) + sigaddset (&blocked_sigs, SIGCHLD); +# endif + ts.tv_sec = sec; + ts.tv_nsec = usec * 1000; +#else tv.tv_sec = sec; tv.tv_usec = usec; +#endif /* !HAVE_PSELECT */ - return select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv); + do + { +#if defined (HAVE_PSELECT) + r = pselect(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &ts, &blocked_sigs); +#else + r = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv); +#endif + e = errno; + if (r < 0 && errno == EINTR) + QUIT; /* just signals, no traps */ + errno = e; + } + while (r < 0 && errno == EINTR); + + return r; } #else /* !HAVE_TIMEVAL || !HAVE_SELECT */ int diff --git a/variables.c b/variables.c index 495ebbf2..e9d4d578 100644 --- a/variables.c +++ b/variables.c @@ -886,7 +886,11 @@ set_pwd () don't find OLDPWD in the environment, or it doesn't name a directory, make a dummy invisible variable for OLDPWD, and mark it as exported. */ temp_var = find_variable ("OLDPWD"); +#if defined (OLDPWD_CHECK_DIRECTORY) if (temp_var == 0 || value_cell (temp_var) == 0 || file_isdir (value_cell (temp_var)) == 0) +#else + if (temp_var == 0 || value_cell (temp_var) == 0) +#endif { temp_var = bind_variable ("OLDPWD", (char *)NULL, 0); VSETATTR (temp_var, (att_exported | att_invisible));