* tracepoint.h (set_traceframe_number)
[deliverable/binutils-gdb.git] / gdb / mi / mi-main.c
index 6dc7609ed6cdb36236adf28357f23ad4595a75a3..9d9e3da2d8341de503200b30c1620a1032842d27 100644 (file)
@@ -1,6 +1,6 @@
 /* MI Command Set.
 
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
    Contributed by Cygnus Solutions (a Red Hat company).
@@ -23,6 +23,7 @@
 /* Work in progress.  */
 
 #include "defs.h"
+#include "arch-utils.h"
 #include "target.h"
 #include "inferior.h"
 #include "gdb_string.h"
 #include "gdb.h"
 #include "frame.h"
 #include "mi-main.h"
+#include "mi-common.h"
 #include "language.h"
+#include "valprint.h"
+#include "inferior.h"
+#include "osdata.h"
+#include "splay-tree.h"
 
 #include <ctype.h>
 #include <sys/time.h>
@@ -62,29 +68,6 @@ enum
     FROM_TTY = 0
   };
 
-/* Enumerations of the actions that may result from calling
-   captured_mi_execute_command.  */
-
-enum captured_mi_execute_command_actions
-  {
-    EXECUTE_COMMAND_DISPLAY_PROMPT,
-    EXECUTE_COMMAND_SUPPRESS_PROMPT
-  };
-
-/* This structure is used to pass information from captured_mi_execute_command
-   to mi_execute_command.  */
-struct captured_mi_execute_command_args
-{
-  /* This return result of the MI command (output).  */
-  enum mi_cmd_result rc;
-
-  /* What action to perform when the call is finished (output).  */
-  enum captured_mi_execute_command_actions action;
-
-  /* The command context to be executed (input).  */
-  struct mi_parse *command;
-};
-
 int mi_debug_p;
 struct ui_file *raw_stdout;
 
@@ -94,18 +77,23 @@ static struct mi_timestamp *current_command_ts;
 
 static int do_timings = 0;
 
-static char *current_token;
+char *current_token;
+int running_result_record_printed = 1;
+
+/* Flag indicating that the target has proceeded since the last
+   command was issued.  */
+int mi_proceeded;
 
 extern void _initialize_mi_main (void);
-static enum mi_cmd_result mi_cmd_execute (struct mi_parse *parse);
+static void mi_cmd_execute (struct mi_parse *parse);
 
 static void mi_execute_cli_command (const char *cmd, int args_p,
                                    const char *args);
-static enum mi_cmd_result mi_execute_async_cli_command (char *cli_command, 
+static void mi_execute_async_cli_command (char *cli_command, 
                                                        char **argv, int argc);
 static int register_changed_p (int regnum, struct regcache *,
                               struct regcache *);
-static void get_register (int regnum, int format);
+static void get_register (struct frame_info *, int regnum, int format);
 
 /* Command implementations.  FIXME: Is this libgdb?  No.  This is the MI
    layer that calls libgdb.  Any operation used in the below should be
@@ -116,7 +104,7 @@ static void timestamp (struct mi_timestamp *tv);
 static void print_diff_now (struct mi_timestamp *start);
 static void print_diff (struct mi_timestamp *start, struct mi_timestamp *end);
 
-enum mi_cmd_result
+void
 mi_cmd_gdb_exit (char *command, char **argv, int argc)
 {
   /* We have to print everything right here because we never return.  */
@@ -124,61 +112,62 @@ mi_cmd_gdb_exit (char *command, char **argv, int argc)
     fputs_unfiltered (current_token, raw_stdout);
   fputs_unfiltered ("^exit\n", raw_stdout);
   mi_out_put (uiout, raw_stdout);
+  gdb_flush (raw_stdout);
   /* FIXME: The function called is not yet a formal libgdb function.  */
   quit_force (NULL, FROM_TTY);
-  return MI_CMD_DONE;
-}
-
-enum mi_cmd_result
-mi_cmd_exec_run (char *command, char **argv, int argc)
-{
-  /* FIXME: Should call a libgdb function, not a cli wrapper.  */
-  return mi_execute_async_cli_command ("run", argv, argc);
 }
 
-enum mi_cmd_result
+void
 mi_cmd_exec_next (char *command, char **argv, int argc)
 {
   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
-  return mi_execute_async_cli_command ("next", argv, argc);
+  if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
+    mi_execute_async_cli_command ("reverse-next", argv + 1, argc - 1);
+  else
+    mi_execute_async_cli_command ("next", argv, argc);
 }
 
-enum mi_cmd_result
+void
 mi_cmd_exec_next_instruction (char *command, char **argv, int argc)
 {
   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
-  return mi_execute_async_cli_command ("nexti", argv, argc);
+  if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
+    mi_execute_async_cli_command ("reverse-nexti", argv + 1, argc - 1);
+  else
+    mi_execute_async_cli_command ("nexti", argv, argc);
 }
 
-enum mi_cmd_result
+void
 mi_cmd_exec_step (char *command, char **argv, int argc)
 {
   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
-  return mi_execute_async_cli_command ("step", argv, argc);
+  if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
+    mi_execute_async_cli_command ("reverse-step", argv + 1, argc - 1);
+  else
+    mi_execute_async_cli_command ("step", argv, argc);
 }
 
-enum mi_cmd_result
+void
 mi_cmd_exec_step_instruction (char *command, char **argv, int argc)
 {
   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
-  return mi_execute_async_cli_command ("stepi", argv, argc);
+  if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
+    mi_execute_async_cli_command ("reverse-stepi", argv + 1, argc - 1);
+  else
+    mi_execute_async_cli_command ("stepi", argv, argc);
 }
 
-enum mi_cmd_result
+void
 mi_cmd_exec_finish (char *command, char **argv, int argc)
 {
   /* FIXME: Should call a libgdb function, not a cli wrapper.  */
-  return mi_execute_async_cli_command ("finish", argv, argc);
-}
-
-enum mi_cmd_result
-mi_cmd_exec_until (char *command, char **argv, int argc)
-{
-  /* FIXME: Should call a libgdb function, not a cli wrapper.  */
-  return mi_execute_async_cli_command ("until", argv, argc);
+  if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
+    mi_execute_async_cli_command ("reverse-finish", argv + 1, argc - 1);
+  else
+    mi_execute_async_cli_command ("finish", argv, argc);
 }
 
-enum mi_cmd_result
+void
 mi_cmd_exec_return (char *command, char **argv, int argc)
 {
   /* This command doesn't really execute the target, it just pops the
@@ -195,15 +184,110 @@ mi_cmd_exec_return (char *command, char **argv, int argc)
   /* Because we have called return_command with from_tty = 0, we need
      to print the frame here.  */
   print_stack_frame (get_selected_frame (NULL), 1, LOC_AND_ADDRESS);
+}
+
+void
+mi_cmd_exec_jump (char *args, char **argv, int argc)
+{
+  /* FIXME: Should call a libgdb function, not a cli wrapper.  */
+  mi_execute_async_cli_command ("jump", argv, argc);
+}
+static int
+proceed_thread_callback (struct thread_info *thread, void *arg)
+{
+  int pid = *(int *)arg;
 
-  return MI_CMD_DONE;
+  if (!is_stopped (thread->ptid))
+    return 0;
+
+  if (PIDGET (thread->ptid) != pid)
+    return 0;
+
+  switch_to_thread (thread->ptid);
+  clear_proceed_status ();
+  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+  return 0;
 }
 
