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> 2007-01-03 Mark Kettenis <kettenis@gnu.org>
* arm-linux-tdep.c (arm_linux_extract_return_value): Remove. * 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) \ $(annotate_h) $(completer_h) $(top_h) $(version_h) $(serial_h) \
$(doublest_h) $(gdb_assert_h) $(readline_h) $(readline_history_h) \ $(doublest_h) $(gdb_assert_h) $(readline_h) $(readline_history_h) \
$(event_top_h) $(gdb_string_h) $(gdb_stat_h) $(ui_out_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) \ tracepoint.o: tracepoint.c $(defs_h) $(symtab_h) $(frame_h) $(gdbtypes_h) \
$(expression_h) $(gdbcmd_h) $(value_h) $(target_h) $(language_h) \ $(expression_h) $(gdbcmd_h) $(value_h) $(target_h) $(language_h) \
$(gdb_string_h) $(inferior_h) $(tracepoint_h) $(remote_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> 2007-01-03 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.cp/classes.exp (test_pointers_to_class_members): Update expected * 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 # 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 # 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" 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_start
gdb_reinitialize_dir $srcdir/$subdir gdb_reinitialize_dir $srcdir/$subdir
@ -178,6 +186,18 @@ operate_and_get_next "operate-and-get-next with secondary prompt" \
"p 5" "" \ "p 5" "" \
"end" ".* = 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 # Now repeat the first test with a history file that fills the entire
# history list. # history list.

110
gdb/top.c
View file

@ -47,6 +47,7 @@
#include "doublest.h" #include "doublest.h"
#include "gdb_assert.h" #include "gdb_assert.h"
#include "main.h" #include "main.h"
#include "event-loop.h"
/* readline include files */ /* readline include files */
#include "readline/readline.h" #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. /* 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 a single gdb invocation. At the ordinary top-level prompt we might
be using the async readline. That means we can't use be using the async readline. That means we can't use
rl_pre_input_hook, since it doesn't work properly in async mode. rl_pre_input_hook, since it doesn't work properly in async mode.
However, for a secondary prompt (" >", such as occurs during a However, for a secondary prompt (" >", such as occurs during a
`define'), gdb just calls readline() directly, running it in `define'), gdb wants a synchronous response.
synchronous mode. So for operate-and-get-next to work in this
situation, we have to switch the hooks around. That is what We used to call readline() directly, running it in synchronous
gdb_readline_wrapper is for. */ 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 * char *
gdb_readline_wrapper (char *prompt) gdb_readline_wrapper (char *prompt)
{ {
/* Set the hook that works in this case. */ struct cleanup *back_to;
if (after_char_processing_hook) struct gdb_readline_wrapper_cleanup *cleanup;
{ char *retval;
rl_pre_input_hook = (Function *) after_char_processing_hook;
after_char_processing_hook = NULL;
}
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;
} }