[PATCH v6 1/2] Make display_gdb_prompt CLI-only.

Pedro Alves
2014-05-23T20:59:21Z

Enabling target-async by default will require implementing sync
execution on top of an async target, much like foreground command are
implemented on the CLI in async mode.

In order to do that, we will need better control of when to print the
MI prompt. Currently the interp->display_prompt_p hook is all we
have, and MI just always returns false, meaning, make
display_gdb_prompt a no-op. We'll need to be able to know to print
the MI prompt in some of the conditions that display_gdb_prompt is
called from the core, but not all.

This is all a litte twisted currently. As we can see,
display_gdb_prompt is really CLI specific, so make the console
interpreters (console/tui) themselves call it. To be able to do that,
and add a few different observers that the interpreters can use to
distinguish when or why the the prompt is being printed:

#1 - one called whenever a command is cancelled due to an error.
#2 - another for when a foreground command just finished.

In both cases, CLI wants to print the prompt, while MI doesn't.

MI will want to print the prompt in the second case when in a special
MI mode.

The display_gdb_prompt call in interp_set made me pause. The comment
there reads:

/* Finally, put up the new prompt to show that we are indeed here.
Also, display_gdb_prompt for the console does some readline magic
which is needed for the console interpreter, at least... */

But, that looks very much like a no-op to me currently:

- the MI interpreter always return false in the prompt hook, meaning
actually display no prompt.

- the interpreter used at that point is still quiet. And the
console/tui interpreters return false in the prompt hook if they're
quiet, meaning actually display no prompt.

The only remaining possible use would then be the readline magic. But
whatever that might have been, it's not reacheable today either,
because display_gdb_prompt returns early, before touching readline if
the interpreter returns false in the display_prompt_p hook.

Tested on x86_64 Fedora 20, sync and async modes.

gdb/
2014-05-23 Pedro Alves <palves@redhat.com>

* cli/cli-interp.c (cli_interpreter_display_prompt_p): Delete.
(_initialize_cli_interp): Adjust.
* event-loop.c: Include "observer.h".
(start_event_loop): Notify 'command_error' observers instead of
calling display_gdb_prompt. Remove FIXME comment.
* event-top.c (display_gdb_prompt): Remove call into the
interpreters.
* inf-loop.c: Include "observer.h".
(inferior_event_handler): Notify 'command_error' observers instead
of calling display_gdb_prompt.
* infrun.c (fetch_inferior_event): Notify 'sync_execution_done'
observers instead of calling display_gdb_prompt.
* interps.c (interp_set): Don't call display_gdb_prompt.
(current_interp_display_prompt_p): Delete.
* interps.h (interp_prompt_p): Delete declaration.
(interp_prompt_p_ftype): Delete.
(struct interp_procs) <prompt_proc_p>: Delete field.
(current_interp_display_prompt_p): Delete declaration.
* mi-interp.c (mi_interpreter_prompt_p): Delete.
(_initialize_mi_interp): Adjust.
* tui-interp.c (tui_init): Install 'sync_execution_done' and
'command_error' observers.
(tui_on_sync_execution_done, tui_on_command_error): New
functions.
(tui_display_prompt_p): Delete.
(_initialize_tui_interp): Adjust.

gdb/doc/
2014-05-23 Pedro Alves <palves@redhat.com>

* observer.texi (synchronous_command_done, command_error): New
subjects.
---
gdb/cli/cli-interp.c | 31 ++++++++++++++++++++-----------
gdb/doc/observer.texi | 8 ++++++++
gdb/event-loop.c | 6 ++----
gdb/event-top.c | 5 -----
gdb/inf-loop.c | 3 ++-
gdb/infrun.c | 2 +-
gdb/interps.c | 30 ++++--------------------------
gdb/interps.h | 5 +----
gdb/mi/mi-interp.c | 9 ---------
gdb/tui/tui-interp.c | 32 ++++++++++++++++++++------------
10 files changed, 58 insertions(+), 73 deletions(-)

diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index d3badcd..dc09b24 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -87,6 +87,24 @@ cli_on_no_history (void)
print_no_history_reason (cli_uiout);
}

+/* Observer for the sync_execution_done notification. */
+
+static void
+cli_on_sync_execution_done (void)
+{
+ if (!interp_quiet_p (cli_interp))
+ display_gdb_prompt (NULL);
+}
+
+/* Observer for the command_error notification. */
+
+static void
+cli_on_command_error (void)
+{
+ if (!interp_quiet_p (cli_interp))
+ display_gdb_prompt (NULL);
+}
+
/* These implement the cli out interpreter: */

static void *
@@ -98,6 +116,8 @@ cli_interpreter_init (struct interp *self, int top_level)
observer_attach_signal_exited (cli_on_signal_exited);
observer_attach_exited (cli_on_exited);
observer_attach_no_history (cli_on_no_history);
+ observer_attach_sync_execution_done (cli_on_sync_execution_done);
+ observer_attach_command_error (cli_on_command_error);

