diff options
author | Chet Ramey <chet.ramey@case.edu> | 2011-12-03 13:47:06 -0500 |
---|---|---|
committer | Chet Ramey <chet.ramey@case.edu> | 2011-12-03 13:47:06 -0500 |
commit | 19e1dd936da1a4a41c107c75e1139652582d03b3 (patch) | |
tree | 6b335a27fc96861e5d11b2d38c96b08834843a7d | |
parent | 798a67db11293f88fb381edfba4bd5b0a41d60fe (diff) | |
download | bash-19e1dd936da1a4a41c107c75e1139652582d03b3.tar.gz |
commit bash-20050519 snapshot
-rw-r--r-- | CWRU/CWRU.chlog | 106 | ||||
-rw-r--r-- | CWRU/CWRU.chlog~ | 144 | ||||
-rw-r--r-- | array.c | 4 | ||||
-rw-r--r-- | array.c~ | 1 | ||||
-rw-r--r-- | builtins/exec.def | 3 | ||||
-rw-r--r-- | builtins/exec.def~ | 228 | ||||
-rw-r--r-- | builtins/read.def | 5 | ||||
-rw-r--r-- | builtins/read.def~ | 14 | ||||
-rw-r--r-- | execute_cmd.c | 5 | ||||
-rw-r--r-- | execute_cmd.c~ | 9 | ||||
-rw-r--r-- | jobs.c | 10 | ||||
-rw-r--r-- | jobs.c~ | 1 | ||||
-rw-r--r-- | lib/readline/callback.c | 49 | ||||
-rw-r--r-- | lib/readline/display.c~ | 8 | ||||
-rw-r--r-- | lib/readline/examples/rlptytest.c | 294 | ||||
-rw-r--r-- | lib/readline/macro.c | 9 | ||||
-rw-r--r-- | lib/readline/readline.c | 331 | ||||
-rw-r--r-- | lib/readline/rlprivate.h | 29 | ||||
-rw-r--r-- | lib/readline/search.c | 2 | ||||
-rw-r--r-- | lib/readline/vi_mode.c | 4 | ||||
-rw-r--r-- | parse.y~ | 5 | ||||
-rw-r--r-- | version.c | 4 |
22 files changed, 1155 insertions, 110 deletions
diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 7444a867..5c758cf8 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -11503,3 +11503,109 @@ lib/readline/text.c lib/readline/vi_mode.c - changed set-mark, goto-mark, change-char, and char-search to work when called by callback functions + + 5/17 + ---- + +lib/readline/rlprivate.h + - new struct declaration for a `reading key sequence' context + +lib/readline/readline.c + - new variable, _rl_dispatching_keymap, keeps track of which keymap + we are currently searching + - functions to allocate and deallocate contexts for reading multi-char + key sequences + + 5/18 + ---- +lib/readline/rlprivate.h + - new struct defining a context for multiple-key key sequences (the + base case is escape-prefixed commands) + +lib/readline/readline.c + - change structure of _rl_dispatch_subseq to allow for callback code + to use it - rudimentary support for supporting the existing + recursion using a stack of contexts, each with a reference to the + previous + - fix so that ^G works when in callback mode + +lib/readline/callback.c + - call the appropriate multiple-key sequence callback if the state is + set + + 5/19 + ---- +lib/readline/readline.c + - broke code from _readline_internal_char after call to rl_dispatch + out into separate function: _rl_internal_char_cleanup, callable by + other parts of the code + - change _rl_internal_char_cleanup to unset _rl_want_redisplay after + it calls (*rl_redisplay_func) + +lib/readline/callback.c + - call _rl_internal_char_cleanup from rl_callback_read_char when + appropriate + + 5/24 + ---- +lib/readline/callback.c + - use _rl_dispatch_callback and a chain of _rl_keyseq_contexts to + simulate the recursion used to decode multicharacter key sequences + (even things like ESC- as meta-prefix) + - call setjmp in rl_callback_read_char to give things like rl_abort + a place to jump, since the saved location in readline() will not + be valid + - keep calling _rl_dispatch_callback from rl_callback_read_char while + we are still decoding a multi-key key sequence + - keep calling readline_internal_char from rl_callback_read_char while + we are reading characters from a macro + +lib/readline/macro.c + - use a slightly different strategy upon encountering the end of a macro + when using the callback interface: when the last character of a + macro is read, and we are reading a command, pop the macro off the + stack immediately so the loop in rl_callback_read_char terminates + when it should + +lib/readline/readline.c + - if longjmp() is called and we end up at the saved location while + using the callback interface, just return -- don't go back into a + blocking read + - new function to dispose a chain of rl_keyseq_cxts + - only read new input in _rl_dispatch_callback if the KSEQ_DISPATCHED + flag is not set in the current keyseq context -- if it is, we are + traversing the chain back up and should use what we already saved + - use -3 as a magic value from _rl_dispatch_subseq to indicate that + we're allocating a new context and moving downward in the chain + (a special return value for the benefit of _rl_dispatch_callback) + +lib/readline/rlprivate.h + - new extern declaration for _rl_keyseq_chain_dispose + + 6/1 + --- +builtins/read.def + - fixed a bug that occurred when reading a set number of chars and + the nth char is a backslash (read one too many). Bug reported by + Chris Morgan <chmorgan@gmail.com> + +execute_cmd.c + - fix execute_builtin so the `unset' builtin also operates on the + temporary environment in POSIX mode (as well as source and eval), + so that unsetting variables in the temporary environment doesn't + leave them set when unset completes. Report by Eric Blake + <ebb9@byu.net> + +array.c + - fix from William Park for array_rshift when shifting right on an + empty array -- corrects calculation of array->max_index + +builtins/exec.def + - if an exec fails and the execfail option is set, don't call + restart_job_control unless the shell is interactive or job_control + is set + +jobs.c + - add a run-time check for WCONTINUED being defined in header files + but rejected with EINVAL by waitpid(). Fix from Maciej Rozycki + <macro@linux-mips.org> diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 32e1239f..29ae0607 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -11463,3 +11463,147 @@ lib/readline/callback.c support/shobj-conf,configure.in - add support for dragonfly bsd, the same as freebsd + 5/13-5/15 + --------- +lib/readline/callback.c + - support for readline functions to `register' a function that will + be called when more input is available, with a generic data + structure to encapsulate the arguments and parameters. Primarily + intended for functions that read a single additional character, + like quoted-insert + - support for callback code reading numeric arguments in a loop, + using readline state and an auxiliary variable + - support for callback code performing non-incremental searches using + the same search context struct as the isearch code + +lib/readline/{callback,display}.c + - if a callback function sets `_rl_redisplay_wanted', the redisplay + function will be called as soon as it returns + +lib/readline/input.c + - changes to _rl_read_mbchar to handle reading the null multibyte + character and translating it into '\0' + +lib/readline/misc.c + - break rl_digit_loop() into component functions that can be called + individually from the callback code more easily + - share some of the functions with rl_digit_loop1() in vi_mode.c + +lib/readline/readline.h + - change the version #defines to reflect readline 5.1 + +lib/readline/search.c + - break code into smaller functions that can be composed to work with + the callback code more easily + +lib/readline/text.c + - in rl_quoted_insert(), don't messa around with the tty signals if + running in `callback mode' + +lib/readline/vi_mode.c + - changed set-mark, goto-mark, change-char, and char-search to work + when called by callback functions + + 5/17 + ---- + +lib/readline/rlprivate.h + - new struct declaration for a `reading key sequence' context + +lib/readline/readline.c + - new variable, _rl_dispatching_keymap, keeps track of which keymap + we are currently searching + - functions to allocate and deallocate contexts for reading multi-char + key sequences + + 5/18 + ---- +lib/readline/rlprivate.h + - new struct defining a context for multiple-key key sequences (the + base case is escape-prefixed commands) + +lib/readline/readline.c + - change structure of _rl_dispatch_subseq to allow for callback code + to use it - rudimentary support for supporting the existing + recursion using a stack of contexts, each with a reference to the + previous + - fix so that ^G works when in callback mode + +lib/readline/callback.c + - call the appropriate multiple-key sequence callback if the state is + set + + 5/19 + ---- +lib/readline/readline.c + - broke code from _readline_internal_char after call to rl_dispatch + out into separate function: _rl_internal_char_cleanup, callable by + other parts of the code + - change _rl_internal_char_cleanup to unset _rl_want_redisplay after + it calls (*rl_redisplay_func) + +lib/readline/callback.c + - call _rl_internal_char_cleanup from rl_callback_read_char when + appropriate + + 5/24 + ---- +lib/readline/callback.c + - use _rl_dispatch_callback and a chain of _rl_keyseq_contexts to + simulate the recursion used to decode multicharacter key sequences + (even things like ESC- as meta-prefix) + - call setjmp in rl_callback_read_char to give things like rl_abort + a place to jump, since the saved location in readline() will not + be valid + - keep calling _rl_dispatch_callback from rl_callback_read_char while + we are still decoding a multi-key key sequence + - keep calling readline_internal_char from rl_callback_read_char while + we are reading characters from a macro + +lib/readline/macro.c + - use a slightly different strategy upon encountering the end of a macro + when using the callback interface: when the last character of a + macro is read, and we are reading a command, pop the macro off the + stack immediately so the loop in rl_callback_read_char terminates + when it should + +lib/readline/readline.c + - if longjmp() is called and we end up at the saved location while + using the callback interface, just return -- don't go back into a + blocking read + - new function to dispose a chain of rl_keyseq_cxts + - only read new input in _rl_dispatch_callback if the KSEQ_DISPATCHED + flag is not set in the current keyseq context -- if it is, we are + traversing the chain back up and should use what we already saved + - use -3 as a magic value from _rl_dispatch_subseq to indicate that + we're allocating a new context and moving downward in the chain + (a special return value for the benefit of _rl_dispatch_callback) + +lib/readline/rlprivate.h + - new extern declaration for _rl_keyseq_chain_dispose + + 6/1 + --- +builtins/read.def + - fixed a bug that occurred when reading a set number of chars and + the nth char is a backslash (read one too many) + +execute_cmd.c + - fix execute_builtin so the `unset' builtin also operates on the + temporary environment in POSIX mode (as well as source and eval), + so that unsetting variables in the temporary environment doesn't + leave them set when unset completes + +array.c + - fix from William Park for array_rshift when shifting right on an + empty array -- corrects calculation of array->max_index + +builtins/exec.def + - if an exec fails and the execfail option is set, don't call + restart_job_control unless the shell is interactive or job_control + is set + +jobs.c + - add a run-time check for WCONTINUED being defined in header files + but rejected with EINVAL by waitpid(). Fix from Maciej Rozycki + <macro@linux-mips.org> @@ -257,14 +257,14 @@ char *s; return 1; } - a->max_index += n; - /* * Renumber all elements in the array except the one we just added. */ for ( ; ae != a->head; ae = element_forw(ae)) element_index(ae) += n; + a->max_index = element_index(a->head->prev); + return (a->num_elements); } @@ -556,7 +556,6 @@ ARRAY *a; return (REVERSE_LIST(list, WORD_LIST *)); } -/* XXX - changes needed to support `+=' */ ARRAY * array_assign_list (array, list) ARRAY *array; diff --git a/builtins/exec.def b/builtins/exec.def index acfdae10..0818a25e 100644 --- a/builtins/exec.def +++ b/builtins/exec.def @@ -221,7 +221,8 @@ failed_exec: initialize_signals (1); #if defined (JOB_CONTROL) - restart_job_control (); + if (interactive_shell || job_control) + restart_job_control (); #endif /* JOB_CONTROL */ return (exit_value); diff --git a/builtins/exec.def~ b/builtins/exec.def~ new file mode 100644 index 00000000..acfdae10 --- /dev/null +++ b/builtins/exec.def~ @@ -0,0 +1,228 @@ +This file is exec.def, from which is created exec.c. +It implements the builtin "exec" in Bash. + +Copyright (C) 1987-2003 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. + +$PRODUCES exec.c + +$BUILTIN exec +$FUNCTION exec_builtin +$SHORT_DOC exec [-cl] [-a name] file [redirection ...] +Exec FILE, replacing this shell with the specified program. +If FILE is not specified, the redirections take effect in this +shell. If the first argument is `-l', then place a dash in the +zeroth arg passed to FILE, as login does. If the `-c' option +is supplied, FILE is executed with a null environment. The `-a' +option means to make set argv[0] of the executed process to NAME. +If the file cannot be executed and the shell is not interactive, +then the shell exits, unless the shell option `execfail' is set. +$END + +#include <config.h> + +#include "../bashtypes.h" +#include "posixstat.h" +#include <signal.h> +#include <errno.h> + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include "../bashansi.h" +#include "../bashintl.h" + +#include "../shell.h" +#include "../execute_cmd.h" +#include "../findcmd.h" +#if defined (JOB_CONTROL) +# include "../jobs.h" +#endif +#include "../flags.h" +#include "../trap.h" +#if defined (HISTORY) +# include "../bashhist.h" +#endif +#include "common.h" +#include "bashgetopt.h" + +/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +extern int subshell_environment; +extern REDIRECT *redirection_undo_list; + +int no_exit_on_failed_exec; + +/* If the user wants this to look like a login shell, then + prepend a `-' onto NAME and return the new name. */ +static char * +mkdashname (name) + char *name; +{ + char *ret; + + ret = (char *)xmalloc (2 + strlen (name)); + ret[0] = '-'; + strcpy (ret + 1, name); + return ret; +} + +int +exec_builtin (list) + WORD_LIST *list; +{ + int exit_value = EXECUTION_FAILURE; + int cleanenv, login, opt; + char *argv0, *command, **args, **env, *newname, *com2; + + cleanenv = login = 0; + argv0 = (char *)NULL; + + reset_internal_getopt (); + while ((opt = internal_getopt (list, "cla:")) != -1) + { + switch (opt) + { + case 'c': + cleanenv = 1; + break; + case 'l': + login = 1; + break; + case 'a': + argv0 = list_optarg; + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + /* First, let the redirections remain. */ + dispose_redirects (redirection_undo_list); + redirection_undo_list = (REDIRECT *)NULL; + + if (list == 0) + return (EXECUTION_SUCCESS); + +#if defined (RESTRICTED_SHELL) + if (restricted) + { + sh_restricted ((char *)NULL); + return (EXECUTION_FAILURE); + } +#endif /* RESTRICTED_SHELL */ + + args = strvec_from_word_list (list, 1, 0, (int *)NULL); + + /* A command with a slash anywhere in its name is not looked up in $PATH. */ + command = absolute_program (args[0]) ? args[0] : search_for_command (args[0]); + + if (command == 0) + { + sh_notfound (args[0]); + exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */ + goto failed_exec; + } + + com2 = full_pathname (command); + if (com2) + { + if (command != args[0]) + free (command); + command = com2; + } + + if (argv0) + { + free (args[0]); + args[0] = login ? mkdashname (argv0) : savestring (argv0); + } + else if (login) + { + newname = mkdashname (args[0]); + free (args[0]); + args[0] = newname; + } + + /* Decrement SHLVL by 1 so a new shell started here has the same value, + preserving the appearance. After we do that, we need to change the + exported environment to include the new value. */ + if (cleanenv == 0) + adjust_shell_level (-1); + + if (cleanenv) + env = (char **)NULL; + else + { + maybe_make_export_env (); + env = export_env; + } + +#if defined (HISTORY) + if (interactive_shell && subshell_environment == 0) + maybe_save_shell_history (); +#endif /* HISTORY */ + + restore_original_signals (); + +#if defined (JOB_CONTROL) + if (subshell_environment == 0) + end_job_control (); +#endif /* JOB_CONTROL */ + + shell_execve (command, args, env); + + /* We have to set this to NULL because shell_execve has called realloc() + to stuff more items at the front of the array, which may have caused + the memory to be freed by realloc(). We don't want to free it twice. */ + args = (char **)NULL; + if (cleanenv == 0) + adjust_shell_level (1); + + if (executable_file (command) == 0) + { + builtin_error (_("%s: cannot execute: %s"), command, strerror (errno)); + exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */ + } + else + file_error (command); + +failed_exec: + FREE (command); + + if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0)) + exit_shell (exit_value); + + if (args) + strvec_dispose (args); + + initialize_traps (); + initialize_signals (1); + +#if defined (JOB_CONTROL) + restart_job_control (); +#endif /* JOB_CONTROL */ + + return (exit_value); +} diff --git a/builtins/read.def b/builtins/read.def index dd8a7727..bb01cca7 100644 --- a/builtins/read.def +++ b/builtins/read.def @@ -425,11 +425,11 @@ read_builtin (list) newline pair still disappears from the input. */ if (pass_next) { + pass_next = 0; if (c == '\n') i--; /* back up over the CTLESC */ else - input_string[i++] = c; - pass_next = 0; + goto add_char; continue; } @@ -450,6 +450,7 @@ read_builtin (list) input_string[i++] = CTLESC; } +add_char: input_string[i++] = c; nr++; diff --git a/builtins/read.def~ b/builtins/read.def~ index c5f658e9..69a4426d 100644 --- a/builtins/read.def~ +++ b/builtins/read.def~ @@ -124,7 +124,7 @@ read_builtin (list) WORD_LIST *list; { register char *varname; - int size, i, pass_next, saw_escape, eof, opt, retval, code; + int size, i, nr, pass_next, saw_escape, eof, opt, retval, code; int input_is_tty, input_is_pipe, unbuffered_read; int raw, edit, nchars, silent, have_timeout, fd; unsigned int tmout; @@ -173,7 +173,7 @@ read_builtin (list) #endif tmout = 0; /* no timeout */ - nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0; + nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0; delim = '\n'; /* read until newline */ reset_internal_getopt (); @@ -425,11 +425,15 @@ read_builtin (list) newline pair still disappears from the input. */ if (pass_next) { + pass_next = 0; if (c == '\n') i--; /* back up over the CTLESC */ else +#if 0 input_string[i++] = c; - pass_next = 0; +#else + goto add_char; +#endif continue; } @@ -450,9 +454,11 @@ read_builtin (list) input_string[i++] = CTLESC; } +add_char: input_string[i++] = c; + nr++; - if (nchars > 0 && i >= nchars) + if (nchars > 0 && nr >= nchars) break; } input_string[i] = '\0'; diff --git a/execute_cmd.c b/execute_cmd.c index b17d4073..0c81fff1 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -3051,7 +3051,12 @@ execute_builtin (builtin, words, flags, subshell) /* The temporary environment for a builtin is supposed to apply to all commands executed by that builtin. Currently, this is a problem only with the `source' and `eval' builtins. */ +#if 0 isbltinenv = (builtin == source_builtin || builtin == eval_builtin); +#else + isbltinenv = (builtin == source_builtin || builtin == eval_builtin || builtin == unset_builtin); +#endif + if (isbltinenv) { if (subshell == 0) diff --git a/execute_cmd.c~ b/execute_cmd.c~ index 2de0d28e..82fb057e 100644 --- a/execute_cmd.c~ +++ b/execute_cmd.c~ @@ -369,7 +369,6 @@ shell_control_structure (type) { switch (type) { - case cm_for: #if defined (ARITH_FOR_COMMAND) case cm_arith_for: #endif @@ -386,7 +385,9 @@ shell_control_structure (type) case cm_while: case cm_until: case cm_if: + case cm_for: case cm_group: + case cm_function_def: return (1); default: @@ -3049,8 +3050,14 @@ execute_builtin (builtin, words, flags, subshell) /* The temporary environment for a builtin is supposed to apply to all commands executed by that builtin. Currently, this is a +#if 0 problem only with the `source' and `eval' builtins. */ isbltinenv = (builtin == source_builtin || builtin == eval_builtin); +#else + problem only with the `source', `unset', and `eval' builtins. */ + isbltinenv = (builtin == source_builtin || builtin == eval_builtin || builtin == unset_builtin); +#endif + if (isbltinenv) { if (subshell == 0) @@ -2818,6 +2818,7 @@ waitchld (wpid, block) PROCESS *child; pid_t pid; int call_set_current, last_stopped_job, job, children_exited, waitpid_flags; + static int wcontinued = WCONTINUED; /* run-time fix for glibc problem */ call_set_current = children_exited = 0; last_stopped_job = NO_JOB; @@ -2827,12 +2828,19 @@ waitchld (wpid, block) /* We don't want to be notified about jobs stopping if job control is not active. XXX - was interactive_shell instead of job_control */ waitpid_flags = (job_control && subshell_environment == 0) - ? (WUNTRACED|WCONTINUED) + ? (WUNTRACED|wcontinued) : 0; if (sigchld || block == 0) waitpid_flags |= WNOHANG; pid = WAITPID (-1, &status, waitpid_flags); + /* WCONTINUED may be rejected by waitpid as invalid even when defined */ + if (wcontinued && pid < 0 && errno == EINVAL) + { + wcontinued = 0; + continue; /* jump back to the test and retry without WCONTINUED */ + } + /* The check for WNOHANG is to make sure we decrement sigchld only if it was non-zero before we called waitpid. */ if (sigchld > 0 && (waitpid_flags & WNOHANG)) @@ -755,7 +755,6 @@ bgp_prune () while (bgpids.npid > js.c_childmax) { ps = bgpids.list; -itrace("bgp_prune: deleting %d -> %d", ps->pid, bgpids.npid - 1); bgpids.list = bgpids.list->next; free (ps); bgpids.npid--; diff --git a/lib/readline/callback.c b/lib/readline/callback.c index 9469233d..9120969c 100644 --- a/lib/readline/callback.c +++ b/lib/readline/callback.c @@ -51,7 +51,7 @@ _rl_callback_generic_arg *_rl_callback_data = 0; /* **************************************************************** */ /* */ -/* Callback Readline Functions */ +/* Callback Readline Functions */ /* */ /* **************************************************************** */ @@ -105,7 +105,8 @@ void rl_callback_read_char () { char *line; - int eof; + int eof, jcode; + static procenv_t olevel; if (rl_linefunc == NULL) { @@ -113,6 +114,16 @@ rl_callback_read_char () abort (); } + memcpy ((void *)olevel, (void *)readline_top_level, sizeof (procenv_t)); + jcode = setjmp (readline_top_level); + if (jcode) + { + (*rl_redisplay_function) (); + _rl_want_redisplay = 0; + memcpy ((void *)readline_top_level, (void *)olevel, sizeof (procenv_t)); + return; + } + if (RL_ISSTATE (RL_STATE_ISEARCH)) { eof = _rl_isearch_callback (_rl_iscxt); @@ -130,10 +141,24 @@ rl_callback_read_char () { eof = _rl_arg_callback (_rl_argcxt); if (eof == 0 && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING)) - rl_callback_read_char (); + rl_callback_read_char (); + /* XXX - this should handle _rl_last_command_was_kill better */ + else if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0) + _rl_internal_char_cleanup (); return; } + else if (RL_ISSTATE (RL_STATE_MULTIKEY)) + { + eof = _rl_dispatch_callback (_rl_kscxt); /* For now */ + while ((eof == -1 || eof == -2) && RL_ISSTATE (RL_STATE_MULTIKEY) && _rl_kscxt && (_rl_kscxt->flags & KSEQ_DISPATCHED)) + eof = _rl_dispatch_callback (_rl_kscxt); + if (RL_ISSTATE (RL_STATE_MULTIKEY) == 0) + { + _rl_internal_char_cleanup (); + _rl_want_redisplay = 1; + } + } else if (_rl_callback_func) { /* This allows functions that simply need to read an additional character @@ -144,11 +169,15 @@ rl_callback_read_char () eof = (*_rl_callback_func) (_rl_callback_data); /* If the function `deregisters' itself, make sure the data is cleaned up. */ - if (_rl_callback_func == 0 && _rl_callback_data) - { - _rl_callback_data_dispose (_rl_callback_data); - _rl_callback_data = 0; - } + if (_rl_callback_func == 0) + { + if (_rl_callback_data) + { + _rl_callback_data_dispose (_rl_callback_data); + _rl_callback_data = 0; + } + _rl_internal_char_cleanup (); + } } else eof = readline_internal_char (); @@ -183,10 +212,10 @@ rl_callback_read_char () if (in_handler == 0 && rl_linefunc) _rl_callback_newline (); } - if (rl_pending_input || _rl_pushed_input_available ()) + if (rl_pending_input || _rl_pushed_input_available () || RL_ISSTATE (RL_STATE_MACROINPUT)) eof = readline_internal_char (); else - break; + break; } } diff --git a/lib/readline/display.c~ b/lib/readline/display.c~ index 86a0174a..6ed566a2 100644 --- a/lib/readline/display.c~ +++ b/lib/readline/display.c~ @@ -118,6 +118,7 @@ rl_voidfunc_t *rl_redisplay_function = rl_redisplay; int rl_display_fixed = 0; int _rl_suppress_redisplay = 0; +int _rl_want_redisplay = 0; /* The stuff that gets printed out before the actual text of the line. This is usually pointing to rl_prompt. */ @@ -601,6 +602,7 @@ rl_redisplay () num = 0; #endif +fprintf(stderr, "rl_redisplay: local_prompt = %s\r\n", local_prompt); /* prompt_invis_chars_first_line is the number of invisible characters in the first physical line of the prompt. wrap_offset - prompt_invis_chars_first_line is the number of invis @@ -2050,6 +2052,9 @@ insert_some_chars (string, count, col) char *string; int count, col; { +#if defined (__MSDOS__) || defined (__MINGW32__) + _rl_output_some_chars (string, count); +#else /* DEBUGGING */ if (MB_CUR_MAX == 1 || rl_byte_oriented) if (count != col) @@ -2088,6 +2093,7 @@ insert_some_chars (string, count, col) if (_rl_term_ei && *_rl_term_ei) tputs (_rl_term_ei, 1, _rl_output_character_function); } +#endif /* __MSDOS__ || __MINGW32__ */ } /* Delete COUNT characters from the display line. */ @@ -2098,6 +2104,7 @@ delete_chars (count) if (count > _rl_screenwidth) /* XXX */ return; +#if !defined (__MSDOS__) && !defined (__MINGW32__) if (_rl_term_DC && *_rl_term_DC) { char *buffer; @@ -2110,6 +2117,7 @@ delete_chars (count) while (count--) tputs (_rl_term_dc, 1, _rl_output_character_function); } +#endif /* !__MSDOS__ && !__MINGW32__ */ } void diff --git a/lib/readline/examples/rlptytest.c b/lib/readline/examples/rlptytest.c new file mode 100644 index 00000000..87bfc3a0 --- /dev/null +++ b/lib/readline/examples/rlptytest.c @@ -0,0 +1,294 @@ +#if defined (HAVE_CONFIG_H) +#include <config.h> +#endif + +#include <stdio.h> +#include <sys/types.h> +#include <errno.h> +#include <curses.h> + +#include <stdlib.h> +#include <unistd.h> + +#include <signal.h> + +#if 0 /* LINUX */ +#include <pty.h> +#else +#include <util.h> +#endif + +#ifdef READLINE_LIBRARY +# include "readline.h" +#else +# include <readline/readline.h> +#endif + +/** + * Master/Slave PTY used to keep readline off of stdin/stdout. + */ +static int masterfd = -1; +static int slavefd; + +void +sigint (s) + int s; +{ + tty_reset (STDIN_FILENO); + close (masterfd); + close (slavefd); + printf ("\n"); + exit (0); +} + +static int +user_input() +{ + int size; + const int MAX = 1024; + char *buf = (char *)malloc(MAX+1); + + size = read (STDIN_FILENO, buf, MAX); + if (size == -1) + return -1; + + size = write (masterfd, buf, size); + if (size == -1) + return -1; + + return 0; +} + +static int +readline_input() +{ + const int MAX = 1024; + char *buf = (char *)malloc(MAX+1); + int size; + + size = read (masterfd, buf, MAX); + if (size == -1) + { + free( buf ); + buf = NULL; + return -1; + } + + buf[size] = 0; + + /* Display output from readline */ + if ( size > 0 ) + fprintf(stderr, "%s", buf); + + free( buf ); + buf = NULL; + return 0; +} + +static void +rlctx_send_user_command(char *line) +{ + /* This happens when rl_callback_read_char gets EOF */ + if ( line == NULL ) + return; + + if (strcmp (line, "exit") == 0) { + tty_reset (STDIN_FILENO); + close (masterfd); + close (slavefd); + printf ("\n"); + exit (0); + } + + /* Don't add the enter command */ + if ( line && *line != '\0' ) + add_history(line); +} + +static void +custom_deprep_term_function () +{ +} + +static int +init_readline (int inputfd, int outputfd) +{ + FILE *inputFILE, *outputFILE; + + inputFILE = fdopen (inputfd, "r"); + if (!inputFILE) + return -1; + + outputFILE = fdopen (outputfd, "w"); + if (!outputFILE) + return -1; + + rl_instream = inputFILE; + rl_outstream = outputFILE; + + /* Tell readline what the prompt is if it needs to put it back */ + rl_callback_handler_install("(rltest): ", rlctx_send_user_command); + + /* Set the terminal type to dumb so the output of readline can be + * understood by tgdb */ + if ( rl_reset_terminal("dumb") == -1 ) + return -1; + + /* For some reason, readline can not deprep the terminal. + * However, it doesn't matter because no other application is working on + * the terminal besides readline */ + rl_deprep_term_function = custom_deprep_term_function; + + using_history(); + read_history(".history"); + + return 0; +} + +static int +main_loop(void) +{ + fd_set rset; + int max; + + max = (masterfd > STDIN_FILENO) ? masterfd : STDIN_FILENO; + max = (max > slavefd) ? max : slavefd; + + for (;;) + { + /* Reset the fd_set, and watch for input from GDB or stdin */ + FD_ZERO(&rset); + + FD_SET(STDIN_FILENO, &rset); + FD_SET(slavefd, &rset); + FD_SET(masterfd, &rset); + + /* Wait for input */ + if (select(max + 1, &rset, NULL, NULL, NULL) == -1) + { + if (errno == EINTR) + continue; + else + return -1; + } + + /* Input received through the pty: Handle it + * Wrote to masterfd, slave fd has that input, alert readline to read it. + */ + if (FD_ISSET(slavefd, &rset)) + rl_callback_read_char(); + + /* Input received through the pty. + * Readline read from slavefd, and it wrote to the masterfd. + */ + if (FD_ISSET(masterfd, &rset)) + if ( readline_input() == -1 ) + return -1; + + /* Input received: Handle it, write to masterfd (input to readline) */ + if (FD_ISSET(STDIN_FILENO, &rset)) + if ( user_input() == -1 ) + return -1; + } + + return 0; +} + +/* The terminal attributes before calling tty_cbreak */ +static struct termios save_termios; +static struct winsize size; +static enum { RESET, TCBREAK } ttystate = RESET; + +/* tty_cbreak: Sets terminal to cbreak mode. Also known as noncanonical mode. + * 1. Signal handling is still turned on, so the user can still type those. + * 2. echo is off + * 3. Read in one char at a time. + * + * fd - The file descriptor of the terminal + * + * Returns: 0 on sucess, -1 on error + */ +int tty_cbreak(int fd){ + struct termios buf; + int ttysavefd = -1; + + if(tcgetattr(fd, &save_termios) < 0) + return -1; + + buf = save_termios; + buf.c_lflag &= ~(ECHO | ICANON); + buf.c_iflag &= ~(ICRNL | INLCR); + buf.c_cc[VMIN] = 1; + buf.c_cc[VTIME] = 0; + +#if defined (VLNEXT) && defined (_POSIX_VDISABLE) + buf.c_cc[VLNEXT] = _POSIX_VDISABLE; +#endif + +#if defined (VDSUSP) && defined (_POSIX_VDISABLE) + buf.c_cc[VDSUSP] = _POSIX_VDISABLE; +#endif + + if(tcsetattr(fd, TCSAFLUSH, &buf) < 0) + return -1; + + ttystate = TCBREAK; + ttysavefd = fd; + + /* set size */ + if(ioctl(fd, TIOCGWINSZ, (char *)&size) < 0) + return -1; + +#ifdef DEBUG + err_msg("%d rows and %d cols\n", size.ws_row, size.ws_col); +#endif + + return (0); +} + +/* tty_reset: Sets the terminal attributes back to their previous state. + * PRE: tty_cbreak must have already been called. + * + * fd - The file descrioptor of the terminal to reset. + * + * Returns: 0 on success, -1 on error + */ +int tty_reset(int fd){ + if(ttystate != TCBREAK) + return (0); + + if(tcsetattr(fd, TCSAFLUSH, &save_termios) < 0) + return (-1); + + ttystate = RESET; + + return 0; +} + +int +main() +{ + int val; + val = openpty (&masterfd, &slavefd, NULL, NULL, NULL); + if (val == -1) + return -1; + + val = init_readline (slavefd, slavefd); + if (val == -1) + return -1; + + val = tty_cbreak (STDIN_FILENO); + if (val == -1) + return -1; + + signal (SIGINT, sigint); + + val = main_loop (); + + tty_reset (STDIN_FILENO); + + if (val == -1) + return -1; + + return 0; +} diff --git a/lib/readline/macro.c b/lib/readline/macro.c index b73c3af9..2975bf1f 100644 --- a/lib/readline/macro.c +++ b/lib/readline/macro.c @@ -100,6 +100,8 @@ _rl_with_macro_input (string) int _rl_next_macro_key () { + int c; + if (rl_executing_macro == 0) return (0); @@ -109,7 +111,14 @@ _rl_next_macro_key () return (_rl_next_macro_key ()); } +#if defined (READLINE_CALLBACKS) + c = rl_executing_macro[executing_macro_index++]; + if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_READCMD) && rl_executing_macro[executing_macro_index] == 0) + _rl_pop_executing_macro (); + return c; +#else return (rl_executing_macro[executing_macro_index++]); +#endif } /* Save the currently executing macro on a stack of saved macros. */ diff --git a/lib/readline/readline.c b/lib/readline/readline.c index 2ac77452..aafad068 100644 --- a/lib/readline/readline.c +++ b/lib/readline/readline.c @@ -68,11 +68,11 @@ #include "xmalloc.h" #ifndef RL_LIBRARY_VERSION -# define RL_LIBRARY_VERSION "5.0" +# define RL_LIBRARY_VERSION "5.1" #endif #ifndef RL_READLINE_VERSION -# define RL_READLINE_VERSION 0x0500 +# define RL_READLINE_VERSION 0x0501 #endif extern void _rl_free_history_entry PARAMS((HIST_ENTRY *)); @@ -87,6 +87,9 @@ static void bind_arrow_keys PARAMS((void)); static void readline_default_bindings PARAMS((void)); static void reset_default_bindings PARAMS((void)); +static int _rl_subseq_result PARAMS((int, Keymap, int, int)); +static int _rl_subseq_getchar PARAMS((int)); + /* **************************************************************** */ /* */ /* Line editing input utility */ @@ -104,6 +107,7 @@ int rl_gnu_readline_p = 1; By default, it is the standard emacs keymap. */ Keymap _rl_keymap = emacs_standard_keymap; + /* The current style of editing. */ int rl_editing_mode = emacs_mode; @@ -219,6 +223,9 @@ char *_rl_comment_begin; /* Keymap holding the function currently being executed. */ Keymap rl_executing_keymap; +/* Keymap we're currently using to dispatch. */ +Keymap _rl_dispatching_keymap; + /* Non-zero means to erase entire line, including prompt, on empty input lines. */ int rl_erase_empty_line = 0; @@ -230,6 +237,9 @@ int rl_num_chars_to_read; char *rl_line_buffer = (char *)NULL; int rl_line_buffer_len = 0; +/* Key sequence `contexts' */ +_rl_keyseq_cxt *_rl_kscxt = 0; + /* Forward declarations used by the display, termcap, and history code. */ /* **************************************************************** */ @@ -394,6 +404,36 @@ readline_internal_teardown (eof) return (eof ? (char *)NULL : savestring (the_line)); } +void +_rl_internal_char_cleanup () +{ +#if defined (VI_MODE) + /* In vi mode, when you exit insert mode, the cursor moves back + over the previous character. We explicitly check for that here. */ + if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) + rl_vi_check (); +#endif /* VI_MODE */ + + if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read) + { + (*rl_redisplay_function) (); + _rl_want_redisplay = 0; + rl_newline (1, '\n'); + } + + if (rl_done == 0) + { + (*rl_redisplay_function) (); + _rl_want_redisplay = 0; + } + + /* If the application writer has told us to erase the entire line if + the only character typed was something bound to rl_newline, do so. */ + if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline && + rl_point == 0 && rl_end == 0) + _rl_erase_entire_line (); +} + STATIC_CALLBACK int #if defined (READLINE_CALLBACKS) readline_internal_char () @@ -416,7 +456,16 @@ readline_internal_charloop () code = setjmp (readline_top_level); if (code) - (*rl_redisplay_function) (); + { + (*rl_redisplay_function) (); + _rl_want_redisplay = 0; + /* If we get here, we're not being called from something dispatched + from _rl_callback_read_char(), which sets up its own value of + readline_top_level (saving and restoring the old, of course), so + we can just return here. */ + if (RL_ISSTATE (RL_STATE_CALLBACK)) + return (0); + } if (rl_pending_input == 0) { @@ -455,27 +504,7 @@ readline_internal_charloop () if (rl_pending_input == 0 && lk == _rl_last_command_was_kill) _rl_last_command_was_kill = 0; -#if defined (VI_MODE) - /* In vi mode, when you exit insert mode, the cursor moves back - over the previous character. We explicitly check for that here. */ - if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) - rl_vi_check (); -#endif /* VI_MODE */ - - if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read) - { - (*rl_redisplay_function) (); - rl_newline (1, '\n'); - } - - if (rl_done == 0) - (*rl_redisplay_function) (); - - /* If the application writer has told us to erase the entire line if - the only character typed was something bound to rl_newline, do so. */ - if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline && - rl_point == 0 && rl_end == 0) - _rl_erase_entire_line (); + _rl_internal_char_cleanup (); #if defined (READLINE_CALLBACKS) return 0; @@ -525,6 +554,107 @@ _rl_set_the_line () the_line = rl_line_buffer; } +#if defined (READLINE_CALLBACKS) +_rl_keyseq_cxt * +_rl_keyseq_cxt_alloc () +{ + _rl_keyseq_cxt *cxt; + + cxt = (_rl_keyseq_cxt *)xmalloc (sizeof (_rl_keyseq_cxt)); + + cxt->flags = cxt->subseq_arg = cxt->subseq_retval = 0; + + cxt->okey = 0; + cxt->ocxt = _rl_kscxt; + cxt->childval = 42; /* sentinel value */ + + return cxt; +} + +void +_rl_keyseq_cxt_dispose (cxt) + _rl_keyseq_cxt *cxt; +{ + free (cxt); +} + +void +_rl_keyseq_chain_dispose () +{ + _rl_keyseq_cxt *cxt; + + while (_rl_kscxt) + { + cxt = _rl_kscxt; + _rl_kscxt = _rl_kscxt->ocxt; + _rl_keyseq_cxt_dispose (cxt); + } +} +#endif + +static int +_rl_subseq_getchar (key) + int key; +{ + int k; + + if (key == ESC) + RL_SETSTATE(RL_STATE_METANEXT); + RL_SETSTATE(RL_STATE_MOREINPUT); + k = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (key == ESC) + RL_UNSETSTATE(RL_STATE_METANEXT); + + return k; +} + +#if defined (READLINE_CALLBACKS) +int +_rl_dispatch_callback (cxt) + _rl_keyseq_cxt *cxt; +{ + int nkey, r; + + /* For now */ +#if 1 + /* The first time this context is used, we want to read input and dispatch + on it. When traversing the chain of contexts back `up', we want to use + the value from the next context down. We're simulating recursion using + a chain of contexts. */ + if ((cxt->flags & KSEQ_DISPATCHED) == 0) + { + nkey = _rl_subseq_getchar (cxt->okey); + r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg); + cxt->flags |= KSEQ_DISPATCHED; + } + else + r = cxt->childval; +#else + r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg); +#endif + + /* For now */ + r = _rl_subseq_result (r, cxt->oldmap, cxt->okey, (cxt->flags & KSEQ_SUBSEQ)); + + if (r == 0) /* success! */ + { + _rl_keyseq_chain_dispose (); + RL_UNSETSTATE (RL_STATE_MULTIKEY); + return r; + } + + if (r != -3) /* magic value that says we added to the chain */ + _rl_kscxt = cxt->ocxt; + if (_rl_kscxt) + _rl_kscxt->childval = r; + if (r != -3) + _rl_keyseq_cxt_dispose (cxt); + + return r; +} +#endif /* READLINE_CALLBACKS */ + /* Do the command associated with KEY in MAP. If the associated command is really a keymap, then read another key, and dispatch into that map. */ @@ -533,6 +663,7 @@ _rl_dispatch (key, map) register int key; Keymap map; { + _rl_dispatching_keymap = map; return _rl_dispatch_subseq (key, map, 0); } @@ -545,6 +676,9 @@ _rl_dispatch_subseq (key, map, got_subseq) int r, newkey; char *macro; rl_command_func_t *func; +#if defined (READLINE_CALLBACKS) + _rl_keyseq_cxt *cxt; +#endif if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) { @@ -578,10 +712,6 @@ _rl_dispatch_subseq (key, map, got_subseq) rl_executing_keymap = map; -#if 0 - _rl_suppress_redisplay = (map[key].function == rl_insert) && _rl_input_available (); -#endif - rl_dispatching = 1; RL_SETSTATE(RL_STATE_DISPATCHING); r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key); @@ -613,6 +743,10 @@ _rl_dispatch_subseq (key, map, got_subseq) } else { +#if defined (READLINE_CALLBACKS) + RL_UNSETSTATE (RL_STATE_MULTIKEY); + _rl_keyseq_chain_dispose (); +#endif _rl_abort_internal (); return -1; } @@ -634,66 +768,43 @@ _rl_dispatch_subseq (key, map, got_subseq) #endif rl_key_sequence_length++; + _rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key); - if (key == ESC) - RL_SETSTATE(RL_STATE_METANEXT); - RL_SETSTATE(RL_STATE_MOREINPUT); - newkey = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); - if (key == ESC) - RL_UNSETSTATE(RL_STATE_METANEXT); + /* Allocate new context here. Use linked contexts (linked through + cxt->ocxt) to simulate recursion */ +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + /* Return 0 only the first time, to indicate success to + _rl_callback_read_char. The rest of the time, we're called + from _rl_dispatch_callback, so we return 3 to indicate + special handling is necessary. */ + r = RL_ISSTATE (RL_STATE_MULTIKEY) ? -3 : 0; + cxt = _rl_keyseq_cxt_alloc (); + + if (got_subseq) + cxt->flags |= KSEQ_SUBSEQ; + cxt->okey = key; + cxt->oldmap = map; + cxt->dmap = _rl_dispatching_keymap; + cxt->subseq_arg = got_subseq || cxt->dmap[ANYOTHERKEY].function; + + RL_SETSTATE (RL_STATE_MULTIKEY); + _rl_kscxt = cxt; + + return r; /* don't indicate immediate success */ + } +#endif + newkey = _rl_subseq_getchar (key); if (newkey < 0) { _rl_abort_internal (); return -1; } - r = _rl_dispatch_subseq (newkey, FUNCTION_TO_KEYMAP (map, key), got_subseq || map[ANYOTHERKEY].function); - - if (r == -2) - /* We didn't match anything, and the keymap we're indexed into - shadowed a function previously bound to that prefix. Call - the function. The recursive call to _rl_dispatch_subseq has - already taken care of pushing any necessary input back onto - the input queue with _rl_unget_char. */ - { - Keymap m = FUNCTION_TO_KEYMAP (map, key); - int type = m[ANYOTHERKEY].type; - func = m[ANYOTHERKEY].function; - if (type == ISFUNC && func == rl_do_lowercase_version) - r = _rl_dispatch (_rl_to_lower (key), map); - else if (type == ISFUNC && func == rl_insert) - { - /* If the function that was shadowed was self-insert, we - somehow need a keymap with map[key].func == self-insert. - Let's use this one. */ - int nt = m[key].type; - rl_command_func_t *nf = m[key].function; - - m[key].type = type; - m[key].function = func; - r = _rl_dispatch (key, m); - m[key].type = nt; - m[key].function = nf; - } - else - r = _rl_dispatch (ANYOTHERKEY, m); - } - else if (r && map[ANYOTHERKEY].function) - { - /* We didn't match (r is probably -1), so return something to - tell the caller that it should try ANYOTHERKEY for an - overridden function. */ - _rl_unget_char (key); - return -2; - } - else if (r && got_subseq) - { - /* OK, back up the chain. */ - _rl_unget_char (key); - return -1; - } + r = _rl_dispatch_subseq (newkey, _rl_dispatching_keymap, got_subseq || map[ANYOTHERKEY].function); + return _rl_subseq_result (r, map, key, got_subseq); } else { @@ -717,9 +828,69 @@ _rl_dispatch_subseq (key, map, got_subseq) _rl_vi_textmod_command (key)) _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign); #endif + return (r); } +static int +_rl_subseq_result (r, map, key, got_subseq) + int r; + Keymap map; + int key, got_subseq; +{ + Keymap m; + int type, nt; + rl_command_func_t *func, *nf; + + if (r == -2) + /* We didn't match anything, and the keymap we're indexed into + shadowed a function previously bound to that prefix. Call + the function. The recursive call to _rl_dispatch_subseq has + already taken care of pushing any necessary input back onto + the input queue with _rl_unget_char. */ + { + m = _rl_dispatching_keymap; + type = m[ANYOTHERKEY].type; + func = m[ANYOTHERKEY].function; + if (type == ISFUNC && func == rl_do_lowercase_version) + r = _rl_dispatch (_rl_to_lower (key), map); + else if (type == ISFUNC && func == rl_insert) + { + /* If the function that was shadowed was self-insert, we + somehow need a keymap with map[key].func == self-insert. + Let's use this one. */ + nt = m[key].type; + nf = m[key].function; + + m[key].type = type; + m[key].function = func; + r = _rl_dispatch (key, m); + m[key].type = nt; + m[key].function = nf; + } + else + r = _rl_dispatch (ANYOTHERKEY, m); + } + else if (r && map[ANYOTHERKEY].function) + { + /* We didn't match (r is probably -1), so return something to + tell the caller that it should try ANYOTHERKEY for an + overridden function. */ + _rl_unget_char (key); + _rl_dispatching_keymap = map; + return -2; + } + else if (r && got_subseq) + { + /* OK, back up the chain. */ + _rl_unget_char (key); + _rl_dispatching_keymap = map; + return -1; + } + + return r; +} + /* **************************************************************** */ /* */ /* Initializations */ diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index 4eafa7d6..efc954cc 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -85,6 +85,26 @@ typedef struct __rl_search_context typedef int _rl_arg_cxt; +/* A context for reading key sequences longer than a single character when + using the callback interface. */ +#define KSEQ_DISPATCHED 0x01 +#define KSEQ_SUBSEQ 0x02 +#define KSEQ_RECURSIVE 0x04 + +typedef struct __rl_keyseq_context +{ + int flags; + int subseq_arg; + int subseq_retval; /* XXX */ + Keymap dmap; + + Keymap oldmap; + int okey; + struct __rl_keyseq_context *ocxt; + int childval; +} _rl_keyseq_cxt; + + /* fill in more as needed */ /* `Generic' callback data and functions */ typedef struct __rl_callback_generic_arg { @@ -121,6 +141,8 @@ extern int readline_echoing_p; extern int rl_key_sequence_length; extern int rl_byte_oriented; +extern _rl_keyseq_cxt *_rl_kscxt; + /* display.c */ extern int rl_display_fixed; @@ -167,6 +189,12 @@ extern void readline_internal_setup PARAMS((void)); extern char *readline_internal_teardown PARAMS((int)); extern int readline_internal_char PARAMS((void)); +extern _rl_keyseq_cxt *_rl_keyseq_cxt_alloc PARAMS((void)); +extern void _rl_keyseq_cxt_dispose PARAMS((_rl_keyseq_cxt *)); +extern void _rl_keyseq_chain_dispose PARAMS((void)); + +extern int _rl_dispatch_callback PARAMS((_rl_keyseq_cxt *)); + /* callback.c */ extern _rl_callback_generic_arg *_rl_callback_data_alloc PARAMS((int)); extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *)); @@ -242,6 +270,7 @@ extern void _rl_init_line_state PARAMS((void)); extern void _rl_set_the_line PARAMS((void)); extern int _rl_dispatch PARAMS((int, Keymap)); extern int _rl_dispatch_subseq PARAMS((int, Keymap, int)); +extern void _rl_internal_char_cleanup PARAMS((void)); /* rltty.c */ extern int _rl_disable_tty_signals PARAMS((void)); diff --git a/lib/readline/search.c b/lib/readline/search.c index 103efd1a..b4c174d5 100644 --- a/lib/readline/search.c +++ b/lib/readline/search.c @@ -421,6 +421,7 @@ rl_noninc_reverse_search_again (count, key) return (r != 1); } +#if defined (READLINE_CALLBACKS) int _rl_nsearch_callback (cxt) _rl_search_cxt *cxt; @@ -435,6 +436,7 @@ _rl_nsearch_callback (cxt) r = _rl_nsearch_dosearch (cxt); return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1)); } +#endif static int rl_history_search_internal (count, dir) diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c index 06ec4427..efaef399 100644 --- a/lib/readline/vi_mode.c +++ b/lib/readline/vi_mode.c @@ -1188,7 +1188,7 @@ _rl_vi_callback_char_search (data) _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); #else RL_SETSTATE(RL_STATE_MOREINPUT); - _rl_vi_last_search_char = target = rl_read_key (); + _rl_vi_last_search_char = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); #endif @@ -1437,9 +1437,7 @@ _rl_vi_callback_change_char (data) _rl_callback_generic_arg *data; { int c; -#if defined (HANDLE_MULTIBYTE) char mb[MB_LEN_MAX]; -#endif _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); @@ -1968,6 +1968,7 @@ shell_getc (remove_quoted_newline) } shell_input_line_index = 0; +itrace("reset shell_input_line_index = 0"); shell_input_line_len = i; /* == strlen (shell_input_line) */ set_line_mbstate (); @@ -4614,7 +4615,7 @@ parse_string_to_word_list (s, flags, whom) line_number = orig_line_number + line_number - 1; orig_current_token = current_token; current_token = tok; - yyerror ((char *)NULL); /* does the right thing */ + yyerror (NULL); /* does the right thing */ current_token = orig_current_token; if (wl) dispose_words (wl); @@ -4689,7 +4690,7 @@ parse_compound_assignment (retlenp) if (tok == yacc_EOF) /* ( */ parser_error (orig_line_number, _("unexpected EOF while looking for matching `)'")); else - yyerror ((char *)NULL); /* does the right thing */ + yyerror(NULL); /* does the right thing */ if (wl) dispose_words (wl); wl = &parse_string_error; @@ -1,6 +1,6 @@ /* version.c -- distribution and version numbers. */ -/* Copyright (C) 1989 Free Software Foundation, Inc. +/* Copyright (C) 1989-2005 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -79,5 +79,5 @@ show_shell_version (extended) { printf ("GNU bash, version %s (%s)\n", shell_version_string (), MACHTYPE); if (extended) - printf (_("Copyright (C) 2004 Free Software Foundation, Inc.\n")); + printf (_("Copyright (C) 2005 Free Software Foundation, Inc.\n")); } |