* mi/mi-interp.c (mi_on_normal_stop): Call bpstat_print.
[platform/upstream/binutils.git] / gdb / mi / mi-interp.c
index 87ed17f..2aec1c7 100644 (file)
@@ -1,12 +1,13 @@
 /* MI Interpreter Definitions and Commands for GDB, the GNU debugger.
 
-   Copyright 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -15,9 +16,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "gdb_string.h"
 #include "inferior.h"
 #include "ui-out.h"
 #include "top.h"
-
+#include "exceptions.h"
 #include "mi-main.h"
 #include "mi-cmds.h"
 #include "mi-out.h"
 #include "mi-console.h"
-
-struct mi_interp
-{
-  /* MI's output channels */
-  struct ui_file *out;
-  struct ui_file *err;
-  struct ui_file *log;
-  struct ui_file *targ;
-  struct ui_file *event_channel;
-
-  /* This is the interpreter for the mi... */
-  struct interp *mi2_interp;
-  struct interp *mi1_interp;
-  struct interp *mi_interp;
-};
+#include "mi-common.h"
+#include "observer.h"
+#include "gdbthread.h"
+#include "solist.h"
+#include "gdb.h"
 
 /* These are the interpreter setup, etc. functions for the MI interpreter */
 static void mi_execute_command_wrapper (char *cmd);
 static void mi_command_loop (int mi_version);
-static char *mi_input (char *);
 
 /* These are hooks that we put in place while doing interpreter_exec
    so we can report interesting things that happened "behind the mi's
    back" in this command */
-static int mi_interp_query_hook (const char *ctlstr, va_list ap);
-static char *mi_interp_read_one_line_hook (char *prompt, int repeat,
-                                          char *anno);
+static int mi_interp_query_hook (const char *ctlstr, va_list ap)
+     ATTRIBUTE_PRINTF (1, 0);
 
+static void mi3_command_loop (void);
 static void mi2_command_loop (void);
 static void mi1_command_loop (void);
 
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
+static void mi_on_normal_stop (struct bpstats *bs, int print_frame);
+
+static void mi_new_thread (struct thread_info *t);
+static void mi_thread_exit (struct thread_info *t, int silent);
+static void mi_inferior_added (struct inferior *inf);
+static void mi_inferior_appeared (struct inferior *inf);
+static void mi_inferior_exit (struct inferior *inf);
+static void mi_inferior_removed (struct inferior *inf);
+static void mi_on_resume (ptid_t ptid);
+static void mi_solib_loaded (struct so_list *solib);
+static void mi_solib_unloaded (struct so_list *solib);
+static void mi_about_to_proceed (void);
+static void mi_breakpoint_created (struct breakpoint *b);
+static void mi_breakpoint_deleted (struct breakpoint *b);
+static void mi_breakpoint_modified (struct breakpoint *b);
+
+static int report_initial_inferior (struct inferior *inf, void *closure);
 
 static void *