-enum mi_cmd_result
+static void
+exec_continue (char **argv, int argc)
+{
+  if (argc == 0)
+    continue_1 (0);
+  else if (argc == 1 && strcmp (argv[0], "--all") == 0)
+    continue_1 (1);
+  else if (argc == 2 && strcmp (argv[0], "--thread-group") == 0)
+    {
+      struct cleanup *old_chain;
+      int pid;
+      if (argv[1] == NULL || argv[1] == '\0')
+       error ("Thread group id not specified");
+      pid = atoi (argv[1]);
+      if (!in_inferior_list (pid))
+       error ("Invalid thread group id '%s'", argv[1]);
+
+      old_chain = make_cleanup_restore_current_thread ();
+      iterate_over_threads (proceed_thread_callback, &pid);
+      do_cleanups (old_chain);            
+    }
+  else
+    error ("Usage: -exec-continue [--reverse] [--all|--thread-group id]");
+}
+
+/* continue in reverse direction:
+   XXX: code duplicated from reverse.c */
+
+static void
+exec_direction_default (void *notused)
+{
+  /* Return execution direction to default state.  */
+  execution_direction = EXEC_FORWARD;
+}
+
+static void
+exec_reverse_continue (char **argv, int argc)
+{
+  enum exec_direction_kind dir = execution_direction;
+  struct cleanup *old_chain;
+
+  if (dir == EXEC_ERROR)
+    error (_("Target %s does not support this command."), target_shortname);
+
+  if (dir == EXEC_REVERSE)
+    error (_("Already in reverse mode."));
+
+  if (!target_can_execute_reverse)
+    error (_("Target %s does not support this command."), target_shortname);
+
+  old_chain = make_cleanup (exec_direction_default, NULL);
+  execution_direction = EXEC_REVERSE;
+  exec_continue (argv, argc);
+  do_cleanups (old_chain);
+}
+
+void
 mi_cmd_exec_continue (char *command, char **argv, int argc)
 {
-  /* FIXME: Should call a libgdb function, not a cli wrapper.  */
-  return mi_execute_async_cli_command ("continue", argv, argc);
+  if (argc > 0 && strcmp(argv[0], "--reverse") == 0)
+    exec_reverse_continue (argv + 1, argc - 1);
+  else
+    exec_continue (argv, argc);
+}
+
+static int
+interrupt_thread_callback (struct thread_info *thread, void *arg)
+{
+  int pid = *(int *)arg;
+
+  if (!is_running (thread->ptid))
+    return 0;
+
+  if (PIDGET (thread->ptid) != pid)
+    return 0;
+
+  target_stop (thread->ptid);
+  return 0;
 }
 
 /* Interrupt the execution of the target.  Note how we must play around
@@ -211,23 +295,78 @@ mi_cmd_exec_continue (char *command, char **argv, int argc)
    the result of the interrupt command, and the previous execution
    token when the target finally stops.  See comments in
    mi_cmd_execute.  */
-enum mi_cmd_result
+void
 mi_cmd_exec_interrupt (char *command, char **argv, int argc)
 {
-  if (!target_executing)
-    error ("mi_cmd_exec_interrupt: Inferior not executing.");
+  if (argc == 0)
+    {
+      if (!is_running (inferior_ptid))
+       error ("Current thread is not running.");
 
-  interrupt_target_command (NULL, 0);
-  if (current_token)
-    fputs_unfiltered (current_token, raw_stdout);
-  fputs_unfiltered ("^done", raw_stdout);
-  mi_out_put (uiout, raw_stdout);
-  mi_out_rewind (uiout);
-  fputs_unfiltered ("\n", raw_stdout);
-  return MI_CMD_QUIET;
+      interrupt_target_1 (0);
+    }
+  else if (argc == 1 && strcmp (argv[0], "--all") == 0)
+    {
+      if (!any_running ())
+       error ("Inferior not running.");
+      
+      interrupt_target_1 (1);
+    }
+  else if (argc == 2 && strcmp (argv[0], "--thread-group") == 0)
+    {
+      struct cleanup *old_chain;
+      int pid;
+      if (argv[1] == NULL || argv[1] == '\0')
+       error ("Thread group id not specified");
+      pid = atoi (argv[1]);
+      if (!in_inferior_list (pid))
+       error ("Invalid thread group id '%s'", argv[1]);
+
+      old_chain = make_cleanup_restore_current_thread ();
+      iterate_over_threads (interrupt_thread_callback, &pid);
+      do_cleanups (old_chain);
+    }
+  else
+    error ("Usage: -exec-interrupt [--all|--thread-group id]");
 }
 
-enum mi_cmd_result
+static int
+find_thread_of_process (struct thread_info *ti, void *p)
+{
+  int pid = *(int *)p;
+  if (PIDGET (ti->ptid) == pid && !is_exited (ti->ptid))
+    return 1;
+
+  return 0;
+}
+
+void
+mi_cmd_target_detach (char *command, char **argv, int argc)
+{
+  if (argc != 0 && argc != 1)
+    error ("Usage: -target-detach [thread-group]");
+
+  if (argc == 1)
+    {
+      struct thread_info *tp;
+      char *end = argv[0];
+      int pid = strtol (argv[0], &end, 10);
+      if (*end != '\0')
+       error (_("Cannot parse thread group id '%s'"), argv[0]);
+
+      /* Pick any thread in the desired process.  Current
+        target_detach deteches from the parent of inferior_ptid.  */
+      tp = iterate_over_threads (find_thread_of_process, &pid);
+      if (!tp)
+       error (_("Thread group is empty"));
+
+      switch_to_thread (tp->ptid);
+    }
+
+  detach_command (NULL, 0);
+}
+
+void
 mi_cmd_thread_select (char *command, char **argv, int argc)
 {
   enum gdb_rc rc;
@@ -243,11 +382,9 @@ mi_cmd_thread_select (char *command, char **argv, int argc)
       make_cleanup (xfree, mi_error_message);
       error ("%s", mi_error_message);
     }
-
-  return MI_CMD_DONE;
 }
 
-enum mi_cmd_result
+void
 mi_cmd_thread_list_ids (char *command, char **argv, int argc)
 {
   enum gdb_rc rc;
@@ -263,11 +400,9 @@ mi_cmd_thread_list_ids (char *command, char **argv, int argc)
       make_cleanup (xfree, mi_error_message);
       error ("%s", mi_error_message);
     }
-
-  return MI_CMD_DONE;
 }
 
