diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2011-04-08 16:24:33 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2011-04-08 16:24:33 +0000 |
commit | b667555541a4d65bb9dae6f0e0f240e6a05b148e (patch) | |
tree | b3ae5c92f04ae68fbf9580d6efcf1a1510851495 /readline-6.2/input.c | |
parent | 2011-04-08 Joel Sherrill <joel.sherrill@oarcorp.com> (diff) | |
download | rtems-addon-packages-b667555541a4d65bb9dae6f0e0f240e6a05b148e.tar.bz2 |
2011-04-08 Joel Sherrill <joel.sherrill@oarcorp.com>
* RTEMS_Makefiles/Makefile.readline-6.2, readline-6.2/CHANGELOG,
readline-6.2/CHANGES, readline-6.2/COPYING, readline-6.2/INSTALL,
readline-6.2/MANIFEST, readline-6.2/Makefile.in, readline-6.2/NEWS,
readline-6.2/README, readline-6.2/USAGE, readline-6.2/aclocal.m4,
readline-6.2/ansi_stdlib.h, readline-6.2/bind.c,
readline-6.2/callback.c, readline-6.2/chardefs.h,
readline-6.2/compat.c, readline-6.2/complete.c,
readline-6.2/config.h.in, readline-6.2/configure,
readline-6.2/configure.in, readline-6.2/display.c,
readline-6.2/emacs_keymap.c, readline-6.2/funmap.c,
readline-6.2/histexpand.c, readline-6.2/histfile.c,
readline-6.2/histlib.h, readline-6.2/history.c,
readline-6.2/history.h, readline-6.2/histsearch.c,
readline-6.2/input.c, readline-6.2/isearch.c, readline-6.2/keymaps.c,
readline-6.2/keymaps.h, readline-6.2/kill.c, readline-6.2/macro.c,
readline-6.2/mbutil.c, readline-6.2/misc.c, readline-6.2/nls.c,
readline-6.2/parens.c, readline-6.2/patchlevel,
readline-6.2/posixdir.h, readline-6.2/posixjmp.h,
readline-6.2/posixselect.h, readline-6.2/posixstat.h,
readline-6.2/readline.c, readline-6.2/readline.h,
readline-6.2/rlconf.h, readline-6.2/rldefs.h,
readline-6.2/rlmbutil.h, readline-6.2/rlprivate.h,
readline-6.2/rlshell.h, readline-6.2/rlstdc.h, readline-6.2/rltty.c,
readline-6.2/rltty.h, readline-6.2/rltypedefs.h,
readline-6.2/rlwinsize.h, readline-6.2/savestring.c,
readline-6.2/search.c, readline-6.2/shell.c, readline-6.2/signals.c,
readline-6.2/tcap.h, readline-6.2/terminal.c, readline-6.2/text.c,
readline-6.2/tilde.c, readline-6.2/tilde.h, readline-6.2/undo.c,
readline-6.2/util.c, readline-6.2/vi_keymap.c,
readline-6.2/vi_mode.c, readline-6.2/xfree.c, readline-6.2/xmalloc.c,
readline-6.2/xmalloc.h, readline-6.2/doc/Makefile.in,
readline-6.2/doc/fdl.texi, readline-6.2/doc/history.0,
readline-6.2/doc/history.3, readline-6.2/doc/history.dvi,
readline-6.2/doc/history.html, readline-6.2/doc/history.info,
readline-6.2/doc/history.pdf, readline-6.2/doc/history.ps,
readline-6.2/doc/history.texi, readline-6.2/doc/history_3.ps,
readline-6.2/doc/hstech.texi, readline-6.2/doc/hsuser.texi,
readline-6.2/doc/readline.0, readline-6.2/doc/readline.3,
readline-6.2/doc/readline.dvi, readline-6.2/doc/readline.html,
readline-6.2/doc/readline.info, readline-6.2/doc/readline.pdf,
readline-6.2/doc/readline.ps, readline-6.2/doc/readline_3.ps,
readline-6.2/doc/rlman.texi, readline-6.2/doc/rltech.texi,
readline-6.2/doc/rluser.texi, readline-6.2/doc/rluserman.dvi,
readline-6.2/doc/rluserman.html, readline-6.2/doc/rluserman.info,
readline-6.2/doc/rluserman.pdf, readline-6.2/doc/rluserman.ps,
readline-6.2/doc/rluserman.texi, readline-6.2/doc/texi2dvi,
readline-6.2/doc/texi2html, readline-6.2/doc/texinfo.tex,
readline-6.2/doc/version.texi, readline-6.2/examples/Inputrc,
readline-6.2/examples/Makefile.in,
readline-6.2/examples/excallback.c, readline-6.2/examples/fileman.c,
readline-6.2/examples/histexamp.c, readline-6.2/examples/manexamp.c,
readline-6.2/examples/readlinebuf.h,
readline-6.2/examples/rl-fgets.c, readline-6.2/examples/rl.c,
readline-6.2/examples/rlcat.c, readline-6.2/examples/rlevent.c,
readline-6.2/examples/rlptytest.c, readline-6.2/examples/rltest.c,
readline-6.2/examples/rlversion.c,
readline-6.2/examples/rlwrap-0.30.tar.gz,
readline-6.2/examples/autoconf/BASH_CHECK_LIB_TERMCAP,
readline-6.2/examples/autoconf/RL_LIB_READLINE_VERSION,
readline-6.2/examples/autoconf/wi_LIB_READLINE,
readline-6.2/examples/rlfe/ChangeLog,
readline-6.2/examples/rlfe/Makefile.in,
readline-6.2/examples/rlfe/README,
readline-6.2/examples/rlfe/config.h.in,
readline-6.2/examples/rlfe/configure,
readline-6.2/examples/rlfe/configure.in,
readline-6.2/examples/rlfe/extern.h, readline-6.2/examples/rlfe/os.h,
readline-6.2/examples/rlfe/pty.c, readline-6.2/examples/rlfe/rlfe.c,
readline-6.2/examples/rlfe/screen.h, readline-6.2/shlib/Makefile.in,
readline-6.2/support/config.guess, readline-6.2/support/config.rpath,
readline-6.2/support/config.sub, readline-6.2/support/install.sh,
readline-6.2/support/mkdirs, readline-6.2/support/mkdist,
readline-6.2/support/mkinstalldirs,
readline-6.2/support/shlib-install, readline-6.2/support/shobj-conf,
readline-6.2/support/wcwidth.c: New files.
Diffstat (limited to 'readline-6.2/input.c')
-rw-r--r-- | readline-6.2/input.c | 596 |
1 files changed, 596 insertions, 0 deletions
diff --git a/readline-6.2/input.c b/readline-6.2/input.c new file mode 100644 index 0000000..7c74c99 --- /dev/null +++ b/readline-6.2/input.c @@ -0,0 +1,596 @@ +/* input.c -- character input functions for readline. */ + +/* Copyright (C) 1994-2010 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library (Readline), a library + for reading lines of text with interactive input and history editing. + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with Readline. If not, see <http://www.gnu.org/licenses/>. +*/ + +#define READLINE_LIBRARY + +#if defined (__TANDEM) +# include <floss.h> +#endif + +#if defined (HAVE_CONFIG_H) +# include <config.h> +#endif + +#include <sys/types.h> +#include <fcntl.h> +#if defined (HAVE_SYS_FILE_H) +# include <sys/file.h> +#endif /* HAVE_SYS_FILE_H */ + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include <stdlib.h> +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include "posixselect.h" + +#if defined (FIONREAD_IN_SYS_IOCTL) +# include <sys/ioctl.h> +#endif + +#include <stdio.h> +#include <errno.h> + +#if !defined (errno) +extern int errno; +#endif /* !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 + +/* 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; + +rl_getc_func_t *rl_getc_function = rl_getc; + +static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */ + +static int ibuffer_space PARAMS((void)); +static int rl_get_char PARAMS((int *)); +static int rl_gather_tyi PARAMS((void)); + +/* **************************************************************** */ +/* */ +/* Character Input Buffering */ +/* */ +/* **************************************************************** */ + +static int pop_index, push_index; +static unsigned char ibuffer[512]; +static int ibuffer_len = sizeof (ibuffer) - 1; + +#define any_typein (push_index != pop_index) + +int +_rl_any_typein () +{ + return any_typein; +} + +/* Return the amount of space available in the buffer for stuffing + characters. */ +static int +ibuffer_space () +{ + if (pop_index > push_index) + return (pop_index - push_index - 1); + else + return (ibuffer_len - (push_index - pop_index)); +} + +/* 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. */ +static int +rl_get_char (key) + 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); +} + +/* Stuff KEY into the *front* of the input buffer. + Returns non-zero if successful, zero if there is + no space left in the buffer. */ +int +_rl_unget_char (key) + int key; +{ + if (ibuffer_space ()) + { + pop_index--; + if (pop_index < 0) + pop_index = ibuffer_len; + ibuffer[pop_index] = key; + return (1); + } + return (0); +} + +int +_rl_pushed_input_available () +{ + return (push_index != pop_index); +} + +/* 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 () +{ + int tty; + register int tem, result; + int chars_avail, k; + char input; +#if defined(HAVE_SELECT) + fd_set readfds, exceptfds; + struct timeval timeout; +#endif + + chars_avail = 0; + tty = fileno (rl_instream); + +#if defined (HAVE_SELECT) + FD_ZERO (&readfds); + FD_ZERO (&exceptfds); + FD_SET (tty, &readfds); + FD_SET (tty, &exceptfds); + 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; + result = ioctl (tty, FIONREAD, &chars_avail); + if (result == -1 && errno == EIO) + return -1; +#endif + +#if defined (O_NDELAY) + if (result == -1) + { + tem = fcntl (tty, F_GETFL, 0); + + fcntl (tty, F_SETFL, (tem | O_NDELAY)); + chars_avail = read (tty, &input, 1); + + fcntl (tty, F_SETFL, tem); + if (chars_avail == -1 && errno == EAGAIN) + return 0; + 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 0; + + tem = ibuffer_space (); + + if (chars_avail > tem) + chars_avail = tem; + + /* One cannot read all of the available input. I can only read a single + character at a time, or else programs which require input can be + thwarted. If the buffer is larger than one character, I lose. + Damn! */ + if (tem < ibuffer_len) + chars_avail = 0; + + if (result != -1) + { + while (chars_avail--) + { + 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); + } + + return 1; +} + +int +rl_set_keyboard_input_timeout (u) + 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. + 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 () +{ +#if defined(HAVE_SELECT) + fd_set readfds, exceptfds; + struct timeval timeout; +#endif +#if !defined (HAVE_SELECT) && defined(FIONREAD) + int chars_avail; +#endif + int tty; + + tty = fileno (rl_instream); + +#if defined (HAVE_SELECT) + FD_ZERO (&readfds); + FD_ZERO (&exceptfds); + FD_SET (tty, &readfds); + FD_SET (tty, &exceptfds); + timeout.tv_sec = 0; + timeout.tv_usec = _keyboard_input_timeout; + return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0); +#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 (t) + 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; +{ + int key, t, i; + char *string; + + i = key = 0; + string = (char *)xmalloc (ibuffer_len + 1); + string[i++] = (char) c; + + while ((t = rl_get_char (&key)) && + _rl_keymap[key].type == ISFUNC && + _rl_keymap[key].function == rl_insert) + string[i++] = key; + + if (t) + _rl_unget_char (key); + + string[i] = '\0'; + rl_insert_text (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; +{ + if (ibuffer_space () == 0) + return 0; + + if (key == EOF) + { + 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; +} + +/* Make C be the next command to be executed. */ +int +rl_execute_next (c) + 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 () +{ + rl_pending_input = 0; + RL_UNSETSTATE (RL_STATE_INPUTPENDING); + return 0; +} + +/* **************************************************************** */ +/* */ +/* Character Input */ +/* */ +/* **************************************************************** */ + +/* Read a key, including pending input. */ +int +rl_read_key () +{ + int c; + + rl_key_sequence_length++; + + if (rl_pending_input) + { + c = rl_pending_input; + rl_clear_pending_input (); + } + else + { + /* If input is coming from a macro, then use that. */ + if (c = _rl_next_macro_key ()) + return (c); + + /* If the user has an event function, then call it periodically. */ + if (rl_event_hook) + { + while (rl_event_hook) + { + if (rl_gather_tyi () < 0) /* XXX - EIO */ + { + rl_done = 1; + return ('\n'); + } + RL_CHECK_SIGNALS (); + if (rl_get_char (&c) != 0) + break; + if (rl_done) /* XXX - experimental */ + return ('\n'); + (*rl_event_hook) (); + } + } + else + { + if (rl_get_char (&c) == 0) + c = (*rl_getc_function) (rl_instream); + RL_CHECK_SIGNALS (); + } + } + + return (c); +} + +int +rl_getc (stream) + FILE *stream; +{ + int result; + unsigned char c; + + while (1) + { + RL_CHECK_SIGNALS (); + +#if defined (__MINGW32__) + if (isatty (fileno (stream))) + return (getch ()); +#endif + result = read (fileno (stream), &c, sizeof (unsigned char)); + + if (result == sizeof (unsigned char)) + return (c); + + /* If zero characters are returned, then the file that we are + reading from is empty! Return EOF in that case. */ + if (result == 0) + return (EOF); + +#if defined (__BEOS__) + if (errno == EINTR) + continue; +#endif + +#if defined (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 (sh_unset_nodelay_mode (fileno (stream)) < 0) + return (EOF); + continue; + } + +#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. */ + if (errno != EINTR) + return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); + } +} + +#if defined (HANDLE_MULTIBYTE) +/* read multibyte char */ +int +_rl_read_mbchar (mbchar, size) + 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)) + { + /* shorted bytes */ + 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; + } + + 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 (first, mb, mlen) + int first; + char *mb; + int mlen; +{ + int i, c; + 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)); + if (_rl_get_char_len (mb, &ps) == -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 */ |