-mi_interpreter_init (void)
+mi_interpreter_init (struct interp *interp, int top_level)
 {
   struct mi_interp *mi = XMALLOC (struct mi_interp);
-
-  /* Why is this a part of the mi architecture? */
-
-  mi_setup_architecture_data ();
+  const char *name;
+  int mi_version;
 
   /* HACK: We need to force stdout/stderr to point at the console.  This avoids
      any potential side effects caused by legacy code that is still
@@ -89,6 +92,45 @@ mi_interpreter_init (void)
   mi->targ = mi_console_file_new (raw_stdout, "@", '"');
   mi->event_channel = mi_console_file_new (raw_stdout, "=", 0);
 
+  name = interp_name (interp);
+  /* INTERP_MI selects the most recent released version.  "mi2" was
+     released as part of GDB 6.0.  */
+  if (strcmp (name, INTERP_MI) == 0)
+    mi_version = 2;
+  else if (strcmp (name, INTERP_MI1) == 0)
+    mi_version = 1;
+  else if (strcmp (name, INTERP_MI2) == 0)
+    mi_version = 2;
+  else if (strcmp (name, INTERP_MI3) == 0)
+    mi_version = 3;
+  else
+    gdb_assert_not_reached ("unhandled MI version");
+
+  mi->uiout = mi_out_new (mi_version);
+
+  if (top_level)
+    {
+      observer_attach_new_thread (mi_new_thread);
+      observer_attach_thread_exit (mi_thread_exit);
+      observer_attach_inferior_added (mi_inferior_added);
+      observer_attach_inferior_appeared (mi_inferior_appeared);
+      observer_attach_inferior_exit (mi_inferior_exit);
+      observer_attach_inferior_removed (mi_inferior_removed);
+      observer_attach_normal_stop (mi_on_normal_stop);
+      observer_attach_target_resumed (mi_on_resume);
+      observer_attach_solib_loaded (mi_solib_loaded);
+      observer_attach_solib_unloaded (mi_solib_unloaded);
+      observer_attach_about_to_proceed (mi_about_to_proceed);
+      observer_attach_breakpoint_created (mi_breakpoint_created);
+      observer_attach_breakpoint_deleted (mi_breakpoint_deleted);
+      observer_attach_breakpoint_modified (mi_breakpoint_modified);
+
+      /* The initial inferior is created before this function is called, so we
+        need to report it explicitly.  Use iteration in case future version
+        of GDB creates more than one inferior up-front.  */
+      iterate_over_inferiors (report_initial_inferior, mi);
+    }
+
   return mi;
 }
 
@@ -96,26 +138,23 @@ static int
 mi_interpreter_resume (void *data)
 {
   struct mi_interp *mi = data;
-  /* As per hack note in mi_interpreter_init, swap in the output channels... */
 
+  /* As per hack note in mi_interpreter_init, swap in the output channels... */
   gdb_setup_readline ();
 
-  if (event_loop_p)
-    {
-      /* These overwrite some of the initialization done in
-         _intialize_event_loop. */
-      call_readline = gdb_readline2;
-      input_handler = mi_execute_command_wrapper;
-      add_file_handler (input_fd, stdin_event_handler, 0);
-      async_command_editing_p = 0;
-      /* FIXME: This is a total hack for now.  PB's use of the MI implicitly
-         relies on a bug in the async support which allows asynchronous
-         commands to leak through the commmand loop.  The bug involves
-         (but is not limited to) the fact that sync_execution was
-         erroneously initialized to 0.  Duplicate by initializing it
-         thus here... */
-      sync_execution = 0;
-    }
+  /* These overwrite some of the initialization done in
+     _intialize_event_loop.  */
+  call_readline = gdb_readline2;
+  input_handler = mi_execute_command_wrapper;
+  add_file_handler (input_fd, stdin_event_handler, 0);
+  async_command_editing_p = 0;
+  /* FIXME: This is a total hack for now.  PB's use of the MI
+     implicitly relies on a bug in the async support which allows
+     asynchronous commands to leak through the commmand loop.  The bug
+     involves (but is not limited to) the fact that sync_execution was
+     erroneously initialized to 0.  Duplicate by initializing it thus
+     here...  */
+  sync_execution = 0;
 
   gdb_stdout = mi->out;
   /* Route error and log output through the MI */
@@ -123,20 +162,24 @@ mi_interpreter_resume (void *data)
   gdb_stdlog = mi->log;
   /* Route target output through the MI. */
   gdb_stdtarg = mi->targ;
+  /* Route target error through the MI as well. */
+  gdb_stdtargerr = mi->targ;
 
   /* Replace all the hooks that we know about.  There really needs to
      be a better way of doing this... */
   clear_interpreter_hooks ();
 
-  show_load_progress = mi_load_progress;
+  deprecated_show_load_progress = mi_load_progress;
 
   /* If we're _the_ interpreter, take control. */
   if (current_interp_named_p (INTERP_MI1))
-    command_loop_hook = mi1_command_loop;
-  else if (current_interp_named_p (INTERP_MI))
-    command_loop_hook = mi2_command_loop;
+    deprecated_command_loop_hook = mi1_command_loop;
+  else if (current_interp_named_p (INTERP_MI2))
+    deprecated_command_loop_hook = mi2_command_loop;
+  else if (current_interp_named_p (INTERP_MI3))
+    deprecated_command_loop_hook = mi3_command_loop;
   else
-    return 0;
+    deprecated_command_loop_hook = mi2_command_loop;
 
   return 1;
 }
