X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=readline%2Finput.c;h=95ace842ba20e00f1bce6783b977898921915166;hb=627d4cc2546b4b52bf9d7184927ac4ab5bdcaa83;hp=841f05d1af9ccf55a7cae4cc59beee899c6f0e3a;hpb=9255ee3150832d7e235fc0711f0efa70700559e7;p=deliverable%2Fbinutils-gdb.git diff --git a/readline/input.c b/readline/input.c index 841f05d1af..95ace842ba 100644 --- a/readline/input.c +++ b/readline/input.c @@ -1,26 +1,30 @@ /* input.c -- character input functions for readline. */ -/* Copyright (C) 1994 Free Software Foundation, Inc. +/* Copyright (C) 1994-2017 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. + This file is part of the GNU Readline Library (Readline), 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 + Readline 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 3 of the License, 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 + Readline 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. */ + You should have received a copy of the GNU General Public License + along with Readline. If not, see . +*/ + #define READLINE_LIBRARY +#if defined (__TANDEM) +# include +#endif + #if defined (HAVE_CONFIG_H) # include #endif @@ -41,14 +45,9 @@ # include "ansi_stdlib.h" #endif /* HAVE_STDLIB_H */ -#if defined (HAVE_SELECT) -# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX) -# include -# endif -#endif /* HAVE_SELECT */ -#if defined (HAVE_SYS_SELECT_H) -# include -#endif +#include + +#include "posixselect.h" #if defined (FIONREAD_IN_SYS_IOCTL) # include @@ -77,10 +76,21 @@ extern int errno; # define O_NDELAY O_NONBLOCK /* Posix style */ #endif +#if defined (HAVE_PSELECT) +extern sigset_t _rl_orig_sigset; +#endif + /* Non-null means it is a pointer to a function to run while waiting for character input. */ rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL; +/* A function to call if a read(2) is interrupted by a signal. */ +rl_hook_func_t *rl_signal_event_hook = (rl_hook_func_t *)NULL; + +/* A function to replace _rl_input_available for applications using the + callback interface. */ +rl_hook_func_t *rl_input_available_hook = (rl_hook_func_t *)NULL; + rl_getc_func_t *rl_getc_function = rl_getc; static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */ @@ -89,6 +99,37 @@ static int ibuffer_space PARAMS((void)); static int rl_get_char PARAMS((int *)); static int rl_gather_tyi PARAMS((void)); +#if defined (_WIN32) && !defined (__CYGWIN__) + +/* 'isatty' in the Windows runtime returns non-zero for every + character device, including the null device. Repair that. */ +#include +#include +#define WIN32_LEAN_AND_MEAN 1 +#include + +int w32_isatty (int fd) +{ + if (_isatty(fd)) + { + HANDLE h; + DWORD ignored; + + if ((h = (HANDLE) _get_osfhandle (fd)) == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return 0; + } + if (GetConsoleMode (h, &ignored) != 0) + return 1; + } + errno = ENOTTY; + return 0; +} + +#define isatty(x) w32_isatty(x) +#endif + /* **************************************************************** */ /* */ /* Character Input Buffering */ @@ -102,15 +143,21 @@ static int ibuffer_len = sizeof (ibuffer) - 1; #define any_typein (push_index != pop_index) int -_rl_any_typein () +_rl_any_typein (void) { return any_typein; } +int +_rl_pushed_input_available (void) +{ + return (push_index != pop_index); +} + /* Return the amount of space available in the buffer for stuffing characters. */ static int -ibuffer_space () +ibuffer_space (void) { if (pop_index > push_index) return (pop_index - push_index - 1); @@ -120,17 +167,19 @@ ibuffer_space () /* Get a key from the buffer of characters to be read. Return the key in KEY. - Result is KEY if there was a key, or 0 if there wasn't. */ + Result is non-zero if there was a key, or 0 if there wasn't. */ static int -rl_get_char (key) - int *key; +rl_get_char (int *key) { if (push_index == pop_index) return (0); *key = ibuffer[pop_index++]; - +#if 0 if (pop_index >= ibuffer_len) +#else + if (pop_index > ibuffer_len) +#endif pop_index = 0; return (1); @@ -140,14 +189,13 @@ rl_get_char (key) Returns non-zero if successful, zero if there is no space left in the buffer. */ int -_rl_unget_char (key) - int key; +_rl_unget_char (int key) { if (ibuffer_space ()) { pop_index--; if (pop_index < 0) - pop_index = ibuffer_len - 1; + pop_index = ibuffer_len; ibuffer[pop_index] = key; return (1); } @@ -158,17 +206,19 @@ _rl_unget_char (key) IBUFFER. Otherwise, just return. Returns number of characters read (0 if none available) and -1 on error (EIO). */ static int -rl_gather_tyi () +rl_gather_tyi (void) { int tty; register int tem, result; - int chars_avail; + int chars_avail, k; char input; #if defined(HAVE_SELECT) fd_set readfds, exceptfds; struct timeval timeout; #endif + chars_avail = 0; + input = 0; tty = fileno (rl_instream); #if defined (HAVE_SELECT) @@ -176,19 +226,20 @@ rl_gather_tyi () FD_ZERO (&exceptfds); FD_SET (tty, &readfds); FD_SET (tty, &exceptfds); - timeout.tv_sec = 0; - timeout.tv_usec = _keyboard_input_timeout; + USEC_TO_TIMEVAL (_keyboard_input_timeout, timeout); result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout); if (result <= 0) return 0; /* Nothing to read. */ #endif result = -1; -#if defined (FIONREAD) errno = 0; +#if defined (FIONREAD) result = ioctl (tty, FIONREAD, &chars_avail); if (result == -1 && errno == EIO) return -1; + if (result == -1) + chars_avail = 0; #endif #if defined (O_NDELAY) @@ -202,9 +253,23 @@ rl_gather_tyi () fcntl (tty, F_SETFL, tem); if (chars_avail == -1 && errno == EAGAIN) return 0; + if (chars_avail == -1 && errno == EIO) + return -1; + if (chars_avail == 0) /* EOF */ + { + rl_stuff_char (EOF); + return (0); + } } #endif /* O_NDELAY */ +#if defined (__MINGW32__) + /* Use getch/_kbhit to check for available console input, in the same way + that we read it normally. */ + chars_avail = isatty (tty) ? _kbhit () : 0; + result = 0; +#endif + /* If there's nothing available, don't waste time trying to read something. */ if (chars_avail <= 0) @@ -225,7 +290,14 @@ rl_gather_tyi () if (result != -1) { while (chars_avail--) - rl_stuff_char ((*rl_getc_function) (rl_instream)); + { + RL_CHECK_SIGNALS (); + k = (*rl_getc_function) (rl_instream); + if (rl_stuff_char (k) == 0) + break; /* some problem; no more room */ + if (k == NEWLINE || k == RETURN) + break; + } } else { @@ -237,13 +309,12 @@ rl_gather_tyi () } int -rl_set_keyboard_input_timeout (u) - int u; +rl_set_keyboard_input_timeout (int u) { int o; o = _keyboard_input_timeout; - if (u > 0) + if (u >= 0) _keyboard_input_timeout = u; return (o); } @@ -255,7 +326,7 @@ rl_set_keyboard_input_timeout (u) the user, it should use _rl_input_queued(timeout_value_in_microseconds) instead. */ int -_rl_input_available () +_rl_input_available (void) { #if defined(HAVE_SELECT) fd_set readfds, exceptfds; @@ -266,6 +337,9 @@ _rl_input_available () #endif int tty; + if (rl_input_available_hook) + return (*rl_input_available_hook) (); + tty = fileno (rl_instream); #if defined (HAVE_SELECT) @@ -283,14 +357,18 @@ _rl_input_available () return (chars_avail); #endif +#endif + +#if defined (__MINGW32__) + if (isatty (tty)) + return (_kbhit ()); #endif return 0; } int -_rl_input_queued (t) - int t; +_rl_input_queued (int t) { int old_timeout, r; @@ -301,8 +379,7 @@ _rl_input_queued (t) } void -_rl_insert_typein (c) - int c; +_rl_insert_typein (int c) { int key, t, i; char *string; @@ -321,14 +398,13 @@ _rl_insert_typein (c) string[i] = '\0'; rl_insert_text (string); - free (string); + xfree (string); } /* Add KEY to the buffer of characters to be read. Returns 1 if the character was stuffed correctly; 0 otherwise. */ int -rl_stuff_char (key) - int key; +rl_stuff_char (int key) { if (ibuffer_space () == 0) return 0; @@ -340,7 +416,11 @@ rl_stuff_char (key) RL_SETSTATE (RL_STATE_INPUTPENDING); } ibuffer[push_index++] = key; +#if 0 if (push_index >= ibuffer_len) +#else + if (push_index > ibuffer_len) +#endif push_index = 0; return 1; @@ -348,8 +428,7 @@ rl_stuff_char (key) /* Make C be the next command to be executed. */ int -rl_execute_next (c) - int c; +rl_execute_next (int c) { rl_pending_input = c; RL_SETSTATE (RL_STATE_INPUTPENDING); @@ -358,7 +437,7 @@ rl_execute_next (c) /* Clear any pending input pushed with rl_execute_next() */ int -rl_clear_pending_input () +rl_clear_pending_input (void) { rl_pending_input = 0; RL_UNSETSTATE (RL_STATE_INPUTPENDING); @@ -373,42 +452,49 @@ rl_clear_pending_input () /* Read a key, including pending input. */ int -rl_read_key () +rl_read_key (void) { - int c; - - rl_key_sequence_length++; + int c, r; if (rl_pending_input) { - c = rl_pending_input; + c = rl_pending_input; /* XXX - cast to unsigned char if > 0? */ rl_clear_pending_input (); } else { /* If input is coming from a macro, then use that. */ if (c = _rl_next_macro_key ()) - return (c); + return ((unsigned char)c); /* If the user has an event function, then call it periodically. */ if (rl_event_hook) { - while (rl_event_hook && rl_get_char (&c) == 0) + while (rl_event_hook) { - (*rl_event_hook) (); - if (rl_done) /* XXX - experimental */ - return ('\n'); - if (rl_gather_tyi () < 0) /* XXX - EIO */ + if (rl_get_char (&c) != 0) + break; + + if ((r = rl_gather_tyi ()) < 0) /* XXX - EIO */ { rl_done = 1; - return ('\n'); + return (errno == EIO ? (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF) : '\n'); } + else if (r > 0) /* read something */ + continue; + + RL_CHECK_SIGNALS (); + if (rl_done) /* XXX - experimental */ + return ('\n'); + (*rl_event_hook) (); } } else { if (rl_get_char (&c) == 0) c = (*rl_getc_function) (rl_instream); +/* fprintf(stderr, "rl_read_key: calling RL_CHECK_SIGNALS: _rl_caught_signal = %d", _rl_caught_signal); */ + RL_CHECK_SIGNALS (); } } @@ -416,15 +502,39 @@ rl_read_key () } int -rl_getc (stream) - FILE *stream; +rl_getc (FILE *stream) { int result; unsigned char c; +#if defined (HAVE_PSELECT) + sigset_t empty_set; + fd_set readfds; +#endif while (1) { - result = read (fileno (stream), &c, sizeof (unsigned char)); + RL_CHECK_SIGNALS (); + + /* We know at this point that _rl_caught_signal == 0 */ + +#if defined (__MINGW32__) + if (isatty (fileno (stream))) + return (_getch ()); /* "There is no error return." */ +#endif + result = 0; +#if defined (HAVE_PSELECT) + FD_ZERO (&readfds); + FD_SET (fileno (stream), &readfds); +# if defined (HANDLE_SIGNALS) + result = pselect (fileno (stream) + 1, &readfds, NULL, NULL, NULL, &_rl_orig_sigset); +# else + sigemptyset (&empty_set); + sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &empty_set); + result = pselect (fileno (stream) + 1, &readfds, NULL, NULL, NULL, &empty_set); +# endif /* HANDLE_SIGNALS */ +#endif + if (result >= 0) + result = read (fileno (stream), &c, sizeof (unsigned char)); if (result == sizeof (unsigned char)) return (c); @@ -461,35 +571,75 @@ rl_getc (stream) #undef X_EWOULDBLOCK #undef X_EAGAIN - /* If the error that we received was SIGINT, then try again, - this is simply an interrupted system call to read (). - Otherwise, some error ocurred, also signifying EOF. */ +/* fprintf(stderr, "rl_getc: result = %d errno = %d\n", result, errno); */ + +handle_error: + /* If the error that we received was EINTR, then try again, + this is simply an interrupted system call to read (). We allow + the read to be interrupted if we caught SIGHUP, SIGTERM, or any + of the other signals readline treats specially. If the + application sets an event hook, call it for other signals. + Otherwise (not EINTR), some error occurred, also signifying EOF. */ if (errno != EINTR) - return (EOF); + return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); + /* fatal signals of interest */ +#if defined (SIGHUP) + else if (_rl_caught_signal == SIGHUP || _rl_caught_signal == SIGTERM) +#else + else if (_rl_caught_signal == SIGTERM) +#endif + return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); + /* keyboard-generated signals of interest */ +#if defined (SIGQUIT) + else if (_rl_caught_signal == SIGINT || _rl_caught_signal == SIGQUIT) +#else + else if (_rl_caught_signal == SIGINT) +#endif + RL_CHECK_SIGNALS (); + /* non-keyboard-generated signals of interest */ +#if defined (SIGWINCH) + else if (_rl_caught_signal == SIGWINCH) + RL_CHECK_SIGNALS (); +#endif /* SIGWINCH */ +#if defined (SIGALRM) + else if (_rl_caught_signal == SIGALRM +# if defined (SIGVTALRM) + || _rl_caught_signal == SIGVTALRM +# endif + ) + RL_CHECK_SIGNALS (); +#endif /* SIGALRM */ + + if (rl_signal_event_hook) + (*rl_signal_event_hook) (); } } #if defined (HANDLE_MULTIBYTE) /* read multibyte char */ int -_rl_read_mbchar (mbchar, size) - char *mbchar; - int size; +_rl_read_mbchar (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 */ @@ -499,6 +649,12 @@ _rl_read_mbchar (mbchar, size) ps = ps_back; continue; } + else if (mbchar_bytes_length == 0) + { + mbchar[0] = '\0'; /* null wide character */ + mb_len = 1; + break; + } else if (mbchar_bytes_length > (size_t)(0)) break; } @@ -507,25 +663,23 @@ _rl_read_mbchar (mbchar, size) } /* Read a multibyte-character string whose first character is FIRST into - the buffer MB of length MBLEN. Returns the last character read, which + the buffer MB of length MLEN. Returns the last character read, which may be FIRST. Used by the search functions, among others. Very similar to _rl_read_mbchar. */ int -_rl_read_mbstring (first, mb, mblen) - int first; - char *mb; - int mblen; +_rl_read_mbstring (int first, char *mb, int mlen) { - int i, c; + int i, c, n; mbstate_t ps; c = first; - memset (mb, 0, mblen); - for (i = 0; i < mblen; i++) + memset (mb, 0, mlen); + for (i = 0; c >= 0 && i < mlen; i++) { mb[i] = (char)c; memset (&ps, 0, sizeof (mbstate_t)); - if (_rl_get_char_len (mb, &ps) == -2) + n = _rl_get_char_len (mb, &ps); + if (n == -2) { /* Read more for multibyte character */ RL_SETSTATE (RL_STATE_MOREINPUT);