-enum mi_cmd_result
+void
 mi_cmd_thread_info (char *command, char **argv, int argc)
 {
   int thread = -1;
@@ -278,13 +413,367 @@ mi_cmd_thread_info (char *command, char **argv, int argc)
   if (argc == 1)
     thread = atoi (argv[0]);
 
-  print_thread_info (uiout, thread);
-  return MI_CMD_DONE;
+  print_thread_info (uiout, thread, -1);
+}
+
+struct collect_cores_data
+{
+  int pid;
+
+  VEC (int) *cores;
+};
+
+static int
+collect_cores (struct thread_info *ti, void *xdata)
+{
+  struct collect_cores_data *data = xdata;
+
+  if (ptid_get_pid (ti->ptid) == data->pid)
+    {
+      int core = target_core_of_thread (ti->ptid);
+      if (core != -1)
+       VEC_safe_push (int, data->cores, core);
+    }
+
+  return 0;
+}
+
+static int *
+unique (int *b, int *e)
+{
+  int *d = b;
+  while (++b != e)
+    if (*d != *b)
+      *++d = *b;
+  return ++d;
+}
+
+struct print_one_inferior_data
+{
+  int recurse;
+  VEC (int) *inferiors;
+};
+
+static int
+print_one_inferior (struct inferior *inferior, void *xdata)
+{
+  struct print_one_inferior_data *top_data = xdata;
+
+  if (VEC_empty (int, top_data->inferiors)
+      || bsearch (&(inferior->pid), VEC_address (int, top_data->inferiors),
+                 VEC_length (int, top_data->inferiors), sizeof (int),
+                 compare_positive_ints))
+    {
+      struct collect_cores_data data;
+      struct cleanup *back_to
+       = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+
+      ui_out_field_fmt (uiout, "id", "%d", inferior->pid);
+      ui_out_field_string (uiout, "type", "process");
+      ui_out_field_int (uiout, "pid", inferior->pid);
+
+      data.pid = inferior->pid;
+      data.cores = 0;
+      iterate_over_threads (collect_cores, &data);
+
+      if (!VEC_empty (int, data.cores))
+       {
+         int elt;
+         int i;
+         int *b, *e;
+         struct cleanup *back_to_2 =
+           make_cleanup_ui_out_list_begin_end (uiout, "cores");
+
+         qsort (VEC_address (int, data.cores),
+                VEC_length (int, data.cores), sizeof (int),
+                compare_positive_ints);
+
+         b = VEC_address (int, data.cores);
+         e = b + VEC_length (int, data.cores);
+         e = unique (b, e);
+
+         for (; b != e; ++b)
+           ui_out_field_int (uiout, NULL, *b);
+
+         do_cleanups (back_to_2);
+       }
+
+      if (top_data->recurse)
+       print_thread_info (uiout, -1, inferior->pid);
+
+      do_cleanups (back_to);
+    }
+
+  return 0;
+}
+
+/* Output a field named 'cores' with a list as the value.  The elements of
+   the list are obtained by splitting 'cores' on comma.  */
+
+static void
+output_cores (struct ui_out *uiout, const char *field_name, const char *xcores)
+{
+  struct cleanup *back_to = make_cleanup_ui_out_list_begin_end (uiout,
+                                                               field_name);
+  char *cores = xstrdup (xcores);
+  char *p = cores;
+
+  make_cleanup (xfree, cores);
+
+  for (p = strtok (p, ","); p;  p = strtok (NULL, ","))
+    ui_out_field_string (uiout, NULL, p);
+
+  do_cleanups (back_to);
 }
 
-enum mi_cmd_result
+static void
+free_vector_of_ints (void *xvector)
+{
+  VEC (int) **vector = xvector;
+  VEC_free (int, *vector);
+}
+
+static void
+do_nothing (splay_tree_key k)
+{
+}
+
+static void
+free_vector_of_osdata_items (splay_tree_value xvalue)
+{
+  VEC (osdata_item_s) *value = (VEC (osdata_item_s) *) xvalue;
+  /* We don't free the items itself, it will be done separately.  */
+  VEC_free (osdata_item_s, value);
+}
+
+static int
+splay_tree_int_comparator (splay_tree_key xa, splay_tree_key xb)
+{
+  int a = xa;
+  int b = xb;
+  return a - b;
+}
+
+static void
+free_splay_tree (void *xt)
+{
+  splay_tree t = xt;
+  splay_tree_delete (t);
+}
+
+static void
+list_available_thread_groups (VEC (int) *ids, int recurse)
+{
+  struct osdata *data;
+  struct osdata_item *item;
+  int ix_items;
+  /* This keeps a map from integer (pid) to VEC (struct osdata_item *)*
+     The vector contains information about all threads for the given pid.
+     This is assigned an initial value to avoid "may be used uninitialized"
+     warning from gcc.  */
+  splay_tree tree = NULL;
+
+  /* get_osdata will throw if it cannot return data.  */
+  data = get_osdata ("processes");
+  make_cleanup_osdata_free (data);
+
+  if (recurse)
+    {
+      struct osdata *threads = get_osdata ("threads");
+      make_cleanup_osdata_free (threads);
+
+      tree = splay_tree_new (splay_tree_int_comparator,
+                            do_nothing,
+                            free_vector_of_osdata_items);
+      make_cleanup (free_splay_tree, tree);
+
+      for (ix_items = 0;
+          VEC_iterate (osdata_item_s, threads->items,
+                       ix_items, item);
+          ix_items++)
+       {
+         const char *pid = get_osdata_column (item, "pid");
+         int pid_i = strtoul (pid, NULL, 0);
+         VEC (osdata_item_s) *vec = 0;
+
+         splay_tree_node n = splay_tree_lookup (tree, pid_i);
+         if (!n)
+           {
+             VEC_safe_push (osdata_item_s, vec, item);
+             splay_tree_insert (tree, pid_i, (splay_tree_value)vec);
+           }
+         else
+           {
+             vec = (VEC (osdata_item_s) *) n->value;
+             VEC_safe_push (osdata_item_s, vec, item);
+             n->value = (splay_tree_value) vec;
+           }
+       }
+    }
+
+  make_cleanup_ui_out_list_begin_end (uiout, "groups");
+
+  for (ix_items = 0;
+       VEC_iterate (osdata_item_s, data->items,
+                   ix_items, item);
+       ix_items++)
+    {
+      struct cleanup *back_to;
+
+      const char *pid = get_osdata_column (item, "pid");
+      const char *cmd = get_osdata_column (item, "command");
+      const char *user = get_osdata_column (item, "user");
+      const char *cores = get_osdata_column (item, "cores");
+
+      int pid_i = strtoul (pid, NULL, 0);
+
+      /* At present, the target will return all available processes
+        and if information about specific ones was required, we filter
+        undesired processes here.  */
+      if (ids && bsearch (&pid_i, VEC_address (int, ids),
+                         VEC_length (int, ids),
+                         sizeof (int), compare_positive_ints) == NULL)
+       continue;
+
+
+      back_to = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+
+      ui_out_field_fmt (uiout, "id", "%s", pid);
+      ui_out_field_string (uiout, "type", "process");
+      if (cmd)
+       ui_out_field_string (uiout, "description", cmd);
+      if (user)
+       ui_out_field_string (uiout, "user", user);
+      if (cores)
+       output_cores (uiout, "cores", cores);
+
+      if (recurse)
+       {
+         splay_tree_node n = splay_tree_lookup (tree, pid_i);
+         if (n)
+           {
+             VEC (osdata_item_s) *children = (VEC (osdata_item_s) *) n->value;
+             struct osdata_item *child;
+             int ix_child;
+
+             make_cleanup_ui_out_list_begin_end (uiout, "threads");
+
+             for (ix_child = 0;
+                  VEC_iterate (osdata_item_s, children, ix_child, child);
+                  ++ix_child)
+               {
+                 struct cleanup *back_to_2 =
+                   make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+
+                 const char *tid = get_osdata_column (child, "tid");
+                 const char *tcore = get_osdata_column (child, "core");
+                 ui_out_field_string (uiout, "id", tid);
+                 if (tcore)
+                   ui_out_field_string (uiout, "core", tcore);
+
+                 do_cleanups (back_to_2);
+               }
+           }
+       }
+
+      do_cleanups (back_to);
+    }
+}
+
+void
+mi_cmd_list_thread_groups (char *command, char **argv, int argc)
+{
+  struct cleanup *back_to;
+  int available = 0;
+  int recurse = 0;
+  VEC (int) *ids = 0;
+
+  enum opt
+    {
+      AVAILABLE_OPT, RECURSE_OPT
+    };
+  static struct mi_opt opts[] =
+  {
+    {"-available", AVAILABLE_OPT, 0},
+    {"-recurse", RECURSE_OPT, 1},
+    { 0, 0, 0 }
+  };
+
+  int optind = 0;
+  char *optarg;
+
+  while (1)
+    {
+      int opt = mi_getopt ("-list-thread-groups", argc, argv, opts,
+                          &optind, &optarg);
+      if (opt < 0)
+       break;
+      switch ((enum opt) opt)
+       {
+       case AVAILABLE_OPT:
+         available = 1;
+         break;
+       case RECURSE_OPT:
+         if (strcmp (optarg, "0") == 0)
+           ;
+         else if (strcmp (optarg, "1") == 0)
+           recurse = 1;
+         else
+           error ("only '0' and '1' are valid values for the '--recurse' option");
+         break;
+       }
+    }
+
+  for (; optind < argc; ++optind)
+    {
+      char *end;
+      int inf = strtoul (argv[optind], &end, 0);
+      if (*end != '\0')
+       error ("invalid group id '%s'", argv[optind]);
+      VEC_safe_push (int, ids, inf);
+    }
+  if (VEC_length (int, ids) > 1)
+    qsort (VEC_address (int, ids),
+          VEC_length (int, ids),
+          sizeof (int), compare_positive_ints);
+
+  back_to = make_cleanup (free_vector_of_ints, &ids);
+
+  if (available)
+    {
+      list_available_thread_groups (ids, recurse);
+    }
+  else if (VEC_length (int, ids) == 1)
+    {
+      /* Local thread groups, single id. */
+      int pid = *VEC_address (int, ids);
+      if (!in_inferior_list (pid))
+       error ("Invalid thread group id '%d'", pid);
+      print_thread_info (uiout, -1, pid);
+    }
+  else
+    {
+      struct print_one_inferior_data data;
+      data.recurse = recurse;
+      data.inferiors = ids;
+
+      /* Local thread groups.  Either no explicit ids -- and we
+        print everything, or several explicit ids.  In both cases,
+        we print more than one group, and have to use 'groups'
+        as the top-level element.  */
+      make_cleanup_ui_out_list_begin_end (uiout, "groups");
+      update_thread_list ();
+      iterate_over_inferiors (print_one_inferior, &data);
+    }
+
+  do_cleanups (back_to);
+}
+
+void
 mi_cmd_data_list_register_names (char *command, char **argv, int argc)
 {
+  struct frame_info *frame;
+  struct gdbarch *gdbarch;
   int regnum, numregs;
   int i;
   struct cleanup *cleanup;
@@ -295,8 +784,9 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc)
      In this case, some entries of gdbarch_register_name will change depending
      upon the particular processor being debugged.  */
 