@@ -148,13 +191,14 @@ mi_interpreter_suspend (void *data)
   return 1;
 }
 
-static int
+static struct gdb_exception
 mi_interpreter_exec (void *data, const char *command)
 {
   char *tmp = alloca (strlen (command) + 1);
+
   strcpy (tmp, command);
   mi_execute_command_wrapper (tmp);
-  return 1;
+  return exception_none;
 }
 
 /* Never display the default gdb prompt in mi case.  */
@@ -164,56 +208,27 @@ mi_interpreter_prompt_p (void *data)
   return 0;
 }
 
-static void
-mi_interpreter_exec_continuation (struct continuation_arg *arg)
-{
-  bpstat_do_actions (&stop_bpstat);
-  if (!target_executing)
-    {
-      fputs_unfiltered ("*stopped", raw_stdout);
-      mi_out_put (uiout, raw_stdout);
-      fputs_unfiltered ("\n", raw_stdout);
-      fputs_unfiltered ("(gdb) \n", raw_stdout);
-      gdb_flush (raw_stdout);
-      do_exec_cleanups (ALL_CLEANUPS);
-    }
-  else if (target_can_async_p ())
-    {
-      add_continuation (mi_interpreter_exec_continuation, NULL);
-    }
-}
-
-enum mi_cmd_result
+void
 mi_cmd_interpreter_exec (char *command, char **argv, int argc)
 {
   struct interp *interp_to_use;
-  enum mi_cmd_result result = MI_CMD_DONE;
   int i;
-  struct interp_procs *procs;
+  char *mi_error_message = NULL;
+  struct cleanup *old_chain;
 
   if (argc < 2)
-    {
-      xasprintf (&mi_error_message,
-                "mi_cmd_interpreter_exec: Usage: -interpreter-exec interp command");
-      return MI_CMD_ERROR;
-    }
+    error (_("-interpreter-exec: "
+            "Usage: -interpreter-exec interp command"));
 
   interp_to_use = interp_lookup (argv[0]);
   if (interp_to_use == NULL)
-    {
-      xasprintf (&mi_error_message,
-                "mi_cmd_interpreter_exec: could not find interpreter \"%s\"",
-                argv[0]);
-      return MI_CMD_ERROR;
-    }
+    error (_("-interpreter-exec: could not find interpreter \"%s\""),
+          argv[0]);
 
   if (!interp_exec_p (interp_to_use))
-    {
-      xasprintf (&mi_error_message,
-                "mi_cmd_interpreter_exec: interpreter \"%s\" does not support command execution",
-                argv[0]);
-      return MI_CMD_ERROR;
-    }
+    error (_("-interpreter-exec: interpreter \"%s\" "
+            "does not support command execution"),
+             argv[0]);
 
   /* Insert the MI out hooks, making sure to also call the interpreter's hooks
      if it has any. */
@@ -223,71 +238,45 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
 
   /* Now run the code... */
 
+  old_chain = make_cleanup (null_cleanup, 0);
   for (i = 1; i < argc; i++)
     {
-      char *buff = NULL;
-      /* Do this in a cleaner way...  We want to force execution to be
-         asynchronous for commands that run the target.  */
-      if (target_can_async_p () && (strcmp (argv[0], "console") == 0))
-       {
-         int len = strlen (argv[i]);
-         buff = xmalloc (len + 2);
-         memcpy (buff, argv[i], len);
-         buff[len] = '&';
-         buff[len + 1] = '\0';
-       }
+      struct gdb_exception e = interp_exec (interp_to_use, argv[i]);
 
-      /* We had to set sync_execution = 0 for the mi (well really for Project
-         Builder's use of the mi - particularly so interrupting would work.
-         But for console commands to work, we need to initialize it to 1 -
-         since that is what the cli expects - before running the command,
-         and then set it back to 0 when we are done. */
-      sync_execution = 1;
-      if (interp_exec (interp_to_use, argv[i]) < 0)
+      if (e.reason < 0)
        {
-         mi_error_last_message ();
-         result = MI_CMD_ERROR;
+         mi_error_message = xstrdup (e.message);
+         make_cleanup (xfree, mi_error_message);
          break;
        }
-      xfree (buff);
-      do_exec_error_cleanups (ALL_CLEANUPS);
-      sync_execution = 0;
     }
 
   mi_remove_notify_hooks ();
 
-  /* Okay, now let's see if the command set the inferior going...
-     Tricky point - have to do this AFTER resetting the interpreter, since
-     changing the interpreter will clear out all the continuations for
-     that interpreter... */
-
-  if (target_can_async_p () && target_executing)
-    {
-      fputs_unfiltered ("^running\n", raw_stdout);
-      add_continuation (mi_interpreter_exec_continuation, NULL);
-    }
-
-  return result;
+  if (mi_error_message != NULL)
+    error ("%s", mi_error_message);
+  do_cleanups (old_chain);
 }
 
 /*
- * mi_insert_notify_hooks - This inserts a number of hooks that are meant to produce
- * async-notify ("=") MI messages while running commands in another interpreter
- * using mi_interpreter_exec.  The canonical use for this is to allow access to
- * the gdb CLI interpreter from within the MI, while still producing MI style output
- * when actions in the CLI command change gdb's state.
+ * mi_insert_notify_hooks - This inserts a number of hooks that are
+ * meant to produce async-notify ("=") MI messages while running
+ * commands in another interpreter using mi_interpreter_exec.  The
+ * canonical use for this is to allow access to the gdb CLI
+ * interpreter from within the MI, while still producing MI style
+ * output when actions in the CLI command change gdb's state.
 */
 
 static void
 mi_insert_notify_hooks (void)
 {
-  query_hook = mi_interp_query_hook;
+  deprecated_query_hook = mi_interp_query_hook;
 }
 
 static void
 mi_remove_notify_hooks (void)
 {
-  query_hook = NULL;
+  deprecated_query_hook = NULL;
 }
 
 static int
