/* MI Interpreter Definitions and Commands for GDB, the GNU debugger.
- Copyright (C) 2002-2015 Free Software Foundation, Inc.
+ Copyright (C) 2002-2016 Free Software Foundation, Inc.
This file is part of GDB.
static void mi_new_thread (struct thread_info *t);
static void mi_thread_exit (struct thread_info *t, int silent);
-static void mi_record_changed (struct inferior*, int);
+static void mi_record_changed (struct inferior*, int, const char *,
+ const char *);
static void mi_inferior_added (struct inferior *inf);
static void mi_inferior_appeared (struct inferior *inf);
static void mi_inferior_exit (struct inferior *inf);
static int
mi_interpreter_resume (void *data)
{
- struct mi_interp *mi = data;
+ struct mi_interp *mi = (struct mi_interp *) data;
+ struct ui *ui = current_ui;
/* As per hack note in mi_interpreter_init, swap in the output
channels... */
/* These overwrite some of the initialization done in
_intialize_event_loop. */
- call_readline = gdb_readline2;
- input_handler = mi_execute_command_input_handler;
+ ui->call_readline = gdb_readline_no_editing_callback;
+ ui->input_handler = mi_execute_command_input_handler;
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
error (_("-interpreter-exec: "
"Usage: -interpreter-exec interp command"));
- interp_to_use = interp_lookup (argv[0]);
+ interp_to_use = interp_lookup (current_ui, argv[0]);
if (interp_to_use == NULL)
error (_("-interpreter-exec: could not find interpreter \"%s\""),
argv[0]);
static void
mi_new_thread (struct thread_info *t)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct inferior *inf = find_inferior_ptid (t->ptid);
+ struct cleanup *old_chain;
gdb_assert (inf);
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
+
fprintf_unfiltered (mi->event_channel,
"thread-created,id=\"%d\",group-id=\"i%d\"",
- t->num, inf->num);
+ t->global_num, inf->num);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
static void
inf = find_inferior_ptid (t->ptid);
- mi = top_level_interpreter_data ();
+ mi = (struct mi_interp *) top_level_interpreter_data ();
old_chain = make_cleanup_restore_target_terminal ();
- target_terminal_ours ();
+ target_terminal_ours_for_output ();
+
fprintf_unfiltered (mi->event_channel,
"thread-exited,id=\"%d\",group-id=\"i%d\"",
- t->num, inf->num);
+ t->global_num, inf->num);
gdb_flush (mi->event_channel);
do_cleanups (old_chain);
/* Emit notification on changing the state of record. */
static void
-mi_record_changed (struct inferior *inferior, int started)
+mi_record_changed (struct inferior *inferior, int started, const char *method,
+ const char *format)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
+ struct cleanup *old_chain;
+
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
+
+ if (started)
+ {
+ if (format != NULL)
+ {
+ fprintf_unfiltered (
+ mi->event_channel,
+ "record-started,thread-group=\"i%d\",method=\"%s\",format=\"%s\"",
+ inferior->num, method, format);
+ }
+ else
+ {
+ fprintf_unfiltered (
+ mi->event_channel,
+ "record-started,thread-group=\"i%d\",method=\"%s\"",
+ inferior->num, method);
+ }
+ }
+ else
+ {
+ fprintf_unfiltered (mi->event_channel,
+ "record-stopped,thread-group=\"i%d\"", inferior->num);
+ }
- fprintf_unfiltered (mi->event_channel, "record-%s,thread-group=\"i%d\"",
- started ? "started" : "stopped", inferior->num);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
static void
mi_inferior_added (struct inferior *inf)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
+ struct cleanup *old_chain;
+
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
- target_terminal_ours ();
fprintf_unfiltered (mi->event_channel,
"thread-group-added,id=\"i%d\"",
inf->num);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
static void
mi_inferior_appeared (struct inferior *inf)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
+ struct cleanup *old_chain;
+
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
- target_terminal_ours ();
fprintf_unfiltered (mi->event_channel,
"thread-group-started,id=\"i%d\",pid=\"%d\"",
inf->num, inf->pid);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
static void
mi_inferior_exit (struct inferior *inf)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
+ struct cleanup *old_chain;
+
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
- target_terminal_ours ();
if (inf->has_exit_code)
fprintf_unfiltered (mi->event_channel,
"thread-group-exited,id=\"i%d\",exit-code=\"%s\"",
else
fprintf_unfiltered (mi->event_channel,
"thread-group-exited,id=\"i%d\"", inf->num);
+ gdb_flush (mi->event_channel);
- gdb_flush (mi->event_channel);
+ do_cleanups (old_chain);
}
static void
mi_inferior_removed (struct inferior *inf)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
+ struct cleanup *old_chain;
+
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
- target_terminal_ours ();
fprintf_unfiltered (mi->event_channel,
"thread-group-removed,id=\"i%d\"",
inf->num);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
/* Return the MI interpreter, if it is active -- either because it's
struct interp *interp = find_mi_interpreter ();
if (interp != NULL)
- return interp_data (interp);
+ return (struct mi_interp *) interp_data (interp);
return NULL;
}
|| (tp->control.command_interp != NULL
&& tp->control.command_interp != top_level_interpreter ()))
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi
+ = (struct mi_interp *) top_level_interpreter_data ();
print_stop_event (mi->cli_uiout);
}
- ui_out_field_int (mi_uiout, "thread-id",
- pid_to_thread_id (inferior_ptid));
+ tp = inferior_thread ();
+ ui_out_field_int (mi_uiout, "thread-id", tp->global_num);
if (non_stop)
{
struct cleanup *back_to = make_cleanup_ui_out_list_begin_end
(mi_uiout, "stopped-threads");
- ui_out_field_int (mi_uiout, NULL,
- pid_to_thread_id (inferior_ptid));
+ ui_out_field_int (mi_uiout, NULL, tp->global_num);
do_cleanups (back_to);
}
else
static void
mi_traceframe_changed (int tfnum, int tpnum)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
+ struct cleanup *old_chain;
if (mi_suppress_notification.traceframe)
return;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
if (tfnum >= 0)
fprintf_unfiltered (mi->event_channel, "traceframe-changed,"
fprintf_unfiltered (mi->event_channel, "traceframe-changed,end");
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
/* Emit notification on creating a trace state variable. */
static void
mi_tsv_created (const struct trace_state_variable *tsv)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
+ struct cleanup *old_chain;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
fprintf_unfiltered (mi->event_channel, "tsv-created,"
"name=\"%s\",initial=\"%s\"\n",
tsv->name, plongest (tsv->initial_value));
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
/* Emit notification on deleting a trace state variable. */
static void
mi_tsv_deleted (const struct trace_state_variable *tsv)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
+ struct cleanup *old_chain;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
if (tsv != NULL)
fprintf_unfiltered (mi->event_channel, "tsv-deleted,"
fprintf_unfiltered (mi->event_channel, "tsv-deleted\n");
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
/* Emit notification on modifying a trace state variable. */
static void
mi_tsv_modified (const struct trace_state_variable *tsv)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
+ struct cleanup *old_chain;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
fprintf_unfiltered (mi->event_channel,
"tsv-modified");
ui_out_redirect (mi_uiout, NULL);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
/* Emit notification about a created breakpoint. */
static void
mi_breakpoint_created (struct breakpoint *b)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
+ struct cleanup *old_chain;
if (mi_suppress_notification.breakpoint)
return;
if (b->number <= 0)
return;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
+
fprintf_unfiltered (mi->event_channel,
"breakpoint-created");
/* We want the output from gdb_breakpoint_query to go to
ui_out_redirect (mi_uiout, NULL);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
/* Emit notification about deleted breakpoint. */
static void
mi_breakpoint_deleted (struct breakpoint *b)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
+ struct cleanup *old_chain;
if (mi_suppress_notification.breakpoint)
return;
if (b->number <= 0)
return;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
fprintf_unfiltered (mi->event_channel, "breakpoint-deleted,id=\"%d\"",
b->number);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
/* Emit notification about modified breakpoint. */
static void
mi_breakpoint_modified (struct breakpoint *b)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
+ struct cleanup *old_chain;
if (mi_suppress_notification.breakpoint)
return;
if (b->number <= 0)
return;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
+
fprintf_unfiltered (mi->event_channel,
"breakpoint-modified");
/* We want the output from gdb_breakpoint_query to go to
ui_out_redirect (mi_uiout, NULL);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
static int
mi_output_running_pid (struct thread_info *info, void *arg)
{
- ptid_t *ptid = arg;
+ ptid_t *ptid = (ptid_t *) arg;
if (ptid_get_pid (*ptid) == ptid_get_pid (info->ptid))
fprintf_unfiltered (raw_stdout,
"*running,thread-id=\"%d\"\n",
- info->num);
+ info->global_num);
return 0;
}
{
if (inf->pid != 0)
{
- int *count_p = arg;
+ int *count_p = (int *) arg;
(*count_p)++;
}
struct thread_info *ti = find_thread_ptid (ptid);
gdb_assert (ti);
- fprintf_unfiltered (raw_stdout, "*running,thread-id=\"%d\"\n", ti->num);
+ fprintf_unfiltered (raw_stdout, "*running,thread-id=\"%d\"\n",
+ ti->global_num);
}
if (!running_result_record_printed && mi_proceeded)
for MI3, and may be removed even earlier. SYNC_EXECUTION is
checked here because we only need to emit a prompt if a
synchronous command was issued when the target is async. */
- if (!target_is_async_p () || sync_execution)
+ if (!target_can_async_p () || sync_execution)
fputs_unfiltered ("(gdb) \n", raw_stdout);
}
gdb_flush (raw_stdout);
static void
mi_solib_loaded (struct so_list *solib)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *uiout = interp_ui_out (top_level_interpreter ());
+ struct cleanup *old_chain;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
fprintf_unfiltered (mi->event_channel, "library-loaded");
ui_out_field_int (uiout, "symbols-loaded", solib->symbols_loaded);
if (!gdbarch_has_global_solist (target_gdbarch ()))
{
- ui_out_field_fmt (uiout, "thread-group", "i%d", current_inferior ()->num);
+ ui_out_field_fmt (uiout, "thread-group", "i%d",
+ current_inferior ()->num);
}
ui_out_redirect (uiout, NULL);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
static void
mi_solib_unloaded (struct so_list *solib)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *uiout = interp_ui_out (top_level_interpreter ());
+ struct cleanup *old_chain;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
fprintf_unfiltered (mi->event_channel, "library-unloaded");
ui_out_field_string (uiout, "host-name", solib->so_name);
if (!gdbarch_has_global_solist (target_gdbarch ()))
{
- ui_out_field_fmt (uiout, "thread-group", "i%d", current_inferior ()->num);
+ ui_out_field_fmt (uiout, "thread-group", "i%d",
+ current_inferior ()->num);
}
ui_out_redirect (uiout, NULL);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
/* Emit notification about the command parameter change. */
static void
mi_command_param_changed (const char *param, const char *value)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
+ struct cleanup *old_chain;
if (mi_suppress_notification.cmd_param_changed)
return;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
fprintf_unfiltered (mi->event_channel,
"cmd-param-changed");
ui_out_redirect (mi_uiout, NULL);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
/* Emit notification about the target memory change. */
mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr,
ssize_t len, const bfd_byte *myaddr)
{
- struct mi_interp *mi = top_level_interpreter_data ();
+ struct mi_interp *mi = (struct mi_interp *) top_level_interpreter_data ();
struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
struct obj_section *sec;
+ struct cleanup *old_chain;
if (mi_suppress_notification.memory)
return;
- target_terminal_ours ();
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
fprintf_unfiltered (mi->event_channel,
"memory-changed");
ui_out_redirect (mi_uiout, NULL);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
}
static int
mi_inferior_added assumes that inferior is fully initialized
and top_level_interpreter_data is set, we cannot call
it here. */
- struct mi_interp *mi = closure;
+ struct mi_interp *mi = (struct mi_interp *) closure;
+ struct cleanup *old_chain;
+
+ old_chain = make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
- target_terminal_ours ();
fprintf_unfiltered (mi->event_channel,
"thread-group-added,id=\"i%d\"",
inf->num);
gdb_flush (mi->event_channel);
+
+ do_cleanups (old_chain);
return 0;
}
static struct ui_out *
mi_ui_out (struct interp *interp)
{
- struct mi_interp *mi = interp_data (interp);
+ struct mi_interp *mi = (struct mi_interp *) interp_data (interp);
return mi->mi_uiout;
}
mi_set_logging (struct interp *interp, int start_log,
struct ui_file *out, struct ui_file *logfile)
{
- struct mi_interp *mi = interp_data (interp);
+ struct mi_interp *mi = (struct mi_interp *) interp_data (interp);
if (!mi)
return 0;
return 1;
}
+/* The MI interpreter's vtable. */
+
+static const struct interp_procs mi_interp_procs =
+{
+ mi_interpreter_init, /* init_proc */
+ mi_interpreter_resume, /* resume_proc */
+ mi_interpreter_suspend, /* suspend_proc */
+ mi_interpreter_exec, /* exec_proc */
+ mi_ui_out, /* ui_out_proc */
+ mi_set_logging, /* set_logging_proc */
+ mi_command_loop /* command_loop_proc */
+};
+
+/* Factory for MI interpreters. */
+
+static struct interp *
+mi_interp_factory (const char *name)
+{
+ return interp_new (name, &mi_interp_procs, 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_ui_out, /* ui_out_proc */
- mi_set_logging, /* set_logging_proc */
- mi_command_loop /* command_loop_proc */
- };
-
/* The various interpreter levels. */
- interp_add (interp_new (INTERP_MI1, &procs));
- interp_add (interp_new (INTERP_MI2, &procs));
- interp_add (interp_new (INTERP_MI3, &procs));
- interp_add (interp_new (INTERP_MI, &procs));
+ interp_factory_register (INTERP_MI1, mi_interp_factory);
+ interp_factory_register (INTERP_MI2, mi_interp_factory);
+ interp_factory_register (INTERP_MI3, mi_interp_factory);
+ interp_factory_register (INTERP_MI, mi_interp_factory);
}