-  numregs = gdbarch_num_regs (current_gdbarch)
-           + gdbarch_num_pseudo_regs (current_gdbarch);
+  frame = get_selected_frame (NULL);
+  gdbarch = get_frame_arch (frame);
+  numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
 
   cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-names");
 
@@ -306,13 +796,12 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc)
           regnum < numregs;
           regnum++)
        {
-         if (gdbarch_register_name (current_gdbarch, regnum) == NULL
-             || *(gdbarch_register_name (current_gdbarch, regnum)) == '\0')
+         if (gdbarch_register_name (gdbarch, regnum) == NULL
+             || *(gdbarch_register_name (gdbarch, regnum)) == '\0')
            ui_out_field_string (uiout, NULL, "");
          else
            ui_out_field_string (uiout, NULL,
-                                gdbarch_register_name
-                                  (current_gdbarch, regnum));
+                                gdbarch_register_name (gdbarch, regnum));
        }
     }
 
@@ -323,22 +812,22 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc)
       if (regnum < 0 || regnum >= numregs)
        error ("bad register number");
 
-      if (gdbarch_register_name (current_gdbarch, regnum) == NULL
-         || *(gdbarch_register_name (current_gdbarch, regnum)) == '\0')
+      if (gdbarch_register_name (gdbarch, regnum) == NULL
+         || *(gdbarch_register_name (gdbarch, regnum)) == '\0')
        ui_out_field_string (uiout, NULL, "");
       else
        ui_out_field_string (uiout, NULL,
-                            gdbarch_register_name (current_gdbarch, regnum));
+                            gdbarch_register_name (gdbarch, regnum));
     }
   do_cleanups (cleanup);
-  return MI_CMD_DONE;
 }
 
-enum mi_cmd_result
+void
 mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
 {
   static struct regcache *this_regs = NULL;
   struct regcache *prev_regs;
+  struct gdbarch *gdbarch;
   int regnum, numregs, changed;
   int i;
   struct cleanup *cleanup;
@@ -357,8 +846,8 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
      In this  case, some entries of gdbarch_register_name will change depending
      upon the particular processor being debugged.  */
 
-  numregs = gdbarch_num_regs (current_gdbarch)
-           + gdbarch_num_pseudo_regs (current_gdbarch);
+  gdbarch = get_regcache_arch (this_regs);
+  numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
 
   make_cleanup_ui_out_list_begin_end (uiout, "changed-registers");
 
@@ -368,8 +857,8 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
           regnum < numregs;
           regnum++)
        {
-         if (gdbarch_register_name (current_gdbarch, regnum) == NULL
-             || *(gdbarch_register_name (current_gdbarch, regnum)) == '\0')
+         if (gdbarch_register_name (gdbarch, regnum) == NULL
+             || *(gdbarch_register_name (gdbarch, regnum)) == '\0')
            continue;
          changed = register_changed_p (regnum, prev_regs, this_regs);
          if (changed < 0)
@@ -386,8 +875,8 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
 
       if (regnum >= 0
          && regnum < numregs
-         && gdbarch_register_name (current_gdbarch, regnum) != NULL
-         && *gdbarch_register_name (current_gdbarch, regnum) != '\000')
+         && gdbarch_register_name (gdbarch, regnum) != NULL
+         && *gdbarch_register_name (gdbarch, regnum) != '\000')
        {
          changed = register_changed_p (regnum, prev_regs, this_regs);
          if (changed < 0)
@@ -399,7 +888,6 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
        error ("bad register number");
     }
   do_cleanups (cleanup);
-  return MI_CMD_DONE;
 }
 
 static int