return NULL;
}
@@ -135,16 +155,6 @@ cli_interpreter_suspend (void *data)
return 1;
}

-/* Don't display the prompt if we are set quiet. */
-static int
-cli_interpreter_display_prompt_p (void *data)
-{
- if (interp_quiet_p (NULL))
- return 0;
- else
- return 1;
-}
-
static struct gdb_exception
cli_interpreter_exec (void *data, const char *command_str)
{
@@ -209,7 +219,6 @@ _initialize_cli_interp (void)
cli_interpreter_resume, /* resume_proc */
cli_interpreter_suspend, /* suspend_proc */
cli_interpreter_exec, /* exec_proc */
- cli_interpreter_display_prompt_p, /* prompt_proc_p */
cli_ui_out, /* ui_out_proc */
NULL, /* set_logging_proc */
cli_command_loop /* command_loop_proc */
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
index ee43fc5..2757587 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -114,6 +114,14 @@ The inferior program is finished.
Reverse execution: target ran out of history info.
@end deftypefun

+@deftypefun void sync_execution_done (void)
+A synchronous command finished.
+@end deftypefun
+
+@deftypefun void command_error (void)
+An error was caught while executing a command.
+@end deftypefun
+
@deftypefun void target_changed (struct target_ops *@var{target})
The target's register contents have changed.
@end deftypefun
diff --git a/gdb/event-loop.c b/gdb/event-loop.c
index 7939739..5999c97 100644
--- a/gdb/event-loop.c
+++ b/gdb/event-loop.c
@@ -37,6 +37,7 @@
#include "exceptions.h"
#include "gdb_assert.h"
#include "gdb_select.h"
+#include "observer.h"

/* Tell create_file_handler what events we are interested in.
This is used by the select version of the event loop. */
@@ -441,10 +442,7 @@ start_event_loop (void)
/* If we long-jumped out of do_one_event, we probably didn't
get around to resetting the prompt, which leaves readline
in a messed-up state. Reset it here. */
- /* FIXME: this should really be a call to a hook that is
- interface specific, because interfaces can display the
- prompt in their own way. */
- display_gdb_prompt (0);
+ observer_notify_command_error ();
/* This call looks bizarre, but it is required. If the user
entered a command that caused an error,
after_char_processing_hook won't be called from
diff --git a/gdb/event-top.c b/gdb/event-top.c
index f690bc6..833f49d 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -243,11 +243,6 @@ display_gdb_prompt (char *new_prompt)
/* Reset the nesting depth used when trace-commands is set. */
reset_command_nest_depth ();

- /* Each interpreter has its own rules on displaying the command
- prompt. */
- if (!current_interp_display_prompt_p ())
- return;
-
old_chain = make_cleanup (free_current_contents, &actual_gdb_prompt);

/* Do not call the python hook on an explicit prompt change as
diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c
index f5293ae..247e9d6 100644
--- a/gdb/inf-loop.c
+++ b/gdb/inf-loop.c
@@ -31,6 +31,7 @@
#include "continuations.h"
#include "interps.h"
#include "top.h"
+#include "observer.h"

static int fetch_inferior_event_wrapper (gdb_client_data client_data);

@@ -58,7 +59,7 @@ inferior_event_handler (enum inferior_event_type event_type,
do_all_intermediate_continuations (1);
do_all_continuations (1);
async_enable_stdin ();
- display_gdb_prompt (0);
+ observer_notify_command_error ();
}
break;

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 461f6e7..25626d9 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2938,7 +2938,7 @@ fetch_inferior_event (void *client_data)
restore the prompt (a synchronous execution command has finished,
and we're ready for input). */
if (interpreter_async && was_sync && !sync_execution)
- display_gdb_prompt (0);
+ observer_notify_sync_execution_done ();

if (cmd_done
&& !was_sync
diff --git a/gdb/interps.c b/gdb/interps.c
index f6b941c..5a93095 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -204,19 +204,11 @@ interp_set (struct interp *interp, int top_level)
return 0;
}

- /* Finally, put up the new prompt to show that we are indeed here.
- Also, display_gdb_prompt for the console does some readline magic
- which is needed for the console interpreter, at least... */
-
- if (!first_time)
+ if (!first_time && !interp_quiet_p (interp))
{
- if (!interp_quiet_p (interp))
- {
- xsnprintf (buffer, sizeof (buffer),
- "Switching to interpreter \"%.24s\".\n", interp->name);
- ui_out_text (current_uiout, buffer);
- }
- display_gdb_prompt (NULL);
+ xsnprintf (buffer, sizeof (buffer),
+ "Switching to interpreter \"%.24s\".\n", interp->name);
+ ui_out_text (current_uiout, buffer);
}

return 1;
@@ -304,20 +296,6 @@ current_interp_named_p (const char *interp_name)
return 0;
}

