#include "mi-cmds.h"
#include "mi-out.h"
#include "mi-console.h"
+#include "mi-common.h"
#include "observer.h"
#include "gdbthread.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 void mi_new_thread (struct thread_info *t);
static void mi_thread_exit (struct thread_info *t);
+static void mi_new_inferior (int pid);
+static void mi_inferior_exit (int pid);
+static void mi_on_resume (ptid_t ptid);
static void *
mi_interpreter_init (int top_level)
{
observer_attach_new_thread (mi_new_thread);
observer_attach_thread_exit (mi_thread_exit);
+ observer_attach_new_inferior (mi_new_inferior);
+ observer_attach_inferior_exit (mi_inferior_exit);
observer_attach_normal_stop (mi_on_normal_stop);
+ observer_attach_target_resumed (mi_on_resume);
}
return mi;
return 0;
}
-enum mi_cmd_result
+void
mi_cmd_interpreter_exec (char *command, char **argv, int argc)
{
struct interp *interp_to_use;
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);
- }
-
if (mi_error_message != NULL)
error ("%s", mi_error_message);
do_cleanups (old_chain);
- return MI_CMD_DONE;
}
/*
{
struct mi_interp *mi = top_level_interpreter_data ();
- fprintf_unfiltered (mi->event_channel, "thread-created,id=\"%d\"", t->num);
+ fprintf_unfiltered (mi->event_channel,
+ "thread-created,id=\"%d\",group-id=\"%d\"",
+ t->num, t->ptid.pid);
gdb_flush (mi->event_channel);
}
{
struct mi_interp *mi = top_level_interpreter_data ();
target_terminal_ours ();
- fprintf_unfiltered (mi->event_channel, "thread-exited,id=\"%d\"", t->num);
+ fprintf_unfiltered (mi->event_channel,
+ "thread-exited,id=\"%d\",group-id=\"%d\"",
+ t->num,t->ptid.pid);
gdb_flush (mi->event_channel);
}
+static void
+mi_new_inferior (int pid)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+ target_terminal_ours ();
+ fprintf_unfiltered (mi->event_channel, "thread-group-created,id=\"%d\"",
+ pid);
+ gdb_flush (mi->event_channel);
+}
+
+static void
+mi_inferior_exit (int pid)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+ target_terminal_ours ();
+ fprintf_unfiltered (mi->event_channel, "thread-group-exited,id=\"%d\"",
+ pid);
+ gdb_flush (mi->event_channel);
+}
+
static void
mi_on_normal_stop (struct bpstats *bs)
{
gdb_flush (raw_stdout);
}
+static void
+mi_on_resume (ptid_t ptid)
+{
+ /* To cater for older frontends, emit ^running, but do it only once
+ per each command. We do it here, since at this point we know
+ that the target was successfully resumed, and in non-async mode,
+ we won't return back to MI interpreter code until the target
+ is done running, so delaying the output of "^running" until then
+ will make it impossible for frontend to know what's going on.
+
+ In future (MI3), we'll be outputting "^done" here. */
+ if (!running_result_record_printed)
+ {
+ if (current_token)
+ fputs_unfiltered (current_token, raw_stdout);
+ fputs_unfiltered ("^running\n", raw_stdout);
+ }
+
+ if (PIDGET (ptid) == -1)
+ fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
+ else if (thread_count () == 0)
+ {
+ /* This is a target where for single-threaded programs the thread
+ table has zero threads. Don't print any thread-id field. */
+ fprintf_unfiltered (raw_stdout, "*running\n");
+ }
+ else
+ {
+ struct thread_info *ti = find_thread_pid (ptid);
+ gdb_assert (ti);
+ fprintf_unfiltered (raw_stdout, "*running,thread-id=\"%d\"\n", ti->num);
+ }
+
+ if (!running_result_record_printed)
+ {
+ running_result_record_printed = 1;
+ /* This is what gdb used to do historically -- printing prompt even if
+ it cannot actually accept any input. This will be surely removed
+ for MI3, and may be removed even earler. */
+ /* FIXME: review the use of target_is_async_p here -- is that
+ what we want? */
+ if (!target_is_async_p ())
+ fputs_unfiltered ("(gdb) \n", raw_stdout);
+ }
+ gdb_flush (raw_stdout);
+}
+
extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
void