@@ -435,9 +923,11 @@ register_changed_p (int regnum, struct regcache *prev_regs,
    format argumetn there can be a sequence of numbers, indicating which
    registers to fetch the content of.  If the format is the only argument,
    a list of all the registers with their values is returned.  */
-enum mi_cmd_result
+void
 mi_cmd_data_list_register_values (char *command, char **argv, int argc)
 {
+  struct frame_info *frame;
+  struct gdbarch *gdbarch;
   int regnum, numregs, format;
   int i;
   struct cleanup *list_cleanup, *tuple_cleanup;
@@ -448,14 +938,15 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc)
      In this case, some entries of gdbarch_register_name will change depending
      upon the particular processor being debugged.  */
 
-  numregs = gdbarch_num_regs (current_gdbarch)
-           + gdbarch_num_pseudo_regs (current_gdbarch);
-
   if (argc == 0)
     error ("mi_cmd_data_list_register_values: Usage: -data-list-register-values <format> [<regnum1>...<regnumN>]");
 
   format = (int) argv[0][0];
 
+  frame = get_selected_frame (NULL);
+  gdbarch = get_frame_arch (frame);
+  numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+
   list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-values");
 
   if (argc == 1)           /* No args, beside the format: do all the regs.  */
@@ -464,12 +955,12 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc)
           regnum < numregs;
           regnum++)
        {
-         if (gdbarch_register_name (current_gdbarch, regnum) == NULL
-             || *(gdbarch_register_name (current_gdbarch, regnum)) == '\0')
+         if (gdbarch_register_name (gdbarch, regnum) == NULL
+             || *(gdbarch_register_name (gdbarch, regnum)) == '\0')
            continue;
          tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
          ui_out_field_int (uiout, "number", regnum);
-         get_register (regnum, format);
+         get_register (frame, regnum, format);
          do_cleanups (tuple_cleanup);
        }
     }
@@ -481,25 +972,25 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc)
 
       if (regnum >= 0
          && regnum < numregs
-         && gdbarch_register_name (current_gdbarch, regnum) != NULL
-         && *gdbarch_register_name (current_gdbarch, regnum) != '\000')
+         && gdbarch_register_name (gdbarch, regnum) != NULL
+         && *gdbarch_register_name (gdbarch, regnum) != '\000')
        {
          tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
          ui_out_field_int (uiout, "number", regnum);
-         get_register (regnum, format);
+         get_register (frame, regnum, format);
          do_cleanups (tuple_cleanup);
        }
       else
        error ("bad register number");
     }
   do_cleanups (list_cleanup);
-  return MI_CMD_DONE;
 }
 
 /* Output one register's contents in the desired format.  */
 static void
-get_register (int regnum, int format)
+get_register (struct frame_info *frame, int regnum, int format)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   gdb_byte buffer[MAX_REGISTER_SIZE];
   int optim;
   int realnum;
@@ -512,8 +1003,7 @@ get_register (int regnum, int format)
   if (format == 'N')
     format = 0;
 
-  frame_register (get_selected_frame (NULL), regnum, &optim, &lval, &addr,
-                 &realnum, buffer);
+  frame_register (frame, regnum, &optim, &lval, &addr, &realnum, buffer);
 
   if (optim)
     error ("Optimized out");
@@ -525,10 +1015,10 @@ get_register (int regnum, int format)
 
       strcpy (buf, "0x");
       ptr = buf + 2;
-      for (j = 0; j < register_size (current_gdbarch, regnum); j++)
+      for (j = 0; j < register_size (gdbarch, regnum); j++)
        {
-         int idx = gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG ? j
-         : register_size (current_gdbarch, regnum) - 1 - j;
+         int idx = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ?
+                   j : register_size (gdbarch, regnum) - 1 - j;
          sprintf (ptr, "%02x", (unsigned char) buffer[idx]);
          ptr += 2;
        }
@@ -537,9 +1027,11 @@ get_register (int regnum, int format)
     }
   else
     {
-      val_print (register_type (current_gdbarch, regnum), buffer, 0, 0,
-                stb->stream, format, 1, 0, Val_pretty_default,
-                current_language);
+      struct value_print_options opts;
+      get_formatted_print_options (&opts, format);
+      opts.deref_ref = 1;
+      val_print (register_type (gdbarch, regnum), buffer, 0, 0,
+                stb->stream, 0, &opts, current_language);
       ui_out_field_stream (uiout, "value", stb);
       ui_out_stream_delete (stb);
     }
@@ -548,9 +1040,11 @@ get_register (int regnum, int format)
 /* Write given values into registers. The registers and values are
    given as pairs.  The corresponding MI command is 
    -data-write-register-values <format> [<regnum1> <value1>...<regnumN> <valueN>]*/
-enum mi_cmd_result
+void
 mi_cmd_data_write_register_values (char *command, char **argv, int argc)
 {
+  struct regcache *regcache;
+  struct gdbarch *gdbarch;
   int numregs, i;
   char format;
 
@@ -560,8 +1054,9 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc)
      In this case, some entries of gdbarch_register_name will change depending
      upon the particular processor being debugged.  */
 
-  numregs = gdbarch_num_regs (current_gdbarch)
-           + gdbarch_num_pseudo_regs (current_gdbarch);
+  regcache = get_current_regcache ();
+  gdbarch = get_regcache_arch (regcache);
+  numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
 
   if (argc == 0)
     error ("mi_cmd_data_write_register_values: Usage: -data-write-register-values <format> [<regnum1> <value1>...<regnumN> <valueN>]");
@@ -582,8 +1077,8 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc)
       int regnum = atoi (argv[i]);
 
       if (regnum >= 0 && regnum < numregs
-         && gdbarch_register_name (current_gdbarch, regnum)
-         && *gdbarch_register_name (current_gdbarch, regnum))
+         && gdbarch_register_name (gdbarch, regnum)
+         && *gdbarch_register_name (gdbarch, regnum))
        {
          LONGEST value;
 
@@ -591,24 +1086,24 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc)
          value = parse_and_eval_address (argv[i + 1]);
 
          /* Write it down.  */
-         regcache_cooked_write_signed (get_current_regcache (), regnum, value);
+         regcache_cooked_write_signed (regcache, regnum, value);
        }
       else
        error ("bad register number");
     }
-  return MI_CMD_DONE;
 }
 
 /* Evaluate the value of the argument.  The argument is an
    expression. If the expression contains spaces it needs to be
    included in double quotes.  */
-enum mi_cmd_result
+void
 mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
 {
   struct expression *expr;
   struct cleanup *old_chain = NULL;
   struct value *val;
   struct ui_stream *stb = NULL;
+  struct value_print_options opts;
 
   stb = ui_out_stream_new (uiout);
 
@@ -625,76 +1120,16 @@ mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
   val = evaluate_expression (expr);
 
   /* Print the result of the expression evaluation.  */
+  get_user_print_options (&opts);
+  opts.deref_ref = 0;
   val_print (value_type (val), value_contents (val),
-            value_embedded_offset (val), VALUE_ADDRESS (val),
-            stb->stream, 0, 0, 0, 0, current_language);
+            value_embedded_offset (val), value_address (val),
+            stb->stream, 0, &opts, current_language);
 
   ui_out_field_stream (uiout, "value", stb);
   ui_out_stream_delete (stb);
 
   do_cleanups (old_chain);
