2007-05-31 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / mi / mi-main.c
index 1fa79ceadef2badfadbda10bb5bc4b210377ec00..ad7aae0c5a05c600df953e676f740584c9e810f7 100644 (file)
@@ -1,7 +1,7 @@
 /* MI Command Set.
 
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005 Free Software
-   Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
+   Free Software Foundation, Inc.
 
    Contributed by Cygnus Solutions (a Red Hat company).
 
 
    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.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
-/* Work in progress */
+/* Work in progress */
 
 #include "defs.h"
 #include "target.h"
@@ -40,8 +40,8 @@
 #include "interps.h"
 #include "event-loop.h"
 #include "event-top.h"
-#include "gdbcore.h"           /* for write_memory() */
-#include "value.h"             /* for deprecated_write_register_bytes() */
+#include "gdbcore.h"           /* For write_memory().  */
+#include "value.h"
 #include "regcache.h"
 #include "gdb.h"
 #include "frame.h"
 #include <ctype.h>
 #include <sys/time.h>
 
+#if defined HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_GETRUSAGE
+struct rusage rusage;
+#endif
+
 enum
   {
     FROM_TTY = 0
   };
 
 /* Enumerations of the actions that may result from calling
-   captured_mi_execute_command */
+   captured_mi_execute_command */
 
 enum captured_mi_execute_command_actions
   {
@@ -65,27 +73,32 @@ enum captured_mi_execute_command_actions
   };
 
 /* This structure is used to pass information from captured_mi_execute_command
-   to mi_execute_command. */
+   to mi_execute_command.  */
 struct captured_mi_execute_command_args
 {
-  /* This return result of the MI command (output) */
+  /* This return result of the MI command (output) */
   enum mi_cmd_result rc;
 
-  /* What action to perform when the call is finished (output) */
+  /* What action to perform when the call is finished (output) */
   enum captured_mi_execute_command_actions action;
 
-  /* The command context to be executed (input) */
+  /* The command context to be executed (input) */
   struct mi_parse *command;
 };
 
 int mi_debug_p;
 struct ui_file *raw_stdout;
 
-/* The token of the last asynchronous command */
+/* This is used to pass the current command timestamp
+   down to continuation routines.  */
+static struct mi_timestamp *current_command_ts;
+
+static int do_timings = 0;
+
+/* The token of the last asynchronous command.  */
 static char *last_async_command;
 static char *previous_async_command;
 char *mi_error_message;
-static char *old_regs;
 
 extern void _initialize_mi_main (void);
 static enum mi_cmd_result mi_cmd_execute (struct mi_parse *parse);
@@ -96,22 +109,28 @@ static enum mi_cmd_result mi_execute_async_cli_command (char *mi, char *args, in
 
 static void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg);
 
-static int register_changed_p (int regnum);
+static int register_changed_p (int regnum, struct regcache *,
+                              struct regcache *);
 static int get_register (int regnum, int format);
 
-/* Command implementations. FIXME: Is this libgdb? No.  This is the MI
+/* Command implementations.  FIXME: Is this libgdb?  No.  This is the MI
    layer that calls libgdb.  Any operation used in the below should be
-   formalized. */
+   formalized.  */
+
+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
 mi_cmd_gdb_exit (char *command, char **argv, int argc)
 {
-  /* We have to print everything right here because we never return */
+  /* We have to print everything right here because we never return */
   if (last_async_command)
     fputs_unfiltered (last_async_command, raw_stdout);
   fputs_unfiltered ("^exit\n", raw_stdout);
   mi_out_put (uiout, raw_stdout);
-  /* FIXME: The function called is not yet a formal libgdb function */
+  /* FIXME: The function called is not yet a formal libgdb function */
   quit_force (NULL, FROM_TTY);
   return MI_CMD_DONE;
 }
@@ -119,49 +138,49 @@ mi_cmd_gdb_exit (char *command, char **argv, int argc)
 enum mi_cmd_result
 mi_cmd_exec_run (char *args, int from_tty)
 {
-  /* FIXME: Should call a libgdb function, not a cli wrapper */
+  /* FIXME: Should call a libgdb function, not a cli wrapper */
   return mi_execute_async_cli_command ("run", args, from_tty);
 }
 
 enum mi_cmd_result
 mi_cmd_exec_next (char *args, int from_tty)
 {
-  /* FIXME: Should call a libgdb function, not a cli wrapper */
+  /* FIXME: Should call a libgdb function, not a cli wrapper */
   return mi_execute_async_cli_command ("next", args, from_tty);
 }
 
 enum mi_cmd_result
 mi_cmd_exec_next_instruction (char *args, int from_tty)
 {
-  /* FIXME: Should call a libgdb function, not a cli wrapper */
+  /* FIXME: Should call a libgdb function, not a cli wrapper */
   return mi_execute_async_cli_command ("nexti", args, from_tty);
 }
 
 enum mi_cmd_result
 mi_cmd_exec_step (char *args, int from_tty)
 {
-  /* FIXME: Should call a libgdb function, not a cli wrapper */
+  /* FIXME: Should call a libgdb function, not a cli wrapper */
   return mi_execute_async_cli_command ("step", args, from_tty);
 }
 
 enum mi_cmd_result
 mi_cmd_exec_step_instruction (char *args, int from_tty)
 {
-  /* FIXME: Should call a libgdb function, not a cli wrapper */
+  /* FIXME: Should call a libgdb function, not a cli wrapper */
   return mi_execute_async_cli_command ("stepi", args, from_tty);
 }
 
 enum mi_cmd_result
 mi_cmd_exec_finish (char *args, int from_tty)
 {
-  /* FIXME: Should call a libgdb function, not a cli wrapper */
+  /* FIXME: Should call a libgdb function, not a cli wrapper */
   return mi_execute_async_cli_command ("finish", args, from_tty);
 }
 
 enum mi_cmd_result
 mi_cmd_exec_until (char *args, int from_tty)
 {
-  /* FIXME: Should call a libgdb function, not a cli wrapper */
+  /* FIXME: Should call a libgdb function, not a cli wrapper */
   return mi_execute_async_cli_command ("until", args, from_tty);
 }
 
