diff options
Diffstat (limited to 'gdb/mi')
-rw-r--r-- | gdb/mi/mi-interp.c | 52 | ||||
-rw-r--r-- | gdb/mi/mi-main.c | 77 | ||||
-rw-r--r-- | gdb/mi/mi-main.h | 4 |
3 files changed, 120 insertions, 13 deletions
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index e1dd97f..52a3a62 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -85,6 +85,7 @@ static void mi_breakpoint_modified (struct breakpoint *b); static void mi_command_param_changed (const char *param, const char *value); static void mi_memory_changed (struct inferior *inf, CORE_ADDR memaddr, ssize_t len, const bfd_byte *myaddr); +static void mi_on_sync_execution_done (void); static int report_initial_inferior (struct inferior *inf, void *closure); @@ -158,6 +159,7 @@ mi_interpreter_init (struct interp *interp, int top_level) observer_attach_breakpoint_modified (mi_breakpoint_modified); observer_attach_command_param_changed (mi_command_param_changed); observer_attach_memory_changed (mi_memory_changed); + observer_attach_sync_execution_done (mi_on_sync_execution_done); /* The initial inferior is created before this function is called, so we need to report it explicitly. Use iteration in @@ -304,6 +306,28 @@ mi_execute_command_wrapper (const char *cmd) mi_execute_command (cmd, stdin == instream); } +/* Observer for the synchronous_command_done notification. */ + +static void +mi_on_sync_execution_done (void) +{ + /* MI generally prints a prompt after a command, indicating it's + ready for further input. However, due to an historical wart, if + MI async, and a (CLI) synchronous command was issued, then we + will print the prompt right after printing "^running", even if we + cannot actually accept any input until the target stops. See + mi_on_resume. However, if the target is async but MI is sync, + then we need to output the MI prompt now, to replicate gdb's + behavior when neither the target nor MI are async. (Note this + observer is only called by the asynchronous target event handling + code.) */ + if (!mi_async_p ()) + { + fputs_unfiltered ("(gdb) \n", raw_stdout); + gdb_flush (raw_stdout); + } +} + /* mi_execute_command_wrapper wrapper suitable for INPUT_HANDLER. */ static void @@ -311,8 +335,24 @@ mi_execute_command_input_handler (char *cmd) { mi_execute_command_wrapper (cmd); - fputs_unfiltered ("(gdb) \n", raw_stdout); - gdb_flush (raw_stdout); + /* MI generally prints a prompt after a command, indicating it's + ready for further input. However, due to an historical wart, if + MI is async, and a synchronous command was issued, then we will + print the prompt right after printing "^running", even if we + cannot actually accept any input until the target stops. See + mi_on_resume. + + If MI is not async, then we print the prompt when the command + finishes. If the target is sync, that means output the prompt + now, as in that case executing a command doesn't return until the + command is done. However, if the target is async, we go back to + the event loop and output the prompt in the + 'synchronous_command_done' observer. */ + if (!target_is_async_p () || !sync_execution) + { + fputs_unfiltered ("(gdb) \n", raw_stdout); + gdb_flush (raw_stdout); + } } static void @@ -928,10 +968,10 @@ mi_on_resume (ptid_t ptid) running_result_record_printed = 1; /* This is what gdb used to do historically -- printing prompt even if it cannot actually accept any input. This will be surely removed - for MI3, and may be removed even earler. */ - /* FIXME: review the use of target_is_async_p here -- is that - what we want? */ - if (!target_is_async_p ()) + for MI3, and may be removed even earlier. SYNC_EXECUTION is + checked here because we only need to emit a prompt if a + synchronous command was issued when the target is async. */ + if (!target_is_async_p () || sync_execution) fputs_unfiltered ("(gdb) \n", raw_stdout); } gdb_flush (raw_stdout); diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 9ab4886..96dfc71 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -54,6 +54,7 @@ #include "ada-lang.h" #include "linespec.h" #include "extension.h" +#include "gdbcmd.h" #include <ctype.h> #include <sys/time.h> @@ -105,6 +106,45 @@ static int register_changed_p (int regnum, struct regcache *, static void output_register (struct frame_info *, int regnum, int format, int skip_unavailable); +/* Controls whether the frontend wants MI in async mode. */ +static int mi_async = 0; + +/* The set command writes to this variable. If the inferior is + executing, mi_async is *not* updated. */ +static int mi_async_1 = 0; + +static void +set_mi_async_command (char *args, int from_tty, + struct cmd_list_element *c) +{ + if (have_live_inferiors ()) + { + mi_async_1 = mi_async; + error (_("Cannot change this setting while the inferior is running.")); + } + + mi_async = mi_async_1; +} + +static void +show_mi_async_command (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + fprintf_filtered (file, + _("Whether MI is in asynchronous mode is %s.\n"), + value); +} + +/* A wrapper for target_can_async_p that takes the MI setting into + account. */ + +int +mi_async_p (void) +{ + return mi_async && target_can_async_p (); +} + /* Command implementations. FIXME: Is this libgdb? No. This is the MI layer that calls libgdb. Any operation used in the below should be formalized. */ @@ -229,6 +269,8 @@ proceed_thread_callback (struct thread_info *thread, void *arg) static void exec_continue (char **argv, int argc) { + prepare_execution_command (¤t_target, mi_async_p ()); + if (non_stop) { /* In non-stop mode, 'resume' always resumes a single thread. @@ -395,8 +437,8 @@ run_one_inferior (struct inferior *inf, void *arg) switch_to_thread (null_ptid); set_current_program_space (inf->pspace); } - mi_execute_cli_command (run_cmd, target_can_async_p (), - target_can_async_p () ? "&" : NULL); + mi_execute_cli_command (run_cmd, mi_async_p (), + mi_async_p () ? "&" : NULL); return 0; } @@ -450,8 +492,8 @@ mi_cmd_exec_run (char *command, char **argv, int argc) { const char *run_cmd = start_p ? "start" : "run"; - mi_execute_cli_command (run_cmd, target_can_async_p (), - target_can_async_p () ? "&" : NULL); + mi_execute_cli_command (run_cmd, mi_async_p (), + mi_async_p () ? "&" : NULL); } } @@ -1838,11 +1880,10 @@ mi_cmd_list_target_features (char *command, char **argv, int argc) struct ui_out *uiout = current_uiout; cleanup = make_cleanup_ui_out_list_begin_end (uiout, "features"); - if (target_can_async_p ()) + if (mi_async_p ()) ui_out_field_string (uiout, NULL, "async"); if (target_can_execute_reverse) ui_out_field_string (uiout, NULL, "reverse"); - do_cleanups (cleanup); return; } @@ -2269,7 +2310,7 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc) struct cleanup *old_cleanups; char *run; - if (target_can_async_p ()) + if (mi_async_p ()) run = xstrprintf ("%s %s&", cli_command, argc ? *argv : ""); else run = xstrprintf ("%s %s", cli_command, argc ? *argv : ""); @@ -2920,3 +2961,25 @@ mi_cmd_trace_frame_collected (char *command, char **argv, int argc) do_cleanups (old_chain); } + +void +_initialize_mi_main (void) +{ + struct cmd_list_element *c; + + add_setshow_boolean_cmd ("mi-async", class_run, + &mi_async_1, _("\ +Set whether MI asynchronous mode is enabled."), _("\ +Show whether MI asynchronous mode is enabled."), _("\ +Tells GDB whether MI should be in asynchronous mode."), + set_mi_async_command, + show_mi_async_command, + &setlist, + &showlist); + + /* Alias old "target-async" to "mi-async". */ + c = add_alias_cmd ("target-async", "mi-async", class_run, 0, &setlist); + deprecate_cmd (c, "set mi-async"); + c = add_alias_cmd ("target-async", "mi-async", class_run, 0, &showlist); + deprecate_cmd (c, "show mi-async"); +} diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h index c32845d..530aeb7 100644 --- a/gdb/mi/mi-main.h +++ b/gdb/mi/mi-main.h @@ -28,6 +28,10 @@ extern void mi_load_progress (const char *section_name, extern void mi_print_timing_maybe (void); +/* Whether MI is in async mode. */ + +extern int mi_async_p (void); + extern char *current_token; extern int running_result_record_printed; |