@@ -296,25 +285,6 @@ mi_interp_query_hook (const char *ctlstr, va_list ap)
   return 1;
 }
 
-static char *
-mi_interp_read_one_line_hook (char *prompt, int repeat, char *anno)
-{
-  static char buff[256];
-  printf_unfiltered ("=read-one-line,prompt=\"%s\"\n", prompt);
-  gdb_flush (gdb_stdout);
-  (void) fgets (buff, sizeof (buff), stdin);
-  buff[(strlen (buff) - 1)] = 0;
-  return buff;
-}
-
-static void
-output_control_change_notification (char *notification)
-{
-  printf_unfiltered ("^");
-  printf_unfiltered ("%s\n", notification);
-  gdb_flush (gdb_stdout);
-}
-
 static void
 mi_execute_command_wrapper (char *cmd)
 {
@@ -334,65 +304,432 @@ mi2_command_loop (void)
 }
 
 static void
+mi3_command_loop (void)
+{
+  mi_command_loop (3);
+}
+
+static void
 mi_command_loop (int mi_version)
 {
-#if 0
-  /* HACK: Force stdout/stderr to point at the console.  This avoids
-     any potential side effects caused by legacy code that is still
-     using the TUI / fputs_unfiltered_hook */
-  raw_stdout = stdio_fileopen (stdout);
-  /* Route normal output through the MIx */
-  gdb_stdout = mi_console_file_new (raw_stdout, "~", '"');
-  /* Route error and log output through the MI */
-  gdb_stderr = mi_console_file_new (raw_stdout, "&", '"');
-  gdb_stdlog = gdb_stderr;
-  /* Route target output through the MI. */
-  gdb_stdtarg = mi_console_file_new (raw_stdout, "@", '"');
-  /* HACK: Poke the ui_out table directly.  Should we be creating a
-     mi_out object wired up to the above gdb_stdout / gdb_stderr? */
-  uiout = mi_out_new (mi_version);
-  /* HACK: Override any other interpreter hooks.  We need to create a
-     real event table and pass in that. */
-  init_ui_hook = 0;
-  /* command_loop_hook = 0; */
-  print_frame_info_listing_hook = 0;
-  query_hook = 0;
-  warning_hook = 0;
-  create_breakpoint_hook = 0;
-  delete_breakpoint_hook = 0;
-  modify_breakpoint_hook = 0;
-  interactive_hook = 0;
-  registers_changed_hook = 0;
-  readline_begin_hook = 0;
-  readline_hook = 0;
-  readline_end_hook = 0;
-  register_changed_hook = 0;
-  memory_changed_hook = 0;
-  context_hook = 0;
-  target_wait_hook = 0;
-  call_command_hook = 0;
-  error_hook = 0;
-  error_begin_hook = 0;
-  show_load_progress = mi_load_progress;
-#endif
   /* Turn off 8 bit strings in quoted output.  Any character with the
      high bit set is printed using C's octal format. */
   sevenbit_strings = 1;
   /* Tell the world that we're alive */
   fputs_unfiltered ("(gdb) \n", raw_stdout);
   gdb_flush (raw_stdout);
-  if (!event_loop_p)
-    simplified_command_loop (mi_input, mi_execute_command);
+  start_event_loop ();
+}
+
+static void
+mi_new_thread (struct thread_info *t)
+{
+  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
-    start_event_loop ();
+    fprintf_unfiltered (mi->event_channel,
+                       "thread-group-exited,id=\"i%d\"", inf->num);
+
+  gdb_flush (mi->event_channel);  
 }
 
