/* MI Interpreter Definitions and Commands for GDB, the GNU debugger.
- Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008
+ 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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "gdb_string.h"
#include "mi-cmds.h"
#include "mi-out.h"
#include "mi-console.h"
+#include "observer.h"
+#include "gdbthread.h"
struct mi_interp
{
static void mi_insert_notify_hooks (void);
static void mi_remove_notify_hooks (void);
+static void mi_new_thread (struct thread_info *t);
+static void mi_thread_exit (struct thread_info *t);
+
static void *
-mi_interpreter_init (void)
+mi_interpreter_init (int top_level)
{
struct mi_interp *mi = XMALLOC (struct mi_interp);
mi->targ = mi_console_file_new (raw_stdout, "@", '"');
mi->event_channel = mi_console_file_new (raw_stdout, "=", 0);
+ if (top_level)
+ {
+ observer_attach_new_thread (mi_new_thread);
+ observer_attach_thread_exit (mi_thread_exit);
+ }
+
return mi;
}
}
static void
-mi_interpreter_exec_continuation (struct continuation_arg *arg)
+mi_interpreter_exec_continuation (struct continuation_arg *arg, int error_p)
{
bpstat_do_actions (&stop_bpstat);
+ /* It's not clear what to do in the case of errror -- should we assume that
+ the target is stopped, or that it still runs? */
if (!target_executing)
{
fputs_unfiltered ("*stopped", 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 ())
{
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;
+ char *mi_error_message = NULL;
+ struct cleanup *old_chain;
if (argc < 2)
- {
- mi_error_message = xstrprintf ("mi_cmd_interpreter_exec: Usage: -interpreter-exec interp command");
- return MI_CMD_ERROR;
- }
+ error ("mi_cmd_interpreter_exec: Usage: -interpreter-exec interp command");
interp_to_use = interp_lookup (argv[0]);
if (interp_to_use == NULL)
- {
- mi_error_message = xstrprintf ("mi_cmd_interpreter_exec: could not find interpreter \"%s\"", argv[0]);
- return MI_CMD_ERROR;
- }
+ error ("mi_cmd_interpreter_exec: could not find interpreter \"%s\"", argv[0]);
if (!interp_exec_p (interp_to_use))
- {
- mi_error_message = xstrprintf ("mi_cmd_interpreter_exec: interpreter \"%s\" does not support command execution",
- argv[0]);
- return MI_CMD_ERROR;
- }
+ error ("mi_cmd_interpreter_exec: interpreter \"%s\" does not support command execution",
+ argv[0]);
/* Insert the MI out hooks, making sure to also call the interpreter's hooks
if it has any. */
/* Now run the code... */
+ old_chain = make_cleanup (null_cleanup, 0);
for (i = 1; i < argc; i++)
{
- /* 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;
- {
- struct gdb_exception e = interp_exec (interp_to_use, argv[i]);
- if (e.reason < 0)
- {
- mi_error_message = xstrdup (e.message);
- result = MI_CMD_ERROR;
- break;
- }
- }
- do_exec_error_cleanups (ALL_CLEANUPS);
- sync_execution = 0;
+ struct gdb_exception e = interp_exec (interp_to_use, argv[i]);
+ if (e.reason < 0)
+ {
+ mi_error_message = xstrdup (e.message);
+ make_cleanup (xfree, mi_error_message);
+ break;
+ }
}
mi_remove_notify_hooks ();
add_continuation (mi_interpreter_exec_continuation, NULL);
}
- return result;
+ if (mi_error_message != NULL)
+ error ("%s", mi_error_message);
+ do_cleanups (old_chain);
+ return MI_CMD_DONE;
}
/*
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. */
- deprecated_init_ui_hook = 0;
- /* deprecated_command_loop_hook = 0; */
- deprecated_print_frame_info_listing_hook = 0;
- deprecated_query_hook = 0;
- deprecated_warning_hook = 0;
- deprecated_create_breakpoint_hook = 0;
- deprecated_delete_breakpoint_hook = 0;
- deprecated_modify_breakpoint_hook = 0;
- deprecated_interactive_hook = 0;
- deprecated_readline_begin_hook = 0;
- deprecated_readline_hook = 0;
- deprecated_readline_end_hook = 0;
- deprecated_register_changed_hook = 0;
- deprecated_memory_changed_hook = 0;
- deprecated_context_hook = 0;
- deprecated_target_wait_hook = 0;
- deprecated_call_command_hook = 0;
- deprecated_error_hook = 0;
- deprecated_error_begin_hook = 0;
- deprecated_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;
start_event_loop ();
}
+static void
+mi_new_thread (struct thread_info *t)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ fprintf_unfiltered (mi->event_channel, "thread-created,id=\"%d\"", t->num);
+ gdb_flush (mi->event_channel);
+}
+
+static void
+mi_thread_exit (struct thread_info *t)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ target_terminal_ours ();
+ fprintf_unfiltered (mi->event_channel, "thread-exited,id=\"%d\"", t->num);
+ gdb_flush (mi->event_channel);
+}
+
extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
void