@@ -172,15 +191,15 @@ mi_cmd_exec_return (char *args, int from_tty)
      specified number of frames. */
   if (*args)
     /* Call return_command with from_tty argument equal to 0 so as to
-       avoid being queried. */
+       avoid being queried.  */
     return_command (args, 0);
   else
     /* Call return_command with from_tty argument equal to 0 so as to
-       avoid being queried. */
+       avoid being queried.  */
     return_command (NULL, 0);
 
   /* Because we have called return_command with from_tty = 0, we need
-     to print the frame here. */
+     to print the frame here.  */
   print_stack_frame (get_selected_frame (NULL), 1, LOC_AND_ADDRESS);
 
   return MI_CMD_DONE;
@@ -189,15 +208,15 @@ mi_cmd_exec_return (char *args, int from_tty)
 enum mi_cmd_result
 mi_cmd_exec_continue (char *args, int from_tty)
 {
-  /* FIXME: Should call a libgdb function, not a cli wrapper */
+  /* FIXME: Should call a libgdb function, not a cli wrapper */
   return mi_execute_async_cli_command ("continue", args, from_tty);
 }
 
-/* Interrupt the execution of the target. Note how we must play around
-   with the token varialbes, in order to display the current token in
+/* Interrupt the execution of the target.  Note how we must play around
+   with the token variables, in order to display the current token in
    the result of the interrupt command, and the previous execution
-   token when the target finally stops. See comments in
-   mi_cmd_execute. */
+   token when the target finally stops.  See comments in
+   mi_cmd_execute.  */
 enum mi_cmd_result
 mi_cmd_exec_interrupt (char *args, int from_tty)
 {
@@ -234,11 +253,7 @@ mi_cmd_thread_select (char *command, char **argv, int argc)
   else
     rc = gdb_thread_select (uiout, argv[0], &mi_error_message);
 
-  /* RC is enum gdb_rc if it is successful (>=0)
-     enum return_reason if not (<0). */
-  if ((int) rc < 0 && (enum return_reason) rc == RETURN_ERROR)
-    return MI_CMD_ERROR;
-  else if ((int) rc >= 0 && rc == GDB_RC_FAIL)
+  if (rc == GDB_RC_FAIL)
     return MI_CMD_ERROR;
   else
     return MI_CMD_DONE;
@@ -247,7 +262,7 @@ mi_cmd_thread_select (char *command, char **argv, int argc)
 enum mi_cmd_result
 mi_cmd_thread_list_ids (char *command, char **argv, int argc)
 {
-  enum gdb_rc rc = MI_CMD_DONE;
+  enum gdb_rc rc;
 
   if (argc != 0)
     {
@@ -271,16 +286,17 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc)
   struct cleanup *cleanup;
 
   /* Note that the test for a valid register must include checking the
-     REGISTER_NAME because NUM_REGS may be allocated for the union of
+     REGISTER_NAME because gdbarch_num_regs may be allocated for the union of
      the register sets within a family of related processors.  In this
      case, some entries of REGISTER_NAME will change depending upon
      the particular processor being debugged.  */
 
-  numregs = NUM_REGS + NUM_PSEUDO_REGS;
+  numregs = gdbarch_num_regs (current_gdbarch)
+           + gdbarch_num_pseudo_regs (current_gdbarch);
 
   cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-names");
 
-  if (argc == 0)               /* No args, just do all the regs */
+  if (argc == 0)               /* No args, just do all the regs */
     {
       for (regnum = 0;
           regnum < numregs;
@@ -294,7 +310,7 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc)
        }
     }
 
-  /* Else, list of register #s, just do listed regs */
+  /* Else, list of register #s, just do listed regs */
   for (i = 0; i < argc; i++)
     {
       regnum = atoi (argv[i]);
@@ -317,21 +333,32 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc)
 enum mi_cmd_result
 mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
 {
+  static struct regcache *this_regs = NULL;
+  struct regcache *prev_regs;
   int regnum, numregs, changed;
   int i;
   struct cleanup *cleanup;
 
+  /* The last time we visited this function, the current frame's register
+     contents were saved in THIS_REGS.  Move THIS_REGS over to PREV_REGS,
+     and refresh THIS_REGS with the now-current register contents.  */
+
+  prev_regs = this_regs;
+  this_regs = frame_save_as_regcache (get_selected_frame (NULL));
+  cleanup = make_cleanup_regcache_xfree (prev_regs);
+
   /* Note that the test for a valid register must include checking the
-     REGISTER_NAME because NUM_REGS may be allocated for the union of
+     REGISTER_NAME because gdbarch_num_regs may be allocated for the union of
      the register sets within a family of related processors.  In this
      case, some entries of REGISTER_NAME will change depending upon
      the particular processor being debugged.  */
 
-  numregs = NUM_REGS + NUM_PSEUDO_REGS;
+  numregs = gdbarch_num_regs (current_gdbarch)
+           + gdbarch_num_pseudo_regs (current_gdbarch);
 
-  cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changed-registers");
+  make_cleanup_ui_out_list_begin_end (uiout, "changed-registers");
 
-  if (argc == 0)               /* No args, just do all the regs */
+  if (argc == 0)               /* No args, just do all the regs */
     {
       for (regnum = 0;
           regnum < numregs;
@@ -340,7 +367,7 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
          if (REGISTER_NAME (regnum) == NULL
              || *(REGISTER_NAME (regnum)) == '\0')
            continue;
-         changed = register_changed_p (regnum);
+         changed = register_changed_p (regnum, prev_regs, this_regs);
          if (changed < 0)
            {
              do_cleanups (cleanup);
@@ -352,7 +379,7 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
        }
     }
 
-  /* Else, list of register #s, just do listed regs */
+  /* Else, list of register #s, just do listed regs */
   for (i = 0; i < argc; i++)
     {
       regnum = atoi (argv[i]);
@@ -362,7 +389,7 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
          && REGISTER_NAME (regnum) != NULL
          && *REGISTER_NAME (regnum) != '\000')
        {
-         changed = register_changed_p (regnum);
+         changed = register_changed_p (regnum, prev_regs, this_regs);
          if (changed < 0)
            {
              do_cleanups (cleanup);
@@ -384,32 +411,38 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc)
 }
 
 static int
-register_changed_p (int regnum)
+register_changed_p (int regnum, struct regcache *prev_regs,
+                   struct regcache *this_regs)
 {
-  gdb_byte raw_buffer[MAX_REGISTER_SIZE];
-
-  if (! frame_register_read (deprecated_selected_frame, regnum, raw_buffer))
-    return -1;
+  struct gdbarch *gdbarch = get_regcache_arch (this_regs);
+  gdb_byte prev_buffer[MAX_REGISTER_SIZE];
+  gdb_byte this_buffer[MAX_REGISTER_SIZE];
 
-  if (memcmp (&old_regs[DEPRECATED_REGISTER_BYTE (regnum)], raw_buffer,
-             register_size (current_gdbarch, regnum)) == 0)
+  /* Registers not valid in this frame return count as unchanged.  */
+  if (!regcache_valid_p (this_regs, regnum))
     return 0;
 
-  /* Found a changed register. Return 1. */
+  /* First time through or after gdbarch change consider all registers as
+     changed.  Same for registers not valid in the previous frame.  */
+  if (!prev_regs || get_regcache_arch (prev_regs) != gdbarch
+      || !regcache_valid_p (prev_regs, regnum))
+    return 1;
 
-  memcpy (&old_regs[DEPRECATED_REGISTER_BYTE (regnum)], raw_buffer,
-         register_size (current_gdbarch, regnum));
+  /* Get register contents and compare.  */
+  regcache_cooked_read (prev_regs, regnum, prev_buffer);
+  regcache_cooked_read (this_regs, regnum, this_buffer);
 
-  return 1;
+  return memcmp (prev_buffer, this_buffer,
+                register_size (gdbarch, regnum)) != 0;
 }
 
-/* Return a list of register number and value pairs. The valid
+/* Return a list of register number and value pairs.  The valid
    arguments expected are: a letter indicating the format in which to
-   display the registers contents. This can be one of: x (hexadecimal), d
+   display the registers contents.  This can be one of: x (hexadecimal), d
    (decimal), N (natural), t (binary), o (octal), r (raw).  After the
    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. */
+   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
 mi_cmd_data_list_register_values (char *command, char **argv, int argc)
 {
@@ -418,12 +451,13 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc)
   struct cleanup *list_cleanup, *tuple_cleanup;
 
   /* Note that the test for a valid register must include checking the
-     REGISTER_NAME because NUM_REGS may be allocated for the union of
+     REGISTER_NAME because gdbarch_num_regs may be allocated for the union of
      the register sets within a family of related processors.  In this
      case, some entries of REGISTER_NAME will change depending upon
      the particular processor being debugged.  */
 
-  numregs = NUM_REGS + NUM_PSEUDO_REGS;
+  numregs = gdbarch_num_regs (current_gdbarch)
+           + gdbarch_num_pseudo_regs (current_gdbarch);
 
   if (argc == 0)
     {
@@ -433,15 +467,9 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc)
 
   format = (int) argv[0][0];
 
-  if (!target_has_registers)
-    {
-      mi_error_message = xstrprintf ("mi_cmd_data_list_register_values: No registers.");
-      return MI_CMD_ERROR;
-    }
-
   list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-values");
 
-  if (argc == 1)               /* No args, beside the format: do all the regs */
+  if (argc == 1)           /* No args, beside the format: do all the regs.  */
     {
       for (regnum = 0;
           regnum < numregs;
@@ -462,7 +490,7 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc)
        }
     }
 
-  /* Else, list of register #s, just do listed regs */
+  /* Else, list of register #s, just do listed regs */
   for (i = 1; i < argc; i++)
     {
       regnum = atoi (argv[i]);
@@ -493,7 +521,7 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc)
   return MI_CMD_DONE;
 }
 
-/* Output one register's contents in the desired format. */
+/* Output one register's contents in the desired format.  */
 static int
 get_register (int regnum, int format)
 {
@@ -509,7 +537,7 @@ get_register (int regnum, int format)
   if (format == 'N')
     format = 0;
 
-  frame_register (deprecated_selected_frame, regnum, &optim, &lval, &addr,
+  frame_register (get_selected_frame (NULL), regnum, &optim, &lval, &addr,
                  &realnum, buffer);
 
   if (optim)
@@ -527,7 +555,7 @@ get_register (int regnum, int format)
       ptr = buf + 2;
       for (j = 0; j < register_size (current_gdbarch, regnum); j++)
        {
-         int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j
+         int idx = gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG ? j
          : register_size (current_gdbarch, regnum) - 1 - j;
          sprintf (ptr, "%02x", (unsigned char) buffer[idx]);
          ptr += 2;
@@ -546,24 +574,22 @@ get_register (int regnum, int format)
 }
 
 /* Write given values into registers. The registers and values are
-   given as pairs. The corresponding MI command is 
+   given as pairs.  The corresponding MI command is 
    -data-write-register-values <format> [<regnum1> <value1>...<regnumN> <valueN>]*/
 enum mi_cmd_result
 mi_cmd_data_write_register_values (char *command, char **argv, int argc)
 {
-  int regnum;
-  int i;
-  int numregs;
-  LONGEST value;
+  int numregs, i;
   char format;
 
   /* Note that the test for a valid register must include checking the
-     REGISTER_NAME because NUM_REGS may be allocated for the union of
+     REGISTER_NAME because gdbarch_num_regs may be allocated for the union of
      the register sets within a family of related processors.  In this
      case, some entries of REGISTER_NAME will change depending upon
      the particular processor being debugged.  */
 
-  numregs = NUM_REGS + NUM_PSEUDO_REGS;
+  numregs = gdbarch_num_regs (current_gdbarch)
+           + gdbarch_num_pseudo_regs (current_gdbarch);
 
   if (argc == 0)
     {
@@ -593,26 +619,18 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc)
 
   for (i = 1; i < argc; i = i + 2)
     {
-      regnum = atoi (argv[i]);
+      int regnum = atoi (argv[i]);
 
-      if (regnum >= 0
-         && regnum < numregs
-         && REGISTER_NAME (regnum) != NULL
-         && *REGISTER_NAME (regnum) != '\000')
+      if (regnum >= 0 && regnum < numregs
+         && REGISTER_NAME (regnum) && *REGISTER_NAME (regnum))
        {
-         void *buffer;
-         struct cleanup *old_chain;
+         LONGEST value;
 
-         /* Get the value as a number */
+         /* Get the value as a number */
          value = parse_and_eval_address (argv[i + 1]);
-         /* Get the value into an array */
-         buffer = xmalloc (DEPRECATED_REGISTER_SIZE);
-         old_chain = make_cleanup (xfree, buffer);
-         store_signed_integer (buffer, DEPRECATED_REGISTER_SIZE, value);
-         /* Write it down */
-         deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (regnum), buffer, register_size (current_gdbarch, regnum));
-         /* Free the buffer.  */
-         do_cleanups (old_chain);
+
+         /* Write it down.  */
+         regcache_cooked_write_signed (current_regcache, regnum, value);
        }
       else
        {
@@ -624,12 +642,12 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc)
 }
 
 #if 0
-/*This is commented out because we decided it was not useful. I leave
-   it, just in case. ezannoni:1999-12-08 */
+/* This is commented out because we decided it was not useful.  I leave
+   it, just in case.  ezannoni:1999-12-08 */
 
-/* Assign a value to a variable. The expression argument must be in
-   the form A=2 or "A = 2" (I.e. if there are spaces it needs to be
-   quoted. */
+/* Assign a value to a variable.  The expression argument must be in
+   the form A=2 or "A = 2" i.e. if there are spaces it needs to be
+   quoted.  */
 enum mi_cmd_result
 mi_cmd_data_assign (char *command, char **argv, int argc)
 {
@@ -642,8 +660,8 @@ mi_cmd_data_assign (char *command, char **argv, int argc)
       return MI_CMD_ERROR;
     }
 
-  /* NOTE what follows is a clone of set_command(). FIXME: ezannoni
-     01-12-1999: Need to decide what to do with this for libgdb purposes. */
+  /* NOTE what follows is a clone of set_command().  FIXME: ezannoni
+     01-12-1999: Need to decide what to do with this for libgdb purposes.  */
 
   expr = parse_expression (argv[0]);
   old_chain = make_cleanup (free_current_contents, &expr);
@@ -653,9 +671,9 @@ mi_cmd_data_assign (char *command, char **argv, int argc)
 }
 #endif
 
-/* Evaluate the value of the argument. The argument is an
+/* Evaluate the value of the argument.  The argument is an
    expression. If the expression contains spaces it needs to be
-   included in double quotes. */
+   included in double quotes.  */
 enum mi_cmd_result
 mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
 {
@@ -678,7 +696,7 @@ mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
 
   val = evaluate_expression (expr);
 
-  /* Print the result of the expression evaluation. */
+  /* Print the result of the expression evaluation.  */
   val_print (value_type (val), value_contents (val),
             value_embedded_offset (val), VALUE_ADDRESS (val),
             stb->stream, 0, 0, 0, 0);
@@ -705,7 +723,7 @@ mi_cmd_target_download (char *args, int from_tty)
   return MI_CMD_DONE;
 }
 
-/* Connect to the remote target. */
+/* Connect to the remote target.  */
 enum mi_cmd_result
 mi_cmd_target_select (char *args, int from_tty)
 {
@@ -715,16 +733,16 @@ mi_cmd_target_select (char *args, int from_tty)
   run = xstrprintf ("target %s", args);
   old_cleanups = make_cleanup (xfree, run);
 
-  /* target-select is always synchronous.  once the call has returned
-     we know that we are connected. */
+  /* 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. */
+     change.  */
   execute_command (run, from_tty);
 
   do_cleanups (old_cleanups);
 
-  /* Issue the completion message here. */
+  /* Issue the completion message here.  */
   if (last_async_command)
     fputs_unfiltered (last_async_command, raw_stdout);
   fputs_unfiltered ("^connected", raw_stdout);
@@ -738,9 +756,9 @@ mi_cmd_target_select (char *args, int from_tty)
 /* DATA-MEMORY-READ:
 
    ADDR: start address of data to be dumped.
-   WORD-FORMAT: a char indicating format for the ``word''. See 
+   WORD-FORMAT: a char indicating format for the ``word''.  See 
    the ``x'' command.
-   WORD-SIZE: size of each ``word''; 1,2,4, or 8 bytes
+   WORD-SIZE: size of each ``word''; 1,2,4, or 8 bytes.
    NR_ROW: Number of rows.
    NR_COL: The number of colums (words per row).
    ASCHAR: (OPTIONAL) Append an ascii character dump to each row.  Use
@@ -767,7 +785,7 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
   long word_size;
   char word_asize;
   char aschar;
-  char *mbuf;
+  gdb_byte *mbuf;
   int nr_bytes;
   long offset = 0;
   int optind = 0;
@@ -779,7 +797,7 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
   static struct mi_opt opts[] =
   {
     {"o", OFFSET_OPT, 1},
-    0
+    { 0, 0, 0 }
   };
 
   while (1)
@@ -806,12 +824,12 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
 
   /* Extract all the arguments. */
 
-  /* Start address of the memory dump. */
+  /* Start address of the memory dump.  */
   addr = parse_and_eval_address (argv[0]) + offset;
-  /* The format character to use when displaying a memory word. See
+  /* The format character to use when displaying a memory word.  See
      the ``x'' command. */
   word_format = argv[1][0];
-  /* The size of the memory word. */
+  /* The size of the memory word.  */
   word_size = atol (argv[2]);
   switch (word_size)
     {
@@ -835,43 +853,41 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
       word_type = builtin_type_int8;
       word_asize = 'b';
     }
-  /* The number of rows */
+  /* The number of rows */
   nr_rows = atol (argv[3]);
   if (nr_rows <= 0)
     {
       mi_error_message = xstrprintf ("mi_cmd_data_read_memory: invalid number of rows.");
       return MI_CMD_ERROR;
     }
-  /* number of bytes per row. */
+  /* Number of bytes per row.  */
   nr_cols = atol (argv[4]);
   if (nr_cols <= 0)
     {
       mi_error_message = xstrprintf ("mi_cmd_data_read_memory: invalid number of columns.");
       return MI_CMD_ERROR;
     }
-  /* The un-printable character when printing ascii. */
+  /* The un-printable character when printing ascii.  */
   if (argc == 6)
     aschar = *argv[5];
   else
     aschar = 0;
 
-  /* create a buffer and read it in. */
+  /* Create a buffer and read it in.  */
   total_bytes = word_size * nr_rows * nr_cols;
   mbuf = xcalloc (total_bytes, 1);
   make_cleanup (xfree, mbuf);
-  nr_bytes = 0;
-  while (nr_bytes < total_bytes)
+
+  nr_bytes = target_read (&current_target, TARGET_OBJECT_MEMORY, NULL,
+                         mbuf, addr, total_bytes);
+  if (nr_bytes <= 0)
     {
-      int error;
-      long num = target_read_memory_partial (addr + nr_bytes, mbuf + nr_bytes,
-                                            total_bytes - nr_bytes,
-                                            &error);
-      if (num <= 0)
-       break;
-      nr_bytes += num;
+      do_cleanups (cleanups);
+      mi_error_message = xstrdup ("Unable to read memory.");
+      return MI_CMD_ERROR;
     }
 
-  /* output the header information. */
+  /* Output the header information.  */
   ui_out_field_core_addr (uiout, "addr", addr);
   ui_out_field_int (uiout, "nr-bytes", nr_bytes);
   ui_out_field_int (uiout, "total-bytes", total_bytes);
@@ -880,7 +896,7 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
   ui_out_field_core_addr (uiout, "next-page", addr + total_bytes);
   ui_out_field_core_addr (uiout, "prev-page", addr - total_bytes);
 
-  /* Build the result as a two dimentional table. */
+  /* Build the result as a two dimentional table.  */
   {
     struct ui_stream *stream = ui_out_stream_new (uiout);
     struct cleanup *cleanup_list_memory;
@@ -950,16 +966,16 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
    offset from the beginning of the memory grid row where the cell to
    be written is.
    ADDR: start address of the row in the memory grid where the memory
-   cell is, if OFFSET_COLUMN is specified. Otherwise, the address of
+   cell is, if OFFSET_COLUMN is specified.  Otherwise, the address of
    the location to write to.
-   FORMAT: a char indicating format for the ``word''. See 
+   FORMAT: a char indicating format for the ``word''.  See 
    the ``x'' command.
    WORD_SIZE: size of each ``word''; 1,2,4, or 8 bytes
    VALUE: value to be written into the memory address.
 
    Writes VALUE into ADDR + (COLUMN_OFFSET * WORD_SIZE).
 
-   Prints nothing. */
+   Prints nothing.  */
 enum mi_cmd_result
 mi_cmd_data_write_memory (char *command, char **argv, int argc)
 {
@@ -967,7 +983,7 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc)
   char word_format;
   long word_size;
   /* FIXME: ezannoni 2000-02-17 LONGEST could possibly not be big
-     enough when using a compiler other than GCC. */
+     enough when using a compiler other than GCC.  */
   LONGEST value;
   void *buffer;
   struct cleanup *old_chain;
@@ -981,7 +997,7 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc)
   static struct mi_opt opts[] =
   {
     {"o", OFFSET_OPT, 1},
-    0
+    { 0, 0, 0 }
   };
 
   while (1)
@@ -1006,25 +1022,25 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc)
       return MI_CMD_ERROR;
     }
 
-  /* Extract all the arguments. */
-  /* Start address of the memory dump. */
+  /* Extract all the arguments.  */
+  /* Start address of the memory dump.  */
   addr = parse_and_eval_address (argv[0]);
-  /* The format character to use when displaying a memory word. See
-     the ``x'' command. */
+  /* The format character to use when displaying a memory word.  See
+     the ``x'' command.  */
   word_format = argv[1][0];
   /* The size of the memory word. */
   word_size = atol (argv[2]);
 
-  /* Calculate the real address of the write destination. */
+  /* Calculate the real address of the write destination.  */
   addr += (offset * word_size);
 
-  /* Get the value as a number */
+  /* Get the value as a number */
   value = parse_and_eval_address (argv[3]);
-  /* Get the value into an array */
+  /* Get the value into an array */
   buffer = xmalloc (word_size);
   old_chain = make_cleanup (xfree, buffer);
   store_signed_integer (buffer, word_size, value);
-  /* Write it down to memory */
+  /* Write it down to memory */
   write_memory (addr, buffer, word_size);
   /* Free the buffer.  */
   do_cleanups (old_chain);
@@ -1032,6 +1048,30 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc)
   return MI_CMD_DONE;
 }
 
