diff options
Diffstat (limited to 'contrib/gdb/gdb/mi')
-rw-r--r-- | contrib/gdb/gdb/mi/mi-cmd-break.c | 5 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-cmd-disas.c | 368 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-cmd-env.c | 259 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-cmd-file.c | 67 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-cmd-stack.c | 106 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-cmd-var.c | 87 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-cmds.c | 266 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-cmds.h | 53 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-console.c | 27 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-console.h | 4 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-getopt.c | 16 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-getopt.h | 20 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-interp.c | 406 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-main.c | 437 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-main.h | 33 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-out.c | 115 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-out.h | 3 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-parse.c | 14 | ||||
-rw-r--r-- | contrib/gdb/gdb/mi/mi-symbol-cmds.c | 67 |
19 files changed, 1458 insertions, 895 deletions
diff --git a/contrib/gdb/gdb/mi/mi-cmd-break.c b/contrib/gdb/gdb/mi/mi-cmd-break.c index 5061392..5d15aa9 100644 --- a/contrib/gdb/gdb/mi/mi-cmd-break.c +++ b/contrib/gdb/gdb/mi/mi-cmd-break.c @@ -29,11 +29,6 @@ #include "gdb-events.h" #include "gdb.h" -/* Convenience macro for allocting typesafe memory. */ - -#undef XMALLOC -#define XMALLOC(TYPE) (TYPE*) xmalloc (sizeof (TYPE)) - enum { FROM_TTY = 0 diff --git a/contrib/gdb/gdb/mi/mi-cmd-disas.c b/contrib/gdb/gdb/mi/mi-cmd-disas.c index 7596c06..168ca17 100644 --- a/contrib/gdb/gdb/mi/mi-cmd-disas.c +++ b/contrib/gdb/gdb/mi/mi-cmd-disas.c @@ -24,67 +24,9 @@ #include "value.h" #include "mi-cmds.h" #include "mi-getopt.h" +#include "gdb_string.h" #include "ui-out.h" - -static int gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr, unsigned int len, - disassemble_info * info); -static int compare_lines (const PTR mle1p, const PTR mle2p); - -/* Disassemble functions. FIXME: these do not really belong here. We - should get rid of all the duplicate code in gdb that does the same - thing: disassemble_command() and the gdbtk variation. */ - -/* This Structure is used in mi_cmd_disassemble. - We need a different sort of line table from the normal one cuz we can't - depend upon implicit line-end pc's for lines to do the - reordering in this function. */ - -struct dis_line_entry - { - int line; - CORE_ADDR start_pc; - CORE_ADDR end_pc; - }; - -/* This variable determines where memory used for disassembly is read from. */ -int gdb_disassemble_from_exec = -1; - -/* This is the memory_read_func for gdb_disassemble when we are - disassembling from the exec file. */ -static int -gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr, - unsigned int len, disassemble_info * info) -{ - extern struct target_ops exec_ops; - int res; - - errno = 0; - res = xfer_memory (memaddr, myaddr, len, 0, 0, &exec_ops); - - if (res == len) - return 0; - else if (errno == 0) - return EIO; - else - return errno; -} - -static int -compare_lines (const PTR mle1p, const PTR mle2p) -{ - struct dis_line_entry *mle1, *mle2; - int val; - - mle1 = (struct dis_line_entry *) mle1p; - mle2 = (struct dis_line_entry *) mle2p; - - val = mle1->line - mle2->line; - - if (val != 0) - return val; - - return mle1->start_pc - mle2->start_pc; -} +#include "disasm.h" /* The arguments to be passed on the command line and parsed here are: @@ -106,30 +48,15 @@ compare_lines (const PTR mle1p, const PTR mle2p) MODE: 0 or 1 for disassembly only, or mixed source and disassembly, respectively. */ - enum mi_cmd_result mi_cmd_disassemble (char *command, char **argv, int argc) { - CORE_ADDR pc; + enum mi_cmd_result retval; CORE_ADDR start; int mixed_source_and_assembly; - int num_displayed; - static disassemble_info di; - static int di_initialized; - struct symtab *s; - /* To collect the instruction outputted from opcodes. */ - static struct ui_stream *stb = NULL; - - /* parts of the symbolic representation of the address */ - int line; - int offset; - int unmapped; - char *filename = NULL; - char *name = NULL; - /* Which options have we processed ... */ int file_seen = 0; int line_seen = 0; @@ -148,11 +75,10 @@ mi_cmd_disassemble (char *command, char **argv, int argc) int optind = 0; char *optarg; enum opt - { - FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT - }; - static struct mi_opt opts[] = { + FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT + }; + static struct mi_opt opts[] = { {"f", FILE_OPT, 1}, {"l", LINE_OPT, 1}, {"n", NUM_OPT, 1}, @@ -201,16 +127,19 @@ mi_cmd_disassemble (char *command, char **argv, int argc) if (!((line_seen && file_seen && num_seen && !start_seen && !end_seen) || (line_seen && file_seen && !num_seen && !start_seen && !end_seen) - || (!line_seen && !file_seen && !num_seen && start_seen && end_seen))) - error ("mi_cmd_disassemble: Usage: ( [-f filename -l linenum [-n howmany]] | [-s startaddr -e endaddr]) [--] mixed_mode."); + || (!line_seen && !file_seen && !num_seen && start_seen && end_seen))) + error + ("mi_cmd_disassemble: Usage: ( [-f filename -l linenum [-n howmany]] | [-s startaddr -e endaddr]) [--] mixed_mode."); if (argc != 1) - error ("mi_cmd_disassemble: Usage: [-f filename -l linenum [-n howmany]] [-s startaddr -e endaddr] [--] mixed_mode."); + error + ("mi_cmd_disassemble: Usage: [-f filename -l linenum [-n howmany]] [-s startaddr -e endaddr] [--] mixed_mode."); mixed_source_and_assembly = atoi (argv[0]); if ((mixed_source_and_assembly != 0) && (mixed_source_and_assembly != 1)) error ("mi_cmd_disassemble: Mixed_mode argument must be 0 or 1."); + /* We must get the function beginning and end where line_num is contained. */ @@ -225,275 +154,10 @@ mi_cmd_disassemble (char *command, char **argv, int argc) error ("mi_cmd_disassemble: No function contains specified address"); } - if (!di_initialized) - { - /* We don't add a cleanup for this, because the allocation of - the stream is done once only for each gdb run, and we need to - keep it around until the end. Hopefully there won't be any - errors in the init code below, that make this function bail - out. */ - stb = ui_out_stream_new (uiout); - INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream, - (fprintf_ftype) fprintf_unfiltered); - di.flavour = bfd_target_unknown_flavour; - di.memory_error_func = dis_asm_memory_error; - di.print_address_func = dis_asm_print_address; - di_initialized = 1; - } - - di.mach = TARGET_PRINT_INSN_INFO->mach; - if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) - di.endian = BFD_ENDIAN_BIG; - else - di.endian = BFD_ENDIAN_LITTLE; - - /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to - determine whether or not to do disassembly from target memory or from the - exec file: - - If we're debugging a local process, read target memory, instead of the - exec file. This makes disassembly of functions in shared libs work - correctly. Also, read target memory if we are debugging native threads. - - Else, we're debugging a remote process, and should disassemble from the - exec file for speed. However, this is no good if the target modifies its - code (for relocation, or whatever). - */ - - if (gdb_disassemble_from_exec == -1) - { - if (strcmp (target_shortname, "child") == 0 - || strcmp (target_shortname, "procfs") == 0 - || strcmp (target_shortname, "vxprocess") == 0 - || strstr (target_shortname, "-threads") != NULL) - gdb_disassemble_from_exec = 0; /* It's a child process, read inferior mem */ - else - gdb_disassemble_from_exec = 1; /* It's remote, read the exec file */ - } - - if (gdb_disassemble_from_exec) - di.read_memory_func = gdb_dis_asm_read_memory; - else - di.read_memory_func = dis_asm_read_memory; - - /* If just doing straight assembly, all we need to do is disassemble - everything between low and high. If doing mixed source/assembly, - we've got a totally different path to follow. */ - - if (mixed_source_and_assembly) - { - /* Come here for mixed source/assembly */ - /* The idea here is to present a source-O-centric view of a - function to the user. This means that things are presented - in source order, with (possibly) out of order assembly - immediately following. */ - struct symtab *symtab; - struct linetable_entry *le; - int nlines; - int newlines; - struct dis_line_entry *mle; - struct symtab_and_line sal; - int i; - int out_of_order; - int next_line; - - /* Assume symtab is valid for whole PC range */ - symtab = find_pc_symtab (low); - - if (!symtab || !symtab->linetable) - goto assembly_only; - - /* First, convert the linetable to a bunch of my_line_entry's. */ - - le = symtab->linetable->item; - nlines = symtab->linetable->nitems; - - if (nlines <= 0) - goto assembly_only; - - mle = (struct dis_line_entry *) alloca (nlines * sizeof (struct dis_line_entry)); - - out_of_order = 0; - - /* Copy linetable entries for this function into our data - structure, creating end_pc's and setting out_of_order as - appropriate. */ - - /* First, skip all the preceding functions. */ - - for (i = 0; i < nlines - 1 && le[i].pc < low; i++); - - /* Now, copy all entries before the end of this function. */ - - newlines = 0; - for (; i < nlines - 1 && le[i].pc < high; i++) - { - if (le[i].line == le[i + 1].line - && le[i].pc == le[i + 1].pc) - continue; /* Ignore duplicates */ - - /* Skip any end-of-function markers. */ - if (le[i].line == 0) - continue; - - mle[newlines].line = le[i].line; - if (le[i].line > le[i + 1].line) - out_of_order = 1; - mle[newlines].start_pc = le[i].pc; - mle[newlines].end_pc = le[i + 1].pc; - newlines++; - } - - /* If we're on the last line, and it's part of the function, - then we need to get the end pc in a special way. */ - - if (i == nlines - 1 - && le[i].pc < high) - { - mle[newlines].line = le[i].line; - mle[newlines].start_pc = le[i].pc; - sal = find_pc_line (le[i].pc, 0); - mle[newlines].end_pc = sal.end; - newlines++; - } - - /* Now, sort mle by line #s (and, then by addresses within - lines). */ - - if (out_of_order) - qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines); - - /* Now, for each line entry, emit the specified lines (unless - they have been emitted before), followed by the assembly code - for that line. */ - - next_line = 0; /* Force out first line */ - ui_out_list_begin (uiout, "asm_insns"); - num_displayed = 0; - for (i = 0; i < newlines; i++) - { - int close_list = 1; - /* Print out everything from next_line to the current line. */ - if (mle[i].line >= next_line) - { - if (next_line != 0) - { - /* Just one line to print. */ - if (next_line == mle[i].line) - { - ui_out_tuple_begin (uiout, "src_and_asm_line"); - print_source_lines (symtab, next_line, mle[i].line + 1, 0); - } - else - { - /* Several source lines w/o asm instructions associated. */ - for (; next_line < mle[i].line; next_line++) - { - ui_out_tuple_begin (uiout, "src_and_asm_line"); - print_source_lines (symtab, next_line, mle[i].line + 1, 0); - ui_out_list_begin (uiout, "line_asm_insn"); - ui_out_list_end (uiout); - ui_out_tuple_end (uiout); - } - /* Print the last line and leave list open for - asm instructions to be added. */ - ui_out_tuple_begin (uiout, "src_and_asm_line"); - print_source_lines (symtab, next_line, mle[i].line + 1, 0); - } - } - else - { - ui_out_tuple_begin (uiout, "src_and_asm_line"); - print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0); - } - - next_line = mle[i].line + 1; - ui_out_list_begin (uiout, "line_asm_insn"); - if (i + 1 < newlines && mle[i + 1].line <= mle[i].line) - close_list = 0; - } - for (pc = mle[i].start_pc; pc < mle[i].end_pc;) - { - QUIT; - if (how_many >= 0) - { - if (num_displayed >= how_many) - break; - else - num_displayed++; - } - ui_out_tuple_begin (uiout, NULL); - ui_out_field_core_addr (uiout, "address", pc); - - if (!build_address_symbolic (pc, 0, &name, &offset, &filename, &line, &unmapped)) - { - /* We don't care now about line, filename and - unmapped, but we might in the future. */ - ui_out_field_string (uiout, "func-name", name); - ui_out_field_int (uiout, "offset", offset); - } - if (filename != NULL) - xfree (filename); - if (name != NULL) - xfree (name); - - ui_file_rewind (stb->stream); - pc += (*tm_print_insn) (pc, &di); - ui_out_field_stream (uiout, "inst", stb); - ui_file_rewind (stb->stream); - ui_out_tuple_end (uiout); - } - if (close_list) - { - ui_out_list_end (uiout); - ui_out_tuple_end (uiout); - close_list = 0; - } - if (how_many >= 0) - if (num_displayed >= how_many) - break; - } - ui_out_list_end (uiout); - } - else - { - assembly_only: - ui_out_list_begin (uiout, "asm_insns"); - num_displayed = 0; - for (pc = low; pc < high;) - { - QUIT; - if (how_many >= 0) - { - if (num_displayed >= how_many) - break; - else - num_displayed++; - } - ui_out_tuple_begin (uiout, NULL); - ui_out_field_core_addr (uiout, "address", pc); - - if (!build_address_symbolic (pc, 0, &name, &offset, &filename, &line, &unmapped)) - { - /* We don't care now about line, filename and - unmapped. But we might in the future. */ - ui_out_field_string (uiout, "func-name", name); - ui_out_field_int (uiout, "offset", offset); - } - if (filename != NULL) - xfree (filename); - if (name != NULL) - xfree (name); - - ui_file_rewind (stb->stream); - pc += (*tm_print_insn) (pc, &di); - ui_out_field_stream (uiout, "inst", stb); - ui_file_rewind (stb->stream); - ui_out_tuple_end (uiout); - } - ui_out_list_end (uiout); - } - gdb_flush (gdb_stdout); + gdb_disassembly (uiout, + file_string, + line_num, + mixed_source_and_assembly, how_many, low, high); return MI_CMD_DONE; } diff --git a/contrib/gdb/gdb/mi/mi-cmd-env.c b/contrib/gdb/gdb/mi/mi-cmd-env.c new file mode 100644 index 0000000..439c719 --- /dev/null +++ b/contrib/gdb/gdb/mi/mi-cmd-env.c @@ -0,0 +1,259 @@ +/* MI Command Set - environment commands. + + Copyright 2002, 2003, 2004 Free Software Foundation, Inc. + + Contributed by Red Hat Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "value.h" +#include "mi-out.h" +#include "mi-cmds.h" +#include "mi-getopt.h" +#include "symtab.h" +#include "target.h" +#include "environ.h" +#include "command.h" +#include "ui-out.h" +#include "top.h" + +#include "gdb_string.h" +#include "gdb_stat.h" + +static void env_mod_path (char *dirname, char **which_path); +extern void _initialize_mi_cmd_env (void); + +static const char path_var_name[] = "PATH"; +static char *orig_path = NULL; + +/* The following is copied from mi-main.c so for m1 and below we can + perform old behavior and use cli commands. If ARGS is non-null, + append it to the CMD. */ +static void +env_execute_cli_command (const char *cmd, const char *args) +{ + if (cmd != 0) + { + struct cleanup *old_cleanups; + char *run; + if (args != NULL) + xasprintf (&run, "%s %s", cmd, args); + else + run = xstrdup (cmd); + old_cleanups = make_cleanup (xfree, run); + execute_command ( /*ui */ run, 0 /*from_tty */ ); + do_cleanups (old_cleanups); + return; + } +} + + +/* Print working directory. */ +enum mi_cmd_result +mi_cmd_env_pwd (char *command, char **argv, int argc) +{ + if (argc > 0) + error ("mi_cmd_env_pwd: No arguments required"); + + if (mi_version (uiout) < 2) + { + env_execute_cli_command ("pwd", NULL); + return MI_CMD_DONE; + } + + /* Otherwise the mi level is 2 or higher. */ + + getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)); + ui_out_field_string (uiout, "cwd", gdb_dirbuf); + + return MI_CMD_DONE; +} + +/* Change working directory. */ +enum mi_cmd_result +mi_cmd_env_cd (char *command, char **argv, int argc) +{ + if (argc == 0 || argc > 1) + error ("mi_cmd_env_cd: Usage DIRECTORY"); + + env_execute_cli_command ("cd", argv[0]); + + return MI_CMD_DONE; +} + +static void +env_mod_path (char *dirname, char **which_path) +{ + if (dirname == 0 || dirname[0] == '\0') + return; + + /* Call add_path with last arg 0 to indicate not to parse for + separator characters. */ + add_path (dirname, which_path, 0); +} + +/* Add one or more directories to start of executable search path. */ +enum mi_cmd_result +mi_cmd_env_path (char *command, char **argv, int argc) +{ + char *exec_path; + char *env; + int reset = 0; + int optind = 0; + int i; + char *optarg; + enum opt + { + RESET_OPT + }; + static struct mi_opt opts[] = + { + {"r", RESET_OPT, 0}, + 0 + }; + + dont_repeat (); + + if (mi_version (uiout) < 2) + { + for (i = argc - 1; i >= 0; --i) + env_execute_cli_command ("path", argv[i]); + return MI_CMD_DONE; + } + + /* Otherwise the mi level is 2 or higher. */ + while (1) + { + int opt = mi_getopt ("mi_cmd_env_path", argc, argv, opts, + &optind, &optarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case RESET_OPT: + reset = 1; + break; + } + } + argv += optind; + argc -= optind; + + + if (reset) + { + /* Reset implies resetting to original path first. */ + exec_path = xstrdup (orig_path); + } + else + { + /* Otherwise, get current path to modify. */ + env = get_in_environ (inferior_environ, path_var_name); + + /* Can be null if path is not set. */ + if (!env) + env = ""; + exec_path = xstrdup (env); + } + + for (i = argc - 1; i >= 0; --i) + env_mod_path (argv[i], &exec_path); + + set_in_environ (inferior_environ, path_var_name, exec_path); + xfree (exec_path); + env = get_in_environ (inferior_environ, path_var_name); + ui_out_field_string (uiout, "path", env); + + return MI_CMD_DONE; +} + +/* Add zero or more directories to the front of the source path. */ +enum mi_cmd_result +mi_cmd_env_dir (char *command, char **argv, int argc) +{ + int i; + int optind = 0; + int reset = 0; + char *optarg; + enum opt + { + RESET_OPT + }; + static struct mi_opt opts[] = + { + {"r", RESET_OPT, 0}, + 0 + }; + + dont_repeat (); + + if (mi_version (uiout) < 2) + { + for (i = argc - 1; i >= 0; --i) + env_execute_cli_command ("dir", argv[i]); + return MI_CMD_DONE; + } + + /* Otherwise mi level is 2 or higher. */ + while (1) + { + int opt = mi_getopt ("mi_cmd_env_dir", argc, argv, opts, + &optind, &optarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case RESET_OPT: + reset = 1; + break; + } + } + argv += optind; + argc -= optind; + + if (reset) + { + /* Reset means setting to default path first. */ + xfree (source_path); + init_source_path (); + } + + for (i = argc - 1; i >= 0; --i) + env_mod_path (argv[i], &source_path); + init_last_source_visited (); + + ui_out_field_string (uiout, "source-path", source_path); + forget_cached_source_info (); + + return MI_CMD_DONE; +} + +void +_initialize_mi_cmd_env (void) +{ + char *env; + + /* We want original execution path to reset to, if desired later. */ + env = get_in_environ (inferior_environ, path_var_name); + + /* Can be null if path is not set. */ + if (!env) + env = ""; + orig_path = xstrdup (env); +} diff --git a/contrib/gdb/gdb/mi/mi-cmd-file.c b/contrib/gdb/gdb/mi/mi-cmd-file.c new file mode 100644 index 0000000..eb1d67a --- /dev/null +++ b/contrib/gdb/gdb/mi/mi-cmd-file.c @@ -0,0 +1,67 @@ +/* MI Command Set - breakpoint and watchpoint commands. + Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Contributed by Cygnus Solutions (a Red Hat company). + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "mi-cmds.h" +#include "mi-getopt.h" +#include "ui-out.h" +#include "symtab.h" +#include "source.h" + +/* Return to the client the absolute path and line number of the + current file being executed. */ + +enum mi_cmd_result +mi_cmd_file_list_exec_source_file(char *command, char **argv, int argc) +{ + struct symtab_and_line st; + int optind = 0; + char *optarg; + + if ( !mi_valid_noargs("mi_cmd_file_list_exec_source_file", argc, argv) ) + error ("mi_cmd_file_list_exec_source_file: Usage: No args"); + + + /* Set the default file and line, also get them */ + set_default_source_symtab_and_line(); + st = get_current_source_symtab_and_line(); + + /* We should always get a symtab. + Apparently, filename does not need to be tested for NULL. + The documentation in symtab.h suggests it will always be correct */ + if (!st.symtab) + error ("mi_cmd_file_list_exec_source_file: No symtab"); + + /* Extract the fullname if it is not known yet */ + if (st.symtab->fullname == NULL) + symtab_to_filename (st.symtab); + + /* We may not be able to open the file (not available). */ + if (st.symtab->fullname == NULL) + error ("mi_cmd_file_list_exec_source_file: File not found"); + + /* Print to the user the line, filename and fullname */ + ui_out_field_int (uiout, "line", st.line); + ui_out_field_string (uiout, "file", st.symtab->filename); + ui_out_field_string (uiout, "fullname", st.symtab->fullname); + + return MI_CMD_DONE; +} diff --git a/contrib/gdb/gdb/mi/mi-cmd-stack.c b/contrib/gdb/gdb/mi/mi-cmd-stack.c index 0e4bdf4..7db9ffb 100644 --- a/contrib/gdb/gdb/mi/mi-cmd-stack.c +++ b/contrib/gdb/gdb/mi/mi-cmd-stack.c @@ -1,5 +1,5 @@ /* MI Command Set - stack commands. - Copyright 2000, 2002 Free Software Foundation, Inc. + Copyright 2000, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -26,11 +26,10 @@ #include "mi-cmds.h" #include "ui-out.h" #include "symtab.h" - -/* FIXME: these should go in some .h file but stack.c doesn't have a - corresponding .h file. These wrappers will be obsolete anyway, once - we pull the plug on the sanitization. */ -extern void select_frame_command_wrapper (char *, int); +#include "block.h" +#include "stack.h" +#include "dictionary.h" +#include "gdb_string.h" static void list_args_or_locals (int locals, int values, struct frame_info *fi); @@ -45,6 +44,7 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc) int frame_low; int frame_high; int i; + struct cleanup *cleanup_stack; struct frame_info *fi; if (!target_has_stack) @@ -76,7 +76,7 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc) if (fi == NULL) error ("mi_cmd_stack_list_frames: Not enough frames in stack."); - ui_out_list_begin (uiout, "stack"); + cleanup_stack = make_cleanup_ui_out_list_begin_end (uiout, "stack"); /* Now let;s print the frames up to frame_high, or until there are frames in the stack. */ @@ -95,7 +95,7 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc) 0 /* args */ ); } - ui_out_list_end (uiout); + do_cleanups (cleanup_stack); if (i < frame_high) error ("mi_cmd_stack_list_frames: Not enough frames in stack."); @@ -138,10 +138,26 @@ mi_cmd_stack_info_depth (char *command, char **argv, int argc) enum mi_cmd_result mi_cmd_stack_list_locals (char *command, char **argv, int argc) { + struct frame_info *frame; + enum print_values print_values; + if (argc != 1) error ("mi_cmd_stack_list_locals: Usage: PRINT_VALUES"); - list_args_or_locals (1, atoi (argv[0]), selected_frame); + frame = get_selected_frame (); + + if (strcmp (argv[0], "0") == 0 + || strcmp (argv[0], "--no-values") == 0) + print_values = PRINT_NO_VALUES; + else if (strcmp (argv[0], "1") == 0 + || strcmp (argv[0], "--all-values") == 0) + print_values = PRINT_ALL_VALUES; + else if (strcmp (argv[0], "2") == 0 + || strcmp (argv[0], "--simple-values") == 0) + print_values = PRINT_SIMPLE_VALUES; + else + error ("Unknown value for PRINT_VALUES: must be: 0 or \"--no-values\", 1 or \"--all-values\", 2 or \"--simple-values\""); + list_args_or_locals (1, print_values, frame); return MI_CMD_DONE; } @@ -155,6 +171,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) int frame_high; int i; struct frame_info *fi; + struct cleanup *cleanup_stack_args; if (argc < 1 || argc > 3 || argc == 2) error ("mi_cmd_stack_list_args: Usage: PRINT_VALUES [FRAME_LOW FRAME_HIGH]"); @@ -182,7 +199,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) if (fi == NULL) error ("mi_cmd_stack_list_args: Not enough frames in stack."); - ui_out_list_begin (uiout, "stack-args"); + cleanup_stack_args = make_cleanup_ui_out_list_begin_end (uiout, "stack-args"); /* Now let's print the frames up to frame_high, or until there are frames in the stack. */ @@ -190,14 +207,15 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) fi && (i <= frame_high || frame_high == -1); i++, fi = get_prev_frame (fi)) { + struct cleanup *cleanup_frame; QUIT; - ui_out_tuple_begin (uiout, "frame"); + cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame"); ui_out_field_int (uiout, "level", i); list_args_or_locals (0, atoi (argv[0]), fi); - ui_out_tuple_end (uiout); + do_cleanups (cleanup_frame); } - ui_out_list_end (uiout); + do_cleanups (cleanup_stack_args); if (i < frame_high) error ("mi_cmd_stack_list_args: Not enough frames in stack."); @@ -213,18 +231,21 @@ list_args_or_locals (int locals, int values, struct frame_info *fi) { struct block *block; struct symbol *sym; - int i, nsyms; + struct dict_iterator iter; + int nsyms; + struct cleanup *cleanup_list; static struct ui_stream *stb = NULL; + struct type *type; stb = ui_out_stream_new (uiout); - block = get_frame_block (fi); + block = get_frame_block (fi, 0); - ui_out_list_begin (uiout, locals ? "locals" : "args"); + cleanup_list = make_cleanup_ui_out_list_begin_end (uiout, locals ? "locals" : "args"); while (block != 0) { - ALL_BLOCK_SYMBOLS (block, i, sym) + ALL_BLOCK_SYMBOLS (block, iter, sym) { int print_me = 0; @@ -248,6 +269,7 @@ list_args_or_locals (int locals, int values, struct frame_info *fi) case LOC_REGPARM_ADDR: /* indirect register arg */ case LOC_LOCAL_ARG: /* stack arg */ case LOC_BASEREG_ARG: /* basereg arg */ + case LOC_COMPUTED_ARG: /* arg with computed location */ if (!locals) print_me = 1; break; @@ -256,29 +278,47 @@ list_args_or_locals (int locals, int values, struct frame_info *fi) case LOC_BASEREG: /* basereg local */ case LOC_STATIC: /* static */ case LOC_REGISTER: /* register */ + case LOC_COMPUTED: /* computed location */ if (locals) print_me = 1; break; } if (print_me) { - if (values) - ui_out_tuple_begin (uiout, NULL); - ui_out_field_string (uiout, "name", SYMBOL_NAME (sym)); + struct cleanup *cleanup_tuple = NULL; + struct symbol *sym2; + if (values != PRINT_NO_VALUES) + cleanup_tuple = + make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + ui_out_field_string (uiout, "name", SYMBOL_PRINT_NAME (sym)); - if (values) - { - struct symbol *sym2; - if (!locals) - sym2 = lookup_symbol (SYMBOL_NAME (sym), - block, VAR_NAMESPACE, - (int *) NULL, - (struct symtab **) NULL); - else + if (!locals) + sym2 = lookup_symbol (SYMBOL_NATURAL_NAME (sym), + block, VAR_DOMAIN, + (int *) NULL, + (struct symtab **) NULL); + else sym2 = sym; + switch (values) + { + case PRINT_SIMPLE_VALUES: + type = check_typedef (sym2->type); + type_print (sym2->type, "", stb->stream, -1); + ui_out_field_stream (uiout, "type", stb); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + { + print_variable_value (sym2, fi, stb->stream); + ui_out_field_stream (uiout, "value", stb); + } + do_cleanups (cleanup_tuple); + break; + case PRINT_ALL_VALUES: print_variable_value (sym2, fi, stb->stream); ui_out_field_stream (uiout, "value", stb); - ui_out_tuple_end (uiout); + do_cleanups (cleanup_tuple); + break; } } } @@ -287,7 +327,7 @@ list_args_or_locals (int locals, int values, struct frame_info *fi) else block = BLOCK_SUPERBLOCK (block); } - ui_out_list_end (uiout); + do_cleanups (cleanup_list); ui_out_stream_delete (stb); } @@ -302,8 +342,8 @@ mi_cmd_stack_select_frame (char *command, char **argv, int argc) /* with no args, don't change frame */ if (argc == 0) - select_frame_command_wrapper (0, 1 /* not used */ ); + select_frame_command (0, 1 /* not used */ ); else - select_frame_command_wrapper (argv[0], 1 /* not used */ ); + select_frame_command (argv[0], 1 /* not used */ ); return MI_CMD_DONE; } diff --git a/contrib/gdb/gdb/mi/mi-cmd-var.c b/contrib/gdb/gdb/mi/mi-cmd-var.c index 0c84064..709ed30 100644 --- a/contrib/gdb/gdb/mi/mi-cmd-var.c +++ b/contrib/gdb/gdb/mi/mi-cmd-var.c @@ -1,5 +1,7 @@ /* MI Command Set - varobj commands. - Copyright 2000 Free Software Foundation, Inc. + + Copyright 2000, 2002, 2004 Free Software Foundation, Inc. + Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -26,11 +28,7 @@ #include "varobj.h" #include "value.h" #include <ctype.h> - -/* Convenience macro for allocting typesafe memory. */ - -#undef XMALLOC -#define XMALLOC(TYPE) (TYPE*) xmalloc (sizeof (TYPE)) +#include "gdb_string.h" extern int varobjdebug; /* defined in varobj.c */ @@ -83,7 +81,7 @@ mi_cmd_var_create (char *command, char **argv, int argc) else { var_type = USE_SPECIFIED_FRAME; - frameaddr = parse_and_eval_address (frame); + frameaddr = string_to_core_addr (frame); } if (varobjdebug) @@ -191,15 +189,15 @@ mi_cmd_var_set_format (char *command, char **argv, int argc) len = strlen (formspec); - if (STREQN (formspec, "natural", len)) + if (strncmp (formspec, "natural", len) == 0) format = FORMAT_NATURAL; - else if (STREQN (formspec, "binary", len)) + else if (strncmp (formspec, "binary", len) == 0) format = FORMAT_BINARY; - else if (STREQN (formspec, "decimal", len)) + else if (strncmp (formspec, "decimal", len) == 0) format = FORMAT_DECIMAL; - else if (STREQN (formspec, "hexadecimal", len)) + else if (strncmp (formspec, "hexadecimal", len) == 0) format = FORMAT_HEXADECIMAL; - else if (STREQN (formspec, "octal", len)) + else if (strncmp (formspec, "octal", len) == 0) format = FORMAT_OCTAL; else error ("mi_cmd_var_set_format: Unknown display format: must be: \"natural\", \"binary\", \"decimal\", \"hexadecimal\", or \"octal\""); @@ -256,39 +254,58 @@ mi_cmd_var_list_children (char *command, char **argv, int argc) struct varobj *var; struct varobj **childlist; struct varobj **cc; + struct cleanup *cleanup_children; int numchild; char *type; + enum print_values print_values; - if (argc != 1) - error ("mi_cmd_var_list_children: Usage: NAME."); + if (argc != 1 && argc != 2) + error ("mi_cmd_var_list_children: Usage: [PRINT_VALUES] NAME"); /* Get varobj handle, if a valid var obj name was specified */ - var = varobj_get_handle (argv[0]); + if (argc == 1) var = varobj_get_handle (argv[0]); + else var = varobj_get_handle (argv[1]); if (var == NULL) - error ("mi_cmd_var_list_children: Variable object not found"); + error ("Variable object not found"); numchild = varobj_list_children (var, &childlist); ui_out_field_int (uiout, "numchild", numchild); + if (argc == 2) + if (strcmp (argv[0], "0") == 0 + || strcmp (argv[0], "--no-values") == 0) + print_values = PRINT_NO_VALUES; + else if (strcmp (argv[0], "1") == 0 + || strcmp (argv[0], "--all-values") == 0) + print_values = PRINT_ALL_VALUES; + else + error ("Unknown value for PRINT_VALUES: must be: 0 or \"--no-values\", 1 or \"--all-values\""); + else print_values = PRINT_NO_VALUES; if (numchild <= 0) return MI_CMD_DONE; - ui_out_tuple_begin (uiout, "children"); + if (mi_version (uiout) == 1) + cleanup_children = make_cleanup_ui_out_tuple_begin_end (uiout, "children"); + else + cleanup_children = make_cleanup_ui_out_list_begin_end (uiout, "children"); cc = childlist; while (*cc != NULL) { - ui_out_tuple_begin (uiout, "child"); + struct cleanup *cleanup_child; + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, "child"); ui_out_field_string (uiout, "name", varobj_get_objname (*cc)); ui_out_field_string (uiout, "exp", varobj_get_expression (*cc)); ui_out_field_int (uiout, "numchild", varobj_get_num_children (*cc)); + if (print_values) + ui_out_field_string (uiout, "value", varobj_get_value (*cc)); type = varobj_get_type (*cc); /* C++ pseudo-variables (public, private, protected) do not have a type */ if (type) ui_out_field_string (uiout, "type", varobj_get_type (*cc)); - ui_out_tuple_end (uiout); + do_cleanups (cleanup_child); cc++; } - ui_out_tuple_end (uiout); + do_cleanups (cleanup_children); xfree (childlist); return MI_CMD_DONE; } @@ -407,6 +424,7 @@ mi_cmd_var_update (char *command, char **argv, int argc) struct varobj *var; struct varobj **rootlist; struct varobj **cr; + struct cleanup *cleanup; char *name; int nv; @@ -421,10 +439,13 @@ mi_cmd_var_update (char *command, char **argv, int argc) if ((*name == '*') && (*(name + 1) == '\0')) { nv = varobj_list (&rootlist); - ui_out_tuple_begin (uiout, "changelist"); + if (mi_version (uiout) <= 1) + cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, "changelist"); + else + cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changelist"); if (nv <= 0) { - ui_out_tuple_end (uiout); + do_cleanups (cleanup); return MI_CMD_DONE; } cr = rootlist; @@ -434,7 +455,7 @@ mi_cmd_var_update (char *command, char **argv, int argc) cr++; } xfree (rootlist); - ui_out_tuple_end (uiout); + do_cleanups (cleanup); } else { @@ -443,9 +464,12 @@ mi_cmd_var_update (char *command, char **argv, int argc) if (var == NULL) error ("mi_cmd_var_update: Variable object not found"); - ui_out_tuple_begin (uiout, "changelist"); + if (mi_version (uiout) <= 1) + cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, "changelist"); + else + cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changelist"); varobj_update_one (var); - ui_out_tuple_end (uiout); + do_cleanups (cleanup); } return MI_CMD_DONE; } @@ -459,6 +483,7 @@ varobj_update_one (struct varobj *var) { struct varobj **changelist; struct varobj **cc; + struct cleanup *cleanup = NULL; int nc; nc = varobj_update (&var, &changelist); @@ -471,17 +496,25 @@ varobj_update_one (struct varobj *var) return 1; else if (nc == -1) { + if (mi_version (uiout) > 1) + cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ui_out_field_string (uiout, "name", varobj_get_objname(var)); ui_out_field_string (uiout, "in_scope", "false"); + if (mi_version (uiout) > 1) + do_cleanups (cleanup); return -1; } else if (nc == -2) { + if (mi_version (uiout) > 1) + cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ui_out_field_string (uiout, "name", varobj_get_objname (var)); ui_out_field_string (uiout, "in_scope", "true"); ui_out_field_string (uiout, "new_type", varobj_get_type(var)); ui_out_field_int (uiout, "new_num_children", varobj_get_num_children(var)); + if (mi_version (uiout) > 1) + do_cleanups (cleanup); } else { @@ -489,9 +522,13 @@ varobj_update_one (struct varobj *var) cc = changelist; while (*cc != NULL) { + if (mi_version (uiout) > 1) + cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ui_out_field_string (uiout, "name", varobj_get_objname (*cc)); ui_out_field_string (uiout, "in_scope", "true"); ui_out_field_string (uiout, "type_changed", "false"); + if (mi_version (uiout) > 1) + do_cleanups (cleanup); cc++; } xfree (changelist); diff --git a/contrib/gdb/gdb/mi/mi-cmds.c b/contrib/gdb/gdb/mi/mi-cmds.c index 233d06b..0dfc217 100644 --- a/contrib/gdb/gdb/mi/mi-cmds.c +++ b/contrib/gdb/gdb/mi/mi-cmds.c @@ -1,5 +1,7 @@ -/* MI Command Set. - Copyright 2000, 2001 Free Software Foundation, Inc. +/* MI Command Set for GDB, the GNU debugger. + + Copyright 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -32,134 +34,138 @@ static void build_table (struct mi_cmd *commands); struct mi_cmd mi_cmds[] = { - {"break-after", "ignore %s", 0}, - {"break-catch", 0, 0}, - {"break-commands", 0, 0}, - {"break-condition", "cond %s", 0}, - {"break-delete", "delete breakpoint %s", 0}, - {"break-disable", "disable breakpoint %s", 0}, - {"break-enable", "enable breakpoint %s", 0}, - {"break-info", "info break %s", 0}, - {"break-insert", 0, 0, mi_cmd_break_insert}, - {"break-list", "info break", 0}, - {"break-watch", 0, 0, mi_cmd_break_watch}, - {"data-disassemble", 0, 0, mi_cmd_disassemble}, - {"data-evaluate-expression", 0, 0, mi_cmd_data_evaluate_expression}, - {"data-list-changed-registers", 0, 0, mi_cmd_data_list_changed_registers}, - {"data-list-register-names", 0, 0, mi_cmd_data_list_register_names}, - {"data-list-register-values", 0, 0, mi_cmd_data_list_register_values}, - {"data-read-memory", 0, 0, mi_cmd_data_read_memory}, - {"data-write-memory", 0, 0, mi_cmd_data_write_memory}, - {"data-write-register-values", 0, 0, mi_cmd_data_write_register_values}, - {"display-delete", 0, 0}, - {"display-disable", 0, 0}, - {"display-enable", 0, 0}, - {"display-insert", 0, 0}, - {"display-list", 0, 0}, - {"environment-cd", "cd %s", 0}, - {"environment-directory", "dir %s", 0}, - {"environment-path", "path %s", 0}, - {"environment-pwd", "pwd", 0}, - {"exec-abort", 0, 0}, - {"exec-arguments", "set args %s", 0}, - {"exec-continue", 0, mi_cmd_exec_continue}, - {"exec-finish", 0, mi_cmd_exec_finish}, - {"exec-interrupt", 0, mi_cmd_exec_interrupt}, - {"exec-next", 0, mi_cmd_exec_next}, - {"exec-next-instruction", 0, mi_cmd_exec_next_instruction}, - {"exec-return", 0, mi_cmd_exec_return}, - {"exec-run", 0, mi_cmd_exec_run}, - {"exec-show-arguments", 0, 0}, - {"exec-signal", 0, 0}, - {"exec-step", 0, mi_cmd_exec_step}, - {"exec-step-instruction", 0, mi_cmd_exec_step_instruction}, - {"exec-until", 0, mi_cmd_exec_until}, - {"file-clear", 0, 0}, - {"file-exec-and-symbols", "file %s", 0}, - {"file-exec-file", "exec-file %s", 0}, - {"file-list-exec-sections", 0, 0}, - {"file-list-exec-source-files", 0, 0}, - {"file-list-shared-libraries", 0, 0}, - {"file-list-symbol-files", 0, 0}, - {"file-symbol-file", "symbol-file %s", 0}, - {"gdb-complete", 0, 0}, - {"gdb-exit", 0, 0, mi_cmd_gdb_exit}, - {"gdb-set", "set %s", 0}, - {"gdb-show", "show %s", 0}, - {"gdb-source", 0, 0}, - {"gdb-version", "show version", 0}, - {"kod-info", 0, 0}, - {"kod-list", 0, 0}, - {"kod-list-object-types", 0, 0}, - {"kod-show", 0, 0}, - {"overlay-auto", 0, 0}, - {"overlay-list-mapping-state", 0, 0}, - {"overlay-list-overlays", 0, 0}, - {"overlay-map", 0, 0}, - {"overlay-off", 0, 0}, - {"overlay-on", 0, 0}, - {"overlay-unmap", 0, 0}, - {"signal-handle", 0, 0}, - {"signal-list-handle-actions", 0, 0}, - {"signal-list-signal-types", 0, 0}, - {"stack-info-depth", 0, 0, mi_cmd_stack_info_depth}, - {"stack-info-frame", 0, 0}, - {"stack-list-arguments", 0, 0, mi_cmd_stack_list_args}, - {"stack-list-exception-handlers", 0, 0}, - {"stack-list-frames", 0, 0, mi_cmd_stack_list_frames}, - {"stack-list-locals", 0, 0, mi_cmd_stack_list_locals}, - {"stack-select-frame", 0, 0, mi_cmd_stack_select_frame}, - {"symbol-info-address", 0, 0}, - {"symbol-info-file", 0, 0}, - {"symbol-info-function", 0, 0}, - {"symbol-info-line", 0, 0}, - {"symbol-info-symbol", 0, 0}, - {"symbol-list-functions", 0, 0}, - {"symbol-list-types", 0, 0}, - {"symbol-list-variables", 0, 0}, - {"symbol-locate", 0, 0}, - {"symbol-type", 0, 0}, - {"target-attach", 0, 0}, - {"target-compare-sections", 0, 0}, - {"target-detach", "detach", 0}, - {"target-download", 0, mi_cmd_target_download}, - {"target-exec-status", 0, 0}, - {"target-list-available-targets", 0, 0}, - {"target-list-current-targets", 0, 0}, - {"target-list-parameters", 0, 0}, - {"target-select", 0, mi_cmd_target_select}, - {"thread-info", 0, 0}, - {"thread-list-all-threads", 0, 0}, - {"thread-list-ids", 0, 0, mi_cmd_thread_list_ids}, - {"thread-select", 0, 0, mi_cmd_thread_select}, - {"trace-actions", 0, 0}, - {"trace-delete", 0, 0}, - {"trace-disable", 0, 0}, - {"trace-dump", 0, 0}, - {"trace-enable", 0, 0}, - {"trace-exists", 0, 0}, - {"trace-find", 0, 0}, - {"trace-frame-number", 0, 0}, - {"trace-info", 0, 0}, - {"trace-insert", 0, 0}, - {"trace-list", 0, 0}, - {"trace-pass-count", 0, 0}, - {"trace-save", 0, 0}, - {"trace-start", 0, 0}, - {"trace-stop", 0, 0}, - {"var-assign", 0, 0, mi_cmd_var_assign}, - {"var-create", 0, 0, mi_cmd_var_create}, - {"var-delete", 0, 0, mi_cmd_var_delete}, - {"var-evaluate-expression", 0, 0, mi_cmd_var_evaluate_expression}, - {"var-info-expression", 0, 0, mi_cmd_var_info_expression}, - {"var-info-num-children", 0, 0, mi_cmd_var_info_num_children}, - {"var-info-type", 0, 0, mi_cmd_var_info_type}, - {"var-list-children", 0, 0, mi_cmd_var_list_children}, - {"var-set-format", 0, 0, mi_cmd_var_set_format}, - {"var-show-attributes", 0, 0, mi_cmd_var_show_attributes}, - {"var-show-format", 0, 0, mi_cmd_var_show_format}, - {"var-update", 0, 0, mi_cmd_var_update}, - {0,} + { "break-after", { "ignore", 1 }, NULL, NULL }, + { "break-catch", { NULL, 0 }, NULL, NULL }, + { "break-commands", { NULL, 0 }, NULL, NULL }, + { "break-condition", { "cond", 1 }, NULL, NULL }, + { "break-delete", { "delete breakpoint", 1 }, NULL, NULL }, + { "break-disable", { "disable breakpoint", 1 }, NULL, NULL }, + { "break-enable", { "enable breakpoint", 1 }, NULL, NULL }, + { "break-info", { "info break", 1 }, NULL, NULL }, + { "break-insert", { NULL, 0 }, 0, mi_cmd_break_insert}, + { "break-list", { "info break", }, NULL, NULL }, + { "break-watch", { NULL, 0 }, 0, mi_cmd_break_watch}, + { "data-disassemble", { NULL, 0 }, 0, mi_cmd_disassemble}, + { "data-evaluate-expression", { NULL, 0 }, 0, mi_cmd_data_evaluate_expression}, + { "data-list-changed-registers", { NULL, 0 }, 0, mi_cmd_data_list_changed_registers}, + { "data-list-register-names", { NULL, 0 }, 0, mi_cmd_data_list_register_names}, + { "data-list-register-values", { NULL, 0 }, 0, mi_cmd_data_list_register_values}, + { "data-read-memory", { NULL, 0 }, 0, mi_cmd_data_read_memory}, + { "data-write-memory", { NULL, 0 }, 0, mi_cmd_data_write_memory}, + { "data-write-register-values", { NULL, 0 }, 0, mi_cmd_data_write_register_values}, + { "display-delete", { NULL, 0 }, NULL, NULL }, + { "display-disable", { NULL, 0 }, NULL, NULL }, + { "display-enable", { NULL, 0 }, NULL, NULL }, + { "display-insert", { NULL, 0 }, NULL, NULL }, + { "display-list", { NULL, 0 }, NULL, NULL }, + { "environment-cd", { NULL, 0 }, 0, mi_cmd_env_cd}, + { "environment-directory", { NULL, 0 }, 0, mi_cmd_env_dir}, + { "environment-path", { NULL, 0 }, 0, mi_cmd_env_path}, + { "environment-pwd", { NULL, 0 }, 0, mi_cmd_env_pwd}, + { "exec-abort", { NULL, 0 }, NULL, NULL }, + { "exec-arguments", { "set args", 1 }, NULL, NULL }, + { "exec-continue", { NULL, 0 }, mi_cmd_exec_continue}, + { "exec-finish", { NULL, 0 }, mi_cmd_exec_finish}, + { "exec-interrupt", { NULL, 0 }, mi_cmd_exec_interrupt}, + { "exec-next", { NULL, 0 }, mi_cmd_exec_next}, + { "exec-next-instruction", { NULL, 0 }, mi_cmd_exec_next_instruction}, + { "exec-return", { NULL, 0 }, mi_cmd_exec_return}, + { "exec-run", { NULL, 0 }, mi_cmd_exec_run}, + { "exec-show-arguments", { NULL, 0 }, NULL, NULL }, + { "exec-signal", { NULL, 0 }, NULL, NULL }, + { "exec-step", { NULL, 0 }, mi_cmd_exec_step}, + { "exec-step-instruction", { NULL, 0 }, mi_cmd_exec_step_instruction}, + { "exec-until", { NULL, 0 }, mi_cmd_exec_until}, + { "file-clear", { NULL, 0 }, NULL, NULL }, + { "file-exec-and-symbols", { "file", 1 }, NULL, NULL }, + { "file-exec-file", { "exec-file", 1 }, NULL, NULL }, + { "file-list-exec-sections", { NULL, 0 }, NULL, NULL }, + { "file-list-exec-source-file", { NULL, 0 }, 0, mi_cmd_file_list_exec_source_file}, + { "file-list-exec-source-files", { NULL, 0 }, NULL, NULL }, + { "file-list-shared-libraries", { NULL, 0 }, NULL, NULL }, + { "file-list-symbol-files", { NULL, 0 }, NULL, NULL }, + { "file-symbol-file", { "symbol-file", 1 }, NULL, NULL }, + { "gdb-complete", { NULL, 0 }, NULL, NULL }, + { "gdb-exit", { NULL, 0 }, 0, mi_cmd_gdb_exit}, + { "gdb-set", { "set", 1 }, NULL, NULL }, + { "gdb-show", { "show", 1 }, NULL, NULL }, + { "gdb-source", { NULL, 0 }, NULL, NULL }, + { "gdb-version", { "show version", 0 }, 0 }, + { "interpreter-exec", { NULL, 0 }, 0, mi_cmd_interpreter_exec}, + { "kod-info", { NULL, 0 }, NULL, NULL }, + { "kod-list", { NULL, 0 }, NULL, NULL }, + { "kod-list-object-types", { NULL, 0 }, NULL, NULL }, + { "kod-show", { NULL, 0 }, NULL, NULL }, + { "overlay-auto", { NULL, 0 }, NULL, NULL }, + { "overlay-list-mapping-state", { NULL, 0 }, NULL, NULL }, + { "overlay-list-overlays", { NULL, 0 }, NULL, NULL }, + { "overlay-map", { NULL, 0 }, NULL, NULL }, + { "overlay-off", { NULL, 0 }, NULL, NULL }, + { "overlay-on", { NULL, 0 }, NULL, NULL }, + { "overlay-unmap", { NULL, 0 }, NULL, NULL }, + { "signal-handle", { NULL, 0 }, NULL, NULL }, + { "signal-list-handle-actions", { NULL, 0 }, NULL, NULL }, + { "signal-list-signal-types", { NULL, 0 }, NULL, NULL }, + { "stack-info-depth", { NULL, 0 }, 0, mi_cmd_stack_info_depth}, + { "stack-info-frame", { NULL, 0 }, NULL, NULL }, + { "stack-list-arguments", { NULL, 0 }, 0, mi_cmd_stack_list_args}, + { "stack-list-exception-handlers", { NULL, 0 }, NULL, NULL }, + { "stack-list-frames", { NULL, 0 }, 0, mi_cmd_stack_list_frames}, + { "stack-list-locals", { NULL, 0 }, 0, mi_cmd_stack_list_locals}, + { "stack-select-frame", { NULL, 0 }, 0, mi_cmd_stack_select_frame}, + { "symbol-info-address", { NULL, 0 }, NULL, NULL }, + { "symbol-info-file", { NULL, 0 }, NULL, NULL }, + { "symbol-info-function", { NULL, 0 }, NULL, NULL }, + { "symbol-info-line", { NULL, 0 }, NULL, NULL }, + { "symbol-info-symbol", { NULL, 0 }, NULL, NULL }, + { "symbol-list-functions", { NULL, 0 }, NULL, NULL }, + { "symbol-list-lines", { NULL, 0 }, 0, mi_cmd_symbol_list_lines}, + { "symbol-list-types", { NULL, 0 }, NULL, NULL }, + { "symbol-list-variables", { NULL, 0 }, NULL, NULL }, + { "symbol-locate", { NULL, 0 }, NULL, NULL }, + { "symbol-type", { NULL, 0 }, NULL, NULL }, + { "target-attach", { NULL, 0 }, NULL, NULL }, + { "target-compare-sections", { NULL, 0 }, NULL, NULL }, + { "target-detach", { "detach", 0 }, 0 }, + { "target-disconnect", { "disconnect", 0 }, 0 }, + { "target-download", { NULL, 0 }, mi_cmd_target_download}, + { "target-exec-status", { NULL, 0 }, NULL, NULL }, + { "target-list-available-targets", { NULL, 0 }, NULL, NULL }, + { "target-list-current-targets", { NULL, 0 }, NULL, NULL }, + { "target-list-parameters", { NULL, 0 }, NULL, NULL }, + { "target-select", { NULL, 0 }, mi_cmd_target_select}, + { "thread-info", { NULL, 0 }, NULL, NULL }, + { "thread-list-all-threads", { NULL, 0 }, NULL, NULL }, + { "thread-list-ids", { NULL, 0 }, 0, mi_cmd_thread_list_ids}, + { "thread-select", { NULL, 0 }, 0, mi_cmd_thread_select}, + { "trace-actions", { NULL, 0 }, NULL, NULL }, + { "trace-delete", { NULL, 0 }, NULL, NULL }, + { "trace-disable", { NULL, 0 }, NULL, NULL }, + { "trace-dump", { NULL, 0 }, NULL, NULL }, + { "trace-enable", { NULL, 0 }, NULL, NULL }, + { "trace-exists", { NULL, 0 }, NULL, NULL }, + { "trace-find", { NULL, 0 }, NULL, NULL }, + { "trace-frame-number", { NULL, 0 }, NULL, NULL }, + { "trace-info", { NULL, 0 }, NULL, NULL }, + { "trace-insert", { NULL, 0 }, NULL, NULL }, + { "trace-list", { NULL, 0 }, NULL, NULL }, + { "trace-pass-count", { NULL, 0 }, NULL, NULL }, + { "trace-save", { NULL, 0 }, NULL, NULL }, + { "trace-start", { NULL, 0 }, NULL, NULL }, + { "trace-stop", { NULL, 0 }, NULL, NULL }, + { "var-assign", { NULL, 0 }, 0, mi_cmd_var_assign}, + { "var-create", { NULL, 0 }, 0, mi_cmd_var_create}, + { "var-delete", { NULL, 0 }, 0, mi_cmd_var_delete}, + { "var-evaluate-expression", { NULL, 0 }, 0, mi_cmd_var_evaluate_expression}, + { "var-info-expression", { NULL, 0 }, 0, mi_cmd_var_info_expression}, + { "var-info-num-children", { NULL, 0 }, 0, mi_cmd_var_info_num_children}, + { "var-info-type", { NULL, 0 }, 0, mi_cmd_var_info_type}, + { "var-list-children", { NULL, 0 }, 0, mi_cmd_var_list_children}, + { "var-set-format", { NULL, 0 }, 0, mi_cmd_var_set_format}, + { "var-show-attributes", { NULL, 0 }, 0, mi_cmd_var_show_attributes}, + { "var-show-format", { NULL, 0 }, 0, mi_cmd_var_show_format}, + { "var-update", { NULL, 0 }, 0, mi_cmd_var_update}, + { NULL, } }; /* Pointer to the mi command table (built at run time) */ diff --git a/contrib/gdb/gdb/mi/mi-cmds.h b/contrib/gdb/gdb/mi/mi-cmds.h index 88775e6..5453059 100644 --- a/contrib/gdb/gdb/mi/mi-cmds.h +++ b/contrib/gdb/gdb/mi/mi-cmds.h @@ -1,5 +1,7 @@ -/* MI Command Set. - Copyright 2000 Free Software Foundation, Inc. +/* MI Command Set for GDB, the GNU debugger. + + Copyright 2000, 2003, 2004 Free Software Foundation, Inc. + Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -46,6 +48,12 @@ enum mi_cmd_result MI_CMD_QUIET }; +enum print_values { + PRINT_NO_VALUES, + PRINT_ALL_VALUES, + PRINT_SIMPLE_VALUES +}; + typedef enum mi_cmd_result (mi_cmd_argv_ftype) (char *command, char **argv, int argc); /* Older MI commands have this interface. Retained until all old @@ -64,6 +72,10 @@ extern mi_cmd_argv_ftype mi_cmd_data_list_changed_registers; extern mi_cmd_argv_ftype mi_cmd_data_read_memory; extern mi_cmd_argv_ftype mi_cmd_data_write_memory; extern mi_cmd_argv_ftype mi_cmd_data_write_register_values; +extern mi_cmd_argv_ftype mi_cmd_env_cd; +extern mi_cmd_argv_ftype mi_cmd_env_dir; +extern mi_cmd_argv_ftype mi_cmd_env_path; +extern mi_cmd_argv_ftype mi_cmd_env_pwd; extern mi_cmd_args_ftype mi_cmd_exec_continue; extern mi_cmd_args_ftype mi_cmd_exec_finish; extern mi_cmd_args_ftype mi_cmd_exec_next; @@ -74,12 +86,15 @@ extern mi_cmd_args_ftype mi_cmd_exec_step; extern mi_cmd_args_ftype mi_cmd_exec_step_instruction; extern mi_cmd_args_ftype mi_cmd_exec_until; extern mi_cmd_args_ftype mi_cmd_exec_interrupt; +extern mi_cmd_argv_ftype mi_cmd_file_list_exec_source_file; extern mi_cmd_argv_ftype mi_cmd_gdb_exit; +extern mi_cmd_argv_ftype mi_cmd_interpreter_exec; extern mi_cmd_argv_ftype mi_cmd_stack_info_depth; extern mi_cmd_argv_ftype mi_cmd_stack_list_args; extern mi_cmd_argv_ftype mi_cmd_stack_list_frames; extern mi_cmd_argv_ftype mi_cmd_stack_list_locals; extern mi_cmd_argv_ftype mi_cmd_stack_select_frame; +extern mi_cmd_argv_ftype mi_cmd_symbol_list_lines; extern mi_cmd_args_ftype mi_cmd_target_download; extern mi_cmd_args_ftype mi_cmd_target_select; extern mi_cmd_argv_ftype mi_cmd_thread_list_ids; @@ -99,18 +114,26 @@ extern mi_cmd_argv_ftype mi_cmd_var_update; /* Description of a single command. */ +struct mi_cli +{ + /* Corresponding CLI command. If ARGS_P is non-zero, the MI + command's argument list is appended to the CLI command. */ + const char *cmd; + int args_p; +}; + struct mi_cmd - { - /* official name of the command */ - const char *name; - /* If non-null, the corresponding CLI command that can be used to - implement this MI command */ - const char *cli; - /* If non-null, the function implementing the MI command */ - mi_cmd_args_ftype *args_func; - /* If non-null, the function implementing the MI command */ - mi_cmd_argv_ftype *argv_func; - }; +{ + /* official name of the command. */ + const char *name; + /* The corresponding CLI command that can be used to implement this + MI command (if cli.lhs is non NULL). */ + struct mi_cli cli; + /* If non-null, the function implementing the MI command. */ + mi_cmd_args_ftype *args_func; + /* If non-null, the function implementing the MI command. */ + mi_cmd_argv_ftype *argv_func; +}; /* Lookup a command in the mi comand table */ @@ -122,4 +145,8 @@ extern int mi_debug_p; /* Raw console output - FIXME: should this be a parameter? */ extern struct ui_file *raw_stdout; +extern char *mi_error_message; +extern void mi_error_last_message (void); +extern void mi_execute_command (char *cmd, int from_tty); + #endif diff --git a/contrib/gdb/gdb/mi/mi-console.c b/contrib/gdb/gdb/mi/mi-console.c index 5824f83..aca0086 100644 --- a/contrib/gdb/gdb/mi/mi-console.c +++ b/contrib/gdb/gdb/mi/mi-console.c @@ -1,5 +1,7 @@ /* MI Console code. - Copyright 2000, 2001 Free Software Foundation, Inc. + + Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -23,11 +25,6 @@ #include "mi-console.h" #include "gdb_string.h" -/* Convenience macro for allocting typesafe memory. */ - -#undef XMALLOC -#define XMALLOC(TYPE) (TYPE*) xmalloc (sizeof (TYPE)) - /* MI-console: send output to std-out but correcty encapsulated */ static ui_file_fputs_ftype mi_console_file_fputs; @@ -40,13 +37,14 @@ struct mi_console_file struct ui_file *raw; struct ui_file *buffer; const char *prefix; + char quote; }; int mi_console_file_magic; struct ui_file * mi_console_file_new (struct ui_file *raw, - const char *prefix) + const char *prefix, char quote) { struct ui_file *ui_file = ui_file_new (); struct mi_console_file *mi_console = XMALLOC (struct mi_console_file); @@ -54,6 +52,7 @@ mi_console_file_new (struct ui_file *raw, mi_console->raw = raw; mi_console->buffer = mem_fileopen (); mi_console->prefix = prefix; + mi_console->quote = quote; set_ui_file_fputs (ui_file, mi_console_file_fputs); set_ui_file_flush (ui_file, mi_console_file_flush); set_ui_file_data (ui_file, mi_console, mi_console_file_delete); @@ -99,9 +98,17 @@ mi_console_raw_packet (void *data, if (length_buf > 0) { fputs_unfiltered (mi_console->prefix, mi_console->raw); - fputs_unfiltered ("\"", mi_console->raw); - fputstrn_unfiltered (buf, length_buf, '"', mi_console->raw); - fputs_unfiltered ("\"\n", mi_console->raw); + if (mi_console->quote) + { + fputs_unfiltered ("\"", mi_console->raw); + fputstrn_unfiltered (buf, length_buf, mi_console->quote, mi_console->raw); + fputs_unfiltered ("\"\n", mi_console->raw); + } + else + { + fputstrn_unfiltered (buf, length_buf, 0, mi_console->raw); + fputs_unfiltered ("\n", mi_console->raw); + } gdb_flush (mi_console->raw); } } diff --git a/contrib/gdb/gdb/mi/mi-console.h b/contrib/gdb/gdb/mi/mi-console.h index 6bd03cb..bc6c008 100644 --- a/contrib/gdb/gdb/mi/mi-console.h +++ b/contrib/gdb/gdb/mi/mi-console.h @@ -22,6 +22,8 @@ #ifndef MI_CONSOLE_H #define MI_CONSOLE_H -extern struct ui_file *mi_console_file_new (struct ui_file *raw, const char *prefix); +extern struct ui_file *mi_console_file_new (struct ui_file *raw, + const char *prefix, + char quote); #endif diff --git a/contrib/gdb/gdb/mi/mi-getopt.c b/contrib/gdb/gdb/mi/mi-getopt.c index 59ccdf3..3f2a902 100644 --- a/contrib/gdb/gdb/mi/mi-getopt.c +++ b/contrib/gdb/gdb/mi/mi-getopt.c @@ -74,3 +74,19 @@ mi_getopt (const char *prefix, } error ("%s: Unknown option ``%s''", prefix, arg + 1); } + +int +mi_valid_noargs (const char *prefix, int argc, char **argv) +{ + int optind = 0; + char *optarg; + static struct mi_opt opts[] = + { + 0 + }; + + if (mi_getopt (prefix, argc, argv, opts, &optind, &optarg) == -1) + return 1; + else + return 0; +} diff --git a/contrib/gdb/gdb/mi/mi-getopt.h b/contrib/gdb/gdb/mi/mi-getopt.h index 6b31adf..17d66fb 100644 --- a/contrib/gdb/gdb/mi/mi-getopt.h +++ b/contrib/gdb/gdb/mi/mi-getopt.h @@ -57,4 +57,24 @@ struct mi_opt struct mi_opt; +/* mi_valid_noargs + + Determines if ARGC/ARGV are a valid set of parameters to satisfy + an MI function that is not supposed to recieve any arguments. + + An MI function that should not recieve arguments can still be + passed parameters after the special option '--' such as below. + + Example: The MI function -exec-run takes no args. + However, the client may pass '-exec-run -- -a ...' + See PR-783 + + PREFIX is passed to mi_getopt for an error message. + + This function Returns 1 if the parameter pair ARGC/ARGV are valid + for an MI function that takes no arguments. Otherwise, it returns 0 + and the appropriate error message is displayed by mi_getopt. */ + +extern int mi_valid_noargs (const char *prefix, int argc, char **argv); + #endif diff --git a/contrib/gdb/gdb/mi/mi-interp.c b/contrib/gdb/gdb/mi/mi-interp.c new file mode 100644 index 0000000..08201ca --- /dev/null +++ b/contrib/gdb/gdb/mi/mi-interp.c @@ -0,0 +1,406 @@ +/* MI Interpreter Definitions and Commands for GDB, the GNU debugger. + + Copyright 2002, 2003, 2003 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdb_string.h" +#include "interps.h" +#include "event-top.h" +#include "event-loop.h" +#include "inferior.h" +#include "ui-out.h" +#include "top.h" + +#include "mi-main.h" +#include "mi-cmds.h" +#include "mi-out.h" +#include "mi-console.h" + +struct mi_interp +{ + /* MI's output channels */ + struct ui_file *out; + struct ui_file *err; + struct ui_file *log; + struct ui_file *targ; + struct ui_file *event_channel; + + /* This is the interpreter for the mi... */ + struct interp *mi2_interp; + struct interp *mi1_interp; + struct interp *mi_interp; +}; + +/* These are the interpreter setup, etc. functions for the MI interpreter */ +static void mi_execute_command_wrapper (char *cmd); +static void mi_command_loop (int mi_version); +static char *mi_input (char *); + +/* These are hooks that we put in place while doing interpreter_exec + so we can report interesting things that happened "behind the mi's + back" in this command */ +static int mi_interp_query_hook (const char *ctlstr, va_list ap); + +static void mi3_command_loop (void); +static void mi2_command_loop (void); +static void mi1_command_loop (void); + +static void mi_insert_notify_hooks (void); +static void mi_remove_notify_hooks (void); + +static void * +mi_interpreter_init (void) +{ + struct mi_interp *mi = XMALLOC (struct mi_interp); + + /* Why is this a part of the mi architecture? */ + + mi_setup_architecture_data (); + + /* HACK: We need to 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. So we set up output channels for + this now, and swap them in when we are run. */ + + raw_stdout = stdio_fileopen (stdout); + + /* Create MI channels */ + mi->out = mi_console_file_new (raw_stdout, "~", '"'); + mi->err = mi_console_file_new (raw_stdout, "&", '"'); + mi->log = mi->err; + mi->targ = mi_console_file_new (raw_stdout, "@", '"'); + mi->event_channel = mi_console_file_new (raw_stdout, "=", 0); + + return mi; +} + +static int +mi_interpreter_resume (void *data) +{ + struct mi_interp *mi = data; + /* As per hack note in mi_interpreter_init, swap in the output channels... */ + + gdb_setup_readline (); + + 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: This is a total hack for now. PB's use of the MI implicitly + relies on a bug in the async support which allows asynchronous + commands to leak through the commmand loop. The bug involves + (but is not limited to) the fact that sync_execution was + erroneously initialized to 0. Duplicate by initializing it + thus here... */ + sync_execution = 0; + } + + gdb_stdout = mi->out; + /* Route error and log output through the MI */ + gdb_stderr = mi->err; + gdb_stdlog = mi->log; + /* Route target output through the MI. */ + gdb_stdtarg = mi->targ; + + /* Replace all the hooks that we know about. There really needs to + be a better way of doing this... */ + clear_interpreter_hooks (); + + show_load_progress = mi_load_progress; + + /* If we're _the_ interpreter, take control. */ + if (current_interp_named_p (INTERP_MI1)) + command_loop_hook = mi1_command_loop; + else if (current_interp_named_p (INTERP_MI2)) + command_loop_hook = mi2_command_loop; + else if (current_interp_named_p (INTERP_MI3)) + command_loop_hook = mi3_command_loop; + else + command_loop_hook = mi2_command_loop; + + return 1; +} + +static int +mi_interpreter_suspend (void *data) +{ + gdb_disable_readline (); + return 1; +} + +static int +mi_interpreter_exec (void *data, const char *command) +{ + char *tmp = alloca (strlen (command) + 1); + strcpy (tmp, command); + mi_execute_command_wrapper (tmp); + return 1; +} + +/* Never display the default gdb prompt in mi case. */ +static int +mi_interpreter_prompt_p (void *data) +{ + return 0; +} + +static void +mi_interpreter_exec_continuation (struct continuation_arg *arg) +{ + bpstat_do_actions (&stop_bpstat); + if (!target_executing) + { + fputs_unfiltered ("*stopped", raw_stdout); + 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); + } + else if (target_can_async_p ()) + { + add_continuation (mi_interpreter_exec_continuation, NULL); + } +} + +enum mi_cmd_result +mi_cmd_interpreter_exec (char *command, char **argv, int argc) +{ + struct interp *interp_to_use; + enum mi_cmd_result result = MI_CMD_DONE; + int i; + struct interp_procs *procs; + + if (argc < 2) + { + xasprintf (&mi_error_message, + "mi_cmd_interpreter_exec: Usage: -interpreter-exec interp command"); + return MI_CMD_ERROR; + } + + interp_to_use = interp_lookup (argv[0]); + if (interp_to_use == NULL) + { + xasprintf (&mi_error_message, + "mi_cmd_interpreter_exec: could not find interpreter \"%s\"", + argv[0]); + return MI_CMD_ERROR; + } + + if (!interp_exec_p (interp_to_use)) + { + xasprintf (&mi_error_message, + "mi_cmd_interpreter_exec: interpreter \"%s\" does not support command execution", + argv[0]); + return MI_CMD_ERROR; + } + + /* Insert the MI out hooks, making sure to also call the interpreter's hooks + if it has any. */ + /* KRS: We shouldn't need this... Events should be installed and they should + just ALWAYS fire something out down the MI channel... */ + mi_insert_notify_hooks (); + + /* Now run the code... */ + + for (i = 1; i < argc; i++) + { + char *buff = NULL; + /* Do this in a cleaner way... We want to force execution to be + asynchronous for commands that run the target. */ + if (target_can_async_p () && (strcmp (argv[0], "console") == 0)) + { + int len = strlen (argv[i]); + buff = xmalloc (len + 2); + memcpy (buff, argv[i], len); + buff[len] = '&'; + buff[len + 1] = '\0'; + } + + /* We had to set sync_execution = 0 for the mi (well really for Project + Builder's use of the mi - particularly so interrupting would work. + But for console commands to work, we need to initialize it to 1 - + since that is what the cli expects - before running the command, + and then set it back to 0 when we are done. */ + sync_execution = 1; + if (interp_exec (interp_to_use, argv[i]) < 0) + { + mi_error_last_message (); + result = MI_CMD_ERROR; + break; + } + xfree (buff); + do_exec_error_cleanups (ALL_CLEANUPS); + sync_execution = 0; + } + + mi_remove_notify_hooks (); + + /* Okay, now let's see if the command set the inferior going... + Tricky point - have to do this AFTER resetting the interpreter, since + changing the interpreter will clear out all the continuations for + that interpreter... */ + + if (target_can_async_p () && target_executing) + { + fputs_unfiltered ("^running\n", raw_stdout); + add_continuation (mi_interpreter_exec_continuation, NULL); + } + + return result; +} + +/* + * mi_insert_notify_hooks - This inserts a number of hooks that are meant to produce + * async-notify ("=") MI messages while running commands in another interpreter + * using mi_interpreter_exec. The canonical use for this is to allow access to + * the gdb CLI interpreter from within the MI, while still producing MI style output + * when actions in the CLI command change gdb's state. +*/ + +static void +mi_insert_notify_hooks (void) +{ + query_hook = mi_interp_query_hook; +} + +static void +mi_remove_notify_hooks (void) +{ + query_hook = NULL; +} + +static int +mi_interp_query_hook (const char *ctlstr, va_list ap) +{ + return 1; +} + +static void +mi_execute_command_wrapper (char *cmd) +{ + mi_execute_command (cmd, stdin == instream); +} + +static void +mi1_command_loop (void) +{ + mi_command_loop (1); +} + +static void +mi2_command_loop (void) +{ + mi_command_loop (2); +} + +static void +mi3_command_loop (void) +{ + mi_command_loop (3); +} + +static void +mi_command_loop (int mi_version) +{ +#if 0 + /* 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 (mi_version); + /* 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; +#endif + /* 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); + gdb_flush (raw_stdout); + if (!event_loop_p) + simplified_command_loop (mi_input, mi_execute_command); + else + start_event_loop (); +} + +static char * +mi_input (char *buf) +{ + return gdb_readline (NULL); +} + +extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */ + +void +_initialize_mi_interp (void) +{ + static const struct interp_procs procs = + { + mi_interpreter_init, /* init_proc */ + mi_interpreter_resume, /* resume_proc */ + mi_interpreter_suspend, /* suspend_proc */ + mi_interpreter_exec, /* exec_proc */ + mi_interpreter_prompt_p /* prompt_proc_p */ + }; + + /* The various interpreter levels. */ + interp_add (interp_new (INTERP_MI1, NULL, mi_out_new (1), &procs)); + interp_add (interp_new (INTERP_MI2, NULL, mi_out_new (2), &procs)); + interp_add (interp_new (INTERP_MI3, NULL, mi_out_new (3), &procs)); + + /* "mi" selects the most recent released version. "mi2" was + released as part of GDB 6.0. */ + interp_add (interp_new (INTERP_MI, NULL, mi_out_new (2), &procs)); +} diff --git a/contrib/gdb/gdb/mi/mi-main.c b/contrib/gdb/gdb/mi/mi-main.c index 3a59fc8..c46bf63 100644 --- a/contrib/gdb/gdb/mi/mi-main.c +++ b/contrib/gdb/gdb/mi/mi-main.c @@ -1,5 +1,8 @@ /* MI Command Set. - Copyright 2000, 2001, 2002 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. @@ -33,25 +36,47 @@ #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 "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; @@ -59,33 +84,30 @@ 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 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); - -/* 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); + +/* 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", 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 @@ -161,17 +183,17 @@ mi_cmd_exec_return (char *args, int from_tty) 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); + print_stack_frame (deprecated_selected_frame, + frame_relative_level (deprecated_selected_frame), + LOC_AND_ADDRESS); return MI_CMD_DONE; } @@ -197,7 +219,7 @@ mi_cmd_exec_interrupt (char *args, int from_tty) "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); @@ -226,8 +248,12 @@ mi_cmd_thread_select (char *command, char **argv, int argc) else 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; } @@ -257,6 +283,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 @@ -266,7 +293,7 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc) 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 */ { @@ -288,6 +315,7 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc) regnum = atoi (argv[i]); if (regnum < 0 || regnum >= numregs) { + do_cleanups (cleanup); xasprintf (&mi_error_message, "bad register number"); return MI_CMD_ERROR; } @@ -297,7 +325,7 @@ mi_cmd_data_list_register_names (char *command, char **argv, int argc) else ui_out_field_string (uiout, NULL, REGISTER_NAME (regnum)); } - ui_out_list_end (uiout); + do_cleanups (cleanup); return MI_CMD_DONE; } @@ -306,6 +334,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 @@ -315,7 +344,7 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) 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 */ { @@ -329,6 +358,7 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) changed = register_changed_p (regnum); if (changed < 0) { + do_cleanups (cleanup); xasprintf (&mi_error_message, "mi_cmd_data_list_changed_registers: Unable to read register contents."); return MI_CMD_ERROR; @@ -351,6 +381,7 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) changed = register_changed_p (regnum); if (changed < 0) { + do_cleanups (cleanup); xasprintf (&mi_error_message, "mi_cmd_data_list_register_change: Unable to read register contents."); return MI_CMD_ERROR; @@ -360,30 +391,31 @@ mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) } else { + 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 = alloca (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, + DEPRECATED_REGISTER_RAW_SIZE (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, + DEPRECATED_REGISTER_RAW_SIZE (regnum)); return 1; } @@ -400,6 +432,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 @@ -425,7 +458,7 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) 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 */ { @@ -436,12 +469,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_tuple_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_tuple_end (uiout); + { + do_cleanups (list_cleanup); + return MI_CMD_ERROR; + } + do_cleanups (tuple_cleanup); } } @@ -455,20 +491,24 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) && REGISTER_NAME (regnum) != NULL && *REGISTER_NAME (regnum) != '\000') { - ui_out_tuple_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_tuple_end (uiout); + { + do_cleanups (list_cleanup); + return MI_CMD_ERROR; + } + do_cleanups (tuple_cleanup); } else { + 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; } @@ -476,9 +516,12 @@ mi_cmd_data_list_register_values (char *command, char **argv, int argc) static int get_register (int regnum, int format) { - char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE); - char *virtual_buffer = alloca (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); @@ -486,12 +529,9 @@ 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) { xasprintf (&mi_error_message, "Optimized out"); @@ -500,13 +540,15 @@ get_register (int regnum, int format) /* Convert raw data to virtual format if necessary. */ - if (REGISTER_CONVERTIBLE (regnum)) + if (DEPRECATED_REGISTER_CONVERTIBLE_P () + && DEPRECATED_REGISTER_CONVERTIBLE (regnum)) { - REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum), + DEPRECATED_REGISTER_CONVERT_TO_VIRTUAL (regnum, + register_type (current_gdbarch, regnum), raw_buffer, virtual_buffer); } else - memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum)); + memcpy (virtual_buffer, raw_buffer, DEPRECATED_REGISTER_VIRTUAL_SIZE (regnum)); if (format == 'r') { @@ -515,10 +557,10 @@ get_register (int regnum, int format) strcpy (buf, "0x"); ptr = buf + 2; - for (j = 0; j < REGISTER_RAW_SIZE (regnum); j++) + for (j = 0; j < DEPRECATED_REGISTER_RAW_SIZE (regnum); j++) { - register int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j - : REGISTER_RAW_SIZE (regnum) - 1 - j; + int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j + : DEPRECATED_REGISTER_RAW_SIZE (regnum) - 1 - j; sprintf (ptr, "%02x", (unsigned char) raw_buffer[idx]); ptr += 2; } @@ -527,7 +569,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); @@ -600,11 +642,11 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc) /* Get the value as a number */ value = parse_and_eval_address (argv[i + 1]); /* Get the value into an array */ - buffer = xmalloc (REGISTER_SIZE); + buffer = xmalloc (DEPRECATED_REGISTER_SIZE); old_chain = make_cleanup (xfree, buffer); - store_signed_integer (buffer, REGISTER_SIZE, value); + store_signed_integer (buffer, DEPRECATED_REGISTER_SIZE, value); /* Write it down */ - write_register_bytes (REGISTER_BYTE (regnum), buffer, REGISTER_RAW_SIZE (regnum)); + deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (regnum), buffer, DEPRECATED_REGISTER_RAW_SIZE (regnum)); /* Free the buffer. */ do_cleanups (old_chain); } @@ -887,19 +929,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_tuple_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) @@ -916,7 +961,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; @@ -936,10 +981,10 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) } ui_out_field_stream (uiout, "ascii", stream); } - ui_out_tuple_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; @@ -1034,15 +1079,19 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc) 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) { @@ -1057,11 +1106,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); @@ -1069,7 +1125,7 @@ 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) { @@ -1081,18 +1137,22 @@ captured_mi_execute_command (void *data) } 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: @@ -1101,19 +1161,28 @@ captured_mi_execute_command (void *data) 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; } @@ -1122,6 +1191,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. */ @@ -1132,18 +1204,20 @@ 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 (xfree, msg); @@ -1206,12 +1280,13 @@ mi_cmd_execute (struct mi_parse *parse) 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 @@ -1227,28 +1302,25 @@ 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 */ 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; - xasprintf (&run, cli, args); + if (args_p) + xasprintf (&run, "%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); + cmd, run); old_cleanups = make_cleanup (xfree, run); execute_command ( /*ui */ run, 0 /*from_tty */ ); do_cleanups (old_cleanups); @@ -1335,13 +1407,7 @@ mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg) 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, @@ -1353,7 +1419,8 @@ mi_load_progress (const char *section_name, static char *previous_sect_name = NULL; int new_section; - if (!interpreter_p || strncmp (interpreter_p, "mi", 2) != 0) + if (!current_interp_named_p (INTERP_MI) + && !current_interp_named_p (INTERP_MI1)) return; update_threshold.tv_sec = 0; @@ -1373,17 +1440,18 @@ mi_load_progress (const char *section_name, strcmp (previous_sect_name, section_name) : 1); if (new_section) { + 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_tuple_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_tuple_end (uiout); + do_cleanups (cleanup_tuple); mi_out_put (uiout, raw_stdout); fputs_unfiltered ("\n", raw_stdout); gdb_flush (raw_stdout); @@ -1392,136 +1460,35 @@ 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_tuple_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_tuple_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 (int mi_version) -{ - /* 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 (mi_version); - - /* 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); - gdb_flush (raw_stdout); - - if (!event_loop_p) - simplified_command_loop (mi_input, mi_execute_command); - else - start_event_loop (); -} - -static void -mi0_command_loop (void) -{ - mi_command_loop (0); -} - -static void -mi1_command_loop (void) -{ - mi_command_loop (1); -} - -static void -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 (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 (void) { - if (interpreter_p == NULL) - return; - - /* If we're _the_ interpreter, take control. */ - if (strcmp (interpreter_p, "mi0") == 0) - command_loop_hook = mi0_command_loop; - else if (strcmp (interpreter_p, "mi") == 0 - || strcmp (interpreter_p, "mi1") == 0) - command_loop_hook = mi1_command_loop; - else - return; - - init_ui_hook = mi_init_ui; - 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); } diff --git a/contrib/gdb/gdb/mi/mi-main.h b/contrib/gdb/gdb/mi/mi-main.h new file mode 100644 index 0000000..8e504c6 --- /dev/null +++ b/contrib/gdb/gdb/mi/mi-main.h @@ -0,0 +1,33 @@ +/* MI Internal Functions for GDB, the GNU debugger. + + Copyright 2003 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef MI_MAIN_H +#define MI_MAIN_H + +extern void mi_setup_architecture_data (void); + +extern 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); +#endif + diff --git a/contrib/gdb/gdb/mi/mi-out.c b/contrib/gdb/gdb/mi/mi-out.c index a92ccbe..2be9d17 100644 --- a/contrib/gdb/gdb/mi/mi-out.c +++ b/contrib/gdb/gdb/mi/mi-out.c @@ -1,5 +1,7 @@ /* MI Command Set - output generating routines. - Copyright 2000 Free Software Foundation, Inc. + + Copyright 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -23,12 +25,6 @@ #include "ui-out.h" #include "mi-out.h" -/* Convenience macro for allocting typesafe memory. */ - -#ifndef XMALLOC -#define XMALLOC(TYPE) (TYPE*) xmalloc (sizeof (TYPE)) -#endif - struct ui_out_data { int suppress_field_separator; @@ -36,6 +32,7 @@ struct ui_out_data int mi_version; struct ui_file *buffer; }; +typedef struct ui_out_data mi_out_data; /* These are the MI output functions */ @@ -89,6 +86,7 @@ struct ui_out_impl mi_ui_out_impl = mi_message, mi_wrap_hint, mi_flush, + NULL, 1, /* Needs MI hacks. */ }; @@ -100,9 +98,6 @@ static void mi_open (struct ui_out *uiout, const char *name, enum ui_out_type type); static void mi_close (struct ui_out *uiout, enum ui_out_type type); -static void out_field_fmt (struct ui_out *uiout, int fldno, char *fldname, - char *format,...); - /* Mark beginning of a table */ void @@ -111,16 +106,8 @@ mi_table_begin (struct ui_out *uiout, int nr_rows, const char *tblid) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); mi_open (uiout, tblid, ui_out_type_tuple); - if (data->mi_version == 0) - { - if (nr_rows == 0) - data->suppress_output = 1; - else - mi_open (uiout, "hdr", ui_out_type_list); - return; - } mi_field_int (uiout, -1/*fldno*/, -1/*width*/, -1/*alin*/, "nr_rows", nr_rows); mi_field_int (uiout, -1/*fldno*/, -1/*width*/, -1/*alin*/, @@ -133,13 +120,11 @@ mi_table_begin (struct ui_out *uiout, void mi_table_body (struct ui_out *uiout) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); if (data->suppress_output) return; /* close the table header line if there were any headers */ mi_close (uiout, ui_out_type_list); - if (data->mi_version == 0) - return; mi_open (uiout, "body", ui_out_type_list); } @@ -148,13 +133,8 @@ mi_table_body (struct ui_out *uiout) void mi_table_end (struct ui_out *uiout) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); data->suppress_output = 0; - if (data->mi_version == 0) - { - mi_close (uiout, ui_out_type_tuple); - return; - } mi_close (uiout, ui_out_type_list); /* body */ mi_close (uiout, ui_out_type_tuple); } @@ -166,14 +146,9 @@ mi_table_header (struct ui_out *uiout, int width, enum ui_align alignment, const char *col_name, const char *colhdr) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); if (data->suppress_output) return; - if (data->mi_version == 0) - { - mi_field_string (uiout, 0, width, alignment, 0, colhdr); - return; - } mi_open (uiout, NULL, ui_out_type_tuple); mi_field_int (uiout, 0, 0, 0, "width", width); mi_field_int (uiout, 0, 0, 0, "alignment", alignment); @@ -190,7 +165,7 @@ mi_begin (struct ui_out *uiout, int level, const char *id) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); if (data->suppress_output) return; mi_open (uiout, id, type); @@ -203,7 +178,7 @@ mi_end (struct ui_out *uiout, enum ui_out_type type, int level) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); if (data->suppress_output) return; mi_close (uiout, type); @@ -216,7 +191,7 @@ mi_field_int (struct ui_out *uiout, int fldno, int width, enum ui_align alignment, const char *fldname, int value) { char buffer[20]; /* FIXME: how many chars long a %d can become? */ - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); if (data->suppress_output) return; @@ -230,7 +205,7 @@ void mi_field_skip (struct ui_out *uiout, int fldno, int width, enum ui_align alignment, const char *fldname) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); if (data->suppress_output) return; mi_field_string (uiout, fldno, width, alignment, fldname, ""); @@ -247,7 +222,7 @@ mi_field_string (struct ui_out *uiout, const char *fldname, const char *string) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); if (data->suppress_output) return; field_separator (uiout); @@ -268,7 +243,7 @@ mi_field_fmt (struct ui_out *uiout, int fldno, const char *format, va_list args) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); if (data->suppress_output) return; field_separator (uiout); @@ -306,43 +281,18 @@ mi_wrap_hint (struct ui_out *uiout, char *identstring) void mi_flush (struct ui_out *uiout) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); gdb_flush (data->buffer); } /* local functions */ -/* Like mi_field_fmt, but takes a variable number of args - and makes a va_list and does not insert a separator */ - -/* VARARGS */ -static void -out_field_fmt (struct ui_out *uiout, int fldno, char *fldname, - char *format,...) -{ - struct ui_out_data *data = ui_out_data (uiout); - va_list args; - - field_separator (uiout); - if (fldname) - fprintf_unfiltered (data->buffer, "%s=\"", fldname); - else - fputs_unfiltered ("\"", data->buffer); - - va_start (args, format); - vfprintf_unfiltered (data->buffer, format, args); - - fputs_unfiltered ("\"", data->buffer); - - va_end (args); -} - /* access to ui_out format private members */ static void field_separator (struct ui_out *uiout) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); if (data->suppress_field_separator) data->suppress_field_separator = 0; else @@ -354,7 +304,7 @@ mi_open (struct ui_out *uiout, const char *name, enum ui_out_type type) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); field_separator (uiout); data->suppress_field_separator = 1; if (name) @@ -365,10 +315,7 @@ mi_open (struct ui_out *uiout, fputc_unfiltered ('{', data->buffer); break; case ui_out_type_list: - if (data->mi_version == 0) - fputc_unfiltered ('{', data->buffer); - else - fputc_unfiltered ('[', data->buffer); + fputc_unfiltered ('[', data->buffer); break; default: internal_error (__FILE__, __LINE__, "bad switch"); @@ -379,17 +326,14 @@ static void mi_close (struct ui_out *uiout, enum ui_out_type type) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); switch (type) { case ui_out_type_tuple: fputc_unfiltered ('}', data->buffer); break; case ui_out_type_list: - if (data->mi_version == 0) - fputc_unfiltered ('}', data->buffer); - else - fputc_unfiltered (']', data->buffer); + fputc_unfiltered (']', data->buffer); break; default: internal_error (__FILE__, __LINE__, "bad switch"); @@ -402,7 +346,7 @@ mi_close (struct ui_out *uiout, void mi_out_buffered (struct ui_out *uiout, char *string) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); fprintf_unfiltered (data->buffer, "%s", string); } @@ -411,7 +355,7 @@ mi_out_buffered (struct ui_out *uiout, char *string) void mi_out_rewind (struct ui_out *uiout) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); ui_file_rewind (data->buffer); } @@ -427,18 +371,27 @@ void mi_out_put (struct ui_out *uiout, struct ui_file *stream) { - struct ui_out_data *data = ui_out_data (uiout); + mi_out_data *data = ui_out_data (uiout); ui_file_put (data->buffer, do_write, stream); ui_file_rewind (data->buffer); } +/* Current MI version. */ + +int +mi_version (struct ui_out *uiout) +{ + mi_out_data *data = ui_out_data (uiout); + return data->mi_version; +} + /* initalize private members at startup */ struct ui_out * mi_out_new (int mi_version) { int flags = 0; - struct ui_out_data *data = XMALLOC (struct ui_out_data); + mi_out_data *data = XMALLOC (mi_out_data); data->suppress_field_separator = 0; data->suppress_output = 0; data->mi_version = mi_version; diff --git a/contrib/gdb/gdb/mi/mi-out.h b/contrib/gdb/gdb/mi/mi-out.h index 1ae693f..817f2eb 100644 --- a/contrib/gdb/gdb/mi/mi-out.h +++ b/contrib/gdb/gdb/mi/mi-out.h @@ -30,4 +30,7 @@ extern void mi_out_put (struct ui_out *uiout, struct ui_file *stream); extern void mi_out_rewind (struct ui_out *uiout); extern void mi_out_buffered (struct ui_out *uiout, char *string); +/* Return the version number of the current MI. */ +extern int mi_version (struct ui_out *uiout); + #endif /* MI_OUT_H */ diff --git a/contrib/gdb/gdb/mi/mi-parse.c b/contrib/gdb/gdb/mi/mi-parse.c index 2ed49b8..a0ff889 100644 --- a/contrib/gdb/gdb/mi/mi-parse.c +++ b/contrib/gdb/gdb/mi/mi-parse.c @@ -1,5 +1,7 @@ /* MI Command Set - MI parser. - Copyright 2000, 2001 Free Software Foundation, Inc. + + Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -26,9 +28,6 @@ #include <ctype.h> #include "gdb_string.h" -#undef XMALLOC -#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE))) - static void mi_parse_argv (char *args, struct mi_parse *parse) { @@ -223,7 +222,7 @@ mi_parse (char *cmd) /* For CLI and old ARGS commands, also return the remainder of the command line as a single string. */ if (parse->cmd->args_func != NULL - || parse->cmd->cli != NULL) + || parse->cmd->cli.cmd != NULL) { parse->args = xstrdup (chp); } @@ -232,8 +231,3 @@ mi_parse (char *cmd) parse->op = MI_COMMAND; return parse; } - -void -_initialize_mi_parse (void) -{ -} diff --git a/contrib/gdb/gdb/mi/mi-symbol-cmds.c b/contrib/gdb/gdb/mi/mi-symbol-cmds.c new file mode 100644 index 0000000..1d86d21 --- /dev/null +++ b/contrib/gdb/gdb/mi/mi-symbol-cmds.c @@ -0,0 +1,67 @@ +/* MI Command Set - symbol commands. + Copyright 2003 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "mi-cmds.h" +#include "symtab.h" +#include "ui-out.h" + +/* SYMBOL-LIST-LINES: + + Print the list of all pc addresses and lines of code for + the provided (full or base) source file name. The entries + are sorted in ascending PC order. */ + +enum mi_cmd_result +mi_cmd_symbol_list_lines (char *command, char **argv, int argc) +{ + char *filename; + struct symtab *s; + int i; + struct cleanup *cleanup_stack, *cleanup_tuple; + + if (argc != 1) + error ("mi_cmd_symbol_list_lines: Usage: SOURCE_FILENAME"); + + filename = argv[0]; + s = lookup_symtab (filename); + + if (s == NULL) + error ("mi_cmd_symbol_list_lines: Unknown source file name."); + + /* Now, dump the associated line table. The pc addresses are already + sorted by increasing values in the symbol table, so no need to + perform any other sorting. */ + + cleanup_stack = make_cleanup_ui_out_list_begin_end (uiout, "lines"); + + if (LINETABLE (s) != NULL && LINETABLE (s)->nitems > 0) + for (i = 0; i < LINETABLE (s)->nitems; i++) + { + cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + ui_out_field_core_addr (uiout, "pc", LINETABLE (s)->item[i].pc); + ui_out_field_int (uiout, "line", LINETABLE (s)->item[i].line); + do_cleanups (cleanup_tuple); + } + + do_cleanups (cleanup_stack); + + return MI_CMD_DONE; +} |