#include "objfiles.h"
#include "tracepoint.h"
#include "cli-out.h"
+#include "thread-fsm.h"
/* These are the interpreter setup, etc. functions for the MI
interpreter. */
static int
mi_interpreter_resume (void *data)
{
- struct mi_interp *mi = data;
+ struct mi_interp *mi = (struct mi_interp *) data;
/* As per hack note in mi_interpreter_init, swap in the output
channels... */
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 is sync, then output the MI prompt now, indicating we're
+ ready for further input. */
if (!mi_async_p ())
{
fputs_unfiltered ("(gdb) \n", raw_stdout);
{
mi_execute_command_wrapper (cmd);
- /* 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)
+ /* Print a prompt, indicating we're ready for further input, unless
+ we just started a synchronous command. In that case, we're about
+ to go back to the event loop and will output the prompt in the
+ 'synchronous_command_done' observer when the target next
+ stops. */
+ if (!sync_execution)
{
fputs_unfiltered ("(gdb) \n", raw_stdout);
gdb_flush (raw_stdout);
static void
mi_new_thread (struct thread_info *t)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct inferior *inf = find_inferior_ptid (t->ptid);
gdb_assert (inf);
inf = find_inferior_ptid (t->ptid);
- mi = top_level_interpreter_data ();
+ mi = (struct mi_interp *) top_level_interpreter_data ();
old_chain = make_cleanup_restore_target_terminal ();
target_terminal_ours ();
fprintf_unfiltered (mi->event_channel,
static void
mi_record_changed (struct inferior *inferior, int started)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
fprintf_unfiltered (mi->event_channel, "record-%s,thread-group=\"i%d\"",
started ? "started" : "stopped", inferior->num);
static void
mi_inferior_added (struct inferior *inf)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
target_terminal_ours ();
fprintf_unfiltered (mi->event_channel,
static void
mi_inferior_appeared (struct inferior *inf)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
target_terminal_ours ();
fprintf_unfiltered (mi->event_channel,
static void
mi_inferior_exit (struct inferior *inf)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
target_terminal_ours ();
if (inf->has_exit_code)
static void
mi_inferior_removed (struct inferior *inf)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
target_terminal_ours ();
fprintf_unfiltered (mi->event_channel,
gdb_flush (mi->event_channel);
}
-/* Cleanup that restores a previous current uiout. */
-
-static void
-restore_current_uiout_cleanup (void *arg)
-{
- struct ui_out *saved_uiout = arg;
-
- current_uiout = saved_uiout;
-}
-
/* Return the MI interpreter, if it is active -- either because it's
the top-level interpreter or the interpreter executing the current
command. Returns NULL if the MI interpreter is not being used. */
struct interp *interp = find_mi_interpreter ();
if (interp != NULL)
- return interp_data (interp);
+ return (struct mi_interp *) interp_data (interp);
return NULL;
}
if (print_frame)
{
+ struct thread_info *tp;
int core;
- if (current_uiout != mi_uiout)
- {
- /* The normal_stop function has printed frame information
- into CLI uiout, or some other non-MI uiout. There's no
- way we can extract proper fields from random uiout
- object, so we print the frame again. In practice, this
- can only happen when running a CLI command in MI. */
- struct ui_out *saved_uiout = current_uiout;
- struct target_waitstatus last;
- ptid_t last_ptid;
-
- current_uiout = mi_uiout;
+ tp = inferior_thread ();
- get_last_target_status (&last_ptid, &last);
- print_stop_event (&last);
+ if (tp->thread_fsm != NULL
+ && thread_fsm_finished_p (tp->thread_fsm))
+ {
+ enum async_reply_reason reason;
- current_uiout = saved_uiout;
+ reason = thread_fsm_async_reply_reason (tp->thread_fsm);
+ ui_out_field_string (mi_uiout, "reason",
+ async_reason_lookup (reason));
}
- /* Otherwise, frame information has already been printed by
- normal_stop. */
- else
+ print_stop_event (mi_uiout);
+
+ /* Breakpoint hits should always be mirrored to the console.
+ Deciding what to mirror to the console wrt to breakpoints and
+ random stops gets messy real fast. E.g., say "s" trips on a
+ breakpoint. We'd clearly want to mirror the event to the
+ console in this case. But what about more complicated cases
+ like "s&; thread n; s&", and one of those steps spawning a
+ new thread, and that thread hitting a breakpoint? It's
+ impossible in general to track whether the thread had any
+ relation to the commands that had been executed. So we just
+ simplify and always mirror breakpoints and random events to
+ the console.
+
+ OTOH, we should print the source line to the console when
+ stepping or other similar commands, iff the step was started
+ by a console command, but not if it was started with
+ -exec-step or similar. */
+ if ((bpstat_what (tp->control.stop_bpstat).main_action
+ == BPSTAT_WHAT_STOP_NOISY)
+ || !(tp->thread_fsm != NULL
+ && thread_fsm_finished_p (tp->thread_fsm))
+ || (tp->control.command_interp != NULL
+ && tp->control.command_interp != top_level_interpreter ()))
{
- /* Breakpoint hits should always be mirrored to the console.
- Deciding what to mirror to the console wrt to breakpoints
- and random stops gets messy real fast. E.g., say "s"
- trips on a breakpoint. We'd clearly want to mirror the
- event to the console in this case. But what about more
- complicated cases like "s&; thread n; s&", and one of
- those steps spawning a new thread, and that thread
- hitting a breakpoint? It's impossible in general to
- track whether the thread had any relation to the commands
- that had been executed. So we just simplify and always
- mirror breakpoints and random events to the console.
-
- Also, CLI execution commands (-interpreter-exec console
- "next", for example) in async mode have the opposite
- issue as described in the "then" branch above --
- normal_stop has already printed frame information to MI
- uiout, but nothing has printed the same information to
- the CLI channel. We should print the source line to the
- console when stepping or other similar commands, iff the
- step was started by a console command (but not if it was
- started with -exec-step or similar). */
- struct thread_info *tp = inferior_thread ();
-
- if ((!tp->control.stop_step
- && !tp->control.proceed_to_finish)
- || (tp->control.command_interp != NULL
- && tp->control.command_interp != top_level_interpreter ()))
- {
- struct mi_interp *mi = top_level_interpreter_data ();
- struct target_waitstatus last;
- ptid_t last_ptid;
- struct cleanup *old_chain;
-
- /* Set the current uiout to CLI uiout temporarily. */
- old_chain = make_cleanup (restore_current_uiout_cleanup,
- current_uiout);
- current_uiout = mi->cli_uiout;
-
- get_last_target_status (&last_ptid, &last);
- print_stop_event (&last);
-
- do_cleanups (old_chain);
- }
+ struct mi_interp *mi
+ = (struct mi_interp *) top_level_interpreter_data ();
+
+ print_stop_event (mi->cli_uiout);
}
ui_out_field_int (mi_uiout, "thread-id",
static void
mi_traceframe_changed (int tfnum, int tpnum)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
if (mi_suppress_notification.traceframe)
return;
static void
mi_tsv_created (const struct trace_state_variable *tsv)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
target_terminal_ours ();
static void
mi_tsv_deleted (const struct trace_state_variable *tsv)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
target_terminal_ours ();
static void
mi_tsv_modified (const struct trace_state_variable *tsv)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
target_terminal_ours ();
static void
mi_breakpoint_created (struct breakpoint *b)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
- volatile struct gdb_exception e;
if (mi_suppress_notification.breakpoint)
return;
breakpoint_created notifications. So, we use
ui_out_redirect. */
ui_out_redirect (mi_uiout, mi->event_channel);
- TRY_CATCH (e, RETURN_MASK_ERROR)
- gdb_breakpoint_query (mi_uiout, b->number, NULL);
+ TRY
+ {
+ gdb_breakpoint_query (mi_uiout, b->number, NULL);
+ }
+ CATCH (e, RETURN_MASK_ERROR)
+ {
+ }
+ END_CATCH
+
ui_out_redirect (mi_uiout, NULL);
gdb_flush (mi->event_channel);
static void
mi_breakpoint_deleted (struct breakpoint *b)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
if (mi_suppress_notification.breakpoint)
return;
static void
mi_breakpoint_modified (struct breakpoint *b)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
- volatile struct gdb_exception e;
if (mi_suppress_notification.breakpoint)
return;
breakpoint_created notifications. So, we use
ui_out_redirect. */
ui_out_redirect (mi_uiout, mi->event_channel);
- TRY_CATCH (e, RETURN_MASK_ERROR)
- gdb_breakpoint_query (mi_uiout, b->number, NULL);
+ TRY
+ {
+ gdb_breakpoint_query (mi_uiout, b->number, NULL);
+ }
+ CATCH (e, RETURN_MASK_ERROR)
+ {
+ }
+ END_CATCH
+
ui_out_redirect (mi_uiout, NULL);
gdb_flush (mi->event_channel);
static int
mi_output_running_pid (struct thread_info *info, void *arg)
{
- ptid_t *ptid = arg;
+ ptid_t *ptid = (ptid_t *) arg;
if (ptid_get_pid (*ptid) == ptid_get_pid (info->ptid))
fprintf_unfiltered (raw_stdout,
{
if (inf->pid != 0)
{
- int *count_p = arg;
+ int *count_p = (int *) arg;
(*count_p)++;
}
static void
mi_solib_loaded (struct so_list *solib)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *uiout = interp_ui_out (top_level_interpreter ());
target_terminal_ours ();
static void
mi_solib_unloaded (struct so_list *solib)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *uiout = interp_ui_out (top_level_interpreter ());
target_terminal_ours ();
static void
mi_command_param_changed (const char *param, const char *value)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
if (mi_suppress_notification.cmd_param_changed)
mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr,
ssize_t len, const bfd_byte *myaddr)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
struct obj_section *sec;
mi_inferior_added assumes that inferior is fully initialized
and top_level_interpreter_data is set, we cannot call
it here. */
- struct mi_interp *mi = closure;
+ struct mi_interp *mi = (struct mi_interp *) closure;
target_terminal_ours ();
fprintf_unfiltered (mi->event_channel,
static struct ui_out *
mi_ui_out (struct interp *interp)
{
- struct mi_interp *mi = interp_data (interp);
+ struct mi_interp *mi = (struct mi_interp *) interp_data (interp);
return mi->mi_uiout;
}
mi_set_logging (struct interp *interp, int start_log,
struct ui_file *out, struct ui_file *logfile)
{
- struct mi_interp *mi = interp_data (interp);
+ struct mi_interp *mi = (struct mi_interp *) interp_data (interp);
if (!mi)
return 0;