-static char *
-mi_input (char *buf)
+static void
+mi_inferior_removed (struct inferior *inf)
 {
-  return gdb_readline (NULL);
+  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;
+
+         current_uiout = mi_uiout;
+         bpstat_print (bs);
+         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 non-zero, no MI notifications will be emitted in
+   response to breakpoint change observers.  */
+int mi_suppress_breakpoint_notifications = 0;
+
+/* 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 ());
+  struct gdb_exception e;
+
+  if (mi_suppress_breakpoint_notifications)
+    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 the 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_breakpoint_notifications)
+    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 ());
+  struct gdb_exception e;
+
+  if (mi_suppress_breakpoint_notifications)
+    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 the 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)
+{
+  struct mi_interp *mi = top_level_interpreter_data ();
+
+  target_terminal_ours ();
+  if (gdbarch_has_global_solist (target_gdbarch))
+    fprintf_unfiltered (mi->event_channel,
+                       "library-unloaded,id=\"%s\",target-name=\"%s\","
+                       "host-name=\"%s\"",
+                       solib->so_original_name, solib->so_original_name,
+                       solib->so_name);
+  else
+    fprintf_unfiltered (mi->event_channel,
+                       "library-unloaded,id=\"%s\",target-name=\"%s\","
+                       "host-name=\"%s\",thread-group=\"i%d\"",
+                       solib->so_original_name, solib->so_original_name,
+                       solib->so_name, current_inferior ()->num);
+
+  gdb_flush (mi->event_channel);
+}
+
+static int
+report_initial_inferior (struct inferior *inf, void *closure)
+{
+  /* This function is called from mi_intepreter_init, and since
+     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;
+
+  target_terminal_ours ();
+  fprintf_unfiltered (mi->event_channel,
+                     "thread-group-added,id=\"i%d\"",
+                     inf->num);
+  gdb_flush (mi->event_channel);
+  return 0;
+}
+
+static struct ui_out *
+mi_ui_out (struct interp *interp)
+{
+  struct mi_interp *mi = interp_data (interp);
+
+  return mi->uiout;
+}
+
+extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
+
 void
 _initialize_mi_interp (void)
 {
@@ -402,11 +739,13 @@ _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_interpreter_prompt_p,   /* prompt_proc_p */
+    mi_ui_out                  /* ui_out_proc */
   };
 
-  /* Create MI1 interpreter */
-  interp_add (interp_new (INTERP_MI1, NULL, mi_out_new (1), &procs));
-
-  interp_add (interp_new (INTERP_MI, NULL, mi_out_new (3), &procs));
+  /* The various interpreter levels.  */
+  interp_add (interp_new (INTERP_MI1, &procs));
+  interp_add (interp_new (INTERP_MI2, &procs));
+  interp_add (interp_new (INTERP_MI3, &procs));
+  interp_add (interp_new (INTERP_MI, &procs));
 }