-
-  return MI_CMD_DONE;
-}
-
-enum mi_cmd_result
-mi_cmd_target_download (char *command, char **argv, int argc)
-{
-  char *run;
-  struct cleanup *old_cleanups = NULL;
-
-  /* There may be at most one parameter -- the name of the
-     file to download.  */
-  run = xstrprintf ("load %s", argc ? *argv : "");
-  old_cleanups = make_cleanup (xfree, run);
-  execute_command (run, 0);
-
-  do_cleanups (old_cleanups);
-  return MI_CMD_DONE;
-}
-
-/* Connect to the remote target.  */
-enum mi_cmd_result
-mi_cmd_target_select (char *command, char **argv, int argc)
-{
-  char *run = NULL;
-  struct cleanup *old_cleanups = NULL;
-  int i;
-
-  if (argc == 0)
-    error ("no target type specified");
-    
-  for (i = 0; i < argc; ++i)
-    {
-      if (i == 0)
-       run = concat ("target ", argv[0], NULL);
-      else
-       {
-         char *prev = run;
-         run = concat (run, " ", argv[i], NULL);
-         xfree (prev);
-       }
-    }
-  
-  old_cleanups = make_cleanup (xfree, run);
-
-  /* target-select is always synchronous.  Once the call has returned
-     we know that we are connected.  */
-  /* NOTE: At present all targets that are connected are also
-     (implicitly) talking to a halted target.  In the future this may
-     change.  */
-  execute_command (run, 0);
-
-  do_cleanups (old_cleanups);
-
-  /* Issue the completion message here.  */
-  if (current_token)
-    fputs_unfiltered (current_token, raw_stdout);
-  fputs_unfiltered ("^connected", raw_stdout);
-  mi_out_put (uiout, raw_stdout);
-  mi_out_rewind (uiout);
-  fputs_unfiltered ("\n", raw_stdout);
-  return MI_CMD_QUIET;
 }
 
 /* DATA-MEMORY-READ:
@@ -716,9 +1151,10 @@ mi_cmd_target_select (char *command, char **argv, int argc)
    Returns: 
    The number of bytes read is SIZE*ROW*COL. */
 
-enum mi_cmd_result
+void
 mi_cmd_data_read_memory (char *command, char **argv, int argc)
 {
+  struct gdbarch *gdbarch = get_current_arch ();
   struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
   CORE_ADDR addr;
   long total_bytes;
@@ -775,23 +1211,23 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
   switch (word_size)
     {
     case 1:
-      word_type = builtin_type_int8;
+      word_type = builtin_type (gdbarch)->builtin_int8;
       word_asize = 'b';
       break;
     case 2:
-      word_type = builtin_type_int16;
+      word_type = builtin_type (gdbarch)->builtin_int16;
       word_asize = 'h';
       break;
     case 4:
-      word_type = builtin_type_int32;
+      word_type = builtin_type (gdbarch)->builtin_int32;
       word_asize = 'w';
       break;
     case 8:
-      word_type = builtin_type_int64;
+      word_type = builtin_type (gdbarch)->builtin_int64;
       word_asize = 'g';
       break;
     default:
-      word_type = builtin_type_int8;
+      word_type = builtin_type (gdbarch)->builtin_int8;
       word_asize = 'b';
     }
   /* The number of rows.  */
@@ -815,19 +1251,24 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
   mbuf = xcalloc (total_bytes, 1);
   make_cleanup (xfree, mbuf);
 
-  nr_bytes = target_read (&current_target, TARGET_OBJECT_MEMORY, NULL,
-                         mbuf, addr, total_bytes);
+  /* Dispatch memory reads to the topmost target, not the flattened
+     current_target.  */
+  nr_bytes = target_read_until_error (current_target.beneath,
+                                     TARGET_OBJECT_MEMORY, NULL, mbuf,
+                                     addr, total_bytes);
   if (nr_bytes <= 0)
     error ("Unable to read memory.");
 
   /* Output the header information.  */
-  ui_out_field_core_addr (uiout, "addr", addr);
+  ui_out_field_core_addr (uiout, "addr", gdbarch, addr);
   ui_out_field_int (uiout, "nr-bytes", nr_bytes);
   ui_out_field_int (uiout, "total-bytes", total_bytes);
-  ui_out_field_core_addr (uiout, "next-row", addr + word_size * nr_cols);
-  ui_out_field_core_addr (uiout, "prev-row", addr - word_size * nr_cols);
-  ui_out_field_core_addr (uiout, "next-page", addr + total_bytes);
-  ui_out_field_core_addr (uiout, "prev-page", addr - total_bytes);
+  ui_out_field_core_addr (uiout, "next-row",
+                         gdbarch, addr + word_size * nr_cols);
+  ui_out_field_core_addr (uiout, "prev-row",
+                         gdbarch, addr - word_size * nr_cols);
+  ui_out_field_core_addr (uiout, "next-page", gdbarch, addr + total_bytes);
+  ui_out_field_core_addr (uiout, "prev-page", gdbarch, addr - total_bytes);
 
   /* Build the result as a two dimentional table.  */
   {
@@ -844,10 +1285,13 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
        int col_byte;
        struct cleanup *cleanup_tuple;
        struct cleanup *cleanup_list_data;
+       struct value_print_options opts;
+
        cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
-       ui_out_field_core_addr (uiout, "addr", addr + row_byte);
+       ui_out_field_core_addr (uiout, "addr", gdbarch, addr + row_byte);
        /* ui_out_field_core_addr_symbolic (uiout, "saddr", addr + row_byte); */
        cleanup_list_data = make_cleanup_ui_out_list_begin_end (uiout, "data");
+       get_formatted_print_options (&opts, word_format);
        for (col = 0, col_byte = row_byte;
             col < nr_cols;
             col++, col_byte += word_size)
@@ -859,7 +1303,7 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
            else
              {
                ui_file_rewind (stream->stream);
-               print_scalar_formatted (mbuf + col_byte, word_type, word_format,
+               print_scalar_formatted (mbuf + col_byte, word_type, &opts,
                                        word_asize, stream->stream);
                ui_out_field_stream (uiout, NULL, stream);
              }
@@ -890,7 +1334,6 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
     do_cleanups (cleanup_list_memory);
   }
   do_cleanups (cleanups);
-  return MI_CMD_DONE;
 }
 
 /* DATA-MEMORY-WRITE:
@@ -909,9 +1352,11 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
    Writes VALUE into ADDR + (COLUMN_OFFSET * WORD_SIZE).
 
    Prints nothing.  */
-enum mi_cmd_result
+void
 mi_cmd_data_write_memory (char *command, char **argv, int argc)
 {
+  struct gdbarch *gdbarch = get_current_arch ();
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR addr;
   char word_format;
   long word_size;
@@ -969,16 +1414,14 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc)
   /* Get the value into an array.  */
   buffer = xmalloc (word_size);
   old_chain = make_cleanup (xfree, buffer);
-  store_signed_integer (buffer, word_size, value);
+  store_signed_integer (buffer, word_size, byte_order, value);
   /* Write it down to memory.  */
   write_memory (addr, buffer, word_size);
   /* Free the buffer.  */
   do_cleanups (old_chain);
-
-  return MI_CMD_DONE;
 }
 
-enum mi_cmd_result
+void
 mi_cmd_enable_timings (char *command, char **argv, int argc)
 {
   if (argc == 0)
@@ -995,14 +1438,13 @@ mi_cmd_enable_timings (char *command, char **argv, int argc)
   else
     goto usage_error;
     
-  return MI_CMD_DONE;
+  return;
 
  usage_error:
   error ("mi_cmd_enable_timings: Usage: %s {yes|no}", command);
-  return MI_CMD_DONE;
 }
 
