Re: [PATCH] MI: new timing command

Nick Roberts
2007-01-03T21:50:22Z

> I don't even understand why we're having this conversation. Please
> follow the coding standard unless you have a good justification not to;
> that's why we call it the standard. Thanks.

Sure, I didn't say that I wouldn't do it. I'm just waiting for Eli to tell
me if it works with get_run_time. Meanwhile here's a revised version of
mi-main.c. I've even made line breaks before, instead of after, operators!

--
Nick http://www.inet.net.nz/~nickrob

*** mi-main.c 02 Jan 2007 10:53:22 +1300 1.87
--- mi-main.c 04 Jan 2007 10:40:53 +1300
***************
*** 22,28 ****
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */

! /* Work in progress */

#include "defs.h"
#include "target.h"
--- 22,28 ----
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */

! /* Work in progress. */

#include "defs.h"
#include "target.h"
***************
*** 40,47 ****
#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 "regcache.h"
#include "gdb.h"
#include "frame.h"
--- 40,47 ----
#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 "regcache.h"
#include "gdb.h"
#include "frame.h"
***************
*** 50,62 ****
#include <ctype.h>
#include <sys/time.h>

enum
{
FROM_TTY = 0
};

/* Enumerations of the actions that may result from calling
! captured_mi_execute_command */

enum captured_mi_execute_command_actions
{
--- 50,66 ----
#include <ctype.h>
#include <sys/time.h>

+ #if defined HAVE_SYS_RESOURCE_H
+ #include <sys/resource.h>
+ #endif
+
enum
{
FROM_TTY = 0
};

/* Enumerations of the actions that may result from calling
! captured_mi_execute_command. */

enum captured_mi_execute_command_actions
{
*************** enum captured_mi_execute_command_actions
*** 65,87 ****
};

/* 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;

! /* The token of the last asynchronous command */
static char *last_async_command;
static char *previous_async_command;
char *mi_error_message;
--- 69,97 ----
};