-/* This is called in display_gdb_prompt. If the proc returns a zero
- value, display_gdb_prompt will return without displaying the
- prompt. */
-int
-current_interp_display_prompt_p (void)
-{
- if (current_interpreter == NULL
- || current_interpreter->procs->prompt_proc_p == NULL)
- return 0;
- else
- return current_interpreter->procs->prompt_proc_p (current_interpreter->
- data);
-}
-
/* The interpreter that is active while `interp_exec' is active, NULL
at all other times. */
static struct interp *command_interpreter;
diff --git a/gdb/interps.h b/gdb/interps.h
index 13edf42..197fa55 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -29,7 +29,6 @@ struct interp;

extern int interp_resume (struct interp *interp);
extern int interp_suspend (struct interp *interp);
-extern int interp_prompt_p (struct interp *interp);
extern struct gdb_exception interp_exec (struct interp *interp,
const char *command);
extern int interp_quiet_p (struct interp *interp);
@@ -37,7 +36,6 @@ extern int interp_quiet_p (struct interp *interp);
typedef void *(interp_init_ftype) (struct interp *self, int top_level);
typedef int (interp_resume_ftype) (void *data);
typedef int (interp_suspend_ftype) (void *data);
-typedef int (interp_prompt_p_ftype) (void *data);
typedef struct gdb_exception (interp_exec_ftype) (void *data,
const char *command);
typedef void (interp_command_loop_ftype) (void *data);
@@ -53,7 +51,6 @@ struct interp_procs
interp_resume_ftype *resume_proc;
interp_suspend_ftype *suspend_proc;
interp_exec_ftype *exec_proc;
- interp_prompt_p_ftype *prompt_proc_p;

/* Returns the ui_out currently used to collect results for this
interpreter. It can be a formatter for stdout, as is the case
@@ -79,7 +76,7 @@ extern const char *interp_name (struct interp *interp);
extern struct interp *interp_set_temp (const char *name);

extern int current_interp_named_p (const char *name);
-extern int current_interp_display_prompt_p (void);
+
extern void current_interp_command_loop (void);

/* Call this function to give the current interpreter an opportunity
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index e8e30e2..e1dd97f 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -223,14 +223,6 @@ mi_interpreter_exec (void *data, const char *command)
return exception_none;
}

-/* Never display the default GDB prompt in MI case. */
-
-static int
-mi_interpreter_prompt_p (void *data)
-{
- return 0;
-}
-
void
mi_cmd_interpreter_exec (char *command, char **argv, int argc)
{
@@ -1142,7 +1134,6 @@ _initialize_mi_interp (void)
mi_interpreter_resume, /* resume_proc */
mi_interpreter_suspend, /* suspend_proc */
mi_interpreter_exec, /* exec_proc */
- mi_interpreter_prompt_p, /* prompt_proc_p */
mi_ui_out, /* ui_out_proc */
mi_set_logging, /* set_logging_proc */
mi_command_loop /* command_loop_proc */
diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c
index cd11148..147a424 100644
--- a/gdb/tui/tui-interp.c
+++ b/gdb/tui/tui-interp.c
@@ -104,6 +104,24 @@ tui_on_no_history (void)
print_no_history_reason (tui_ui_out (tui_interp));
}

+/* Observer for the sync_execution_done notification. */
+
+static void
+tui_on_sync_execution_done (void)
+{
+ if (!interp_quiet_p (tui_interp))
+ display_gdb_prompt (NULL);
+}
+
+/* Observer for the command_error notification. */
+
+static void
+tui_on_command_error (void)
+{
+ if (!interp_quiet_p (tui_interp))
+ display_gdb_prompt (NULL);
+}
+
/* These implement the TUI interpreter. */

static void *
@@ -127,6 +145,8 @@ tui_init (struct interp *self, int top_level)
observer_attach_signal_exited (tui_on_signal_exited);
observer_attach_exited (tui_on_exited);
observer_attach_no_history (tui_on_no_history);
+ observer_attach_sync_execution_done (tui_on_sync_execution_done);
+ observer_attach_command_error (tui_on_command_error);

return NULL;
}
@@ -177,17 +197,6 @@ tui_suspend (void *data)
return 1;
}

-/* Display the prompt if we are silent. */
-
-static int
-tui_display_prompt_p (void *data)
-{
- if (interp_quiet_p (NULL))
- return 0;
- else
- return 1;
-}
-
static struct ui_out *
tui_ui_out (struct interp *self)
{
@@ -214,7 +223,6 @@ _initialize_tui_interp (void)
tui_resume,
tui_suspend,
tui_exec,
- tui_display_prompt_p,
tui_ui_out,
NULL,
cli_command_loop
--
1.9.0