+enum mi_cmd_result
+mi_cmd_enable_timings (char *command, char **argv, int argc)
+{
+  if (argc == 0)
+    do_timings = 1;
+  else if (argc == 1)
+    {
+      if (strcmp (argv[0], "yes") == 0)
+       do_timings = 1;
+      else if (strcmp (argv[0], "no") == 0)
+       do_timings = 0;
+      else
+       goto usage_error;
+    }
+  else
+    goto usage_error;
+    
+  return MI_CMD_DONE;
+
+ usage_error:
+  error ("mi_cmd_enable_timings: Usage: %s {yes|no}", command);
+  return MI_CMD_ERROR;
+}
+
 /* Execute a command within a safe environment.
    Return <0 for error; >=0 for ok.
 
@@ -1046,11 +1086,13 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
     (struct captured_mi_execute_command_args *) data;
   struct mi_parse *context = args->command;
 
+  struct mi_timestamp cmd_finished;
+
   switch (context->op)
     {
 
     case MI_COMMAND:
-      /* A MI command was read from the input stream */
+      /* 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",
@@ -1058,13 +1100,20 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
       /* 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. */
+         that.  */
       args->action = EXECUTE_COMMAND_DISPLAY_PROMPT;
+
+      if (do_timings)
+       current_command_ts = context->cmd_start;
+
       args->rc = mi_cmd_execute (context);
 
