2007-01-03 Jan Kratochvil <jan.kratochvil@redhat.com>

Daniel Jacobowitz  <dan@codesourcery.com>

	* Makefile.in (top.o): Update.
	* top.c (gdb_readline_wrapper_done, gdb_readline_wrapper_result)
	(saved_after_char_processing_hook, gdb_readline_wrapper_line)
	(struct gdb_readline_wrapper_cleanup, gdb_readline_wrapper_cleanup):
	New.
	(gdb_readline_wrapper): Rewrite to use asynchronous readline.

2007-01-03  Jan Kratochvil  <jan.kratochvil@redhat.com>
	    Daniel Jacobowitz  <dan@codesourcery.com>

	* gdb.base/readline.exp: Set $TERM.  Test arrow keys in
	secondary prompts.
This commit is contained in:
Daniel Jacobowitz 2007-01-03 21:46:12 +00:00
parent 1c63d08666
commit 2e03ee74df
5 changed files with 136 additions and 14 deletions

View File

@ -1,3 +1,13 @@
2007-01-03 Jan Kratochvil <jan.kratochvil@redhat.com>
Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (top.o): Update.
* top.c (gdb_readline_wrapper_done, gdb_readline_wrapper_result)
(saved_after_char_processing_hook, gdb_readline_wrapper_line)
(struct gdb_readline_wrapper_cleanup, gdb_readline_wrapper_cleanup):
New.
(gdb_readline_wrapper): Rewrite to use asynchronous readline.
2007-01-03 Mark Kettenis <kettenis@gnu.org>
* arm-linux-tdep.c (arm_linux_extract_return_value): Remove.

View File

@ -2782,7 +2782,7 @@ top.o: top.c $(defs_h) $(gdbcmd_h) $(call_cmds_h) $(cli_cmds_h) \
$(annotate_h) $(completer_h) $(top_h) $(version_h) $(serial_h) \
$(doublest_h) $(gdb_assert_h) $(readline_h) $(readline_history_h) \
$(event_top_h) $(gdb_string_h) $(gdb_stat_h) $(ui_out_h) \
$(cli_out_h) $(main_h)
$(cli_out_h) $(main_h) $(event_loop_h)
tracepoint.o: tracepoint.c $(defs_h) $(symtab_h) $(frame_h) $(gdbtypes_h) \
$(expression_h) $(gdbcmd_h) $(value_h) $(target_h) $(language_h) \
$(gdb_string_h) $(inferior_h) $(tracepoint_h) $(remote_h) \

View File

@ -1,3 +1,9 @@
2007-01-03 Jan Kratochvil <jan.kratochvil@redhat.com>
Daniel Jacobowitz <dan@codesourcery.com>
* gdb.base/readline.exp: Set $TERM. Test arrow keys in
secondary prompts.
2007-01-03 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.cp/classes.exp (test_pointers_to_class_members): Update expected

View File

@ -1,4 +1,4 @@
# Copyright 2002 Free Software Foundation, Inc.
# Copyright 2002, 2003, 2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -159,6 +159,14 @@ if [info exists env(INPUTRC)] {
}
set env(INPUTRC) "/dev/null"
# The arrow key test relies on the standard VT100 bindings, so make
# sure that an appropriate terminal is selected. The same bug
# doesn't show up if we use ^P / ^N instead.
if [info exists env(TERM)] {
set old_term $env(TERM)
}
set env(TERM) "vt100"
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
@ -178,6 +186,18 @@ operate_and_get_next "operate-and-get-next with secondary prompt" \
"p 5" "" \
"end" ".* = 5"
# Verify that arrow keys work in secondary prompts. The control
# sequence is a hard-coded VT100 up arrow.
gdb_test "print 42" "\\\$\[0-9\]* = 42"
set msg "arrow keys with secondary prompt"
gdb_test_multiple "if 1 > 0\n\033\[A\033\[A\nend" $msg {
-re ".*\\\$\[0-9\]* = 42\r\n$gdb_prompt $" {
pass $msg
}
-re ".*Undefined command:.*$gdb_prompt $" {
fail $msg
}
}
# Now repeat the first test with a history file that fills the entire
# history list.

110
gdb/top.c
View File

