X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fmi%2Fmi-main.c;h=6158c8ff439c522452dcfbcdfd4678a8f106a1fe;hb=d9d9c31f313042e074b7c77bf6bd1d808202e6fb;hp=b7b5ae3b964505b7a8f947b04c54c31a48fedeb4;hpb=d0352a18a504a4e7b761f6b3264cf11347d8d056;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index b7b5ae3b96..6158c8ff43 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -1,5 +1,5 @@ /* MI Command Set. - Copyright (C) 2000, Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -33,23 +33,46 @@ #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 write_register_bytes() */ +#include "value.h" /* for deprecated_write_register_bytes() */ +#include "regcache.h" +#include "gdb.h" +#include "frame.h" + #include #include -/* 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; @@ -57,35 +80,29 @@ 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 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 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 + +/* A helper function which will set mi_error_message to + error_last_message. */ +void +mi_error_last_message (void) +{ + char *s = error_last_message (); + xasprintf (&mi_error_message, s); + xfree (s); +} /* Command implementations. FIXME: Is this libgdb? No. This is the MI layer that calls libgdb. Any operation used in the below should be @@ -156,24 +173,22 @@ mi_cmd_exec_until (char *args, int from_tty) 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 (deprecated_selected_frame, + frame_relative_level (deprecated_selected_frame), + LOC_AND_ADDRESS); return MI_CMD_DONE; } @@ -193,25 +208,24 @@ mi_cmd_exec_continue (char *args, int from_tty) 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."); + xasprintf (&mi_error_message, + "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; } @@ -222,15 +236,19 @@ mi_cmd_thread_select (char *command, char **argv, int argc) if (argc != 1) { - asprintf (&mi_error_message, - "mi_cmd_thread_select: USAGE: threadnum."); + xasprintf (&mi_error_message, + "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; } @@ -242,14 +260,12 @@ mi_cmd_thread_list_ids (char *command, char **argv, int argc) if (argc != 0) { - asprintf (&mi_error_message, - "mi_cmd_thread_list_ids: No arguments required."); + xasprintf (&mi_error_message, + "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; @@ -262,6 +278,7 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc) { 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 @@ -269,9 +286,9 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc) 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 */ { @@ -281,9 +298,9 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc) { 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)); } } @@ -291,19 +308,19 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc) 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); + xasprintf (&mi_error_message, "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; } @@ -312,6 +329,7 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) { 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 @@ -319,9 +337,9 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) case, some entries of REGISTER_NAME will change depending upon the particular processor being debugged. */ - numregs = ARCH_NUM_REGS; + numregs = NUM_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 */ { @@ -335,8 +353,9 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) 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); + xasprintf (&mi_error_message, + "mi_cmd_data_list_changed_registers: Unable to read register contents."); return MI_CMD_ERROR; } else if (changed) @@ -357,8 +376,9 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) 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); + xasprintf (&mi_error_message, + "mi_cmd_data_list_register_change: Unable to read register contents."); return MI_CMD_ERROR; } else if (changed) @@ -366,20 +386,21 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) } else { - asprintf (&mi_error_message, "bad register number"); + do_cleanups (cleanup); + xasprintf (&mi_error_message, "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, @@ -406,6 +427,7 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) { 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 @@ -413,12 +435,12 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) case, some entries of REGISTER_NAME will change depending upon the particular processor being debugged. */ - numregs = ARCH_NUM_REGS; + numregs = NUM_REGS; if (argc == 0) { - asprintf (&mi_error_message, - "mi_cmd_data_list_register_values: Usage: -data-list-register-values [...]"); + xasprintf (&mi_error_message, + "mi_cmd_data_list_register_values: Usage: -data-list-register-values [...]"); return MI_CMD_ERROR; } @@ -426,11 +448,12 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) if (!target_has_registers) { - asprintf (&mi_error_message, "mi_cmd_data_list_register_values: No registers."); + xasprintf (&mi_error_message, + "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 */ { @@ -441,12 +464,15 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) 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); } } @@ -460,20 +486,24 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) && 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); + xasprintf (&mi_error_message, "bad register number"); return MI_CMD_ERROR; } } - ui_out_list_end (uiout); + do_cleanups (list_cleanup); return MI_CMD_DONE; } @@ -481,9 +511,12 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) static int get_register (int regnum, int format) { - char raw_buffer[MAX_REGISTER_RAW_SIZE]; - char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; + char raw_buffer[MAX_REGISTER_SIZE]; + char virtual_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); @@ -491,15 +524,12 @@ get_register (int regnum, int format) 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, raw_buffer); + if (optim) { - asprintf (&mi_error_message, "Optimized out"); + xasprintf (&mi_error_message, "Optimized out"); return -1; } @@ -507,7 +537,8 @@ get_register (int regnum, int format) if (REGISTER_CONVERTIBLE (regnum)) { - REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum), + REGISTER_CONVERT_TO_VIRTUAL (regnum, + register_type (current_gdbarch, regnum), raw_buffer, virtual_buffer); } else @@ -522,7 +553,7 @@ get_register (int regnum, int format) ptr = buf + 2; for (j = 0; j < REGISTER_RAW_SIZE (regnum); j++) { - register int idx = TARGET_BYTE_ORDER == BIG_ENDIAN ? j + register int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j : REGISTER_RAW_SIZE (regnum) - 1 - j; sprintf (ptr, "%02x", (unsigned char) raw_buffer[idx]); ptr += 2; @@ -532,7 +563,7 @@ get_register (int regnum, int format) } else { - val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0, 0, + val_print (register_type (current_gdbarch, regnum), virtual_buffer, 0, 0, stb->stream, format, 1, 0, Val_pretty_default); ui_out_field_stream (uiout, "value", stb); ui_out_stream_delete (stb); @@ -549,7 +580,6 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc) int regnum; int i; int numregs; - char *buffer; LONGEST value; char format; @@ -559,12 +589,12 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc) case, some entries of REGISTER_NAME will change depending upon the particular processor being debugged. */ - numregs = ARCH_NUM_REGS; + numregs = NUM_REGS; if (argc == 0) { - asprintf (&mi_error_message, - "mi_cmd_data_write_register_values: Usage: -data-write-register-values [ ... ]"); + xasprintf (&mi_error_message, + "mi_cmd_data_write_register_values: Usage: -data-write-register-values [ ... ]"); return MI_CMD_ERROR; } @@ -572,19 +602,22 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc) if (!target_has_registers) { - asprintf (&mi_error_message, "mi_cmd_data_write_register_values: No registers."); + xasprintf (&mi_error_message, + "mi_cmd_data_write_register_values: No registers."); return MI_CMD_ERROR; } if (!(argc - 1)) { - asprintf (&mi_error_message, "mi_cmd_data_write_register_values: No regs and values specified."); + xasprintf (&mi_error_message, + "mi_cmd_data_write_register_values: No regs and values specified."); return MI_CMD_ERROR; } if ((argc - 1) % 2) { - asprintf (&mi_error_message, "mi_cmd_data_write_register_values: Regs and vals are not in pairs."); + xasprintf (&mi_error_message, + "mi_cmd_data_write_register_values: Regs and vals are not in pairs."); return MI_CMD_ERROR; } @@ -597,18 +630,23 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc) && 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 = (unsigned char *) xmalloc (REGISTER_SIZE); - store_signed_integer (buffer, REGISTER_SIZE, value); + buffer = xmalloc (DEPRECATED_REGISTER_SIZE); + old_chain = make_cleanup (xfree, buffer); + store_signed_integer (buffer, DEPRECATED_REGISTER_SIZE, value); /* Write it down */ - write_register_bytes (REGISTER_BYTE (regnum), buffer, REGISTER_RAW_SIZE (regnum)); - /* write_register_bytes (REGISTER_BYTE (regnum), buffer, REGISTER_SIZE); */ + deprecated_write_register_bytes (REGISTER_BYTE (regnum), buffer, REGISTER_RAW_SIZE (regnum)); + /* Free the buffer. */ + do_cleanups (old_chain); } else { - asprintf (&mi_error_message, "bad register number"); + xasprintf (&mi_error_message, "bad register number"); return MI_CMD_ERROR; } } @@ -630,8 +668,8 @@ mi_cmd_data_assign (char *command, char **argv, int argc) if (argc != 1) { - asprintf (&mi_error_message, - "mi_cmd_data_assign: Usage: -data-assign expression"); + xasprintf (&mi_error_message, + "mi_cmd_data_assign: Usage: -data-assign expression"); return MI_CMD_ERROR; } @@ -654,15 +692,15 @@ mi_cmd_data_evaluate_expression (char *command, char **argv, int argc) { 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"); + xasprintf (&mi_error_message, + "mi_cmd_data_evaluate_expression: Usage: -data-evaluate-expression expression"); return MI_CMD_ERROR; } @@ -691,10 +729,8 @@ mi_cmd_target_download (char *args, int from_tty) 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); + xasprintf (&run, "load %s", args); + old_cleanups = make_cleanup (xfree, run); execute_command (run, from_tty); do_cleanups (old_cleanups); @@ -708,10 +744,8 @@ mi_cmd_target_select (char *args, int from_tty) 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); + xasprintf (&run, "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. */ @@ -798,8 +832,8 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) 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]."); + xasprintf (&mi_error_message, + "mi_cmd_data_read_memory: Usage: ADDR WORD-FORMAT WORD-SIZE NR-ROWS NR-COLS [ASCHAR]."); return MI_CMD_ERROR; } @@ -838,16 +872,16 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) nr_rows = atol (argv[3]); if (nr_rows <= 0) { - asprintf (&mi_error_message, - "mi_cmd_data_read_memory: invalid number of rows."); + xasprintf (&mi_error_message, + "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."); + xasprintf (&mi_error_message, + "mi_cmd_data_read_memory: invalid number of columns."); } /* The un-printable character when printing ascii. */ if (argc == 6) @@ -857,12 +891,12 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) /* create a buffer and read it in. */ total_bytes = word_size * nr_rows * nr_cols; - mbuf = calloc (total_bytes, 1); - make_cleanup (free, mbuf); + mbuf = xcalloc (total_bytes, 1); + make_cleanup (xfree, mbuf); if (mbuf == NULL) { - asprintf (&mi_error_message, - "mi_cmd_data_read_memory: out of memory."); + xasprintf (&mi_error_message, + "mi_cmd_data_read_memory: out of memory."); return MI_CMD_ERROR; } nr_bytes = 0; @@ -889,19 +923,22 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) /* 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) @@ -918,7 +955,7 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) ui_out_field_stream (uiout, NULL, stream); } } - ui_out_list_end (uiout); + do_cleanups (cleanup_list_data); if (aschar) { int byte; @@ -938,10 +975,10 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) } 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; @@ -972,7 +1009,8 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc) /* 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; @@ -1004,8 +1042,8 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc) if (argc != 4) { - asprintf (&mi_error_message, - "mi_cmd_data_write_memory: Usage: [-o COLUMN_OFFSET] ADDR FORMAT WORD-SIZE VALUE."); + xasprintf (&mi_error_message, + "mi_cmd_data_write_memory: Usage: [-o COLUMN_OFFSET] ADDR FORMAT WORD-SIZE VALUE."); return MI_CMD_ERROR; } @@ -1024,23 +1062,30 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc) /* 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. + + args->action will tell mi_execute_command what action + to perfrom after the given command has executed (display/supress + prompt, display error). */ static int -captured_mi_execute_command (void *data) +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) { @@ -1055,11 +1100,18 @@ captured_mi_execute_command (void *data) 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); @@ -1067,30 +1119,34 @@ captured_mi_execute_command (void *data) 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 1; } 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 1; + } break; case CLI_COMMAND: @@ -1102,16 +1158,25 @@ captured_mi_execute_command (void *data) /* 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); + + /* If we changed interpreters, DON'T print out anything. */ + if (current_interp_named_p (INTERP_MI) + || current_interp_named_p (INTERP_MI1)) + { + /* 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; } @@ -1120,6 +1185,9 @@ void mi_execute_command (char *cmd, int from_tty) { struct mi_parse *command; + struct captured_mi_execute_command_args args; + struct ui_out *saved_uiout = uiout; + int result; /* This is to handle EOF (^D). We just quit gdb. */ /* FIXME: we should call some API function here. */ @@ -1130,21 +1198,23 @@ mi_execute_command (char *cmd, int from_tty) if (command != NULL) { - /* FIXME: cagney/1999-11-04: Can this use of catch_errors either + /* 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_exceptions (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 < 0) { char *msg = error_last_message (); - struct cleanup *cleanup = make_cleanup (free, msg); + struct cleanup *cleanup = make_cleanup (xfree, msg); /* The command execution failed and error() was called somewhere */ fputs_unfiltered (command->token, raw_stdout); @@ -1155,8 +1225,8 @@ mi_execute_command (char *cmd, int from_tty) mi_parse_free (command); } - gdb_flush (raw_stdout); fputs_unfiltered ("(gdb) \n", raw_stdout); + gdb_flush (raw_stdout); /* print any buffered hook code */ /* ..... */ } @@ -1225,12 +1295,6 @@ mi_cmd_execute (struct mi_parse *parse) } } -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 */ @@ -1242,14 +1306,12 @@ mi_execute_cli_command (const char *cli, char *args) { struct cleanup *old_cleanups; char *run; - asprintf (&run, cli, args); + xasprintf (&run, cli, args); 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); + old_cleanups = make_cleanup (xfree, run); execute_command ( /*ui */ run, 0 /*from_tty */ ); do_cleanups (old_cleanups); return; @@ -1269,18 +1331,15 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty) 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"); + xasprintf (&run, "%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); + xasprintf (&run, "%s %s", mi, args); + old_cleanups = make_cleanup (xfree, run); } if (!target_can_async_p ()) @@ -1292,6 +1351,7 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty) fputs_unfiltered (last_async_command, raw_stdout); fputs_unfiltered ("^running\n", raw_stdout); fputs_unfiltered ("(gdb) \n", raw_stdout); + gdb_flush (raw_stdout); } else { @@ -1333,16 +1393,11 @@ mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg) 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, @@ -1354,7 +1409,8 @@ mi_load_progress (const char *section_name, 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; @@ -1374,17 +1430,18 @@ mi_load_progress (const char *section_name, 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); @@ -1393,118 +1450,36 @@ mi_load_progress (const char *section_name, 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 () +void +mi_setup_architecture_data (void) { /* 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; -{ - /* Eventually this will contain code that takes control of the - console. */ -} - 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? */ + register_gdbarch_swap (&old_regs, sizeof (old_regs), NULL); + register_gdbarch_swap (NULL, 0, mi_setup_architecture_data); }