+      if (do_timings)
+          timestamp (&cmd_finished);
+
       if (!target_can_async_p () || !target_executing)
        {
-         /* print the result if there were no errors
+         /* 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 
@@ -1076,6 +1125,10 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
              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 if (args->rc == MI_CMD_ERROR)
@@ -1096,7 +1149,7 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
       else if (sync_execution)
        {
          /* Don't print the prompt. We are executing the target in
-            synchronous mode. */
+            synchronous mode.  */
          args->action = EXECUTE_COMMAND_SUPRESS_PROMPT;
          return;
        }
@@ -1113,23 +1166,37 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
        /* Call the "console" interpreter.  */
        argv[0] = "console";
        argv[1] = context->command;
-       mi_cmd_interpreter_exec ("-interpreter-exec", argv, 2);
+       args->rc = mi_cmd_interpreter_exec ("-interpreter-exec", argv, 2);
 
-       /* If we changed interpreters, DON'T print out anything. */
+       /* If we changed interpreters, DON'T print out anything.  */
        if (current_interp_named_p (INTERP_MI)
            || current_interp_named_p (INTERP_MI1)
            || current_interp_named_p (INTERP_MI2)
            || current_interp_named_p (INTERP_MI3))
          {
-           /* print the result */
-           /* FIXME: Check for errors here. */
-           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;
-           args->rc = MI_CMD_DONE;
+           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);
+               fputs_unfiltered ("\n", raw_stdout);
+               args->action = EXECUTE_COMMAND_DISPLAY_PROMPT;
+             }
+           else if (args->rc == MI_CMD_ERROR)
+             {
+               if (mi_error_message)
+                 {
+                   fputs_unfiltered (context->token, raw_stdout);
+                   fputs_unfiltered ("^error,msg=\"", raw_stdout);
+                   fputstr_unfiltered (mi_error_message, '"', raw_stdout);
+                   xfree (mi_error_message);
+                   fputs_unfiltered ("\"\n", raw_stdout);
+                 }
+               mi_out_rewind (uiout);
+             }
+           else
+             mi_out_rewind (uiout);
          }
        break;
       }
