3cdd4d2bbe
215816). - Resolves: rhbz#215816
166 lines
5.7 KiB
Diff
166 lines
5.7 KiB
Diff
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=215816
|
||
|
||
|
||
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.
|
||
|
||
|
||
--- ./gdb/Makefile.in 3 Jan 2007 18:05:43 -0000 1.864
|
||
+++ ./gdb/Makefile.in 3 Jan 2007 21:22:46 -0000
|
||
@@ -2782,7 +2782,7 @@ top.o: top.c $(defs_h) $(gdbcmd_h) $(cal
|
||
$(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) \
|
||
--- ./gdb/top.c 1 Jan 2007 05:57:49 -0000 1.116
|
||
+++ ./gdb/top.c 3 Jan 2007 21:22:47 -0000
|
||
@@ -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"
|
||
@@ -710,24 +710,84 @@
|
||
}
|
||
|
||
/* 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;
|
||
|
||
/* Before calling readline, ensure we have the terminal. If we don't
|
||
have the terminal and call readline, we risk the possibility of
|
||
@@ -737,7 +797,32 @@
|
||
a page break prompt. */
|
||
terminal_ours ();
|
||
|
||
- 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;
|
||
}
|
||
|
||
|