Make display_gdb_prompt CLI-only.

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-29  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-29  Pedro Alves  <palves@redhat.com>

	* observer.texi (sync_execution_done, command_error): New
	subjects.
This commit is contained in:
Pedro Alves 2014-05-23 11:37:12 +01:00
parent fd664c9176
commit 92bcb5f949
12 changed files with 92 additions and 73 deletions

View File

@ -1,3 +1,32 @@
2014-05-29 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.
2014-05-29 Pedro Alves <palves@redhat.com> 2014-05-29 Pedro Alves <palves@redhat.com>
PR gdb/13860 PR gdb/13860

View File

@ -87,6 +87,24 @@ cli_on_no_history (void)
print_no_history_reason (cli_uiout); 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: */ /* These implement the cli out interpreter: */
static void * 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_signal_exited (cli_on_signal_exited);
observer_attach_exited (cli_on_exited); observer_attach_exited (cli_on_exited);
observer_attach_no_history (cli_on_no_history); 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; return NULL;
} }
@ -135,16 +155,6 @@ cli_interpreter_suspend (void *data)
return 1; 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 static struct gdb_exception
cli_interpreter_exec (void *data, const char *command_str) cli_interpreter_exec (void *data, const char *command_str)
{ {
@ -209,7 +219,6 @@ _initialize_cli_interp (void)
cli_interpreter_resume, /* resume_proc */ cli_interpreter_resume, /* resume_proc */
cli_interpreter_suspend, /* suspend_proc */ cli_interpreter_suspend, /* suspend_proc */
cli_interpreter_exec, /* exec_proc */ cli_interpreter_exec, /* exec_proc */
cli_interpreter_display_prompt_p, /* prompt_proc_p */
cli_ui_out, /* ui_out_proc */ cli_ui_out, /* ui_out_proc */
NULL, /* set_logging_proc */ NULL, /* set_logging_proc */
cli_command_loop /* command_loop_proc */ cli_command_loop /* command_loop_proc */

View File

@ -1,3 +1,8 @@
2014-05-29 Pedro Alves <palves@redhat.com>
* observer.texi (sync_execution_done, command_error): New
subjects.
2014-05-29 Pedro Alves <palves@redhat.com> 2014-05-29 Pedro Alves <palves@redhat.com>
PR gdb/13860 PR gdb/13860

View File

@ -114,6 +114,14 @@ The inferior program is finished.
Reverse execution: target ran out of history info. Reverse execution: target ran out of history info.
@end deftypefun @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}) @deftypefun void target_changed (struct target_ops *@var{target})
The target's register contents have changed. The target's register contents have changed.
@end deftypefun @end deftypefun

View File

@ -37,6 +37,7 @@
#include "exceptions.h" #include "exceptions.h"
#include "gdb_assert.h" #include "gdb_assert.h"
#include "gdb_select.h" #include "gdb_select.h"
#include "observer.h"
/* Tell create_file_handler what events we are interested in. /* Tell create_file_handler what events we are interested in.
This is used by the select version of the event loop. */ 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 /* If we long-jumped out of do_one_event, we probably didn't
get around to resetting the prompt, which leaves readline get around to resetting the prompt, which leaves readline
in a messed-up state. Reset it here. */ in a messed-up state. Reset it here. */
/* FIXME: this should really be a call to a hook that is observer_notify_command_error ();
interface specific, because interfaces can display the
prompt in their own way. */
display_gdb_prompt (0);
/* This call looks bizarre, but it is required. If the user /* This call looks bizarre, but it is required. If the user
entered a command that caused an error, entered a command that caused an error,
after_char_processing_hook won't be called from after_char_processing_hook won't be called from

View File

@ -243,11 +243,6 @@ display_gdb_prompt (char *new_prompt)
/* Reset the nesting depth used when trace-commands is set. */ /* Reset the nesting depth used when trace-commands is set. */
reset_command_nest_depth (); 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); old_chain = make_cleanup (free_current_contents, &actual_gdb_prompt);
/* Do not call the python hook on an explicit prompt change as /* Do not call the python hook on an explicit prompt change as

View File

@ -31,6 +31,7 @@
#include "continuations.h" #include "continuations.h"
#include "interps.h" #include "interps.h"
#include "top.h" #include "top.h"
#include "observer.h"
static int fetch_inferior_event_wrapper (gdb_client_data client_data); 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_intermediate_continuations (1);
do_all_continuations (1); do_all_continuations (1);
async_enable_stdin (); async_enable_stdin ();
display_gdb_prompt (0); observer_notify_command_error ();
} }
break; break;

View File

@ -2950,7 +2950,7 @@ fetch_inferior_event (void *client_data)
restore the prompt (a synchronous execution command has finished, restore the prompt (a synchronous execution command has finished,
and we're ready for input). */ and we're ready for input). */
if (interpreter_async && was_sync && !sync_execution) if (interpreter_async && was_sync && !sync_execution)
display_gdb_prompt (0); observer_notify_sync_execution_done ();
if (cmd_done if (cmd_done
&& !was_sync && !was_sync

View File

@ -204,19 +204,11 @@ interp_set (struct interp *interp, int top_level)
return 0; return 0;
} }
/* Finally, put up the new prompt to show that we are indeed here. if (!first_time && !interp_quiet_p (interp))
Also, display_gdb_prompt for the console does some readline magic
which is needed for the console interpreter, at least... */
if (!first_time)
{ {
if (!interp_quiet_p (interp)) xsnprintf (buffer, sizeof (buffer),
{ "Switching to interpreter \"%.24s\".\n", interp->name);
xsnprintf (buffer, sizeof (buffer), ui_out_text (current_uiout, buffer);
"Switching to interpreter \"%.24s\".\n", interp->name);
ui_out_text (current_uiout, buffer);
}
display_gdb_prompt (NULL);
} }
return 1; return 1;
@ -304,20 +296,6 @@ current_interp_named_p (const char *interp_name)
return 0; 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 /* The interpreter that is active while `interp_exec' is active, NULL
at all other times. */ at all other times. */
static struct interp *command_interpreter; static struct interp *command_interpreter;