-enum mi_cmd_result
+void
 mi_cmd_list_features (char *command, char **argv, int argc)
 {
   if (argc == 0)
@@ -1014,15 +1456,35 @@ mi_cmd_list_features (char *command, char **argv, int argc)
       ui_out_field_string (uiout, NULL, "pending-breakpoints");
       ui_out_field_string (uiout, NULL, "thread-info");
       
+#if HAVE_PYTHON
+      ui_out_field_string (uiout, NULL, "python");
+#endif
+      
       do_cleanups (cleanup);
-
-      return MI_CMD_DONE;
+      return;
     }
 
   error ("-list-features should be passed no arguments");
-  return MI_CMD_DONE;
 }
+
+void
+mi_cmd_list_target_features (char *command, char **argv, int argc)
+{
+  if (argc == 0)
+    {
+      struct cleanup *cleanup = NULL;
+      cleanup = make_cleanup_ui_out_list_begin_end (uiout, "features");      
+
+      if (target_can_async_p ())
+       ui_out_field_string (uiout, NULL, "async");
+      
+      do_cleanups (cleanup);
+      return;
+    }
+
+  error ("-list-target-features should be passed no arguments");
+}
+
 /* Execute a command within a safe environment.
    Return <0 for error; >=0 for ok.
 
@@ -1033,61 +1495,52 @@ mi_cmd_list_features (char *command, char **argv, int argc)
 static void
 captured_mi_execute_command (struct ui_out *uiout, void *data)
 {
-  struct captured_mi_execute_command_args *args =
-    (struct captured_mi_execute_command_args *) data;
-  struct mi_parse *context = args->command;
+  struct cleanup *cleanup;
+  struct mi_parse *context = (struct mi_parse *) data;
+
+  if (do_timings)
+    current_command_ts = context->cmd_start;
 
-  struct mi_timestamp cmd_finished;
+  current_token = xstrdup (context->token);
+  cleanup = make_cleanup (free_current_contents, &current_token);
 
+  running_result_record_printed = 0;
+  mi_proceeded = 0;
   switch (context->op)
     {
-
     case MI_COMMAND:
       /* A MI command was read from the input stream.  */
       if (mi_debug_p)
        /* FIXME: gdb_???? */
        fprintf_unfiltered (raw_stdout, " token=`%s' command=`%s' args=`%s'\n",
                            context->token, context->command, context->args);
-      /* FIXME: cagney/1999-09-25: Rather than this convoluted
-         condition expression, each function should return an
-         indication of what action is required and then switch on
-         that.  */
-      args->action = EXECUTE_COMMAND_DISPLAY_PROMPT;
 
-      if (do_timings)
-       current_command_ts = context->cmd_start;
 
-      args->rc = mi_cmd_execute (context);
+      mi_cmd_execute (context);
 
-      if (do_timings)
-       timestamp (&cmd_finished);
+      /* Print the result if there were no errors.
 
-      if (!target_can_async_p () || !target_executing)
+        Remember that on the way out of executing a command, you have
+        to directly use the mi_interp's uiout, since the command could 
+        have reset the interpreter, in which case the current uiout 
+        will most likely crash in the mi_out_* routines.  */
+      if (!running_result_record_printed)
        {
-         /* Print the result if there were no errors.
-
-            Remember that on the way out of executing a command, you have
-            to directly use the mi_interp's uiout, since the command could 
-            have reset the interpreter, in which case the current uiout 
-            will most likely crash in the mi_out_* routines.  */
-         if (args->rc == MI_CMD_DONE)
-           {
-             fputs_unfiltered (context->token, raw_stdout);
-             fputs_unfiltered ("^done", raw_stdout);
-             mi_out_put (uiout, raw_stdout);
-             mi_out_rewind (uiout);
-             /* Have to check cmd_start, since the command could be
-                -enable-timings.  */
-             if (do_timings && context->cmd_start)
-                 print_diff (context->cmd_start, &cmd_finished);
-             fputs_unfiltered ("\n", raw_stdout);
-           }
-         else
+         fputs_unfiltered (context->token, raw_stdout);
+         /* There's no particularly good reason why target-connect results
+            in not ^done.  Should kill ^connected for MI3.  */
+         fputs_unfiltered (strcmp (context->command, "target-select") == 0
+                           ? "^connected" : "^done", raw_stdout);
+         mi_out_put (uiout, raw_stdout);
+         mi_out_rewind (uiout);
+         mi_print_timing_maybe ();
+         fputs_unfiltered ("\n", raw_stdout);
+       }
+      else
            /* The command does not want anything to be printed.  In that
               case, the command probably should not have written anything
               to uiout, but in case it has written something, discard it.  */
-           mi_out_rewind (uiout);
-       }
+       mi_out_rewind (uiout);
       break;
 
     case CLI_COMMAND:
@@ -1101,7 +1554,7 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
        /* Call the "console" interpreter.  */
        argv[0] = "console";
        argv[1] = context->command;
-       args->rc = mi_cmd_interpreter_exec ("-interpreter-exec", argv, 2);
+       mi_cmd_interpreter_exec ("-interpreter-exec", argv, 2);
 
        /* If we changed interpreters, DON'T print out anything.  */
        if (current_interp_named_p (INTERP_MI)
@@ -1109,14 +1562,14 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
            || current_interp_named_p (INTERP_MI2)
            || current_interp_named_p (INTERP_MI3))
          {
-           if (args->rc == MI_CMD_DONE)
+           if (!running_result_record_printed)
              {
                fputs_unfiltered (context->token, raw_stdout);
                fputs_unfiltered ("^done", raw_stdout);
                mi_out_put (uiout, raw_stdout);
                mi_out_rewind (uiout);
-               fputs_unfiltered ("\n", raw_stdout);
-               args->action = EXECUTE_COMMAND_DISPLAY_PROMPT;
+               mi_print_timing_maybe ();
+               fputs_unfiltered ("\n", raw_stdout);            
              }
            else
              mi_out_rewind (uiout);
@@ -1126,6 +1579,8 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
 
     }
 
+  do_cleanups (cleanup);
+
   return;
 }
 
