From 97be3d8ed96e6249ef07e2973e72060876856d21 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Wed, 7 Dec 2011 09:04:55 -0500 Subject: [PATCH] commit bash-20070316 snapshot --- .gdb_history | 16 -- CWRU/CWRU.chlog | 44 +++++ CWRU/CWRU.chlog~ | 43 +++++ builtins/evalfile.c | 16 +- builtins/evalfile.c~ | 16 +- include/typemax.h | 4 + include/typemax.h~ | 80 ++++++++ lib/readline/complete.c | 1 + lib/readline/display.c | 48 ++++- lib/readline/display.c~ | 69 +++++-- lib/readline/input.c~ | 23 ++- lib/readline/mbutil.c | 7 +- lib/readline/mbutil.c~ | 373 ++++++++++++++++++++++++++++++++++++++ lib/readline/rlprivate.h | 1 + lib/readline/rlprivate.h~ | 4 +- lib/readline/text.c | 6 + lib/readline/text.c~ | 15 ++ lib/readline/util.c | 58 ++++++ lib/readline/util.c~ | 58 +++++- parse.y | 12 +- parse.y~ | 15 +- patchlevel.h | 4 +- patchlevel.h~ | 2 +- 23 files changed, 840 insertions(+), 75 deletions(-) create mode 100644 include/typemax.h~ create mode 100644 lib/readline/mbutil.c~ diff --git a/.gdb_history b/.gdb_history index f39ae744d..ff604669b 100644 --- a/.gdb_history +++ b/.gdb_history @@ -1,17 +1 @@ quit -break _rl_move_cursor_relative -att 29981 -c -where -p _rl_last_c_pos -break rl_redisplay -c -break update_line -c -detach -att 29981 -c -i break -att 112 -c -quit diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 59a740326..f7a50ba4e 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -14381,3 +14381,47 @@ lib/readline/display.c the last invisible character in the prompt, since they both denote buffer indices when in a multibyte locale, whereas `dpos' is a display position + + 3/13 + ---- +lib/readline/complete.c + - set rl_completion_append_character to the default (' ') in + set_completion_defaults(). Fixes bug reported by David Emerson + + + 3/23 + ---- +builtins/evalfile.c + - make sure read() returns a value >= 0 before using it as an index + into string[] + - use a variable of type `ssize_t' for return value from read() + - only try to read the entire contents of a regular file in one shot + if the file size is less than SSIZE_MAX. These fix problems + reported by hooanon05@yahoo.co.jp. + +include/typemax.h + - define SSIZE_MAX as 32767 if it's not defined + +lib/readline/display.c + - in rl_redisplay() and update_line(), if redrawing the prompt because + it contains invisible characters, make sure we redraw the character + indicating a modified history line and take it into account when + computing _rl_last_c_pos + - in update_line, if deleting characters and redrawing the new text, + make sure we adjust _rl_last_c_pos by wrap_offset in a multibyte + locale if the text we're drawing starts before or at the last + invisible character in the prompt string. Fixes bug reported on + bug-readline by J Pelkey + +parse.y + - when adding at CTLESC character to the current token, do not + escape it with CTLESC if pass_next_character indicates that the + CTLESC was escaped by a backslash. Fixes bug reported by + Paul Bagshaw . + + 3/25 + ---- +lib/readline/text.c + - in rl_forward_char, short-circuit the loop if in emacs mode and + rl_point == rl_end. Fixes problem with multibyte locales + reported by Len Lattanzi diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index e65982f38..b02d220ac 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -14375,3 +14375,46 @@ builtins/common.c - add calls to top_level_cleanup before calls to jump_to_top_level in a builtin command context (no_args(), get_numeric_arg()). Fixes bug reported by Ian Watson + +lib/readline/display.c + - in _rl_move_cursor_relative, use `new' when comparing against + the last invisible character in the prompt, since they both denote + buffer indices when in a multibyte locale, whereas `dpos' is a + display position + + 3/13 + ---- +lib/readline/complete.c + - set rl_completion_append_character to the default (' ') in + set_completion_defaults(). Fixes bug reported by David Emerson + + + 3/23 + ---- +builtins/evalfile.c + - make sure read() returns a value >= 0 before using it as an index + into string[] + - use a variable of type `ssize_t' for return value from read() + - only try to read the entire contents of a regular file in one shot + if the file size is less than SSIZE_MAX. These fix problems + reported by hooanon05@yahoo.co.jp. + +include/typemax.h + - define SSIZE_MAX as 32767 if it's not defined + +lib/readline/display.c + - in rl_redisplay() and update_line(), if redrawing the prompt because + it contains invisible characters, make sure we redraw the character + indicating a modified history line and take it into account when + computing _rl_last_c_pos + - in update_line, if deleting characters and redrawing the new text, + make sure we adjust _rl_last_c_pos by wrap_offset in a multibyte + locale if the text we're drawing starts before or at the last + invisible character in the prompt string. Fixes bug reported on + bug-readline by J Pelkey + +parse.y + - when adding at CTLESC character to the current token, do not + escape it with CTLESC if pass_next_character indicates that the + CTLESC was escaped by a backslash. Fixes bug reported by + Paul Bagshaw . diff --git a/builtins/evalfile.c b/builtins/evalfile.c index b8e9640c9..ac29ae803 100644 --- a/builtins/evalfile.c +++ b/builtins/evalfile.c @@ -45,6 +45,8 @@ # include "../bashhist.h" #endif +#include + #include "common.h" #if !defined (errno) @@ -78,6 +80,7 @@ _evalfile (filename, flags) volatile int old_interactive; procenv_t old_return_catch; int return_val, fd, result, pflags; + ssize_t nr; /* return value from read(2) */ char *string; struct stat finfo; size_t file_size; @@ -147,26 +150,27 @@ file_error_and_exit: setmode (fd, O_TEXT); #endif - if (S_ISREG (finfo.st_mode)) + if (S_ISREG (finfo.st_mode) && file_size <= SSIZE_MAX) { string = (char *)xmalloc (1 + file_size); - result = read (fd, string, file_size); - string[result] = '\0'; + nr = read (fd, string, file_size); + if (nr >= 0) + string[nr] = '\0'; } else - result = zmapfd (fd, &string, 0); + nr = zmapfd (fd, &string, 0); return_val = errno; close (fd); errno = return_val; - if (result < 0) /* XXX was != file_size, not < 0 */ + if (nr < 0) /* XXX was != file_size, not < 0 */ { free (string); goto file_error_and_exit; } - if (result == 0) + if (nr == 0) { free (string); return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1); diff --git a/builtins/evalfile.c~ b/builtins/evalfile.c~ index 5faf9f713..a78235b14 100644 --- a/builtins/evalfile.c~ +++ b/builtins/evalfile.c~ @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2003 Free Software Foundation, Inc. +/* Copyright (C) 1996-2006 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -45,6 +45,8 @@ # include "../bashhist.h" #endif +#include + #include "common.h" #if !defined (errno) @@ -78,6 +80,7 @@ _evalfile (filename, flags) volatile int old_interactive; procenv_t old_return_catch; int return_val, fd, result, pflags; + ssize_t nr; /* return value from read(2) */ char *string; struct stat finfo; size_t file_size; @@ -147,20 +150,21 @@ file_error_and_exit: setmode (fd, O_TEXT); #endif - if (S_ISREG (finfo.st_mode)) + if (S_ISREG (finfo.st_mode) && file_size <= SSIZE_MAX) { string = (char *)xmalloc (1 + file_size); - result = read (fd, string, file_size); - string[result] = '\0'; + nr = read (fd, string, file_size); + if (nr >= 0) + string[nr] = '\0'; } else - result = zmapfd (fd, &string, 0); + nr = zmapfd (fd, &string, 0); return_val = errno; close (fd); errno = return_val; - if (result < 0) /* XXX was != file_size, not < 0 */ + if (nr < 0) /* XXX was != file_size, not < 0 */ { free (string); goto file_error_and_exit; diff --git a/include/typemax.h b/include/typemax.h index 42ae517dc..ff63d3b90 100644 --- a/include/typemax.h +++ b/include/typemax.h @@ -77,4 +77,8 @@ static const unsigned long long int maxquad = ULLONG_MAX; # define ULLONG_MAX maxquad #endif +#ifndef SSIZE_MAX +# define SSIZE_MAX 32767 /* POSIX minimum max */ +#endif + #endif /* _SH_TYPEMAX_H */ diff --git a/include/typemax.h~ b/include/typemax.h~ new file mode 100644 index 000000000..42ae517dc --- /dev/null +++ b/include/typemax.h~ @@ -0,0 +1,80 @@ +/* typemax.h -- encapsulate max values for long, long long, etc. */ + +/* Copyright (C) 2001 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +/* + * NOTE: This should be included after config.h, limits.h, stdint.h, and + * inttypes.h + */ + +#ifndef _SH_TYPEMAX_H +#define _SH_TYPEMAX_H + +#ifndef CHAR_BIT +# define CHAR_BIT 8 +#endif + +/* Nonzero if the integer type T is signed. */ +#ifndef TYPE_SIGNED +# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) +#endif + +#ifndef TYPE_MINIMUM +# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ + ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \ + : (t) 0)) +#endif + +#ifndef TYPE_MAXIMUM +# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) +#endif + +#ifdef HAVE_LONG_LONG +# ifndef LLONG_MAX +# define LLONG_MAX TYPE_MAXIMUM(long long int) +# define LLONG_MIN TYPE_MINIMUM(long long int) +# endif +# ifndef ULLONG_MAX +# define ULLONG_MAX TYPE_MAXIMUM(unsigned long long int) +# endif +#endif + +#ifndef ULONG_MAX +# define ULONG_MAX ((unsigned long) ~(unsigned long) 0) +#endif + +#ifndef LONG_MAX +# define LONG_MAX ((long int) (ULONG_MAX >> 1)) +# define LONG_MIN ((long int) (-LONG_MAX - 1L)) +#endif + +#ifndef INT_MAX /* ouch */ +# define INT_MAX TYPE_MAXIMUM(int) +# define INT_MIN TYPE_MINIMUM(int) +# define UINT_MAX ((unsigned int) ~(unsigned int)0) +#endif + +/* workaround for gcc bug in versions < 2.7 */ +#if defined (HAVE_LONG_LONG) && __GNUC__ == 2 && __GNUC_MINOR__ < 7 +static const unsigned long long int maxquad = ULLONG_MAX; +# undef ULLONG_MAX +# define ULLONG_MAX maxquad +#endif + +#endif /* _SH_TYPEMAX_H */ diff --git a/lib/readline/complete.c b/lib/readline/complete.c index c9e061150..64e4a235d 100644 --- a/lib/readline/complete.c +++ b/lib/readline/complete.c @@ -416,6 +416,7 @@ set_completion_defaults (what_to_do) rl_filename_quoting_desired = 1; rl_completion_type = what_to_do; rl_completion_suppress_append = rl_completion_suppress_quote = 0; + rl_completion_append_character = ' '; /* The completion entry function may optionally change this. */ rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs; diff --git a/lib/readline/display.c b/lib/readline/display.c index 5c4fd26e4..b48477776 100644 --- a/lib/readline/display.c +++ b/lib/readline/display.c @@ -106,7 +106,7 @@ static int _rl_col_width PARAMS((const char *, int, int)); /* _rl_last_c_pos is an absolute cursor position in multibyte locales and a buffer index in others. This macro is used when deciding whether the current cursor position is in the middle of a prompt string containing - invisible characters. */ + invisible characters. XXX - might need to take `modmark' into account. */ #define PROMPT_ENDING_INDEX \ ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1) @@ -214,6 +214,10 @@ static int prompt_last_screen_line; static int prompt_physical_chars; +/* set to a non-zero value by rl_redisplay if we are marking modified history + lines and the current line is so marked. */ +static int modmark; + /* Variables to save and restore prompt and display information. */ /* These are getting numerous enough that it's time to create a struct. */ @@ -487,7 +491,7 @@ rl_redisplay () register int in, out, c, linenum, cursor_linenum; register char *line; int inv_botlin, lb_botlin, lb_linenum, o_cpos; - int newlines, lpos, temp, modmark, n0, num; + int newlines, lpos, temp, n0, num; char *prompt_this_line; #if defined (HANDLE_MULTIBYTE) wchar_t wc; @@ -1043,11 +1047,14 @@ rl_redisplay () if (_rl_term_cr) tputs (_rl_term_cr, 1, _rl_output_character_function); #endif + if (modmark) + _rl_output_some_chars ("*", 1); + _rl_output_some_chars (local_prompt, nleft); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset; + _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset + modmark; else - _rl_last_c_pos = nleft; + _rl_last_c_pos = nleft + modmark; } /* Where on that line? And where does that line start @@ -1317,7 +1324,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) /* See if the old line is a subset of the new line, so that the only change is adding characters. */ temp = (omax < nmax) ? omax : nmax; - if (memcmp (old, new, temp) == 0) + if (memcmp (old, new, temp) == 0) /* adding at the end */ { ofd = old + temp; nfd = new + temp; @@ -1470,16 +1477,18 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) #else tputs (_rl_term_cr, 1, _rl_output_character_function); #endif + if (modmark) + _rl_output_some_chars ("*", 1); _rl_output_some_chars (local_prompt, lendiff); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { /* We take wrap_offset into account here so we can pass correct information to _rl_move_cursor_relative. */ - _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset; + _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset + modmark; cpos_adjusted = 1; } else - _rl_last_c_pos = lendiff; + _rl_last_c_pos = lendiff + modmark; } /* When this function returns, _rl_last_c_pos is correct, and an absolute @@ -1615,9 +1624,20 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) temp = nls - nfd; if (temp > 0) { + /* If nfd begins at the prompt, or before the invisible + characters in the prompt, we need to adjust _rl_last_c_pos + in a multibyte locale to account for the wrap offset and + set cpos_adjusted accordingly. */ _rl_output_some_chars (nfd, temp); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos += _rl_col_width (nfd, 0, temp); + { + _rl_last_c_pos += _rl_col_width (nfd, 0, temp); + if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) + { + _rl_last_c_pos -= wrap_offset; + cpos_adjusted = 1; + } + } else _rl_last_c_pos += temp; } @@ -1627,8 +1647,20 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) { if (temp > 0) { + /* If nfd begins at the prompt, or before the invisible + characters in the prompt, we need to adjust _rl_last_c_pos + in a multibyte locale to account for the wrap offset and + set cpos_adjusted accordingly. */ _rl_output_some_chars (nfd, temp); _rl_last_c_pos += col_temp; /* XXX */ + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) + { + _rl_last_c_pos -= wrap_offset; + cpos_adjusted = 1; + } + } } lendiff = (oe - old) - (ne - new); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) diff --git a/lib/readline/display.c~ b/lib/readline/display.c~ index 304fba5fd..f0d5e2d29 100644 --- a/lib/readline/display.c~ +++ b/lib/readline/display.c~ @@ -106,7 +106,7 @@ static int _rl_col_width PARAMS((const char *, int, int)); /* _rl_last_c_pos is an absolute cursor position in multibyte locales and a buffer index in others. This macro is used when deciding whether the current cursor position is in the middle of a prompt string containing - invisible characters. */ + invisible characters. XXX - might need to take `modmark' into account. */ #define PROMPT_ENDING_INDEX \ ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1) @@ -214,6 +214,10 @@ static int prompt_last_screen_line; static int prompt_physical_chars; +/* set to a non-zero value by rl_redisplay if we are marking modified history + lines and the current line is so marked. */ +static int modmark; + /* Variables to save and restore prompt and display information. */ /* These are getting numerous enough that it's time to create a struct. */ @@ -487,7 +491,7 @@ rl_redisplay () register int in, out, c, linenum, cursor_linenum; register char *line; int inv_botlin, lb_botlin, lb_linenum, o_cpos; - int newlines, lpos, temp, modmark, n0, num; + int newlines, lpos, temp, n0, num; char *prompt_this_line; #if defined (HANDLE_MULTIBYTE) wchar_t wc; @@ -1043,11 +1047,14 @@ rl_redisplay () if (_rl_term_cr) tputs (_rl_term_cr, 1, _rl_output_character_function); #endif + if (modmark) + _rl_output_some_chars ("*", 1); + _rl_output_some_chars (local_prompt, nleft); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset; + _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset + modmark; else - _rl_last_c_pos = nleft; + _rl_last_c_pos = nleft + modmark; } /* Where on that line? And where does that line start @@ -1310,6 +1317,9 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) } +_rl_trace("update_line: old = %p \"%s\"", old, old); +_rl_trace("update_line: new = %p \"%s\"", new, new); + /* Find first difference. */ #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) @@ -1317,7 +1327,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) /* See if the old line is a subset of the new line, so that the only change is adding characters. */ temp = (omax < nmax) ? omax : nmax; - if (memcmp (old, new, temp) == 0) + if (memcmp (old, new, temp) == 0) /* adding at the end */ { ofd = old + temp; nfd = new + temp; @@ -1346,6 +1356,8 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) } } } +_rl_trace("update_line: ofd = %p \"%s\"", ofd, ofd); +_rl_trace("update_line: nfd = %p \"%s\"", nfd, nfd); } else #endif @@ -1360,6 +1372,9 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++); for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++); +_rl_trace("update_line: oe = %p \"%s\"", oe, oe); +_rl_trace("update_line: ne = %p \"%s\"", ne, ne); + /* If no difference, continue to next line. */ if (ofd == oe && nfd == ne) return; @@ -1438,6 +1453,9 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) } } +_rl_trace("update_line: ols = %p \"%s\"", ols, ols); +_rl_trace("update_line: nls = %p \"%s\"", nls, nls); + /* count of invisible characters in the current invisible line. */ current_invis_chars = W_OFFSET (current_line, wrap_offset); if (_rl_last_v_pos != current_line) @@ -1470,6 +1488,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) #else tputs (_rl_term_cr, 1, _rl_output_character_function); #endif +_rl_trace("update_line: redrawing prompt"); _rl_output_some_chars (local_prompt, lendiff); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { @@ -1480,6 +1499,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) } else _rl_last_c_pos = lendiff; +_rl_trace("update_line: redrawing prompt: _rl_last_c_pos = %d", _rl_last_c_pos); } /* When this function returns, _rl_last_c_pos is correct, and an absolute @@ -1506,6 +1526,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) else col_lendiff = lendiff; +_rl_trace("update_line: lendiff = %d col_lendiff = %d", lendiff, col_lendiff); /* If we are changing the number of invisible characters in a line, and the spot of first difference is before the end of the invisible chars, lendiff needs to be adjusted. */ @@ -1524,6 +1545,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) } } +_rl_trace("update_line: after adjustment: lendiff = %d col_lendiff = %d", lendiff, col_lendiff); /* Insert (diff (len (old), len (new)) ch. */ temp = ne - nfd; if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) @@ -1615,9 +1637,20 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) temp = nls - nfd; if (temp > 0) { + /* If nfd begins at the prompt, or before the invisible + characters in the prompt, we need to adjust _rl_last_c_pos + in a multibyte locale to account for the wrap offset and + set cpos_adjusted accordingly. */ _rl_output_some_chars (nfd, temp); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos += _rl_col_width (nfd, 0, temp); + { + _rl_last_c_pos += _rl_col_width (nfd, 0, temp); + if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) + { + _rl_last_c_pos -= wrap_offset; + cpos_adjusted = 1; + } + } else _rl_last_c_pos += temp; } @@ -1627,8 +1660,20 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) { if (temp > 0) { + /* If nfd begins at the prompt, or before the invisible + characters in the prompt, we need to adjust _rl_last_c_pos + in a multibyte locale to account for the wrap offset and + set cpos_adjusted accordingly. */ _rl_output_some_chars (nfd, temp); _rl_last_c_pos += col_temp; /* XXX */ + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible)) + { + _rl_last_c_pos -= wrap_offset; + cpos_adjusted = 1; + } + } } lendiff = (oe - old) - (ne - new); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) @@ -1764,16 +1809,10 @@ _rl_move_cursor_relative (new, data) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { dpos = _rl_col_width (data, 0, new); - /* PROMPT_MULTIBYTE_CHARS is the difference between the number of - non-invisible characters in the prompt string and the number of - physical characters displayed on the screen. wrap_offset is - computed using the former. The computation above doesn't take - this into account. */ -#if 0 - if ((dpos+prompt_multibyte_chars) > prompt_last_invisible) /* XXX - don't use woff here */ -#else + /* Use NEW when comparing against the last invisible character in the + prompt string, since they're both buffer indices and DPOS is a + desired display position. */ if (new > prompt_last_invisible) /* XXX - don't use woff here */ -#endif { dpos -= woff; /* Since this will be assigned to _rl_last_c_pos at the end (more diff --git a/lib/readline/input.c~ b/lib/readline/input.c~ index 8996e522d..6b0bd6b27 100644 --- a/lib/readline/input.c~ +++ b/lib/readline/input.c~ @@ -469,7 +469,10 @@ rl_getc (stream) /* If zero characters are returned, then the file that we are reading from is empty! Return EOF in that case. */ if (result == 0) +{ +_rl_trace("rl_getc: result == 0 returning EOF"); return (EOF); +} #if defined (__BEOS__) if (errno == EINTR) @@ -502,7 +505,13 @@ rl_getc (stream) this is simply an interrupted system call to read (). Otherwise, some error ocurred, also signifying EOF. */ if (errno != EINTR) +{ +if (RL_ISSTATE(RL_STATE_READCMD)) + _rl_trace("rl_getc: returning READERR: errno = %d", errno); +else + _rl_trace("rl_getc: returning EOF: errno = %d", errno); return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); +} } } @@ -513,20 +522,26 @@ _rl_read_mbchar (mbchar, size) char *mbchar; int size; { - int mb_len = 0; + int mb_len, c; size_t mbchar_bytes_length; wchar_t wc; mbstate_t ps, ps_back; memset(&ps, 0, sizeof (mbstate_t)); memset(&ps_back, 0, sizeof (mbstate_t)); - + + mb_len = 0; while (mb_len < size) { RL_SETSTATE(RL_STATE_MOREINPUT); - mbchar[mb_len++] = rl_read_key (); + c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (c < 0) + break; + + mbchar[mb_len++] = c; + mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps); if (mbchar_bytes_length == (size_t)(-1)) break; /* invalid byte sequence for the current locale */ @@ -564,7 +579,7 @@ _rl_read_mbstring (first, mb, mlen) c = first; memset (mb, 0, mlen); - for (i = 0; i < mlen; i++) + for (i = 0; c > 0 && i < mlen; i++) { mb[i] = (char)c; memset (&ps, 0, sizeof (mbstate_t)); diff --git a/lib/readline/mbutil.c b/lib/readline/mbutil.c index 17dde53ed..a0e53d11f 100644 --- a/lib/readline/mbutil.c +++ b/lib/readline/mbutil.c @@ -91,8 +91,9 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero) return seed; point = seed + _rl_adjust_point (string, seed, &ps); - /* if this is true, means that seed was not pointed character - started byte. So correct the point and consume count */ + /* if this is true, means that seed was not pointing to a byte indicating + the beginning of a multibyte character. Correct the point and consume + one char. */ if (seed < point) count--; @@ -101,7 +102,7 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero) tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps); if (MB_INVALIDCH ((size_t)tmp)) { - /* invalid bytes. asume a byte represents a character */ + /* invalid bytes. assume a byte represents a character */ point++; count--; /* reset states. */ diff --git a/lib/readline/mbutil.c~ b/lib/readline/mbutil.c~ new file mode 100644 index 000000000..17dde53ed --- /dev/null +++ b/lib/readline/mbutil.c~ @@ -0,0 +1,373 @@ +/* mbutil.c -- readline multibyte character utility functions */ + +/* Copyright (C) 2001-2005 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include +#include "posixjmp.h" + +#if defined (HAVE_UNISTD_H) +# include /* for _POSIX_VERSION */ +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include +#include + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" +#include "rlmbutil.h" + +#if defined (TIOCSTAT_IN_SYS_IOCTL) +# include +#endif /* TIOCSTAT_IN_SYS_IOCTL */ + +/* Some standard library routines. */ +#include "readline.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +/* Declared here so it can be shared between the readline and history + libraries. */ +#if defined (HANDLE_MULTIBYTE) +int rl_byte_oriented = 0; +#else +int rl_byte_oriented = 1; +#endif + +/* **************************************************************** */ +/* */ +/* Multibyte Character Utility Functions */ +/* */ +/* **************************************************************** */ + +#if defined(HANDLE_MULTIBYTE) + +static int +_rl_find_next_mbchar_internal (string, seed, count, find_non_zero) + char *string; + int seed, count, find_non_zero; +{ + size_t tmp; + mbstate_t ps; + int point; + wchar_t wc; + + tmp = 0; + + memset(&ps, 0, sizeof (mbstate_t)); + if (seed < 0) + seed = 0; + if (count <= 0) + return seed; + + point = seed + _rl_adjust_point (string, seed, &ps); + /* if this is true, means that seed was not pointed character + started byte. So correct the point and consume count */ + if (seed < point) + count--; + + while (count > 0) + { + tmp = mbrtowc (&wc, string+point, strlen(string + point), &ps); + if (MB_INVALIDCH ((size_t)tmp)) + { + /* invalid bytes. asume a byte represents a character */ + point++; + count--; + /* reset states. */ + memset(&ps, 0, sizeof(mbstate_t)); + } + else if (MB_NULLWCH (tmp)) + break; /* found wide '\0' */ + else + { + /* valid bytes */ + point += tmp; + if (find_non_zero) + { + if (wcwidth (wc) == 0) + continue; + else + count--; + } + else + count--; + } + } + + if (find_non_zero) + { + tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps); + while (tmp > 0 && wcwidth (wc) == 0) + { + point += tmp; + tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps); + if (MB_NULLWCH (tmp) || MB_INVALIDCH (tmp)) + break; + } + } + + return point; +} + +static int +_rl_find_prev_mbchar_internal (string, seed, find_non_zero) + char *string; + int seed, find_non_zero; +{ + mbstate_t ps; + int prev, non_zero_prev, point, length; + size_t tmp; + wchar_t wc; + + memset(&ps, 0, sizeof(mbstate_t)); + length = strlen(string); + + if (seed < 0) + return 0; + else if (length < seed) + return length; + + prev = non_zero_prev = point = 0; + while (point < seed) + { + tmp = mbrtowc (&wc, string + point, length - point, &ps); + if (MB_INVALIDCH ((size_t)tmp)) + { + /* in this case, bytes are invalid or shorted to compose + multibyte char, so assume that the first byte represents + a single character anyway. */ + tmp = 1; + /* clear the state of the byte sequence, because + in this case effect of mbstate is undefined */ + memset(&ps, 0, sizeof (mbstate_t)); + + /* Since we're assuming that this byte represents a single + non-zero-width character, don't forget about it. */ + prev = point; + } + else if (MB_NULLWCH (tmp)) + break; /* Found '\0' char. Can this happen? */ + else + { + if (find_non_zero) + { + if (wcwidth (wc) != 0) + prev = point; + } + else + prev = point; + } + + point += tmp; + } + + return prev; +} + +/* return the number of bytes parsed from the multibyte sequence starting + at src, if a non-L'\0' wide character was recognized. It returns 0, + if a L'\0' wide character was recognized. It returns (size_t)(-1), + if an invalid multibyte sequence was encountered. It returns (size_t)(-2) + if it couldn't parse a complete multibyte character. */ +int +_rl_get_char_len (src, ps) + char *src; + mbstate_t *ps; +{ + size_t tmp; + + tmp = mbrlen((const char *)src, (size_t)strlen (src), ps); + if (tmp == (size_t)(-2)) + { + /* shorted to compose multibyte char */ + if (ps) + memset (ps, 0, sizeof(mbstate_t)); + return -2; + } + else if (tmp == (size_t)(-1)) + { + /* invalid to compose multibyte char */ + /* initialize the conversion state */ + if (ps) + memset (ps, 0, sizeof(mbstate_t)); + return -1; + } + else if (tmp == (size_t)0) + return 0; + else + return (int)tmp; +} + +/* compare the specified two characters. If the characters matched, + return 1. Otherwise return 0. */ +int +_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2) + char *buf1; + int pos1; + mbstate_t *ps1; + char *buf2; + int pos2; + mbstate_t *ps2; +{ + int i, w1, w2; + + if ((w1 = _rl_get_char_len (&buf1[pos1], ps1)) <= 0 || + (w2 = _rl_get_char_len (&buf2[pos2], ps2)) <= 0 || + (w1 != w2) || + (buf1[pos1] != buf2[pos2])) + return 0; + + for (i = 1; i < w1; i++) + if (buf1[pos1+i] != buf2[pos2+i]) + return 0; + + return 1; +} + +/* adjust pointed byte and find mbstate of the point of string. + adjusted point will be point <= adjusted_point, and returns + differences of the byte(adjusted_point - point). + if point is invalied (point < 0 || more than string length), + it returns -1 */ +int +_rl_adjust_point(string, point, ps) + char *string; + int point; + mbstate_t *ps; +{ + size_t tmp = 0; + int length; + int pos = 0; + + length = strlen(string); + if (point < 0) + return -1; + if (length < point) + return -1; + + while (pos < point) + { + tmp = mbrlen (string + pos, length - pos, ps); + if (MB_INVALIDCH ((size_t)tmp)) + { + /* in this case, bytes are invalid or shorted to compose + multibyte char, so assume that the first byte represents + a single character anyway. */ + pos++; + /* clear the state of the byte sequence, because + in this case effect of mbstate is undefined */ + if (ps) + memset (ps, 0, sizeof (mbstate_t)); + } + else if (MB_NULLWCH (tmp)) + pos++; + else + pos += tmp; + } + + return (pos - point); +} + +int +_rl_is_mbchar_matched (string, seed, end, mbchar, length) + char *string; + int seed, end; + char *mbchar; + int length; +{ + int i; + + if ((end - seed) < length) + return 0; + + for (i = 0; i < length; i++) + if (string[seed + i] != mbchar[i]) + return 0; + return 1; +} + +wchar_t +_rl_char_value (buf, ind) + char *buf; + int ind; +{ + size_t tmp; + wchar_t wc; + mbstate_t ps; + int l; + + if (MB_LEN_MAX == 1 || rl_byte_oriented) + return ((wchar_t) buf[ind]); + l = strlen (buf); + if (ind >= l - 1) + return ((wchar_t) buf[ind]); + memset (&ps, 0, sizeof (mbstate_t)); + tmp = mbrtowc (&wc, buf + ind, l - ind, &ps); + if (MB_INVALIDCH (tmp) || MB_NULLWCH (tmp)) + return ((wchar_t) buf[ind]); + return wc; +} +#endif /* HANDLE_MULTIBYTE */ + +/* Find next `count' characters started byte point of the specified seed. + If flags is MB_FIND_NONZERO, we look for non-zero-width multibyte + characters. */ +#undef _rl_find_next_mbchar +int +_rl_find_next_mbchar (string, seed, count, flags) + char *string; + int seed, count, flags; +{ +#if defined (HANDLE_MULTIBYTE) + return _rl_find_next_mbchar_internal (string, seed, count, flags); +#else + return (seed + count); +#endif +} + +/* Find previous character started byte point of the specified seed. + Returned point will be point <= seed. If flags is MB_FIND_NONZERO, + we look for non-zero-width multibyte characters. */ +#undef _rl_find_prev_mbchar +int +_rl_find_prev_mbchar (string, seed, flags) + char *string; + int seed, flags; +{ +#if defined (HANDLE_MULTIBYTE) + return _rl_find_prev_mbchar_internal (string, seed, flags); +#else + return ((seed == 0) ? seed : seed - 1); +#endif +} diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index 6da935af9..8e1079940 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -34,6 +34,7 @@ * * *************************************************************************/ +#define EMACS_MODE() (rl_editing_mode == emacs_mode) #define VI_COMMAND_MODE() (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) #define VI_INSERT_MODE() (rl_editing_mode == vi_mode && _rl_keymap == vi_insertion_keymap) diff --git a/lib/readline/rlprivate.h~ b/lib/readline/rlprivate.h~ index 520fd5b19..6da935af9 100644 --- a/lib/readline/rlprivate.h~ +++ b/lib/readline/rlprivate.h~ @@ -34,8 +34,8 @@ * * *************************************************************************/ -#define VI_COMMAND_MODE (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) -#define VI_INSERT_MODE (rl_editing_mode == vi_mode && _rl_keymap == vi_insertion_keymap) +#define VI_COMMAND_MODE() (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) +#define VI_INSERT_MODE() (rl_editing_mode == vi_mode && _rl_keymap == vi_insertion_keymap) /************************************************************************* * * diff --git a/lib/readline/text.c b/lib/readline/text.c index 32a1cc413..502925855 100644 --- a/lib/readline/text.c +++ b/lib/readline/text.c @@ -296,6 +296,12 @@ rl_forward_char (count, key) if (count > 0) { + if (rl_point == rl_end && EMACS_MODE()) + { + rl_ding (); + return 0; + } + point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); #if defined (VI_MODE) diff --git a/lib/readline/text.c~ b/lib/readline/text.c~ index f636e872e..32dfde818 100644 --- a/lib/readline/text.c~ +++ b/lib/readline/text.c~ @@ -296,6 +296,12 @@ rl_forward_char (count, key) if (count > 0) { + if (rl_point == rl_end && EMACS_MODE) + { + rl_ding (); + return 0; + } + point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); #if defined (VI_MODE) @@ -857,6 +863,9 @@ _rl_insert_next (count) c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (c < 0) + return -1; + #if defined (HANDLE_SIGNALS) if (RL_ISSTATE (RL_STATE_CALLBACK) == 0) _rl_restore_tty_signals (); @@ -1520,6 +1529,9 @@ _rl_char_search (count, fdir, bdir) mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX); + if (mb_len <= 0) + return -1; + if (count < 0) return (_rl_char_search_internal (-count, bdir, mbchar, mb_len)); else @@ -1536,6 +1548,9 @@ _rl_char_search (count, fdir, bdir) c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (c < 0) + return -1; + if (count < 0) return (_rl_char_search_internal (-count, bdir, c)); else diff --git a/lib/readline/util.c b/lib/readline/util.c index ad15394c4..396007f43 100644 --- a/lib/readline/util.c +++ b/lib/readline/util.c @@ -278,6 +278,7 @@ _rl_errmsg (va_alist) va_end (args); } + #else /* !USE_VARARGS */ void _rl_ttymsg (format, arg1, arg2) @@ -443,3 +444,60 @@ _rl_savestring (s) { return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s))); } + +#if defined (USE_VARARGS) +static FILE *_rl_tracefp; + +void +#if defined (PREFER_STDARG) +_rl_trace (const char *format, ...) +#else +_rl_trace (va_alist) + va_dcl +#endif +{ + va_list args; +#if defined (PREFER_VARARGS) + char *format; +#endif + +#if defined (PREFER_STDARG) + va_start (args, format); +#else + va_start (args); + format = va_arg (args, char *); +#endif + + if (_rl_tracefp == 0) + _rl_tropen (); + vfprintf (_rl_tracefp, format, args); + fprintf (_rl_tracefp, "\n"); + fflush (_rl_tracefp); + + va_end (args); +} + +int +_rl_tropen () +{ + char fnbuf[128]; + + if (_rl_tracefp) + fclose (_rl_tracefp); + sprintf (fnbuf, "/var/tmp/rltrace.%ld", getpid()); + unlink(fnbuf); + _rl_tracefp = fopen (fnbuf, "w+"); + return _rl_tracefp != 0; +} + +int +_rl_trclose () +{ + int r; + + r = fclose (_rl_tracefp); + _rl_tracefp = 0; + return r; +} + +#endif diff --git a/lib/readline/util.c~ b/lib/readline/util.c~ index bdc2e13fb..d166ecf12 100644 --- a/lib/readline/util.c~ +++ b/lib/readline/util.c~ @@ -66,7 +66,7 @@ in words, or 1 if it is. */ int _rl_allow_pathname_alphabetic_chars = 0; -static const char *pathname_alphabetic_chars = "/-_=~.#$"; +static const char * const pathname_alphabetic_chars = "/-_=~.#$"; int rl_alphabetic (c) @@ -278,6 +278,7 @@ _rl_errmsg (va_alist) va_end (args); } + #else /* !USE_VARARGS */ void _rl_ttymsg (format, arg1, arg2) @@ -443,3 +444,58 @@ _rl_savestring (s) { return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s))); } + +#if defined (USE_VARARGS) +static FILE *_rl_tracefp; + +void +#if defined (PREFER_STDARG) +_rl_trace (const char *format, ...) +#else +_rl_trace (va_alist) + va_dcl +#endif +{ + va_list args; +#if defined (PREFER_VARARGS) + char *format; +#endif + +#if defined (PREFER_STDARG) + va_start (args, format); +#else + va_start (args); + format = va_arg (args, char *); +#endif + + if (_rl_tracefp == 0) + _rl_tropen (); + vfprintf (_rl_tracefp, format, args); + fprintf (_rl_tracefp, "\n"); + fflush (_rl_tracefp); + + va_end (args); +} + +int +_rl_tropen () +{ + char fnbuf[128]; + + sprintf (fnbuf, "/var/tmp/rltrace.%ld", getpid()); + unlink(fnbuf); + _rl_tracefp = fopen (fnbuf, "w+"); + return _rl_tracefp != 0; +} + +int +_rl_trclose () +{ + int r; + + r = fclose (_rl_tracefp); + _rl_tracefp = 0; + return r; +} + +#endif diff --git a/parse.y b/parse.y index b8d6372de..c28857b1f 100644 --- a/parse.y +++ b/parse.y @@ -1,6 +1,6 @@ /* Yacc grammar for bash. */ -/* Copyright (C) 1989-2006 Free Software Foundation, Inc. +/* Copyright (C) 1989-2007 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -3376,7 +3376,7 @@ read_token_word (character) if (pass_next_character) { pass_next_character = 0; - goto got_character; + goto got_escaped_character; } cd = current_delimiter (dstack); @@ -3650,12 +3650,14 @@ read_token_word (character) got_character: - all_digit_token &= DIGIT (character); - dollar_present |= character == '$'; - if (character == CTLESC || character == CTLNUL) token[token_index++] = CTLESC; + got_escaped_character: + + all_digit_token &= DIGIT (character); + dollar_present |= character == '$'; + token[token_index++] = character; RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size, diff --git a/parse.y~ b/parse.y~ index 7a83d46fb..56e5ee29b 100644 --- a/parse.y~ +++ b/parse.y~ @@ -1,6 +1,6 @@ /* Yacc grammar for bash. */ -/* Copyright (C) 1989-2006 Free Software Foundation, Inc. +/* Copyright (C) 1989-2007 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -3375,8 +3375,9 @@ read_token_word (character) if (pass_next_character) { +itrace("read_token_word: pass_next_character = 1 read %c (%d)", character, character); pass_next_character = 0; - goto got_character; + goto got_escaped_character; } cd = current_delimiter (dstack); @@ -3650,12 +3651,14 @@ read_token_word (character) got_character: - all_digit_token &= DIGIT (character); - dollar_present |= character == '$'; - if (character == CTLESC || character == CTLNUL) token[token_index++] = CTLESC; + got_escaped_character: + + all_digit_token &= DIGIT (character); + dollar_present |= character == '$'; + token[token_index++] = character; RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size, @@ -3859,7 +3862,7 @@ reset_readline_prompt () /* A list of tokens which can be followed by newlines, but not by semi-colons. When concatenating multiple lines of history, the newline separator for such tokens is replaced with a space. */ -static int no_semi_successors[] = { +static const int no_semi_successors[] = { '\n', '{', '(', ')', ';', '&', '|', CASE, DO, ELSE, IF, SEMI_SEMI, THEN, UNTIL, WHILE, AND_AND, OR_OR, IN, 0 diff --git a/patchlevel.h b/patchlevel.h index e1c2c8abd..0c2b52409 100644 --- a/patchlevel.h +++ b/patchlevel.h @@ -1,6 +1,6 @@ /* patchlevel.h -- current bash patch level */ -/* Copyright (C) 2001-2006 Free Software Foundation, Inc. +/* Copyright (C) 2001-2007 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -25,6 +25,6 @@ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh looks for to find the patch level (for the sccs version string). */ -#define PATCHLEVEL 9 +#define PATCHLEVEL 15 #endif /* _PATCHLEVEL_H_ */ diff --git a/patchlevel.h~ b/patchlevel.h~ index 97207aea0..e1c2c8abd 100644 --- a/patchlevel.h~ +++ b/patchlevel.h~ @@ -25,6 +25,6 @@ regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh looks for to find the patch level (for the sccs version string). */ -#define PATCHLEVEL 5 +#define PATCHLEVEL 9 #endif /* _PATCHLEVEL_H_ */ -- 2.47.3