@@ -1147,8 +1214,8 @@ mi_execute_command (char *cmd, int from_tty)
   struct captured_mi_execute_command_args args;
   struct ui_out *saved_uiout = uiout;
 
-  /* This is to handle EOF (^D). We just quit gdb. */
-  /* FIXME: we should call some API function here. */
+  /* This is to handle EOF (^D). We just quit gdb.  */
+  /* FIXME: we should call some API function here.  */
   if (cmd == 0)
     quit_force (NULL, from_tty);
 
@@ -1157,8 +1224,16 @@ mi_execute_command (char *cmd, int from_tty)
   if (command != NULL)
     {
       struct gdb_exception result;
+
+      if (do_timings)
+       {
+         command->cmd_start = (struct mi_timestamp *)
+           xmalloc (sizeof (struct mi_timestamp));
+         timestamp (command->cmd_start);
+       }
+
       /* FIXME: cagney/1999-11-04: Can this use of catch_exceptions either
-         be pushed even further down or even eliminated? */
+         be pushed even further down or even eliminated?  */
       args.command = command;
       result = catch_exception (uiout, captured_mi_execute_command, &args,
                                RETURN_MASK_ALL);
@@ -1167,48 +1242,54 @@ mi_execute_command (char *cmd, int from_tty)
       if (args.action == EXECUTE_COMMAND_SUPRESS_PROMPT)
        {
          /* The command is executing synchronously.  Bail out early
-            suppressing the finished prompt. */
+            suppressing the finished prompt.  */
          mi_parse_free (command);
          return;
        }
       if (result.reason < 0)
        {
          /* The command execution failed and error() was called
-            somewhere */
+            somewhere */
          fputs_unfiltered (command->token, raw_stdout);
          fputs_unfiltered ("^error,msg=\"", raw_stdout);
-         fputstr_unfiltered (result.message, '"', raw_stdout);
+         if (result.message == NULL)
+           fputs_unfiltered ("unknown error", raw_stdout);
+         else
+             fputstr_unfiltered (result.message, '"', raw_stdout);
          fputs_unfiltered ("\"\n", raw_stdout);
+         mi_out_rewind (uiout);
        }
       mi_parse_free (command);
     }
 
   fputs_unfiltered ("(gdb) \n", raw_stdout);
   gdb_flush (raw_stdout);