@ -47,6 +47,7 @@
#include "doublest.h"
#include "gdb_assert.h"
#include "main.h"
#include "event-loop.h"
/* readline include files */
#include "readline/readline.h"
@ -712,26 +713,111 @@ The filename in which to record the command history is \"%s\".\n"),
}
/* This is like readline(), but it has some gdb-specific behavior.
gdb can use readline in both the synchronous and async modes during
gdb may want readline in both the synchronous and async modes during
a single gdb invocation. At the ordinary top-level prompt we might
be using the async readline. That means we can't use
rl_pre_input_hook, since it doesn't work properly in async mode.
However, for a secondary prompt (" >", such as occurs during a
`define'), gdb just calls readline() directly, running it in
synchronous mode. So for operate-and-get-next to work in this
situation, we have to switch the hooks around. That is what
gdb_readline_wrapper is for. */
`define'), gdb wants a synchronous response.
We used to call readline() directly, running it in synchronous
mode. But mixing modes this way is not supported, and as of
readline 5.x it no longer works; the arrow keys come unbound during
the synchronous call. So we make a nested call into the event
loop. That's what gdb_readline_wrapper is for. */
/* A flag set as soon as gdb_readline_wrapper_line is called; we can't
rely on gdb_readline_wrapper_result, which might still be NULL if
the user types Control-D for EOF. */
static int gdb_readline_wrapper_done;
/* The result of the current call to gdb_readline_wrapper, once a newline
is seen. */
static char *gdb_readline_wrapper_result;
/* Any intercepted hook. Operate-and-get-next sets this, expecting it
to be called after the newline is processed (which will redisplay
the prompt). But in gdb_readline_wrapper we will not get a new
prompt until the next call, or until we return to the event loop.
So we disable this hook around the newline and restore it before we
return. */
static void (*saved_after_char_processing_hook) (void);
/* This function is called when readline has seen a complete line of
text. */
static void
gdb_readline_wrapper_line (char *line)
{
gdb_assert (!gdb_readline_wrapper_done);
gdb_readline_wrapper_result = line;
gdb_readline_wrapper_done = 1;
/* Prevent operate-and-get-next from acting too early. */
saved_after_char_processing_hook = after_char_processing_hook;
after_char_processing_hook = NULL;
}
struct gdb_readline_wrapper_cleanup
{
void (*handler_orig) (char *);
char *prompt_orig;
int already_prompted_orig;
};
static void
gdb_readline_wrapper_cleanup (void *arg)
{
struct gdb_readline_wrapper_cleanup *cleanup = arg;
gdb_assert (rl_already_prompted == 1);
rl_already_prompted = cleanup->already_prompted_orig;
PROMPT (0) = cleanup->prompt_orig;
gdb_assert (input_handler == gdb_readline_wrapper_line);
input_handler = cleanup->handler_orig;
gdb_readline_wrapper_result = NULL;
gdb_readline_wrapper_done = 0;
after_char_processing_hook = saved_after_char_processing_hook;
saved_after_char_processing_hook = NULL;
xfree (cleanup);
}
char *
gdb_readline_wrapper (char *prompt)
{
/* Set the hook that works in this case. */
if (after_char_processing_hook)
{
rl_pre_input_hook = (Function *) after_char_processing_hook;
after_char_processing_hook = NULL;
}
struct cleanup *back_to;
struct gdb_readline_wrapper_cleanup *cleanup;
char *retval;
return readline (prompt);
cleanup = xmalloc (sizeof (*cleanup));
cleanup->handler_orig = input_handler;
input_handler = gdb_readline_wrapper_line;
cleanup->prompt_orig = get_prompt ();
PROMPT (0) = prompt;
cleanup->already_prompted_orig = rl_already_prompted;
back_to = make_cleanup (gdb_readline_wrapper_cleanup, cleanup);
/* Display our prompt and prevent double prompt display. */
display_gdb_prompt (NULL);
rl_already_prompted = 1;
if (after_char_processing_hook)
(*after_char_processing_hook) ();
gdb_assert (after_char_processing_hook == NULL);
/* gdb_do_one_event argument is unused. */
while (gdb_do_one_event (NULL) >= 0)
if (gdb_readline_wrapper_done)
break;
retval = gdb_readline_wrapper_result;
do_cleanups (back_to);
return retval;
}