+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+ struct inferior *inf = find_inferior_pid (ptid_get_pid (t->ptid));
+
+ gdb_assert (inf);
+
+ fprintf_unfiltered (mi->event_channel,
+ "thread-created,id=\"%d\",group-id=\"i%d\"",
+ t->num, inf->num);
+ gdb_flush (mi->event_channel);
+}
+
+static void
+mi_thread_exit (struct thread_info *t, int silent)
+{
+ struct mi_interp *mi;
+ struct inferior *inf;
+
+ if (silent)
+ return;
+
+ inf = find_inferior_pid (ptid_get_pid (t->ptid));
+
+ mi = top_level_interpreter_data ();
+ target_terminal_ours ();
+ fprintf_unfiltered (mi->event_channel,
+ "thread-exited,id=\"%d\",group-id=\"i%d\"",
+ t->num, inf->num);
+ gdb_flush (mi->event_channel);
+}
+
+static void
+mi_inferior_added (struct inferior *inf)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ target_terminal_ours ();
+ fprintf_unfiltered (mi->event_channel,
+ "thread-group-added,id=\"i%d\"",
+ inf->num);
+ gdb_flush (mi->event_channel);
+}
+
+static void
+mi_inferior_appeared (struct inferior *inf)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ target_terminal_ours ();
+ fprintf_unfiltered (mi->event_channel,
+ "thread-group-started,id=\"i%d\",pid=\"%d\"",
+ inf->num, inf->pid);
+ gdb_flush (mi->event_channel);
+}
+
+static void
+mi_inferior_exit (struct inferior *inf)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ target_terminal_ours ();
+ if (inf->has_exit_code)
+ fprintf_unfiltered (mi->event_channel,
+ "thread-group-exited,id=\"i%d\",exit-code=\"%s\"",
+ inf->num, int_string (inf->exit_code, 8, 0, 0, 1));
+ else
+ fprintf_unfiltered (mi->event_channel,
+ "thread-group-exited,id=\"i%d\"", inf->num);
+
+ gdb_flush (mi->event_channel);
+}
+
+static void
+mi_inferior_removed (struct inferior *inf)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ target_terminal_ours ();
+ fprintf_unfiltered (mi->event_channel,
+ "thread-group-removed,id=\"i%d\"",
+ inf->num);
+ gdb_flush (mi->event_channel);
+}
+
+static void
+mi_on_normal_stop (struct bpstats *bs, int print_frame)
+{
+ /* Since this can be called when CLI command is executing,
+ using cli interpreter, be sure to use MI uiout for output,
+ not the current one. */
+ struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
+
+ if (print_frame)
+ {
+ 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;
+
+ get_last_target_status (&last_ptid, &last);
+ bpstat_print (bs, last.kind);
+
+ print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC);
+ current_uiout = saved_uiout;
+ }
+
+ ui_out_field_int (mi_uiout, "thread-id",
+ pid_to_thread_id (inferior_ptid));
+ if (non_stop)
+ {
+ struct cleanup *back_to = make_cleanup_ui_out_list_begin_end
+ (mi_uiout, "stopped-threads");
+
+ ui_out_field_int (mi_uiout, NULL,
+ pid_to_thread_id (inferior_ptid));
+ do_cleanups (back_to);
+ }
+ else
+ ui_out_field_string (mi_uiout, "stopped-threads", "all");
+
+ core = target_core_of_thread (inferior_ptid);
+ if (core != -1)
+ ui_out_field_int (mi_uiout, "core", core);
+ }
+
+ fputs_unfiltered ("*stopped", raw_stdout);
+ mi_out_put (mi_uiout, raw_stdout);
+ mi_out_rewind (mi_uiout);
+ mi_print_timing_maybe ();
+ fputs_unfiltered ("\n", raw_stdout);
+ gdb_flush (raw_stdout);
+}
+
+static void
+mi_about_to_proceed (void)
+{
+ /* Suppress output while calling an inferior function. */
+
+ if (!ptid_equal (inferior_ptid, null_ptid))
+ {
+ struct thread_info *tp = inferior_thread ();
+
+ if (tp->control.in_infcall)
+ return;
+ }
+
+ mi_proceeded = 1;
+}
+
+/* When the element is non-zero, no MI notifications will be emitted in
+ response to the corresponding observers. */
+
+struct mi_suppress_notification mi_suppress_notification =
+ {
+ 0,
+ 0,
+ 0,
+ };
+
+/* Emit notification on changing a traceframe. */
+
+static void
+mi_traceframe_changed (int tfnum, int tpnum)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ if (mi_suppress_notification.traceframe)
+ return;
+
+ target_terminal_ours ();
+
+ if (tfnum >= 0)
+ fprintf_unfiltered (mi->event_channel, "traceframe-changed,"
+ "num=\"%d\",tracepoint=\"%d\"\n",
+ tfnum, tpnum);
+ else
+ fprintf_unfiltered (mi->event_channel, "traceframe-changed,end");
+
+ gdb_flush (mi->event_channel);
+}
+
+/* Emit notification on creating a trace state variable. */
+
+static void
+mi_tsv_created (const char *name, LONGEST value)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ target_terminal_ours ();
+
+ fprintf_unfiltered (mi->event_channel, "tsv-created,"
+ "name=\"%s\",value=\"%s\"\n",
+ name, plongest (value));
+
+ gdb_flush (mi->event_channel);
+}
+
+/* Emit notification on deleting a trace state variable. */
+
+static void
+mi_tsv_deleted (const char *name)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ target_terminal_ours ();
+
+ if (name != NULL)
+ fprintf_unfiltered (mi->event_channel, "tsv-deleted,"
+ "name=\"%s\"\n", name);
+ else
+ fprintf_unfiltered (mi->event_channel, "tsv-deleted\n");
+
+ gdb_flush (mi->event_channel);
+}
+
+/* Emit notification about a created breakpoint. */
+
+static void
+mi_breakpoint_created (struct breakpoint *b)
+{
+ struct mi_interp *mi = 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;
+
+ if (b->number <= 0)
+ return;
+
+ target_terminal_ours ();
+ fprintf_unfiltered (mi->event_channel,
+ "breakpoint-created");
+ /* We want the output from gdb_breakpoint_query to go to
+ mi->event_channel. One approach would be to just call
+ gdb_breakpoint_query, and then use mi_out_put to send the current
+ content of mi_outout into mi->event_channel. However, that will
+ break if anything is output to mi_uiout prior to calling the
+ 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);
+ ui_out_redirect (mi_uiout, NULL);
+
+ gdb_flush (mi->event_channel);
+}
+
+/* Emit notification about deleted breakpoint. */
+
+static void
+mi_breakpoint_deleted (struct breakpoint *b)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ if (mi_suppress_notification.breakpoint)
+ return;
+
+ if (b->number <= 0)
+ return;
+
+ target_terminal_ours ();
+
+ fprintf_unfiltered (mi->event_channel, "breakpoint-deleted,id=\"%d\"",
+ b->number);
+
+ gdb_flush (mi->event_channel);
+}
+
+/* Emit notification about modified breakpoint. */
+
+static void
+mi_breakpoint_modified (struct breakpoint *b)
+{
+ struct mi_interp *mi = 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;
+
+ if (b->number <= 0)
+ return;
+
+ target_terminal_ours ();
+ fprintf_unfiltered (mi->event_channel,
+ "breakpoint-modified");
+ /* We want the output from gdb_breakpoint_query to go to
+ mi->event_channel. One approach would be to just call
+ gdb_breakpoint_query, and then use mi_out_put to send the current
+ content of mi_outout into mi->event_channel. However, that will
+ break if anything is output to mi_uiout prior to calling the
+ 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);
+ 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;
+
+ if (ptid_get_pid (*ptid) == ptid_get_pid (info->ptid))
+ fprintf_unfiltered (raw_stdout,
+ "*running,thread-id=\"%d\"\n",
+ info->num);
+
+ return 0;
+}
+
+static int
+mi_inferior_count (struct inferior *inf, void *arg)
+{
+ if (inf->pid != 0)
+ {
+ int *count_p = arg;
+ (*count_p)++;
+ }
+
+ return 0;
+}
+
+static void
+mi_on_resume (ptid_t ptid)
+{
+ struct thread_info *tp = NULL;
+
+ if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
+ tp = inferior_thread ();
+ else
+ tp = find_thread_ptid (ptid);
+
+ /* Suppress output while calling an inferior function. */
+ if (tp->control.in_infcall)
+ return;
+
+ /* To cater for older frontends, emit ^running, but do it only once
+ per each command. We do it here, since at this point we know
+ that the target was successfully resumed, and in non-async mode,
+ we won't return back to MI interpreter code until the target
+ is done running, so delaying the output of "^running" until then
+ will make it impossible for frontend to know what's going on.
+
+ In future (MI3), we'll be outputting "^done" here. */
+ if (!running_result_record_printed && mi_proceeded)
+ {
+ fprintf_unfiltered (raw_stdout, "%s^running\n",
+ current_token ? current_token : "");
+ }
+
+ if (PIDGET (ptid) == -1)
+ fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
+ else if (ptid_is_pid (ptid))
+ {
+ int count = 0;
+
+ /* Backwards compatibility. If there's only one inferior,
+ output "all", otherwise, output each resumed thread
+ individually. */
+ iterate_over_inferiors (mi_inferior_count, &count);
+
+ if (count == 1)
+ fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
+ else
+ iterate_over_threads (mi_output_running_pid, &ptid);
+ }
+ else
+ {
+ struct thread_info *ti = find_thread_ptid (ptid);
+
+ gdb_assert (ti);
+ fprintf_unfiltered (raw_stdout, "*running,thread-id=\"%d\"\n", ti->num);
+ }
+
+ if (!running_result_record_printed && mi_proceeded)
+ {
+ 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 ())
+ fputs_unfiltered ("(gdb) \n", raw_stdout);
+ }
+ gdb_flush (raw_stdout);
+}
+
+static void
+mi_solib_loaded (struct so_list *solib)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ target_terminal_ours ();
+ if (gdbarch_has_global_solist (target_gdbarch))
+ fprintf_unfiltered (mi->event_channel,
+ "library-loaded,id=\"%s\",target-name=\"%s\","
+ "host-name=\"%s\",symbols-loaded=\"%d\"",
+ solib->so_original_name, solib->so_original_name,
+ solib->so_name, solib->symbols_loaded);
+ else
+ fprintf_unfiltered (mi->event_channel,
+ "library-loaded,id=\"%s\",target-name=\"%s\","
+ "host-name=\"%s\",symbols-loaded=\"%d\","
+ "thread-group=\"i%d\"",
+ solib->so_original_name, solib->so_original_name,
+ solib->so_name, solib->symbols_loaded,
+ current_inferior ()->num);
+
+ gdb_flush (mi->event_channel);
+}
+
+static void
+mi_solib_unloaded (struct so_list *solib)