summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2011-12-03 13:47:06 -0500
committerChet Ramey <chet.ramey@case.edu>2011-12-03 13:47:06 -0500
commit19e1dd936da1a4a41c107c75e1139652582d03b3 (patch)
tree6b335a27fc96861e5d11b2d38c96b08834843a7d
parent798a67db11293f88fb381edfba4bd5b0a41d60fe (diff)
downloadbash-19e1dd936da1a4a41c107c75e1139652582d03b3.tar.gz
commit bash-20050519 snapshot
-rw-r--r--CWRU/CWRU.chlog106
-rw-r--r--CWRU/CWRU.chlog~144
-rw-r--r--array.c4
-rw-r--r--array.c~1
-rw-r--r--builtins/exec.def3
-rw-r--r--builtins/exec.def~228
-rw-r--r--builtins/read.def5
-rw-r--r--builtins/read.def~14
-rw-r--r--execute_cmd.c5
-rw-r--r--execute_cmd.c~9
-rw-r--r--jobs.c10
-rw-r--r--jobs.c~1
-rw-r--r--lib/readline/callback.c49
-rw-r--r--lib/readline/display.c~8
-rw-r--r--lib/readline/examples/rlptytest.c294
-rw-r--r--lib/readline/macro.c9
-rw-r--r--lib/readline/readline.c331
-rw-r--r--lib/readline/rlprivate.h29
-rw-r--r--lib/readline/search.c2
-rw-r--r--lib/readline/vi_mode.c4
-rw-r--r--parse.y~5
-rw-r--r--version.c4
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>
diff --git a/array.c b/array.c
index 69672d14..c32b6134 100644
--- a/array.c
+++ b/array.c
@@ -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);
}
diff --git a/array.c~ b/array.c~
index 2b362c67..69672d14 100644
--- a/array.c~
+++ b/array.c~
@@ -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)
diff --git a/jobs.c b/jobs.c
index f8a5c819..05d93950 100644
--- a/jobs.c
+++ b/jobs.c
@@ -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))
diff --git a/jobs.c~ b/jobs.c~
index faa264ae..f8a5c819 100644
--- a/jobs.c~
+++ b/jobs.c~
@@ -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);
diff --git a/parse.y~ b/parse.y~
index 4c57ff4b..9ea5b6de 100644
--- a/parse.y~
+++ b/parse.y~
@@ -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;
diff --git a/version.c b/version.c
index bad76b01..f3733727 100644
--- a/version.c
+++ b/version.c
@@ -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"));
}