/* 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;

! /* 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 void mi_exec_async_cli_cmd_contin
*** 99,117 ****
static int register_changed_p (int regnum);
static int get_register (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
! formalized. */

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 */
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 */
quit_force (NULL, FROM_TTY);
return MI_CMD_DONE;
}
--- 109,132 ----
static int register_changed_p (int regnum);
static int get_register (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
! 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. */
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. */
quit_force (NULL, FROM_TTY);
return MI_CMD_DONE;
}
*************** mi_cmd_gdb_exit (char *command, char **a
*** 119,167 ****
enum mi_cmd_result
mi_cmd_exec_run (char *args, int from_tty)
{
! /* 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 */
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 */
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 */
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 */
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 */
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 */
return mi_execute_async_cli_command ("until", args, from_tty);
}

--- 134,182 ----
enum mi_cmd_result
mi_cmd_exec_run (char *args, int from_tty)
{
! /* 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. */
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. */
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. */
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. */
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. */
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. */
return mi_execute_async_cli_command ("until", args, from_tty);
}

*************** mi_cmd_exec_return (char *args, int from
*** 172,186 ****
specified number of frames. */
if (*args)
/* Call return_command with from_tty argument equal to 0 so as to
! avoid being queried. */
return_command (args, 0);
else
/* Call return_command with from_tty argument equal to 0 so as to
! avoid being queried. */
return_command (NULL, 0);

/* 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);

return MI_CMD_DONE;
--- 187,201 ----
specified number of frames. */
if (*args)
/* Call return_command with from_tty argument equal to 0 so as to
! avoid being queried. */
return_command (args, 0);
else
/* Call return_command with from_tty argument equal to 0 so as to
! avoid being queried. */
return_command (NULL, 0);

/* 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);

return MI_CMD_DONE;
*************** mi_cmd_exec_return (char *args, int from
*** 189,203 ****
enum mi_cmd_result
mi_cmd_exec_continue (char *args, int from_tty)
{
! /* 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
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
mi_cmd_exec_interrupt (char *args, int from_tty)
{
--- 204,218 ----
enum mi_cmd_result
mi_cmd_exec_continue (char *args, int from_tty)
{
! /* 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 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. */
enum mi_cmd_result
mi_cmd_exec_interrupt (char *args, int from_tty)
{
*************** mi_cmd_thread_select (char *command, cha
*** 235,241 ****
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)
--- 250,256 ----
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)
*************** mi_cmd_data_list_register_names (char *c
*** 280,286 ****

cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-names");

! if (argc == 0) /* No args, just do all the regs */
{
for (regnum = 0;
regnum < numregs;
--- 295,301 ----

cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-names");

! if (argc == 0) /* No args, just do all the regs. */
{
for (regnum = 0;
regnum < numregs;
*************** mi_cmd_data_list_register_names (char *c
*** 294,300 ****
}
}

! /* Else, list of register #s, just do listed regs */
for (i = 0; i < argc; i++)
{
regnum = atoi (argv[i]);
--- 309,315 ----
}
}

! /* Else, list of register #s, just do listed regs. */
for (i = 0; i < argc; i++)
{
regnum = atoi (argv[i]);
*************** mi_cmd_data_list_changed_registers (char
*** 331,337 ****

cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changed-registers");

! if (argc == 0) /* No args, just do all the regs */
{
for (regnum = 0;
regnum < numregs;
--- 346,352 ----

cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changed-registers");

! if (argc == 0) /* No args, just do all the regs. */
{
for (regnum = 0;
regnum < numregs;
*************** mi_cmd_data_list_changed_registers (char
*** 352,358 ****
}
}

! /* Else, list of register #s, just do listed regs */
for (i = 0; i < argc; i++)
{
regnum = atoi (argv[i]);
--- 367,373 ----
}
}

! /* Else, list of register #s, just do listed regs. */
for (i = 0; i < argc; i++)
{
regnum = atoi (argv[i]);
*************** register_changed_p (int regnum)
*** 395,401 ****
register_size (current_gdbarch, regnum)) == 0)
return 0;

! /* Found a changed register. Return 1. */

memcpy (&old_regs[DEPRECATED_REGISTER_BYTE (regnum)], raw_buffer,
register_size (current_gdbarch, regnum));
--- 410,416 ----
register_size (current_gdbarch, regnum)) == 0)
return 0;

! /* Found a changed register. Return 1. */

memcpy (&old_regs[DEPRECATED_REGISTER_BYTE (regnum)], raw_buffer,
register_size (current_gdbarch, regnum));
*************** register_changed_p (int regnum)
*** 403,415 ****
return 1;
}

! /* 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
(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. */
enum mi_cmd_result
mi_cmd_data_list_register_values (char *command, char **argv, int argc)
{
--- 418,430 ----
return 1;
}

! /* 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
(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. */
enum mi_cmd_result
mi_cmd_data_list_register_values (char *command, char **argv, int argc)
{
*************** mi_cmd_data_list_register_values (char *
*** 435,441 ****

list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-values");

! if (argc == 1) /* No args, beside the format: do all the regs */
{
for (regnum = 0;
regnum < numregs;
--- 450,456 ----

list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-values");

! if (argc == 1) /* No args, beside the format: do all the regs. */
{
for (regnum = 0;
regnum < numregs;
*************** mi_cmd_data_list_register_values (char *
*** 456,462 ****
}
}

! /* Else, list of register #s, just do listed regs */
for (i = 1; i < argc; i++)
{
regnum = atoi (argv[i]);
--- 471,477 ----
}
}

! /* Else, list of register #s, just do listed regs. */
for (i = 1; i < argc; i++)
{
regnum = atoi (argv[i]);
*************** mi_cmd_data_list_register_values (char *
*** 487,493 ****
return MI_CMD_DONE;
}

! /* Output one register's contents in the desired format. */
static int
get_register (int regnum, int format)
{
--- 502,508 ----
return MI_CMD_DONE;
}

! /* Output one register's contents in the desired format. */
static int
get_register (int regnum, int format)
{
*************** get_register (int regnum, int format)
*** 539,546 ****
return 1;
}

! /* 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
mi_cmd_data_write_register_values (char *command, char **argv, int argc)
--- 554,561 ----
return 1;
}

! /* Write given values into registers. T he 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
mi_cmd_data_write_register_values (char *command, char **argv, int argc)
*************** mi_cmd_data_write_register_values (char
*** 564,575 ****

format = (int) argv[0][0];

- if (!target_has_registers)
- {
- mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: No registers.");
- return MI_CMD_ERROR;
- }
-
if (!(argc - 1))
{
mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: No regs and values specified.");
--- 579,584 ----
*************** mi_cmd_data_write_register_values (char
*** 594,600 ****
/* Get the value as a number. */
value = parse_and_eval_address (argv[i + 1]);

! /* Write it down */
regcache_cooked_write_signed (current_regcache, regnum, value);
}
else
--- 603,609 ----
/* Get the value as a number. */
value = parse_and_eval_address (argv[i + 1]);

! /* Write it down. */
regcache_cooked_write_signed (current_regcache, regnum, value);
}
else
*************** mi_cmd_data_write_register_values (char
*** 607,618 ****
}

#if 0
! /*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. */
enum mi_cmd_result
mi_cmd_data_assign (char *command, char **argv, int argc)
{
--- 616,627 ----
}

#if 0
! /* 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. */
enum mi_cmd_result
mi_cmd_data_assign (char *command, char **argv, int argc)
{
*************** mi_cmd_data_assign (char *command, char
*** 625,632 ****
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. */

expr = parse_expression (argv[0]);
old_chain = make_cleanup (free_current_contents, &expr);
--- 634,641 ----
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. */

expr = parse_expression (argv[0]);
old_chain = make_cleanup (free_current_contents, &expr);
*************** mi_cmd_data_assign (char *command, char
*** 636,644 ****
}
#endif

! /* 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
mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
{
--- 645,653 ----
}
#endif

! /* 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
mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
{
*************** mi_cmd_data_evaluate_expression (char *c
*** 661,667 ****

val = evaluate_expression (expr);

! /* 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);
--- 670,676 ----

val = evaluate_expression (expr);

! /* 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);
*************** mi_cmd_target_download (char *args, int
*** 688,694 ****
return MI_CMD_DONE;
}

! /* Connect to the remote target. */
enum mi_cmd_result
mi_cmd_target_select (char *args, int from_tty)
{
--- 697,703 ----
return MI_CMD_DONE;
}

! /* Connect to the remote target. */
enum mi_cmd_result
mi_cmd_target_select (char *args, int from_tty)
{
*************** mi_cmd_target_select (char *args, int fr
*** 698,713 ****
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. */
/* 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, from_tty);

do_cleanups (old_cleanups);

! /* Issue the completion message here. */
if (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("^connected", raw_stdout);
--- 707,722 ----
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. */
/* 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, from_tty);

do_cleanups (old_cleanups);

! /* Issue the completion message here. */
if (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("^connected", raw_stdout);
*************** mi_cmd_target_select (char *args, int fr
*** 721,729 ****
/* DATA-MEMORY-READ:

ADDR: start address of data to be dumped.
! 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
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
--- 730,738 ----
/* DATA-MEMORY-READ:

ADDR: start address of data to be dumped.
! 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.
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
*************** mi_cmd_data_read_memory (char *command,
*** 789,800 ****

/* Extract all the arguments. */

! /* 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 ``x'' command. */
word_format = argv[1][0];
! /* The size of the memory word. */
word_size = atol (argv[2]);
switch (word_size)
{
--- 798,809 ----

/* Extract all the arguments. */

! /* 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 ``x'' command. */
word_format = argv[1][0];
! /* The size of the memory word. */
word_size = atol (argv[2]);
switch (word_size)
{
*************** mi_cmd_data_read_memory (char *command,
*** 818,844 ****
word_type = builtin_type_int8;
word_asize = 'b';
}
! /* 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. */
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. */
if (argc == 6)
aschar = *argv[5];
else
aschar = 0;

! /* create a buffer and read it in. */
total_bytes = word_size * nr_rows * nr_cols;
mbuf = xcalloc (total_bytes, 1);
make_cleanup (xfree, mbuf);
--- 827,853 ----
word_type = builtin_type_int8;
word_asize = 'b';
}
! /* 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. */
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. */
if (argc == 6)
aschar = *argv[5];
else
aschar = 0;

! /* Create a buffer and read it in. */
total_bytes = word_size * nr_rows * nr_cols;
mbuf = xcalloc (total_bytes, 1);
make_cleanup (xfree, mbuf);
*************** mi_cmd_data_read_memory (char *command,
*** 852,858 ****
return MI_CMD_ERROR;
}

! /* 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);
--- 861,867 ----
return MI_CMD_ERROR;
}

! /* 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);
*************** mi_cmd_data_read_memory (char *command,
*** 861,867 ****
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. */
{
struct ui_stream *stream = ui_out_stream_new (uiout);
struct cleanup *cleanup_list_memory;
--- 870,876 ----
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. */
{
struct ui_stream *stream = ui_out_stream_new (uiout);
struct cleanup *cleanup_list_memory;
*************** mi_cmd_data_read_memory (char *command,
*** 931,946 ****
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
the location to write to.
! 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. */
enum mi_cmd_result
mi_cmd_data_write_memory (char *command, char **argv, int argc)
{
--- 940,955 ----
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
the location to write to.
! 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. */
enum mi_cmd_result
mi_cmd_data_write_memory (char *command, char **argv, int argc)
{
*************** mi_cmd_data_write_memory (char *command,
*** 948,954 ****
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. */
LONGEST value;
void *buffer;
struct cleanup *old_chain;
--- 957,963 ----
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. */
LONGEST value;
void *buffer;
struct cleanup *old_chain;
*************** mi_cmd_data_write_memory (char *command,
*** 987,1011 ****
return MI_CMD_ERROR;
}

! /* 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. */
word_format = argv[1][0];
/* The size of the memory word. */
word_size = atol (argv[2]);

! /* Calculate the real address of the write destination. */
addr += (offset * word_size);

! /* Get the value as a number */
value = parse_and_eval_address (argv[3]);
! /* 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_memory (addr, buffer, word_size);
/* Free the buffer. */
do_cleanups (old_chain);
--- 996,1020 ----
return MI_CMD_ERROR;
}

! /* 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. */
word_format = argv[1][0];
/* The size of the memory word. */
word_size = atol (argv[2]);

! /* Calculate the real address of the write destination. */
addr += (offset * word_size);

! /* Get the value as a number. */
value = parse_and_eval_address (argv[3]);
! /* 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_memory (addr, buffer, word_size);
/* Free the buffer. */
do_cleanups (old_chain);
*************** mi_cmd_data_write_memory (char *command,
*** 1013,1018 ****
--- 1022,1051 ----
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.

*************** captured_mi_execute_command (struct ui_o
*** 1027,1037 ****
(struct captured_mi_execute_command_args *) data;
struct mi_parse *context = args->command;

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",
--- 1060,1072 ----
(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. */
if (mi_debug_p)
/* FIXME: gdb_???? */
fprintf_unfiltered (raw_stdout, " token=`%s' command=`%s' args=`%s'\n",
*************** captured_mi_execute_command (struct ui_o
*** 1039,1051 ****
/* 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;
args->rc = mi_cmd_execute (context);

if (!target_can_async_p () || !target_executing)
{
! /* 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
--- 1074,1093 ----
/* 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);

+ if (do_timings)
+ timestamp (&cmd_finished);
+
if (!target_can_async_p () || !target_executing)
{
! /* 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
*************** captured_mi_execute_command (struct ui_o
*** 1057,1062 ****
--- 1099,1108 ----
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)
*************** captured_mi_execute_command (struct ui_o
*** 1077,1083 ****
else if (sync_execution)
{
/* Don't print the prompt. We are executing the target in
! synchronous mode. */
args->action = EXECUTE_COMMAND_SUPRESS_PROMPT;
return;
}
--- 1123,1129 ----
else if (sync_execution)
{
/* Don't print the prompt. We are executing the target in
! synchronous mode. */
args->action = EXECUTE_COMMAND_SUPRESS_PROMPT;
return;
}
*************** mi_execute_command (char *cmd, int from_
*** 1142,1149 ****
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. */
if (cmd == 0)
quit_force (NULL, from_tty);

--- 1188,1195 ----
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. */
if (cmd == 0)
quit_force (NULL, from_tty);

*************** mi_execute_command (char *cmd, int from_
*** 1152,1159 ****
if (command != NULL)
{
struct gdb_exception result;
/* FIXME: cagney/1999-11-04: Can this use of catch_exceptions either
! be pushed even further down or even eliminated? */
args.command = command;
result = catch_exception (uiout, captured_mi_execute_command, &args,
RETURN_MASK_ALL);
--- 1198,1213 ----
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? */
args.command = command;
result = catch_exception (uiout, captured_mi_execute_command, &args,
RETURN_MASK_ALL);
*************** mi_execute_command (char *cmd, int from_
*** 1162,1168 ****
if (args.action == EXECUTE_COMMAND_SUPRESS_PROMPT)
{
/* The command is executing synchronously. Bail out early
! suppressing the finished prompt. */
mi_parse_free (command);
return;
}
--- 1216,1222 ----
if (args.action == EXECUTE_COMMAND_SUPRESS_PROMPT)
{
/* The command is executing synchronously. Bail out early
! suppressing the finished prompt. */
mi_parse_free (command);
return;
}
*************** mi_execute_command (char *cmd, int from_
*** 1184,1190 ****

fputs_unfiltered ("(gdb) \n", raw_stdout);
gdb_flush (raw_stdout);
! /* print any buffered hook code */
/* ..... */
}

--- 1238,1244 ----

fputs_unfiltered ("(gdb) \n", raw_stdout);
gdb_flush (raw_stdout);
! /* Print any buffered hook code. */
/* ..... */
}

*************** mi_cmd_execute (struct mi_parse *parse)
*** 1197,1213 ****
/* 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 */
/* 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
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
command, when over, will copy that token back into the
! default token string (last_async_command). */

if (target_executing)
{
--- 1251,1267 ----
/* 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. */
/* 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
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
command, when over, will copy that token back into the
! default token string (last_async_command). */

if (target_executing)
{
*************** mi_cmd_execute (struct mi_parse *parse)
*** 1234,1248 ****
else if (parse->cmd->cli.cmd != 0)
{
/* FIXME: DELETE THIS. */
! /* 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. */
fputs_unfiltered (parse->token, raw_stdout);
fputs_unfiltered ("^error,msg=\"", raw_stdout);
fputs_unfiltered ("Undefined mi command: ", raw_stdout);
--- 1288,1302 ----
else if (parse->cmd->cli.cmd != 0)
{
/* FIXME: DELETE THIS. */
! /* 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. */
fputs_unfiltered (parse->token, raw_stdout);
fputs_unfiltered ("^error,msg=\"", raw_stdout);
fputs_unfiltered ("Undefined mi command: ", raw_stdout);
*************** mi_cmd_execute (struct mi_parse *parse)
*** 1254,1261 ****
}

/* 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 */

void
mi_execute_cli_command (const char *cmd, int args_p, const char *args)
--- 1308,1315 ----
}

/* 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. */

void
mi_execute_cli_command (const char *cmd, int args_p, const char *args)
*************** mi_execute_async_cli_command (char *mi,
*** 1307,1313 ****
{
/* NOTE: For synchronous targets asynchronous behavour is faked by
printing out the GDB prompt before we even try to execute the
! command. */
if (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("^running\n", raw_stdout);
--- 1361,1367 ----
{
/* NOTE: For synchronous targets asynchronous behavour is faked by
printing out the GDB prompt before we even try to execute the
! command. */
if (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("^running\n", raw_stdout);
*************** mi_execute_async_cli_command (char *mi,
*** 1319,1325 ****
/* 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 (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("^running\n", raw_stdout);
--- 1373,1379 ----
/* 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 (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("^running\n", raw_stdout);
*************** mi_execute_async_cli_command (char *mi,
*** 1330,1344 ****
if (!target_can_async_p ())
{
/* Do this before doing any printing. It would appear that some
! 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. */
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);
fputs_unfiltered ("\n", raw_stdout);
return MI_CMD_QUIET;
}
--- 1384,1400 ----
if (!target_can_async_p ())
{
/* Do this before doing any printing. It would appear that some
! 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. */
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;
}
*************** _initialize_mi_main (void)
*** 1455,1457 ****
--- 1511,1559 ----
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;
+ #ifdef HAVE_GETRUSAGE
+ gettimeofday (&tv->wallclock, NULL);
+ getrusage (RUSAGE_SELF, &tv->rusage);
+ #else
+ usec = get_run_time ();
+ tv->wallclock.tv_sec = usec/1000000;
+ tv->wallclock.utv_sec = usec - 1000000*tv->wallclock.tv_sec;
+ tv->rusage.ru_utime.tv_sec = 0;
+ tv->rusage.ru_utime.tv_usec = 0;
+ tv->rusage.ru_stime.tv_sec = 0;
+ tv->rusage.ru_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) * 1000000)
+ + (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->rusage.ru_utime, end->rusage.ru_utime)
+ / 1000000.0,
+ timeval_diff (start->rusage.ru_stime, end->rusage.ru_stime)
+ / 1000000.0);
+ }