/* MI Command Set.
- Copyright (C) 2000, Free Software Foundation, Inc.
+
+ Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation,
+ Inc.
+
Contributed by Cygnus Solutions (a Red Hat company).
This file is part of GDB.
#include "target.h"
#include "inferior.h"
#include "gdb_string.h"
+#include "exceptions.h"
#include "top.h"
#include "gdbthread.h"
#include "mi-cmds.h"
#include "mi-console.h"
#include "ui-out.h"
#include "mi-out.h"
+#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"
+#include "mi-main.h"
+
#include <ctype.h>
#include <sys/time.h>
-/* Convenience macro for allocting typesafe memory. */
-
-#undef XMALLOC
-#define XMALLOC(TYPE) (TYPE*) xmalloc (sizeof (TYPE))
-
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_SUPRESS_PROMPT,
+ EXECUTE_COMMAND_DISPLAY_ERROR
+ };
+
+/* 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;
-static char *mi_error_message;
+char *mi_error_message;
static char *old_regs;
extern void _initialize_mi_main (void);
-static char *mi_input (char *);
-static void mi_execute_command (char *cmd, int from_tty);
static enum mi_cmd_result mi_cmd_execute (struct mi_parse *parse);
-static void mi_execute_cli_command (const char *cli, char *args);
+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 *mi, char *args, int from_tty);
-static void mi_execute_command_wrapper (char *cmd);
-void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg);
-static void free_and_reset (char **arg);
+static void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg);
static int register_changed_p (int regnum);
static int get_register (int regnum, int format);
-static void mi_load_progress (const char *section_name,
- unsigned long sent_so_far,
- unsigned long total_section,
- unsigned long total_sent,
- unsigned long grand_total);
-
-#ifdef UI_OUT
-/* FIXME: these should go in some .h file, but infcmd.c doesn't have a
- corresponding .h file. These wrappers will be obsolete anyway, once
- we pull the plug on the sanitization. */
-extern void interrupt_target_command_wrapper (char *, int);
-extern void return_command_wrapper (char *, int);
-#endif
/* Command implementations. FIXME: Is this libgdb? No. This is the MI
layer that calls libgdb. Any operation used in the below should be
enum mi_cmd_result
mi_cmd_exec_return (char *args, int from_tty)
{
-#ifdef UI_OUT
/* This command doesn't really execute the target, it just pops the
specified number of frames. */
if (*args)
/* Call return_command with from_tty argument equal to 0 so as to
avoid being queried. */
- return_command_wrapper (args, 0);
+ return_command (args, 0);
else
/* Call return_command with from_tty argument equal to 0 so as to
avoid being queried. */
- return_command_wrapper (NULL, 0);
+ return_command (NULL, 0);
/* Because we have called return_command with from_tty = 0, we need
to print the frame here. */
- show_and_print_stack_frame (selected_frame,
- selected_frame_level,
- LOC_AND_ADDRESS);
-#endif
+ print_stack_frame (get_selected_frame (NULL), 1, LOC_AND_ADDRESS);
return MI_CMD_DONE;
}
enum mi_cmd_result
mi_cmd_exec_interrupt (char *args, int from_tty)
{
-#ifdef UI_OUT
if (!target_executing)
{
- asprintf (&mi_error_message, "mi_cmd_exec_interrupt: Inferior not executing.");
+ mi_error_message = xstrprintf ("mi_cmd_exec_interrupt: Inferior not executing.");
return MI_CMD_ERROR;
}
- interrupt_target_command_wrapper (args, from_tty);
+ interrupt_target_command (args, from_tty);
if (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("^done", raw_stdout);
- free (last_async_command);
+ xfree (last_async_command);
if (previous_async_command)
last_async_command = xstrdup (previous_async_command);
- free (previous_async_command);
+ xfree (previous_async_command);
previous_async_command = NULL;
mi_out_put (uiout, raw_stdout);
mi_out_rewind (uiout);
fputs_unfiltered ("\n", raw_stdout);
-#endif
return MI_CMD_QUIET;
}
if (argc != 1)
{
- asprintf (&mi_error_message,
- "mi_cmd_thread_select: USAGE: threadnum.");
+ mi_error_message = xstrprintf ("mi_cmd_thread_select: USAGE: threadnum.");
return MI_CMD_ERROR;
}
else
- rc = gdb_thread_select (argv[0]);
+ rc = gdb_thread_select (uiout, argv[0]);
- if (rc == GDB_RC_FAIL)
+ /* 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_CAUGHT_ERROR;
+ else if ((int) rc >= 0 && rc == GDB_RC_FAIL)
+ return MI_CMD_ERROR;
else
return MI_CMD_DONE;
}
if (argc != 0)
{
- asprintf (&mi_error_message,
- "mi_cmd_thread_list_ids: No arguments required.");
+ mi_error_message = xstrprintf ("mi_cmd_thread_list_ids: No arguments required.");
return MI_CMD_ERROR;
}
else
-#ifdef UI_OUT
- rc = gdb_list_thread_ids ();
-#endif
+ rc = gdb_list_thread_ids (uiout);
if (rc == GDB_RC_FAIL)
return MI_CMD_CAUGHT_ERROR;
{
int regnum, numregs;
int i;
+ 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
case, some entries of REGISTER_NAME will change depending upon
the particular processor being debugged. */
- numregs = ARCH_NUM_REGS;
+ numregs = NUM_REGS + NUM_PSEUDO_REGS;
- ui_out_list_begin (uiout, "register-names");
+ cleanup = make_cleanup_ui_out_list_begin_end (uiout, "register-names");
if (argc == 0) /* No args, just do all the regs */
{
{
if (REGISTER_NAME (regnum) == NULL
|| *(REGISTER_NAME (regnum)) == '\0')
- continue;
-
- ui_out_field_string (uiout, NULL, REGISTER_NAME (regnum));
+ ui_out_field_string (uiout, NULL, "");
+ else
+ ui_out_field_string (uiout, NULL, REGISTER_NAME (regnum));
}
}
for (i = 0; i < argc; i++)
{
regnum = atoi (argv[i]);
-
- if (regnum >= 0
- && regnum < numregs
- && REGISTER_NAME (regnum) != NULL
- && *REGISTER_NAME (regnum) != '\000')
- ui_out_field_string (uiout, NULL, REGISTER_NAME (regnum));
- else
+ if (regnum < 0 || regnum >= numregs)
{
- asprintf (&mi_error_message, "bad register number");
+ do_cleanups (cleanup);
+ mi_error_message = xstrprintf ("bad register number");
return MI_CMD_ERROR;
}
+ if (REGISTER_NAME (regnum) == NULL
+ || *(REGISTER_NAME (regnum)) == '\0')
+ ui_out_field_string (uiout, NULL, "");
+ else
+ ui_out_field_string (uiout, NULL, REGISTER_NAME (regnum));
}
- ui_out_list_end (uiout);
+ do_cleanups (cleanup);
return MI_CMD_DONE;
}
{
int regnum, numregs, changed;
int i;
+ 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
case, some entries of REGISTER_NAME will change depending upon
the particular processor being debugged. */
- numregs = ARCH_NUM_REGS;
+ numregs = NUM_REGS + NUM_PSEUDO_REGS;
- ui_out_list_begin (uiout, "changed-registers");
+ cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changed-registers");
if (argc == 0) /* No args, just do all the regs */
{
changed = register_changed_p (regnum);
if (changed < 0)
{
- asprintf (&mi_error_message,
- "mi_cmd_data_list_changed_registers: Unable to read register contents.");
+ do_cleanups (cleanup);
+ mi_error_message = xstrprintf ("mi_cmd_data_list_changed_registers: Unable to read register contents.");
return MI_CMD_ERROR;
}
else if (changed)
changed = register_changed_p (regnum);
if (changed < 0)
{
- asprintf (&mi_error_message,
- "mi_cmd_data_list_register_change: Unable to read register contents.");
+ do_cleanups (cleanup);
+ mi_error_message = xstrprintf ("mi_cmd_data_list_register_change: Unable to read register contents.");
return MI_CMD_ERROR;
}
else if (changed)
}
else
{
- asprintf (&mi_error_message, "bad register number");
+ do_cleanups (cleanup);
+ mi_error_message = xstrprintf ("bad register number");
return MI_CMD_ERROR;
}
}
- ui_out_list_end (uiout);
+ do_cleanups (cleanup);
return MI_CMD_DONE;
}
static int
register_changed_p (int regnum)
{
- char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ char raw_buffer[MAX_REGISTER_SIZE];
- if (read_relative_register_raw_bytes (regnum, raw_buffer))
+ if (! frame_register_read (deprecated_selected_frame, regnum, raw_buffer))
return -1;
- if (memcmp (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
- REGISTER_RAW_SIZE (regnum)) == 0)
+ if (memcmp (&old_regs[DEPRECATED_REGISTER_BYTE (regnum)], raw_buffer,
+ register_size (current_gdbarch, regnum)) == 0)
return 0;
/* Found a changed register. Return 1. */
- memcpy (&old_regs[REGISTER_BYTE (regnum)], raw_buffer,
- REGISTER_RAW_SIZE (regnum));
+ memcpy (&old_regs[DEPRECATED_REGISTER_BYTE (regnum)], raw_buffer,
+ register_size (current_gdbarch, regnum));
return 1;
}
{
int regnum, numregs, format, result;
int i;
+ 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
case, some entries of REGISTER_NAME will change depending upon
the particular processor being debugged. */
- numregs = ARCH_NUM_REGS;
+ numregs = NUM_REGS + NUM_PSEUDO_REGS;
if (argc == 0)
{
- asprintf (&mi_error_message,
- "mi_cmd_data_list_register_values: Usage: -data-list-register-values <format> [<regnum1>...<regnumN>]");
+ mi_error_message = xstrprintf ("mi_cmd_data_list_register_values: Usage: -data-list-register-values <format> [<regnum1>...<regnumN>]");
return MI_CMD_ERROR;
}
if (!target_has_registers)
{
- asprintf (&mi_error_message, "mi_cmd_data_list_register_values: No registers.");
+ mi_error_message = xstrprintf ("mi_cmd_data_list_register_values: No registers.");
return MI_CMD_ERROR;
}
- ui_out_list_begin (uiout, "register-values");
+ 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 (REGISTER_NAME (regnum) == NULL
|| *(REGISTER_NAME (regnum)) == '\0')
continue;
- ui_out_list_begin (uiout, NULL);
+ tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
ui_out_field_int (uiout, "number", regnum);
result = get_register (regnum, format);
if (result == -1)
- return MI_CMD_ERROR;
- ui_out_list_end (uiout);
+ {
+ do_cleanups (list_cleanup);
+ return MI_CMD_ERROR;
+ }
+ do_cleanups (tuple_cleanup);
}
}
&& REGISTER_NAME (regnum) != NULL
&& *REGISTER_NAME (regnum) != '\000')
{
- ui_out_list_begin (uiout, NULL);
+ tuple_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
ui_out_field_int (uiout, "number", regnum);
result = get_register (regnum, format);
if (result == -1)
- return MI_CMD_ERROR;
- ui_out_list_end (uiout);
+ {
+ do_cleanups (list_cleanup);
+ return MI_CMD_ERROR;
+ }
+ do_cleanups (tuple_cleanup);
}
else
{
- asprintf (&mi_error_message, "bad register number");
+ do_cleanups (list_cleanup);
+ mi_error_message = xstrprintf ("bad register number");
return MI_CMD_ERROR;
}
}
- ui_out_list_end (uiout);
+ do_cleanups (list_cleanup);
return MI_CMD_DONE;
}
static int
get_register (int regnum, int format)
{
- char raw_buffer[MAX_REGISTER_RAW_SIZE];
- char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+ char buffer[MAX_REGISTER_SIZE];
int optim;
+ int realnum;
+ CORE_ADDR addr;
+ enum lval_type lval;
static struct ui_stream *stb = NULL;
stb = ui_out_stream_new (uiout);
if (format == 'N')
format = 0;
- /* read_relative_register_raw_bytes returns a virtual frame pointer
- (FRAME_FP (selected_frame)) if regnum == FP_REGNUM instead
- of the real contents of the register. To get around this,
- use get_saved_register instead. */
- get_saved_register (raw_buffer, &optim, (CORE_ADDR *) NULL, selected_frame,
- regnum, (enum lval_type *) NULL);
+ frame_register (deprecated_selected_frame, regnum, &optim, &lval, &addr,
+ &realnum, buffer);
+
if (optim)
{
- asprintf (&mi_error_message, "Optimized out");
+ mi_error_message = xstrprintf ("Optimized out");
return -1;
}
- /* Convert raw data to virtual format if necessary. */
-
- if (REGISTER_CONVERTIBLE (regnum))
- {
- REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum),
- raw_buffer, virtual_buffer);
- }
- else
- memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
-
if (format == 'r')
{
int j;
strcpy (buf, "0x");
ptr = buf + 2;
- for (j = 0; j < REGISTER_RAW_SIZE (regnum); j++)
+ for (j = 0; j < register_size (current_gdbarch, regnum); j++)
{
- register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j
- : REGISTER_RAW_SIZE (regnum) - 1 - j;
- sprintf (ptr, "%02x", (unsigned char) raw_buffer[idx]);
+ int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j
+ : register_size (current_gdbarch, regnum) - 1 - j;
+ sprintf (ptr, "%02x", (unsigned char) buffer[idx]);
ptr += 2;
}
ui_out_field_string (uiout, "value", buf);
}
else
{
- val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0, 0,
+ val_print (register_type (current_gdbarch, regnum), buffer, 0, 0,
stb->stream, format, 1, 0, Val_pretty_default);
ui_out_field_stream (uiout, "value", stb);
ui_out_stream_delete (stb);
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)
+{
+ int regnum;
+ int i;
+ int numregs;
+ LONGEST value;
+ 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
+ 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;
+
+ if (argc == 0)
+ {
+ mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: Usage: -data-write-register-values <format> [<regnum1> <value1>...<regnumN> <valueN>]");
+ return MI_CMD_ERROR;
+ }
+
+ 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.");
+ return MI_CMD_ERROR;
+ }
+
+ if ((argc - 1) % 2)
+ {
+ mi_error_message = xstrprintf ("mi_cmd_data_write_register_values: Regs and vals are not in pairs.");
+ return MI_CMD_ERROR;
+ }
+
+ for (i = 1; i < argc; i = i + 2)
+ {
+ regnum = atoi (argv[i]);
+
+ if (regnum >= 0
+ && regnum < numregs
+ && REGISTER_NAME (regnum) != NULL
+ && *REGISTER_NAME (regnum) != '\000')
+ {
+ void *buffer;
+ struct cleanup *old_chain;
+
+ /* 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);
+ }
+ else
+ {
+ mi_error_message = xstrprintf ("bad register number");
+ return MI_CMD_ERROR;
+ }
+ }
+ return MI_CMD_DONE;
+}
+
#if 0
/*This is commented out because we decided it was not useful. I leave
it, just in case. ezannoni:1999-12-08 */
if (argc != 1)
{
- asprintf (&mi_error_message,
- "mi_cmd_data_assign: Usage: -data-assign expression");
+ mi_error_message = xstrprintf ("mi_cmd_data_assign: Usage: -data-assign expression");
return MI_CMD_ERROR;
}
01-12-1999: Need to decide what to do with this for libgdb purposes. */
expr = parse_expression (argv[0]);
- old_chain = make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+ old_chain = make_cleanup (free_current_contents, &expr);
evaluate_expression (expr);
do_cleanups (old_chain);
return MI_CMD_DONE;
{
struct expression *expr;
struct cleanup *old_chain = NULL;
- value_ptr val;
+ struct value *val;
struct ui_stream *stb = NULL;
stb = ui_out_stream_new (uiout);
if (argc != 1)
{
- asprintf (&mi_error_message,
- "mi_cmd_data_evaluate_expression: Usage: -data-evaluate-expression expression");
+ mi_error_message = xstrprintf ("mi_cmd_data_evaluate_expression: Usage: -data-evaluate-expression expression");
return MI_CMD_ERROR;
}
expr = parse_expression (argv[0]);
- old_chain = make_cleanup ((make_cleanup_func) free_current_contents, &expr);
+ old_chain = make_cleanup (free_current_contents, &expr);
val = evaluate_expression (expr);
/* Print the result of the expression evaluation. */
- val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+ val_print (value_type (val), VALUE_CONTENTS (val),
VALUE_EMBEDDED_OFFSET (val), VALUE_ADDRESS (val),
stb->stream, 0, 0, 0, 0);
char *run;
struct cleanup *old_cleanups = NULL;
- asprintf (&run, "load %s", args);
- if (run == 0)
- internal_error ("mi_cmd_target_download: no memory");
- old_cleanups = make_cleanup (free, run);
+ run = xstrprintf ("load %s", args);
+ old_cleanups = make_cleanup (xfree, run);
execute_command (run, from_tty);
do_cleanups (old_cleanups);
char *run;
struct cleanup *old_cleanups = NULL;
- asprintf (&run, "target %s", args);
- if (run == 0)
- internal_error ("mi_cmd_target_select: no memory");
- old_cleanups = make_cleanup (free, run);
+ 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. */
if (argc < 5 || argc > 6)
{
- asprintf (&mi_error_message,
- "mi_cmd_data_read_memory: Usage: ADDR WORD-FORMAT WORD-SIZE NR-ROWS NR-COLS [ASCHAR].");
+ mi_error_message = xstrprintf ("mi_cmd_data_read_memory: Usage: ADDR WORD-FORMAT WORD-SIZE NR-ROWS NR-COLS [ASCHAR].");
return MI_CMD_ERROR;
}
nr_rows = atol (argv[3]);
if (nr_rows <= 0)
{
- asprintf (&mi_error_message,
- "mi_cmd_data_read_memory: invalid number of rows.");
+ 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)
{
- asprintf (&mi_error_message,
- "mi_cmd_data_read_memory: invalid number of columns.");
+ 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)
/* create a buffer and read it in. */
total_bytes = word_size * nr_rows * nr_cols;
- mbuf = calloc (total_bytes, 1);
- make_cleanup (free, mbuf);
- if (mbuf == NULL)
- {
- asprintf (&mi_error_message,
- "mi_cmd_data_read_memory: out of memory.");
- return MI_CMD_ERROR;
- }
+ mbuf = xcalloc (total_bytes, 1);
+ make_cleanup (xfree, mbuf);
nr_bytes = 0;
while (nr_bytes < total_bytes)
{
/* Build the result as a two dimentional table. */
{
struct ui_stream *stream = ui_out_stream_new (uiout);
+ struct cleanup *cleanup_list_memory;
int row;
int row_byte;
- ui_out_list_begin (uiout, "memory");
+ cleanup_list_memory = make_cleanup_ui_out_list_begin_end (uiout, "memory");
for (row = 0, row_byte = 0;
row < nr_rows;
row++, row_byte += nr_cols * word_size)
{
int col;
int col_byte;
- ui_out_list_begin (uiout, NULL);
+ struct cleanup *cleanup_tuple;
+ struct cleanup *cleanup_list_data;
+ 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_symbolic (uiout, "saddr", addr + row_byte); */
- ui_out_list_begin (uiout, "data");
+ cleanup_list_data = make_cleanup_ui_out_list_begin_end (uiout, "data");
for (col = 0, col_byte = row_byte;
col < nr_cols;
col++, col_byte += word_size)
ui_out_field_stream (uiout, NULL, stream);
}
}
- ui_out_list_end (uiout);
+ do_cleanups (cleanup_list_data);
if (aschar)
{
int byte;
}
ui_out_field_stream (uiout, "ascii", stream);
}
- ui_out_list_end (uiout);
+ do_cleanups (cleanup_tuple);
}
ui_out_stream_delete (stream);
- ui_out_list_end (uiout);
+ do_cleanups (cleanup_list_memory);
}
do_cleanups (cleanups);
return MI_CMD_DONE;
/* FIXME: ezannoni 2000-02-17 LONGEST could possibly not be big
enough when using a compiler other than GCC. */
LONGEST value;
- unsigned char *buffer;
+ void *buffer;
+ struct cleanup *old_chain;
long offset = 0;
int optind = 0;
char *optarg;
if (argc != 4)
{
- asprintf (&mi_error_message,
- "mi_cmd_data_write_memory: Usage: [-o COLUMN_OFFSET] ADDR FORMAT WORD-SIZE VALUE.");
+ mi_error_message = xstrprintf ("mi_cmd_data_write_memory: Usage: [-o COLUMN_OFFSET] ADDR FORMAT WORD-SIZE VALUE.");
return MI_CMD_ERROR;
}
/* Get the value as a number */
value = parse_and_eval_address (argv[3]);
/* Get the value into an array */
- buffer = (unsigned char *) xmalloc (word_size);
+ 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);
return MI_CMD_DONE;
}
-/* Execute a command within a safe environment. Return >0 for
- ok. Return <0 for supress prompt. Return 0 to have the error
- extracted from error_last_message(). */
+/* Execute a command within a safe environment.
+ Return <0 for error; >=0 for ok.
-static int
-captured_mi_execute_command (void *data)
+ args->action will tell mi_execute_command what action
+ to perfrom after the given command has executed (display/supress
+ prompt, display error). */
+
+static void
+captured_mi_execute_command (struct ui_out *uiout, void *data)
{
- struct mi_parse *context = data;
- enum mi_cmd_result rc;
+ struct captured_mi_execute_command_args *args =
+ (struct captured_mi_execute_command_args *) data;
+ struct mi_parse *context = args->command;
switch (context->op)
{
condition expression, each function should return an
indication of what action is required and then switch on
that. */
- rc = mi_cmd_execute (context);
+ 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 */
- if (rc == MI_CMD_DONE)
+ /* 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_rewind (uiout);
fputs_unfiltered ("\n", raw_stdout);
}
- else if (rc == MI_CMD_ERROR)
+ 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);
- free (mi_error_message);
+ xfree (mi_error_message);
fputs_unfiltered ("\"\n", raw_stdout);
}
mi_out_rewind (uiout);
}
- else if (rc == MI_CMD_CAUGHT_ERROR)
+ else if (args->rc == MI_CMD_CAUGHT_ERROR)
{
mi_out_rewind (uiout);
- return 0;
+ args->action = EXECUTE_COMMAND_DISPLAY_ERROR;
+ return;
}
else
mi_out_rewind (uiout);
}
else if (sync_execution)
- /* Don't print the prompt. We are executing the target in
- synchronous mode. */
- return -1;
+ {
+ /* Don't print the prompt. We are executing the target in
+ synchronous mode. */
+ args->action = EXECUTE_COMMAND_SUPRESS_PROMPT;
+ return;
+ }
break;
case CLI_COMMAND:
mi commands */
/* echo the command on the console. */
fprintf_unfiltered (gdb_stdlog, "%s\n", context->command);
- /* FIXME: If the command string has something that looks like
- a format spec (e.g. %s) we will get a core dump */
- mi_execute_cli_command ("%s", context->command);
- /* 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);
+ mi_execute_cli_command (context->command, 0, NULL);
+
+ /* 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;
+ }
break;
}
- return 1;
+
+ return;
}
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. */
/* FIXME: we should call some API function here. */
if (command != NULL)
{
- /* FIXME: cagney/1999-11-04: Can this use of catch_errors either
+ struct exception result;
+ /* FIXME: cagney/1999-11-04: Can this use of catch_exceptions either
be pushed even further down or even eliminated? */
- int rc = catch_errors (captured_mi_execute_command, command, "",
- RETURN_MASK_ALL);
- if (rc < 0)
+ args.command = command;
+ result = catch_exception (uiout, captured_mi_execute_command, &args,
+ RETURN_MASK_ALL);
+
+ if (args.action == EXECUTE_COMMAND_SUPRESS_PROMPT)
{
/* The command is executing synchronously. Bail out early
suppressing the finished prompt. */
mi_parse_free (command);
return;
}
- if (rc == 0)
+ if (args.action == EXECUTE_COMMAND_DISPLAY_ERROR
+ || result.reason < 0)
{
- char *msg = error_last_message ();
- struct cleanup *cleanup = make_cleanup (free, msg);
+ char *msg = result.message;
+ struct cleanup *cleanup = make_cleanup (xfree, msg);
/* The command execution failed and error() was called
somewhere */
fputs_unfiltered (command->token, raw_stdout);
mi_parse_free (command);
}
- gdb_flush (raw_stdout);
fputs_unfiltered ("(gdb) \n", raw_stdout);
+ gdb_flush (raw_stdout);
/* print any buffered hook code */
/* ..... */
}
}
}
last_async_command = xstrdup (parse->token);
- make_exec_cleanup ((make_cleanup_func) free_and_reset, &last_async_command);
+ make_exec_cleanup (free_current_contents, &last_async_command);
/* FIXME: DELETE THIS! */
if (parse->cmd->args_func != NULL)
return parse->cmd->args_func (parse->args, 0 /*from_tty */ );
return parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
}
- else if (parse->cmd->cli != 0)
+ 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, parse->args);
+ mi_execute_cli_command (parse->cmd->cli.cmd, parse->cmd->cli.args_p,
+ parse->args);
return MI_CMD_DONE;
}
else
}
}
-void
-free_and_reset (char **arg)
-{
- free (*arg);
- *arg = NULL;
-}
-
-static void
-mi_execute_command_wrapper (char *cmd)
-{
- mi_execute_command (cmd, stdin == instream);
-}
-
/* 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 *cli, char *args)
+mi_execute_cli_command (const char *cmd, int args_p, const char *args)
{
- if (cli != 0)
+ if (cmd != 0)
{
struct cleanup *old_cleanups;
char *run;
- asprintf (&run, cli, args);
+ if (args_p)
+ run = xstrprintf ("%s %s", cmd, args);
+ else
+ run = xstrdup (cmd);
if (mi_debug_p)
/* FIXME: gdb_???? */
fprintf_unfiltered (gdb_stdout, "cli=%s run=%s\n",
- cli, run);
- if (run == 0)
- abort ();
- old_cleanups = make_cleanup (free, run);
+ cmd, run);
+ old_cleanups = make_cleanup (xfree, run);
execute_command ( /*ui */ run, 0 /*from_tty */ );
do_cleanups (old_cleanups);
return;
make_exec_cleanup (free, async_args);
strcpy (async_args, args);
strcat (async_args, "&");
- asprintf (&run, "%s %s", mi, async_args);
- if (run == 0)
- internal_error ("mi_execute_async_cli_command: no memory");
+ run = xstrprintf ("%s %s", mi, async_args);
make_exec_cleanup (free, run);
add_continuation (mi_exec_async_cli_cmd_continuation, NULL);
+ old_cleanups = NULL;
}
else
{
- asprintf (&run, "%s %s", mi, args);
- if (run == 0)
- internal_error ("mi_execute_async_cli_command: no memory");
- old_cleanups = make_cleanup (free, run);
+ run = xstrprintf ("%s %s", mi, args);
+ old_cleanups = make_cleanup (xfree, run);
}
if (!target_can_async_p ())
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("^running\n", raw_stdout);
fputs_unfiltered ("(gdb) \n", raw_stdout);
+ gdb_flush (raw_stdout);
}
else
{
mi_out_put (uiout, raw_stdout);
fputs_unfiltered ("\n", raw_stdout);
fputs_unfiltered ("(gdb) \n", raw_stdout);
+ gdb_flush (raw_stdout);
do_exec_cleanups (ALL_CLEANUPS);
}
-static char *
-mi_input (char *buf)
-{
- return gdb_readline (NULL);
-}
-
-static void
+void
mi_load_progress (const char *section_name,
unsigned long sent_so_far,
unsigned long total_section,
static char *previous_sect_name = NULL;
int new_section;
- if (!interpreter_p || strcmp (interpreter_p, "mi") != 0)
+ if (!current_interp_named_p (INTERP_MI)
+ && !current_interp_named_p (INTERP_MI1))
return;
update_threshold.tv_sec = 0;
strcmp (previous_sect_name, section_name) : 1);
if (new_section)
{
- free (previous_sect_name);
+ struct cleanup *cleanup_tuple;
+ xfree (previous_sect_name);
previous_sect_name = xstrdup (section_name);
if (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("+download", raw_stdout);
- ui_out_list_begin (uiout, NULL);
+ cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
ui_out_field_string (uiout, "section", section_name);
ui_out_field_int (uiout, "section-size", total_section);
ui_out_field_int (uiout, "total-size", grand_total);
- ui_out_list_end (uiout);
+ do_cleanups (cleanup_tuple);
mi_out_put (uiout, raw_stdout);
fputs_unfiltered ("\n", raw_stdout);
gdb_flush (raw_stdout);
if (delta.tv_sec >= update_threshold.tv_sec &&
delta.tv_usec >= update_threshold.tv_usec)
{
+ struct cleanup *cleanup_tuple;
last_update.tv_sec = time_now.tv_sec;
last_update.tv_usec = time_now.tv_usec;
if (last_async_command)
fputs_unfiltered (last_async_command, raw_stdout);
fputs_unfiltered ("+download", raw_stdout);
- ui_out_list_begin (uiout, NULL);
+ cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
ui_out_field_string (uiout, "section", section_name);
ui_out_field_int (uiout, "section-sent", sent_so_far);
ui_out_field_int (uiout, "section-size", total_section);
ui_out_field_int (uiout, "total-sent", total_sent);
ui_out_field_int (uiout, "total-size", grand_total);
- ui_out_list_end (uiout);
+ do_cleanups (cleanup_tuple);
mi_out_put (uiout, raw_stdout);
fputs_unfiltered ("\n", raw_stdout);
gdb_flush (raw_stdout);
}
}
-static void
-mi_command_loop ()
-{
- /* HACK: Force stdout/stderr to point at the console. This avoids
- any potential side effects caused by legacy code that is still
- using the TUI / fputs_unfiltered_hook */
- raw_stdout = stdio_fileopen (stdout);
- /* Route normal output through the MIx */
- gdb_stdout = mi_console_file_new (raw_stdout, "~");
- /* Route error and log output through the MI */
- gdb_stderr = mi_console_file_new (raw_stdout, "&");
- gdb_stdlog = gdb_stderr;
- /* Route target output through the MI. */
- gdb_stdtarg = mi_console_file_new (raw_stdout, "@");
-
- /* HACK: Poke the ui_out table directly. Should we be creating a
- mi_out object wired up to the above gdb_stdout / gdb_stderr? */
- uiout = mi_out_new ();
-
- /* HACK: Override any other interpreter hooks. We need to create a
- real event table and pass in that. */
- init_ui_hook = 0;
- /* command_loop_hook = 0; */
- print_frame_info_listing_hook = 0;
- query_hook = 0;
- warning_hook = 0;
- create_breakpoint_hook = 0;
- delete_breakpoint_hook = 0;
- modify_breakpoint_hook = 0;
- interactive_hook = 0;
- registers_changed_hook = 0;
- readline_begin_hook = 0;
- readline_hook = 0;
- readline_end_hook = 0;
- register_changed_hook = 0;
- memory_changed_hook = 0;
- context_hook = 0;
- target_wait_hook = 0;
- call_command_hook = 0;
- error_hook = 0;
- error_begin_hook = 0;
- show_load_progress = mi_load_progress;
-
- /* Turn off 8 bit strings in quoted output. Any character with the
- high bit set is printed using C's octal format. */
- sevenbit_strings = 1;
-
- /* Tell the world that we're alive */
- fputs_unfiltered ("(gdb) \n", raw_stdout);
-
- if (!event_loop_p)
- simplified_command_loop (mi_input, mi_execute_command);
- else
- start_event_loop ();
-}
-
-static void
-setup_architecture_data ()
-{
- /* don't trust REGISTER_BYTES to be zero. */
- old_regs = xmalloc (REGISTER_BYTES + 1);
- memset (old_regs, 0, REGISTER_BYTES + 1);
-}
-
-static void
-mi_init_ui (arg0)
- char *arg0;
+void
+mi_setup_architecture_data (void)
{
- /* Eventually this will contain code that takes control of the
- console. */
+ 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);
}
void
-_initialize_mi_main ()
+_initialize_mi_main (void)
{
- /* If we're _the_ interpreter, take control. */
- if (interpreter_p
- && strcmp (interpreter_p, "mi") == 0)
- {
- init_ui_hook = mi_init_ui;
- command_loop_hook = mi_command_loop;
- setup_architecture_data ();
- register_gdbarch_swap (&old_regs, sizeof (old_regs), NULL);
- register_gdbarch_swap (NULL, 0, setup_architecture_data);
- if (event_loop_p)
- {
- /* These overwrite some of the initialization done in
- _intialize_event_loop. */
- call_readline = gdb_readline2;
- input_handler = mi_execute_command_wrapper;
- add_file_handler (input_fd, stdin_event_handler, 0);
- async_command_editing_p = 0;
- }
- }
- /* FIXME: Should we notify main that we are here as a possible
- interpreter? */
+ DEPRECATED_REGISTER_GDBARCH_SWAP (old_regs);
+ deprecated_register_gdbarch_swap (NULL, 0, mi_setup_architecture_data);
}
-
-/* Local variables: */
-/* change-log-default-name: "ChangeLog-mi" */
-/* End: */