@@ -1134,7 +1589,6 @@ void
 mi_execute_command (char *cmd, int from_tty)
 {
   struct mi_parse *command;
-  struct captured_mi_execute_command_args args;
   struct ui_out *saved_uiout = uiout;
 
   /* This is to handle EOF (^D). We just quit gdb.  */
@@ -1142,11 +1596,14 @@ mi_execute_command (char *cmd, int from_tty)
   if (cmd == 0)
     quit_force (NULL, from_tty);
 
+  target_log_command (cmd);
+
   command = mi_parse (cmd);
 
   if (command != NULL)
     {
       struct gdb_exception result;
+      ptid_t previous_ptid = inferior_ptid;
 
       if (do_timings)
        {
@@ -1155,8 +1612,7 @@ mi_execute_command (char *cmd, int from_tty)
          timestamp (command->cmd_start);
        }
 
-      args.command = command;
-      result = catch_exception (uiout, captured_mi_execute_command, &args,
+      result = catch_exception (uiout, captured_mi_execute_command, command,
                                RETURN_MASK_ALL);
       if (result.reason < 0)
        {
@@ -1172,12 +1628,46 @@ mi_execute_command (char *cmd, int from_tty)
          mi_out_rewind (uiout);
        }
 
-      mi_parse_free (command);
+      bpstat_do_actions ();
+
+      if (/* The notifications are only output when the top-level
+            interpreter (specified on the command line) is MI.  */      
+         ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ()))
+         /* Don't try report anything if there are no threads -- 
+            the program is dead.  */
+         && thread_count () != 0
+         /* -thread-select explicitly changes thread. If frontend uses that
+            internally, we don't want to emit =thread-selected, since
+            =thread-selected is supposed to indicate user's intentions.  */
+         && strcmp (command->command, "thread-select") != 0)
+       {
+         struct mi_interp *mi = top_level_interpreter_data ();
+         int report_change = 0;
 
-      if (args.action == EXECUTE_COMMAND_SUPPRESS_PROMPT)
-       /* The command is executing synchronously.  Bail out early
-          suppressing the finished prompt.  */
-       return;
+         if (command->thread == -1)
+           {
+             report_change = (!ptid_equal (previous_ptid, null_ptid)
+                              && !ptid_equal (inferior_ptid, previous_ptid)
+                              && !ptid_equal (inferior_ptid, null_ptid));
+           }
+         else if (!ptid_equal (inferior_ptid, null_ptid))
+           {
+             struct thread_info *ti = inferior_thread ();
+             report_change = (ti->num != command->thread);
+           }
+
+         if (report_change)
+           {     
+             struct thread_info *ti = inferior_thread ();
+             target_terminal_ours ();
+             fprintf_unfiltered (mi->event_channel, 
+                                 "thread-selected,id=\"%d\"",
+                                 ti->num);
+             gdb_flush (mi->event_channel);
+           }
+       }
+
+      mi_parse_free (command);
     }
 
   fputs_unfiltered ("(gdb) \n", raw_stdout);
@@ -1186,36 +1676,45 @@ mi_execute_command (char *cmd, int from_tty)
   /* ..... */
 }
 
-static enum mi_cmd_result
+static void
 mi_cmd_execute (struct mi_parse *parse)
 {
   struct cleanup *cleanup;
-  enum mi_cmd_result r;
-  free_all_values ();
+  int i;
 
-  if (parse->cmd->argv_func != NULL)
+  prepare_execute_command ();
+
+  cleanup = make_cleanup (null_cleanup, NULL);
+
+  if (parse->frame != -1 && parse->thread == -1)
+    error (_("Cannot specify --frame without --thread"));
+
+  if (parse->thread != -1)
     {
-      if (target_executing)
-       {
-         if (strcmp (parse->command, "exec-interrupt"))
-           {
-             struct ui_file *stb;
-             stb = mem_fileopen ();
+      struct thread_info *tp = find_thread_id (parse->thread);
+      if (!tp)
+       error (_("Invalid thread id: %d"), parse->thread);
 
-             fputs_unfiltered ("Cannot execute command ", stb);
-             fputstr_unfiltered (parse->command, '"', stb);
-             fputs_unfiltered (" while target running", stb);
+      if (is_exited (tp->ptid))
+       error (_("Thread id: %d has terminated"), parse->thread);
 
-             make_cleanup_ui_file_delete (stb);
-             error_stream (stb);
-           }
-       }
-      current_token = xstrdup (parse->token);
-      cleanup = make_cleanup (free_current_contents, &current_token);
-      r = parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
-      do_cleanups (cleanup);
-      return r;
+      switch_to_thread (tp->ptid);
+    }
+
+  if (parse->frame != -1)
+    {
+      struct frame_info *fid;
+      int frame = parse->frame;
+      fid = find_relative_frame (get_current_frame (), &frame);
+      if (frame == 0)
+       /* find_relative_frame was successful */
+       select_frame (fid);
+      else
+       error (_("Invalid frame id: %d"), frame);
     }
+
+  if (parse->cmd->argv_func != NULL)
+    parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
   else if (parse->cmd->cli.cmd != 0)
     {
       /* FIXME: DELETE THIS. */
@@ -1223,7 +1722,6 @@ mi_cmd_execute (struct mi_parse *parse)
       /* Must be a synchronous one.  */
       mi_execute_cli_command (parse->cmd->cli.cmd, parse->cmd->cli.args_p,
                              parse->args);
-      return MI_CMD_DONE;
     }
   else
     {
@@ -1238,10 +1736,8 @@ mi_cmd_execute (struct mi_parse *parse)
 
       make_cleanup_ui_file_delete (stb);
       error_stream (stb);
-
-      /* unreacheable */
-      return MI_CMD_DONE;
     }
+  do_cleanups (cleanup);
 }
 
 /* FIXME: This is just a hack so we can get some extra commands going.
@@ -1270,7 +1766,7 @@ mi_execute_cli_command (const char *cmd, int args_p, const char *args)
     }
 }
 
-enum mi_cmd_result
+void
 mi_execute_async_cli_command (char *cli_command, char **argv, int argc)
 {
   struct cleanup *old_cleanups;
@@ -1282,35 +1778,12 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc)
     run = xstrprintf ("%s %s", cli_command, argc ? *argv : "");
   old_cleanups = make_cleanup (xfree, run);  
 
-  if (!target_can_async_p ())
-    {
-      /* NOTE: For synchronous targets asynchronous behavour is faked by
-         printing out the GDB prompt before we even try to execute the
-         command.  */
-      if (current_token)
-       fputs_unfiltered (current_token, raw_stdout);
-      fputs_unfiltered ("^running\n", raw_stdout);
-      fputs_unfiltered ("(gdb) \n", raw_stdout);
-      gdb_flush (raw_stdout);
-    }
-  else
-    {
-      /* FIXME: cagney/1999-11-29: Printing this message before
-         calling execute_command is wrong.  It should only be printed
-         once gdb has confirmed that it really has managed to send a
-         run command to the target.  */
-      if (current_token)
-       fputs_unfiltered (current_token, raw_stdout);
-      fputs_unfiltered ("^running\n", raw_stdout);
-
-    }
-
   execute_command ( /*ui */ run, 0 /*from_tty */ );
 
   if (target_can_async_p ())
     {
       /* If we're not executing, an exception should have been throw.  */
-      gdb_assert (target_executing);
+      gdb_assert (is_running (inferior_ptid));
       do_cleanups (old_cleanups);
     }
   else
@@ -1318,11 +1791,7 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc)
       /* Do this before doing any printing.  It would appear that some
          print code leaves garbage around in the buffer.  */
       do_cleanups (old_cleanups);
-      if (do_timings)
-       print_diff_now (current_command_ts);
-      return MI_CMD_QUIET;
-    }    
-  return MI_CMD_DONE;
+    }
 }
 
 void
@@ -1440,6 +1909,15 @@ print_diff_now (struct mi_timestamp *start)
     print_diff (start, &now);
   }
 
+void
+mi_print_timing_maybe (void)
+{
+  /* If the command is -enable-timing then do_timings may be
+     true whilst current_command_ts is not initialized.  */
+  if (do_timings && current_command_ts)
+    print_diff_now (current_command_ts);
+}
+
 static long 
 timeval_diff (struct timeval start, struct timeval end)
   {
This page took 0.044531 seconds and 4 git commands to generate.