X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=readline%2Finput.c;h=95ace842ba20e00f1bce6783b977898921915166;hb=627d4cc2546b4b52bf9d7184927ac4ab5bdcaa83;hp=3b48483d2625a705d8ddd1c8186cdcc6f48b34fd;hpb=abd8680d6efd97e7ba848a6392ee3ad72be18cd0;p=deliverable%2Fbinutils-gdb.git diff --git a/readline/input.c b/readline/input.c index 3b48483d26..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, - 675 Mass Ave, Cambridge, MA 02139, 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 @@ -63,48 +62,73 @@ extern int errno; /* System-specific feature definitions and include files. */ #include "rldefs.h" +#include "rlmbutil.h" /* Some standard library routines. */ #include "readline.h" +#include "rlprivate.h" +#include "rlshell.h" +#include "xmalloc.h" + /* What kind of non-blocking I/O do we have? */ #if !defined (O_NDELAY) && defined (O_NONBLOCK) # define O_NDELAY O_NONBLOCK /* Posix style */ #endif -/* Functions imported from other files in the library. */ -extern char *xmalloc (), *xrealloc (); +#if defined (HAVE_PSELECT) +extern sigset_t _rl_orig_sigset; +#endif -/* Variables and functions from macro.c. */ -extern void _rl_add_macro_char (); -extern void _rl_with_macro_input (); -extern int _rl_next_macro_key (); -extern int _rl_defining_kbd_macro; +/* 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; -#if defined (VI_MODE) -extern void _rl_vi_set_last (); -extern int _rl_vi_textmod_command (); -#endif /* VI_MODE */ +/* 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; -extern FILE *rl_instream, *rl_outstream; -extern Function *rl_last_func; -extern int rl_key_sequence_length; -extern int rl_pending_input; -extern int rl_editing_mode; +/* 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; -extern Keymap _rl_keymap; +rl_getc_func_t *rl_getc_function = rl_getc; -extern int _rl_convert_meta_chars_to_ascii; +static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */ -#if defined (__GO32__) -# include -#endif /* __GO32__ */ +static int ibuffer_space PARAMS((void)); +static int rl_get_char PARAMS((int *)); +static int rl_gather_tyi PARAMS((void)); -/* Non-null means it is a pointer to a function to run while waiting for - character input. */ -Function *rl_event_hook = (Function *)NULL; +#if defined (_WIN32) && !defined (__CYGWIN__) -Function *rl_getc_function = rl_getc; +/* '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 /* **************************************************************** */ /* */ @@ -119,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); @@ -137,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); @@ -156,46 +188,37 @@ rl_get_char (key) /* Stuff KEY into the *front* of the input buffer. Returns non-zero if successful, zero if there is no space left in the buffer. */ -static int -rl_unget_char (key) - int key; +int +_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); } return (0); } -/* If a character is available to be read, then read it - and stuff it into IBUFFER. Otherwise, just return. */ -static void -rl_gather_tyi () +/* If a character is available to be read, then read it and stuff it into + IBUFFER. Otherwise, just return. Returns number of characters read + (0 if none available) and -1 on error (EIO). */ +static int +rl_gather_tyi (void) { -#if defined (__GO32__) - char input; - - if (isatty (0) && kbhit () && ibuffer_space ()) - { - int i; - i = (*rl_getc_function) (rl_instream); - rl_stuff_char (i); - } -#else /* !__GO32__ */ - 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) @@ -203,15 +226,20 @@ rl_gather_tyi () FD_ZERO (&exceptfds); FD_SET (tty, &readfds); FD_SET (tty, &exceptfds); - timeout.tv_sec = 0; - timeout.tv_usec = 100000; /* 0.1 seconds */ - if (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) <= 0) - return; /* Nothing to read. */ + 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; + 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) @@ -224,14 +252,28 @@ rl_gather_tyi () fcntl (tty, F_SETFL, tem); if (chars_avail == -1 && errno == EAGAIN) - return; + 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) - return; + return 0; tem = ibuffer_space (); @@ -248,30 +290,56 @@ 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 { if (chars_avail) rl_stuff_char (input); } -#endif /* !__GO32__ */ + + return 1; +} + +int +rl_set_keyboard_input_timeout (int u) +{ + int o; + + o = _keyboard_input_timeout; + if (u >= 0) + _keyboard_input_timeout = u; + return (o); } /* Is there input available to be read on the readline input file - descriptor? Only works if the system has select(2) or FIONREAD. */ + descriptor? Only works if the system has select(2) or FIONREAD. + Uses the value of _keyboard_input_timeout as the timeout; if another + readline function wants to specify a timeout and not leave it up to + 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; struct timeval timeout; #endif -#if defined(FIONREAD) +#if !defined (HAVE_SELECT) && defined(FIONREAD) int chars_avail; #endif int tty; + if (rl_input_available_hook) + return (*rl_input_available_hook) (); + tty = fileno (rl_instream); #if defined (HAVE_SELECT) @@ -280,27 +348,44 @@ _rl_input_available () FD_SET (tty, &readfds); FD_SET (tty, &exceptfds); timeout.tv_sec = 0; - timeout.tv_usec = 100000; /* 0.1 seconds */ + timeout.tv_usec = _keyboard_input_timeout; return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0); -#endif +#else #if defined (FIONREAD) if (ioctl (tty, FIONREAD, &chars_avail) == 0) return (chars_avail); #endif +#endif + +#if defined (__MINGW32__) + if (isatty (tty)) + return (_kbhit ()); +#endif + return 0; } +int +_rl_input_queued (int t) +{ + int old_timeout, r; + + old_timeout = rl_set_keyboard_input_timeout (t); + r = _rl_input_available (); + rl_set_keyboard_input_timeout (old_timeout); + return r; +} + void -_rl_insert_typein (c) - int c; +_rl_insert_typein (int c) { int key, t, i; char *string; i = key = 0; - string = xmalloc (ibuffer_len + 1); + string = (char *)xmalloc (ibuffer_len + 1); string[i++] = (char) c; while ((t = rl_get_char (&key)) && @@ -309,18 +394,17 @@ _rl_insert_typein (c) string[i++] = key; if (t) - rl_unget_char (key); + _rl_unget_char (key); 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; @@ -329,9 +413,14 @@ rl_stuff_char (key) { key = NEWLINE; rl_pending_input = EOF; + 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; @@ -339,10 +428,19 @@ 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); + return 0; +} + +/* Clear any pending input pushed with rl_execute_next() */ +int +rl_clear_pending_input (void) +{ + rl_pending_input = 0; + RL_UNSETSTATE (RL_STATE_INPUTPENDING); return 0; } @@ -354,36 +452,49 @@ rl_execute_next (c) /* 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; - rl_pending_input = 0; + 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) { + if (rl_get_char (&c) != 0) + break; + + if ((r = rl_gather_tyi ()) < 0) /* XXX - EIO */ + { + rl_done = 1; + 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) (); - rl_gather_tyi (); } } 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 (); } } @@ -391,20 +502,39 @@ rl_read_key () } int -rl_getc (stream) - FILE *stream; +rl_getc (FILE *stream) { - int result, flags; + int result; unsigned char c; - -#if defined (__GO32__) - if (isatty (0)) - return (getkey () & 0x7F); -#endif /* __GO32__ */ +#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); @@ -420,40 +550,145 @@ rl_getc (stream) #endif #if defined (EWOULDBLOCK) - if (errno == EWOULDBLOCK) +# define X_EWOULDBLOCK EWOULDBLOCK +#else +# define X_EWOULDBLOCK -99 +#endif + +#if defined (EAGAIN) +# define X_EAGAIN EAGAIN +#else +# define X_EAGAIN -99 +#endif + + if (errno == X_EWOULDBLOCK || errno == X_EAGAIN) { - if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0) + if (sh_unset_nodelay_mode (fileno (stream)) < 0) return (EOF); - if (flags & O_NDELAY) - { - flags &= ~O_NDELAY; - fcntl (fileno (stream), F_SETFL, flags); - continue; - } continue; } -#endif /* EWOULDBLOCK */ -#if defined (_POSIX_VERSION) && defined (EAGAIN) && defined (O_NONBLOCK) - if (errno == EAGAIN) +#undef X_EWOULDBLOCK +#undef X_EAGAIN + +/* 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 (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 (char *mbchar, int size) +{ + 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); + 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 */ + else if (mbchar_bytes_length == (size_t)(-2)) { - if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0) - return (EOF); - if (flags & O_NONBLOCK) - { - flags &= ~O_NONBLOCK; - fcntl (fileno (stream), F_SETFL, flags); - continue; - } + /* shorted bytes */ + ps = ps_back; + continue; + } + else if (mbchar_bytes_length == 0) + { + mbchar[0] = '\0'; /* null wide character */ + mb_len = 1; + break; } -#endif /* _POSIX_VERSION && EAGAIN && O_NONBLOCK */ + else if (mbchar_bytes_length > (size_t)(0)) + break; + } -#if !defined (__GO32__) - /* 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. */ - if (errno != EINTR) - return (EOF); -#endif /* !__GO32__ */ + return mb_len; +} + +/* Read a multibyte-character string whose first character is FIRST into + 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 (int first, char *mb, int mlen) +{ + int i, c, n; + mbstate_t ps; + + c = first; + memset (mb, 0, mlen); + for (i = 0; c >= 0 && i < mlen; i++) + { + mb[i] = (char)c; + memset (&ps, 0, sizeof (mbstate_t)); + n = _rl_get_char_len (mb, &ps); + if (n == -2) + { + /* Read more for multibyte character */ + RL_SETSTATE (RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE (RL_STATE_MOREINPUT); + } + else + break; } + return c; } +#endif /* HANDLE_MULTIBYTE */