View File

@ -29,7 +29,6 @@ struct interp;
extern int interp_resume (struct interp *interp); extern int interp_resume (struct interp *interp);
extern int interp_suspend (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, extern struct gdb_exception interp_exec (struct interp *interp,
const char *command); const char *command);
extern int interp_quiet_p (struct interp *interp); 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 void *(interp_init_ftype) (struct interp *self, int top_level);
typedef int (interp_resume_ftype) (void *data); typedef int (interp_resume_ftype) (void *data);
typedef int (interp_suspend_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, typedef struct gdb_exception (interp_exec_ftype) (void *data,
const char *command); const char *command);
typedef void (interp_command_loop_ftype) (void *data); typedef void (interp_command_loop_ftype) (void *data);
@ -53,7 +51,6 @@ struct interp_procs
interp_resume_ftype *resume_proc; interp_resume_ftype *resume_proc;
interp_suspend_ftype *suspend_proc; interp_suspend_ftype *suspend_proc;
interp_exec_ftype *exec_proc; interp_exec_ftype *exec_proc;
interp_prompt_p_ftype *prompt_proc_p;
/* Returns the ui_out currently used to collect results for this /* Returns the ui_out currently used to collect results for this
interpreter. It can be a formatter for stdout, as is the case 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 struct interp *interp_set_temp (const char *name);
extern int current_interp_named_p (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); extern void current_interp_command_loop (void);
/* Call this function to give the current interpreter an opportunity /* Call this function to give the current interpreter an opportunity

View File

@ -223,14 +223,6 @@ mi_interpreter_exec (void *data, const char *command)
return exception_none; return exception_none;
} }
/* Never display the default GDB prompt in MI case. */
static int
mi_interpreter_prompt_p (void *data)
{
return 0;
}
void void
mi_cmd_interpreter_exec (char *command, char **argv, int argc) 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_resume, /* resume_proc */
mi_interpreter_suspend, /* suspend_proc */ mi_interpreter_suspend, /* suspend_proc */
mi_interpreter_exec, /* exec_proc */ mi_interpreter_exec, /* exec_proc */
mi_interpreter_prompt_p, /* prompt_proc_p */
mi_ui_out, /* ui_out_proc */ mi_ui_out, /* ui_out_proc */
mi_set_logging, /* set_logging_proc */ mi_set_logging, /* set_logging_proc */
mi_command_loop /* command_loop_proc */ mi_command_loop /* command_loop_proc */

View File

@ -104,6 +104,24 @@ tui_on_no_history (void)
print_no_history_reason (tui_ui_out (tui_interp)); 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. */ /* These implement the TUI interpreter. */
static void * static void *
@ -127,6 +145,8 @@ tui_init (struct interp *self, int top_level)
observer_attach_signal_exited (tui_on_signal_exited); observer_attach_signal_exited (tui_on_signal_exited);
observer_attach_exited (tui_on_exited); observer_attach_exited (tui_on_exited);
observer_attach_no_history (tui_on_no_history); 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; return NULL;
} }
@ -177,17 +197,6 @@ tui_suspend (void *data)
return 1; 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 * static struct ui_out *
tui_ui_out (struct interp *self) tui_ui_out (struct interp *self)
{ {
@ -214,7 +223,6 @@ _initialize_tui_interp (void)
tui_resume, tui_resume,
tui_suspend, tui_suspend,
tui_exec, tui_exec,
tui_display_prompt_p,
tui_ui_out, tui_ui_out,
NULL, NULL,
cli_command_loop cli_command_loop