| Index: gdb/mi/mi-interp.c
|
| diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
|
| index c9cd24d676a850f35982cccaeb9a1168b88e630e..b48713676e12470b69e7a8bedca3d4fdd694e09b 100644
|
| --- a/gdb/mi/mi-interp.c
|
| +++ b/gdb/mi/mi-interp.c
|
| @@ -36,15 +36,19 @@
|
| #include "solist.h"
|
| #include "gdb.h"
|
|
|
| -/* These are the interpreter setup, etc. functions for the MI interpreter */
|
| +/* These are the interpreter setup, etc. functions for the MI
|
| + interpreter. */
|
| +
|
| static void mi_execute_command_wrapper (char *cmd);
|
| +static void mi_execute_command_input_handler (char *cmd);
|
| static void mi_command_loop (int mi_version);
|
|
|
| /* 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 */
|
| + 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)
|
| - ATTRIBUTE_PRINTF (1, 0);
|
| + ATTRIBUTE_PRINTF (1, 0);
|
|
|
| static void mi3_command_loop (void);
|
| static void mi2_command_loop (void);
|
| @@ -77,14 +81,15 @@ mi_interpreter_init (struct interp *interp, int top_level)
|
| const char *name;
|
| int mi_version;
|
|
|
| - /* 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. */
|
| + /* Assign the output channel created at startup to its own global,
|
| + so that we can create a console channel that encapsulates and
|
| + prefixes all gdb_output-type bits coming from the rest of the
|
| + debugger. */
|
|
|
| - raw_stdout = stdio_fileopen (stdout);
|
| + raw_stdout = gdb_stdout;
|
|
|
| - /* Create MI channels */
|
| + /* Create MI console channels, each with a different prefix so they
|
| + can be distinguished. */
|
| mi->out = mi_console_file_new (raw_stdout, "~", '"');
|
| mi->err = mi_console_file_new (raw_stdout, "&", '"');
|
| mi->log = mi->err;
|
| @@ -124,9 +129,10 @@ mi_interpreter_init (struct interp *interp, int top_level)
|
| observer_attach_breakpoint_deleted (mi_breakpoint_deleted);
|
| observer_attach_breakpoint_modified (mi_breakpoint_modified);
|
|
|
| - /* The initial inferior is created before this function is called, so we
|
| - need to report it explicitly. Use iteration in case future version
|
| - of GDB creates more than one inferior up-front. */
|
| + /* The initial inferior is created before this function is
|
| + called, so we need to report it explicitly. Use iteration in
|
| + case future version of GDB creates more than one inferior
|
| + up-front. */
|
| iterate_over_inferiors (report_initial_inferior, mi);
|
| }
|
|
|
| @@ -138,13 +144,14 @@ mi_interpreter_resume (void *data)
|
| {
|
| struct mi_interp *mi = data;
|
|
|
| - /* As per hack note in mi_interpreter_init, swap in the output channels... */
|
| + /* As per hack note in mi_interpreter_init, swap in the output
|
| + channels... */
|
| gdb_setup_readline ();
|
|
|
| /* These overwrite some of the initialization done in
|
| _intialize_event_loop. */
|
| call_readline = gdb_readline2;
|
| - input_handler = mi_execute_command_wrapper;
|
| + input_handler = mi_execute_command_input_handler;
|
| 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
|
| @@ -156,12 +163,12 @@ mi_interpreter_resume (void *data)
|
| sync_execution = 0;
|
|
|
| gdb_stdout = mi->out;
|
| - /* Route error and log output through the MI */
|
| + /* Route error and log output through the MI. */
|
| gdb_stderr = mi->err;
|
| gdb_stdlog = mi->log;
|
| - /* Route target output through the MI. */
|
| + /* Route target output through the MI. */
|
| gdb_stdtarg = mi->targ;
|
| - /* Route target error through the MI as well. */
|
| + /* Route target error through the MI as well. */
|
| gdb_stdtargerr = mi->targ;
|
|
|
| /* Replace all the hooks that we know about. There really needs to
|
| @@ -170,7 +177,7 @@ mi_interpreter_resume (void *data)
|
|
|
| deprecated_show_load_progress = mi_load_progress;
|
|
|
| - /* If we're _the_ interpreter, take control. */
|
| + /* If we're _the_ interpreter, take control. */
|
| if (current_interp_named_p (INTERP_MI1))
|
| deprecated_command_loop_hook = mi1_command_loop;
|
| else if (current_interp_named_p (INTERP_MI2))
|
| @@ -200,7 +207,8 @@ mi_interpreter_exec (void *data, const char *command)
|
| return exception_none;
|
| }
|
|
|
| -/* Never display the default gdb prompt in mi case. */
|
| +/* Never display the default GDB prompt in MI case. */
|
| +
|
| static int
|
| mi_interpreter_prompt_p (void *data)
|
| {
|
| @@ -229,13 +237,14 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
|
| "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. */
|
| - /* KRS: We shouldn't need this... Events should be installed and they should
|
| - just ALWAYS fire something out down the MI channel... */
|
| + /* 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... */
|
| + /* Now run the code. */
|
|
|
| old_chain = make_cleanup (null_cleanup, 0);
|
| for (i = 1; i < argc; i++)
|
| @@ -257,14 +266,12 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
|
| do_cleanups (old_chain);
|
| }
|
|
|
| -/*
|
| - * 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.
|
| -*/
|
| +/* 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)
|
| @@ -290,6 +297,17 @@ mi_execute_command_wrapper (char *cmd)
|
| mi_execute_command (cmd, stdin == instream);
|
| }
|
|
|
| +/* mi_execute_command_wrapper wrapper suitable for INPUT_HANDLER. */
|
| +
|
| +static void
|
| +mi_execute_command_input_handler (char *cmd)
|
| +{
|
| + mi_execute_command_wrapper (cmd);
|
| +
|
| + fputs_unfiltered ("(gdb) \n", raw_stdout);
|
| + gdb_flush (raw_stdout);
|
| +}
|
| +
|
| static void
|
| mi1_command_loop (void)
|
| {
|
| @@ -312,11 +330,13 @@ static void
|
| mi_command_loop (int mi_version)
|
| {
|
| /* Turn off 8 bit strings in quoted output. Any character with the
|
| - high bit set is printed using C's octal format. */
|
| + high bit set is printed using C's octal format. */
|
| sevenbit_strings = 1;
|
| - /* Tell the world that we're alive */
|
| +
|
| + /* Tell the world that we're alive. */
|
| fputs_unfiltered ("(gdb) \n", raw_stdout);
|
| gdb_flush (raw_stdout);
|
| +
|
| start_event_loop ();
|
| }
|
|
|
| @@ -420,11 +440,11 @@ mi_on_normal_stop (struct bpstats *bs, int print_frame)
|
|
|
| if (current_uiout != mi_uiout)
|
| {
|
| - /* The normal_stop function has printed frame information into
|
| - CLI uiout, or some other non-MI uiout. There's no way we
|
| - can extract proper fields from random uiout object, so we print
|
| - the frame again. In practice, this can only happen when running
|
| - a CLI command in MI. */
|
| + /* The normal_stop function has printed frame information
|
| + into CLI uiout, or some other non-MI uiout. There's no
|
| + way we can extract proper fields from random uiout
|
| + object, so we print the frame again. In practice, this
|
| + can only happen when running a CLI command in MI. */
|
| struct ui_out *saved_uiout = current_uiout;
|
| struct target_waitstatus last;
|
| ptid_t last_ptid;
|
| @@ -483,15 +503,17 @@ mi_about_to_proceed (void)
|
|
|
| /* When non-zero, no MI notifications will be emitted in
|
| response to breakpoint change observers. */
|
| +
|
| int mi_suppress_breakpoint_notifications = 0;
|
|
|
| /* Emit notification about a created breakpoint. */
|
| +
|
| static void
|
| mi_breakpoint_created (struct breakpoint *b)
|
| {
|
| struct mi_interp *mi = top_level_interpreter_data ();
|
| struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
|
| - struct gdb_exception e;
|
| + volatile struct gdb_exception e;
|
|
|
| if (mi_suppress_breakpoint_notifications)
|
| return;
|
| @@ -503,12 +525,12 @@ mi_breakpoint_created (struct breakpoint *b)
|
| fprintf_unfiltered (mi->event_channel,
|
| "breakpoint-created");
|
| /* We want the output from gdb_breakpoint_query to go to
|
| - mi->event_channel. One approach would be to just
|
| - call gdb_breakpoint_query, and then use mi_out_put to
|
| - send the current content of mi_outout into mi->event_channel.
|
| - However, that will break if anything is output to mi_uiout
|
| - prior the calling the breakpoint_created notifications.
|
| - So, we use ui_out_redirect. */
|
| + mi->event_channel. One approach would be to just call
|
| + gdb_breakpoint_query, and then use mi_out_put to send the current
|
| + content of mi_outout into mi->event_channel. However, that will
|
| + break if anything is output to mi_uiout prior to calling the
|
| + breakpoint_created notifications. So, we use
|
| + ui_out_redirect. */
|
| ui_out_redirect (mi_uiout, mi->event_channel);
|
| TRY_CATCH (e, RETURN_MASK_ERROR)
|
| gdb_breakpoint_query (mi_uiout, b->number, NULL);
|
| @@ -518,6 +540,7 @@ mi_breakpoint_created (struct breakpoint *b)
|
| }
|
|
|
| /* Emit notification about deleted breakpoint. */
|
| +
|
| static void
|
| mi_breakpoint_deleted (struct breakpoint *b)
|
| {
|
| @@ -538,12 +561,13 @@ mi_breakpoint_deleted (struct breakpoint *b)
|
| }
|
|
|
| /* Emit notification about modified breakpoint. */
|
| +
|
| static void
|
| mi_breakpoint_modified (struct breakpoint *b)
|
| {
|
| struct mi_interp *mi = top_level_interpreter_data ();
|
| struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());
|
| - struct gdb_exception e;
|
| + volatile struct gdb_exception e;
|
|
|
| if (mi_suppress_breakpoint_notifications)
|
| return;
|
| @@ -555,12 +579,12 @@ mi_breakpoint_modified (struct breakpoint *b)
|
| fprintf_unfiltered (mi->event_channel,
|
| "breakpoint-modified");
|
| /* We want the output from gdb_breakpoint_query to go to
|
| - mi->event_channel. One approach would be to just
|
| - call gdb_breakpoint_query, and then use mi_out_put to
|
| - send the current content of mi_outout into mi->event_channel.
|
| - However, that will break if anything is output to mi_uiout
|
| - prior the calling the breakpoint_created notifications.
|
| - So, we use ui_out_redirect. */
|
| + mi->event_channel. One approach would be to just call
|
| + gdb_breakpoint_query, and then use mi_out_put to send the current
|
| + content of mi_outout into mi->event_channel. However, that will
|
| + break if anything is output to mi_uiout prior to calling the
|
| + breakpoint_created notifications. So, we use
|
| + ui_out_redirect. */
|
| ui_out_redirect (mi_uiout, mi->event_channel);
|
| TRY_CATCH (e, RETURN_MASK_ERROR)
|
| gdb_breakpoint_query (mi_uiout, b->number, NULL);
|
| @@ -569,7 +593,6 @@ mi_breakpoint_modified (struct breakpoint *b)
|
| gdb_flush (mi->event_channel);
|
| }
|
|
|
| -
|
| static int
|
| mi_output_running_pid (struct thread_info *info, void *arg)
|
| {
|
| @@ -732,20 +755,69 @@ mi_ui_out (struct interp *interp)
|
| return mi->uiout;
|
| }
|
|
|
| +/* Save the original value of raw_stdout here when logging, so we can
|
| + restore correctly when done. */
|
| +
|
| +static struct ui_file *saved_raw_stdout;
|
| +
|
| +/* Do MI-specific logging actions; save raw_stdout, and change all
|
| + the consoles to use the supplied ui-file(s). */
|
| +
|
| +static int
|
| +mi_set_logging (struct interp *interp, int start_log,
|
| + struct ui_file *out, struct ui_file *logfile)
|
| +{
|
| + struct mi_interp *mi = interp_data (interp);
|
| +
|
| + if (!mi)
|
| + return 0;
|
| +
|
| + if (start_log)
|
| + {
|
| + /* The tee created already is based on gdb_stdout, which for MI
|
| + is a console and so we end up in an infinite loop of console
|
| + writing to ui_file writing to console etc. So discard the
|
| + existing tee (it hasn't been used yet, and MI won't ever use
|
| + it), and create one based on raw_stdout instead. */
|
| + if (logfile)
|
| + {
|
| + ui_file_delete (out);
|
| + out = tee_file_new (raw_stdout, 0, logfile, 0);
|
| + }
|
| +
|
| + saved_raw_stdout = raw_stdout;
|
| + raw_stdout = out;
|
| + }
|
| + else
|
| + {
|
| + raw_stdout = saved_raw_stdout;
|
| + saved_raw_stdout = NULL;
|
| + }
|
| +
|
| + mi_console_set_raw (mi->out, raw_stdout);
|
| + mi_console_set_raw (mi->err, raw_stdout);
|
| + mi_console_set_raw (mi->log, raw_stdout);
|
| + mi_console_set_raw (mi->targ, raw_stdout);
|
| + mi_console_set_raw (mi->event_channel, raw_stdout);
|
| +
|
| + return 1;
|
| +}
|
| +
|
| 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 */
|
| - mi_ui_out /* ui_out_proc */
|
| - };
|
| + {
|
| + 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 */
|
| + mi_ui_out, /* ui_out_proc */
|
| + mi_set_logging /* set_logging_proc */
|
| + };
|
|
|
| /* The various interpreter levels. */
|
| interp_add (interp_new (INTERP_MI1, &procs));
|
|
|