-  /* print any buffered hook code */
+  /* Print any buffered hook code.  */
   /* ..... */
 }
 
 static enum mi_cmd_result
 mi_cmd_execute (struct mi_parse *parse)
 {
+  free_all_values ();
+
   if (parse->cmd->argv_func != NULL
       || parse->cmd->args_func != NULL)
     {
       /* FIXME: We need to save the token because the command executed
          may be asynchronous and need to print the token again.
          In the future we can pass the token down to the func
-         and get rid of the last_async_command */
+         and get rid of the last_async_command */
       /* The problem here is to keep the token around when we launch
          the target, and we want to interrupt it later on.  The
          interrupt command will have its own token, but when the
          target stops, we must display the token corresponding to the
-         last execution command given. So we have another string where
+         last execution command given.  So we have another string where
          we copy the token (previous_async_command), if this was
          indeed the token of an execution command, and when we stop we
-         print that one. This is possible because the interrupt
+         print that one.  This is possible because the interrupt
          command, when over, will copy that token back into the
-         default token string (last_async_command). */
+         default token string (last_async_command).  */
 
       if (target_executing)
        {
@@ -1235,15 +1316,15 @@ mi_cmd_execute (struct mi_parse *parse)
   else if (parse->cmd->cli.cmd != 0)
     {
       /* FIXME: DELETE THIS. */
-      /* The operation is still implemented by a cli command */
-      /* Must be a synchronous one */
+      /* The operation is still implemented by a cli command */
+      /* 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
     {
-      /* FIXME: DELETE THIS. */
+      /* FIXME: DELETE THIS.  */
       fputs_unfiltered (parse->token, raw_stdout);
       fputs_unfiltered ("^error,msg=\"", raw_stdout);
       fputs_unfiltered ("Undefined mi command: ", raw_stdout);
@@ -1255,8 +1336,8 @@ mi_cmd_execute (struct mi_parse *parse)
 }
 
 /* FIXME: This is just a hack so we can get some extra commands going.
-   We don't want to channel things through the CLI, but call libgdb directly */
-/* Use only for synchronous commands */
+   We don't want to channel things through the CLI, but call libgdb directly.
+   Use only for synchronous commands.  */
 
 void
 mi_execute_cli_command (const char *cmd, int args_p, const char *args)
@@ -1308,7 +1389,7 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
     {
       /* NOTE: For synchronous targets asynchronous behavour is faked by
          printing out the GDB prompt before we even try to execute the
-         command. */
+         command.  */
       if (last_async_command)
        fputs_unfiltered (last_async_command, raw_stdout);
       fputs_unfiltered ("^running\n", raw_stdout);
@@ -1320,7 +1401,7 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
       /* 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. */
+         run command to the target.  */
       if (last_async_command)
        fputs_unfiltered (last_async_command, raw_stdout);
       fputs_unfiltered ("^running\n", raw_stdout);
@@ -1331,15 +1412,17 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
   if (!target_can_async_p ())
     {
       /* Do this before doing any printing.  It would appear that some
-         print code leaves garbage around in the buffer. */
+         print code leaves garbage around in the buffer.  */
       do_cleanups (old_cleanups);
       /* If the target was doing the operation synchronously we fake
-         the stopped message. */
+         the stopped message.  */
       if (last_async_command)
        fputs_unfiltered (last_async_command, raw_stdout);
       fputs_unfiltered ("*stopped", raw_stdout);
       mi_out_put (uiout, raw_stdout);
       mi_out_rewind (uiout);
+      if (do_timings)
+       print_diff_now (current_command_ts);
       fputs_unfiltered ("\n", raw_stdout);
       return MI_CMD_QUIET;
     }
@@ -1370,9 +1453,18 @@ mi_load_progress (const char *section_name,
   static struct timeval last_update;
   static char *previous_sect_name = NULL;
   int new_section;
+  struct ui_out *saved_uiout;
+
+  /* This function is called through deprecated_show_load_progress
+     which means uiout may not be correct.  Fix it for the duration
+     of this function.  */
+  saved_uiout = uiout;
 
-  if (!current_interp_named_p (INTERP_MI)
-      && !current_interp_named_p (INTERP_MI1))
+  if (current_interp_named_p (INTERP_MI))
+    uiout = mi_out_new (2);
+  else if (current_interp_named_p (INTERP_MI1))
+    uiout = mi_out_new (1);
+  else
     return;
 
   update_threshold.tv_sec = 0;
@@ -1385,7 +1477,7 @@ mi_load_progress (const char *section_name,
   if (delta.tv_usec < 0)
     {
       delta.tv_sec -= 1;
-      delta.tv_usec += 1000000;
+      delta.tv_usec += 1000000L;
     }
 
   new_section = (previous_sect_name ?
@@ -1429,18 +1521,53 @@ mi_load_progress (const char *section_name,
       fputs_unfiltered ("\n", raw_stdout);
       gdb_flush (raw_stdout);
     }
-}
 
-void
-mi_setup_architecture_data (void)
-{
-  old_regs = xmalloc ((NUM_REGS + NUM_PSEUDO_REGS) * MAX_REGISTER_SIZE + 1);
-  memset (old_regs, 0, (NUM_REGS + NUM_PSEUDO_REGS) * MAX_REGISTER_SIZE + 1);
+  xfree (uiout);
+  uiout = saved_uiout;
 }
 
-void
-_initialize_mi_main (void)
-{
-  DEPRECATED_REGISTER_GDBARCH_SWAP (old_regs);
-  deprecated_register_gdbarch_swap (NULL, 0, mi_setup_architecture_data);
-}
+static void 
+timestamp (struct mi_timestamp *tv)
+  {
+    long usec;
+    gettimeofday (&tv->wallclock, NULL);
+#ifdef HAVE_GETRUSAGE
+    getrusage (RUSAGE_SELF, &rusage);
+    tv->utime.tv_sec = rusage.ru_utime.tv_sec;
+    tv->utime.tv_usec = rusage.ru_utime.tv_usec;
+    tv->stime.tv_sec = rusage.ru_stime.tv_sec;
+    tv->stime.tv_usec = rusage.ru_stime.tv_usec;
+#else
+    usec = get_run_time ();
+    tv->utime.tv_sec = usec/1000000L;
+    tv->utime.tv_usec = usec - 1000000L*tv->utime.tv_sec;
+    tv->stime.tv_sec = 0;
+    tv->stime.tv_usec = 0;
+#endif
+  }
+
+static void 
+print_diff_now (struct mi_timestamp *start)
+  {
+    struct mi_timestamp now;
+    timestamp (&now);
+    print_diff (start, &now);
+  }
+
+static long 
+timeval_diff (struct timeval start, struct timeval end)
+  {
+    return ((end.tv_sec - start.tv_sec) * 1000000L)
+      + (end.tv_usec - start.tv_usec);
+  }
+
+static void 
+print_diff (struct mi_timestamp *start, struct mi_timestamp *end)
+  {
+    fprintf_unfiltered
+      (raw_stdout,
+       ",time={wallclock=\"%0.5f\",user=\"%0.5f\",system=\"%0.5f\"}", 
+       timeval_diff (start->wallclock, end->wallclock) / 1000000.0, 
+       timeval_diff (start->utime, end->utime) / 1000000.0, 
+       timeval_diff (start->stime, end->stime) / 1000000.0);
+  }
This page took 0.045654 seconds and 4 git commands to generate.