[PATCH v3 05/34] Make the interpreters be per UI

Pedro Alves
2016-05-06T12:43:02Z

Make each UI have its own interpreter list, top level interpreter,
current interpreter, etc. The "interpreter_async" global is not
really specific to an struct interp (it crosses interpreter-exec ...),
so I moved it to "struct ui" directly, while the other globals were
left hidden in interps.c, opaque to the rest of GDB.

gdb/ChangeLog:
yyyy-mm-dd Pedro Alves <palves@redhat.com>

* breakpoint.c (bpstat_do_actions_1): Access the current UI's
async field instead of the interpreter_async global.
* cli/cli-script.c (execute_user_command, while_command)
(if_command, script_from_file): Likewise.
* compile/compile.c: Include top.h instead of interps.h.
(compile_file_command, compile_code_command)
(compile_print_command): Access the current UI's async field
instead of the interpreter_async global.
* guile/guile.c: Include top.h instead of interps.h.
(guile_repl_command, guile_command, gdbscm_execute_gdb_command):
Access the current UI's async field instead of the
interpreter_async global.
* guile/scm-ports.c: Include top.h instead of interps.h.
(ioscm_with_output_to_port_worker): Access the current UI's async
field instead of the interpreter_async global.
* inf-loop.c (inferior_event_handler): Likewise.
* infcall.c (run_inferior_call): Likewise.
* infrun.c (reinstall_readline_callback_handler_cleanup)
(fetch_inferior_event): Likewise.
* interps.c (interpreter_async): Delete.
(struct ui_interp_info): New.
(get_current_interp_info): New function.
(interp_list, current_interpreter, top_level_interpreter_ptr):
Delete.
(interp_add, interp_set, interp_lookup, interp_ui_out)
(current_interp_set_logging, interp_set_temp)
(current_interp_named_p): Adjust to per-UI interpreters.
(command_interpreter): Delete.
(command_interp, current_interp_command_loop, interp_quiet_p)
(interp_exec, interpreter_exec_cmd, interpreter_completer)
(top_level_interpretertop_level_interpreter)
(top_level_interpreter_data): Adjust to per-UI interpreters.
* interps.h (interpreter_async): Delete.
* main.c (captured_command_loop): Access the current UI's async
field instead of the interpreter_async global.
* python/python.c (python_interactive_command, python_command)
(execute_gdb_command): Likewise.
* top.c (maybe_wait_sync_command_done, execute_command_to_string):
Access the current UI's async field instead of the
interpreter_async global.
* top.h (struct tl_interp_info): Forward declare.
(struct ui) <interp_info, async>: New fields.
---
gdb/breakpoint.c | 2 +-
gdb/cli/cli-script.c | 16 +++---
gdb/compile/compile.c | 14 ++---
gdb/guile/guile.c | 14 ++---
gdb/guile/scm-ports.c | 6 +-
gdb/inf-loop.c | 2 +-
gdb/infcall.c | 6 +-
gdb/infrun.c | 4 +-
gdb/interps.c | 151 +++++++++++++++++++++++++++++++-------------------
gdb/interps.h | 9 ---
gdb/main.c | 2 +-
gdb/python/python.c | 12 ++--
gdb/top.c | 6 +-
gdb/top.h | 15 +++++
14 files changed, 152 insertions(+), 107 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index a39a15c..a28e956 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4733,7 +4733,7 @@ bpstat_do_actions_1 (bpstat *bsp)

if (breakpoint_proceeded)
{
- if (interpreter_async)
+ if (current_ui->async)
/* If we are in async mode, then the target might be still
running, not stopped at any breakpoint, so nothing for
us to do here -- just return to the event loop. */
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 7302330..5fc01b3 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -379,8 +379,8 @@ execute_user_command (struct cmd_list_element *c, char *args)
not confused with Insight. */
in_user_command = 1;

- make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

command_nest_depth++;
while (cmdlines)
@@ -661,8 +661,8 @@ while_command (char *arg, int from_tty)
if (command == NULL)
return;

- old_chain = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ old_chain = make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

execute_control_command_untraced (command);
free_command_lines (&command);
@@ -685,8 +685,8 @@ if_command (char *arg, int from_tty)
if (command == NULL)
return;

- old_chain = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ old_chain = make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

execute_control_command_untraced (command);
free_command_lines (&command);
@@ -1688,8 +1688,8 @@ script_from_file (FILE *stream, const char *file)
source_line_number = 0;
source_file_name = file;

- make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

{

diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 77b4137..0c4a738 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -18,7 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */

#include "defs.h"
-#include "interps.h"
+#include "top.h"
#include "ui-out.h"
#include "command.h"
#include "cli/cli-script.h"
@@ -91,8 +91,8 @@ compile_file_command (char *arg, int from_tty)
char *buffer;
struct cleanup *cleanup;

- cleanup = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ cleanup = make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

/* Check the user did not just <enter> after command. */
if (arg == NULL)
@@ -133,8 +133,8 @@ compile_code_command (char *arg, int from_tty)
struct cleanup *cleanup;
enum compile_i_scope_types scope = COMPILE_I_SIMPLE_SCOPE;

- cleanup = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ cleanup = make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

if (arg != NULL && check_raw_argument (&arg))
{
@@ -187,8 +187,8 @@ compile_print_command (char *arg_param, int from_tty)
enum compile_i_scope_types scope = COMPILE_I_PRINT_ADDRESS_SCOPE;
struct format_data fmt;

- cleanup = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ cleanup = make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

/* Passing &FMT as SCOPE_DATA is safe as do_module_cleanup will not
touch the stale pointer if compile_object_run has already quit. */
diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c
index b010e59..117561d 100644
--- a/gdb/guile/guile.c
+++ b/gdb/guile/guile.c
@@ -27,7 +27,7 @@
#include "cli/cli-utils.h"
#include "command.h"
#include "gdbcmd.h"
-#include "interps.h"
+#include "top.h"
#include "extension-priv.h"
#include "utils.h"
#include "version.h"
@@ -165,8 +165,8 @@ guile_repl_command (char *arg, int from_tty)
{
struct cleanup *cleanup;

- cleanup = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ cleanup = make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

arg = skip_spaces (arg);

@@ -198,8 +198,8 @@ guile_command (char *arg, int from_tty)
{
struct cleanup *cleanup;

- cleanup = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ cleanup = make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

arg = skip_spaces (arg);

@@ -328,8 +328,8 @@ gdbscm_execute_gdb_command (SCM command_scm, SCM rest)
{
struct cleanup *inner_cleanups;

- inner_cleanups = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ inner_cleanups = make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

prevent_dont_repeat ();
if (to_string)
diff --git a/gdb/guile/scm-ports.c b/gdb/guile/scm-ports.c
index b0f576e..5559475 100644
--- a/gdb/guile/scm-ports.c
+++ b/gdb/guile/scm-ports.c
@@ -23,7 +23,7 @@

#include "defs.h"
#include "gdb_select.h"
-#include "interps.h"
+#include "top.h"
#include "target.h"
#include "guile-internal.h"

@@ -517,8 +517,8 @@ ioscm_with_output_to_port_worker (SCM port, SCM thunk, enum oport oport,

cleanups = set_batch_flag_and_make_cleanup_restore_page_info ();

- make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

port_file = ioscm_file_port_new (port);

diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c
index 2591ae9..d006df8 100644
--- a/gdb/inf-loop.c
+++ b/gdb/inf-loop.c
@@ -61,7 +61,7 @@ inferior_event_handler (enum inferior_event_type event_type,

/* When running a command list (from a user command, say), these
are only run when the command list is all done. */
- if (interpreter_async)
+ if (current_ui->async)
{
check_frame_language_change ();

diff --git a/gdb/infcall.c b/gdb/infcall.c
index 77cd931..11f5aba 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -560,13 +560,13 @@ run_inferior_call (struct call_thread_fsm *sm,
ptid_t call_thread_ptid = call_thread->ptid;
int saved_sync_execution = sync_execution;
int was_running = call_thread->state == THREAD_RUNNING;
- int saved_interpreter_async = interpreter_async;
+ int saved_ui_async = current_ui->async;

/* Infcalls run synchronously, in the foreground. */
sync_execution = 1;
/* So that we don't print the prompt prematurely in
fetch_inferior_event. */
- interpreter_async = 0;
+ current_ui->async = 0;

call_thread->control.in_infcall = 1;

@@ -601,7 +601,7 @@ run_inferior_call (struct call_thread_fsm *sm,
again here. In other cases, stdin will be re-enabled by
inferior_event_handler, when an exception is thrown. */
sync_execution = saved_sync_execution;
- interpreter_async = saved_interpreter_async;
+ current_ui->async = saved_ui_async;

/* At this point the current thread may have changed. Refresh
CALL_THREAD as it could be invalid if its thread has exited. */
diff --git a/gdb/infrun.c b/gdb/infrun.c
index cfb1d06..ba7144a 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3806,7 +3806,7 @@ wait_for_inferior (void)
static void
reinstall_readline_callback_handler_cleanup (void *arg)
{
- if (!interpreter_async)
+ if (!current_ui->async)
{
/* We're not going back to the top level event loop yet. Don't
install the readline callback, as it'd prep the terminal,
@@ -3993,7 +3993,7 @@ fetch_inferior_event (void *client_data)
/* If the inferior was in sync execution mode, and now isn't,
restore the prompt (a synchronous execution command has finished,
and we're ready for input). */
- if (interpreter_async && was_sync && !sync_execution)
+ if (current_ui->async && was_sync && !sync_execution)
observer_notify_sync_execution_done ();

if (cmd_done
diff --git a/gdb/interps.c b/gdb/interps.c
index b188d08..7f57132 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -39,11 +39,31 @@
#include "top.h" /* For command_loop. */
#include "continuations.h"

-/* True if the current interpreter in is async mode. See interps.h
- for more details. This starts out disabled, until all the explicit
- command line arguments (e.g., `gdb -ex "start" -ex "next"') are
- processed. */
-int interpreter_async = 0;
+/* Each UI has its own independent set of interpreters. */
+
+struct ui_interp_info
+{
+ /* Each top level has its own independent set of interpreters. */
+ struct interp *interp_list;
+ struct interp *current_interpreter;
+ struct interp *top_level_interpreter_ptr;
+
+ /* The interpreter that is active while `interp_exec' is active, NULL
+ at all other times. */
+ struct interp *command_interpreter;
+};
+
+/* Get the current UI's ui_interp_info object. Never returns NULL. */
+
+static struct ui_interp_info *
+get_current_interp_info (void)
+{
+ struct ui *ui = current_ui;
+
+ if (ui->interp_info == NULL)
+ ui->interp_info = XCNEW (struct ui_interp_info);
+ return ui->interp_info;
+}

struct interp
{
@@ -71,12 +91,6 @@ struct interp

void _initialize_interpreter (void);

-/* Variables local to this file: */
-
-static struct interp *interp_list = NULL;
-static struct interp *current_interpreter = NULL;
-static struct interp *top_level_interpreter_ptr = NULL;
-
/* interp_new - This allocates space for a new interpreter,
fills the fields from the inputs, and returns a pointer to the
interpreter. */
@@ -104,10 +118,12 @@ interp_new (const char *name, const struct interp_procs *procs)
void
interp_add (struct interp *interp)
{
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
+
gdb_assert (interp_lookup (interp->name) == NULL);

- interp->next = interp_list;
- interp_list = interp;
+ interp->next = ui_interp->interp_list;
+ ui_interp->interp_list = interp;
}

/* This sets the current interpreter to be INTERP. If INTERP has not
@@ -127,24 +143,24 @@ interp_add (struct interp *interp)
int
interp_set (struct interp *interp, int top_level)
{
- struct interp *old_interp = current_interpreter;
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
+ struct interp *old_interp = ui_interp->current_interpreter;
int first_time = 0;
char buffer[64];

/* If we already have an interpreter, then trying to
set top level interpreter is kinda pointless. */
- gdb_assert (!top_level || !current_interpreter);
- gdb_assert (!top_level || !top_level_interpreter_ptr);
+ gdb_assert (!top_level || !ui_interp->current_interpreter);
+ gdb_assert (!top_level || !ui_interp->top_level_interpreter_ptr);

- if (current_interpreter != NULL)
+ if (old_interp != NULL)
{
ui_out_flush (current_uiout);
- if (current_interpreter->procs->suspend_proc
- && !current_interpreter->procs->suspend_proc (current_interpreter->
- data))
+ if (old_interp->procs->suspend_proc
+ && !old_interp->procs->suspend_proc (old_interp->data))
{
error (_("Could not suspend interpreter \"%s\"."),
- current_interpreter->name);
+ old_interp->name);
}
}
else
@@ -152,18 +168,18 @@ interp_set (struct interp *interp, int top_level)
first_time = 1;
}

- current_interpreter = interp;
+ ui_interp->current_interpreter = interp;
if (top_level)
- top_level_interpreter_ptr = interp;
+ ui_interp->top_level_interpreter_ptr = interp;

/* We use interpreter_p for the "set interpreter" variable, so we need
to make sure we have a malloc'ed copy for the set command to free. */
if (interpreter_p != NULL
- && strcmp (current_interpreter->name, interpreter_p) != 0)
+ && strcmp (interp->name, interpreter_p) != 0)
{
xfree (interpreter_p);

- interpreter_p = xstrdup (current_interpreter->name);
+ interpreter_p = xstrdup (interp->name);
}

/* Run the init proc. If it fails, try to restore the old interp. */
@@ -209,12 +225,15 @@ interp_set (struct interp *interp, int top_level)
struct interp *
interp_lookup (const char *name)
{
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
struct interp *interp;

if (name == NULL || strlen (name) == 0)
return NULL;

- for (interp = interp_list; interp != NULL; interp = interp->next)
+ for (interp = ui_interp->interp_list;
+ interp != NULL;
+ interp = interp->next)
{
if (strcmp (interp->name, name) == 0)
return interp;
@@ -228,34 +247,37 @@ interp_lookup (const char *name)
struct ui_out *
interp_ui_out (struct interp *interp)
{
- if (interp != NULL)
- return interp->procs->ui_out_proc (interp);
+ struct ui_interp_info *ui_interp = get_current_interp_info ();

- return current_interpreter->procs->ui_out_proc (current_interpreter);
+ if (interp == NULL)
+ interp = ui_interp->current_interpreter;
+ return interp->procs->ui_out_proc (interp);
}

int
current_interp_set_logging (int start_log, struct ui_file *out,
struct ui_file *logfile)
{
- if (current_interpreter == NULL
- || current_interpreter->procs->set_logging_proc == NULL)
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
+ struct interp *interp = ui_interp->current_interpreter;
+
+ if (interp == NULL
+ || interp->procs->set_logging_proc == NULL)
return 0;

- return current_interpreter->procs->set_logging_proc (current_interpreter,
- start_log, out,
- logfile);
+ return interp->procs->set_logging_proc (interp, start_log, out, logfile);
}

/* Temporarily overrides the current interpreter. */
struct interp *
interp_set_temp (const char *name)
{
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
struct interp *interp = interp_lookup (name);
- struct interp *old_interp = current_interpreter;
+ struct interp *old_interp = ui_interp->current_interpreter;

if (interp)
- current_interpreter = interp;
+ ui_interp->current_interpreter = interp;
return old_interp;
}

@@ -279,16 +301,15 @@ interp_name (struct interp *interp)
int
current_interp_named_p (const char *interp_name)
{
- if (current_interpreter)
- return (strcmp (current_interpreter->name, interp_name) == 0);
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
+ struct interp *interp = ui_interp->current_interpreter;
+
+ if (interp != NULL)
+ return (strcmp (interp->name, interp_name) == 0);

return 0;
}

-/* The interpreter that is active while `interp_exec' is active, NULL
- at all other times. */
-static struct interp *command_interpreter;
-
/* The interpreter that was active when a command was executed.
Normally that'd always be CURRENT_INTERPRETER, except that MI's
-interpreter-exec command doesn't actually flip the current
@@ -302,28 +323,35 @@ static struct interp *command_interpreter;
struct interp *
command_interp (void)
{
- if (command_interpreter != NULL)
- return command_interpreter;
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
+
+ if (ui_interp->command_interpreter != NULL)
+ return ui_interp->command_interpreter;
else
- return current_interpreter;
+ return ui_interp->current_interpreter;
}

/* Run the current command interpreter's main loop. */
void
current_interp_command_loop (void)
{
- gdb_assert (current_interpreter != NULL);
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
+ struct interp *interp = ui_interp->current_interpreter;
+
+ gdb_assert (ui_interp->current_interpreter != NULL);

- current_interpreter->procs->command_loop_proc (current_interpreter->data);
+ interp->procs->command_loop_proc (interp->data);
}

int
interp_quiet_p (struct interp *interp)
{
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
+
if (interp != NULL)
return interp->quiet_p;
else
- return current_interpreter->quiet_p;
+ return ui_interp->current_interpreter->quiet_p;
}

static int
@@ -341,18 +369,20 @@ interp_set_quiet (struct interp *interp, int quiet)
struct gdb_exception
interp_exec (struct interp *interp, const char *command_str)
{
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
+
struct gdb_exception ex;
struct interp *save_command_interp;

gdb_assert (interp->procs->exec_proc != NULL);

/* See `command_interp' for why we do this. */
- save_command_interp = command_interpreter;
- command_interpreter = interp;
+ save_command_interp = ui_interp->command_interpreter;
+ ui_interp->command_interpreter = interp;

ex = interp->procs->exec_proc (interp->data, command_str);

- command_interpreter = save_command_interp;
+ ui_interp->command_interpreter = save_command_interp;

return ex;
}
@@ -379,6 +409,7 @@ clear_interpreter_hooks (void)
static void
interpreter_exec_cmd (char *args, int from_tty)
{
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
struct interp *old_interp, *interp_to_use;
char **prules = NULL;
char **trule = NULL;
@@ -400,7 +431,7 @@ interpreter_exec_cmd (char *args, int from_tty)
if (nrules < 2)
error (_("usage: interpreter-exec <interpreter> [ <command> ... ]"));

- old_interp = current_interpreter;
+ old_interp = ui_interp->current_interpreter;

interp_to_use = interp_lookup (prules[0]);
if (interp_to_use == NULL)
@@ -438,12 +469,15 @@ static VEC (char_ptr) *
interpreter_completer (struct cmd_list_element *ignore,
const char *text, const char *word)
{
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
int textlen;
VEC (char_ptr) *matches = NULL;
struct interp *interp;

textlen = strlen (text);
- for (interp = interp_list; interp != NULL; interp = interp->next)
+ for (interp = ui_interp->interp_list;
+ interp != NULL;
+ interp = interp->next)
{
if (strncmp (interp->name, text, textlen) == 0)
{
@@ -474,14 +508,19 @@ interpreter_completer (struct cmd_list_element *ignore,
struct interp *
top_level_interpreter (void)
{
- return top_level_interpreter_ptr;
+ struct ui_interp_info *ui_interp = get_current_interp_info ();
+
+ return ui_interp->top_level_interpreter_ptr;
}

void *
top_level_interpreter_data (void)
{
- gdb_assert (top_level_interpreter_ptr);
- return top_level_interpreter_ptr->data;
+ struct interp *interp;
+
+ interp = top_level_interpreter ();
+ gdb_assert (interp != NULL);
+ return interp->data;
}

/* This just adds the "interpreter-exec" command. */
diff --git a/gdb/interps.h b/gdb/interps.h
index 19cd1c2..f0badc5 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -93,15 +93,6 @@ extern struct interp *top_level_interpreter (void);

extern struct interp *command_interp (void);

-/* True if the current interpreter is in async mode, false if in sync
- mode. If in sync mode, running a synchronous execution command
- (with execute_command, e.g, "next") will not return until the
- command is finished. If in async mode, then running a synchronous
- command returns right after resuming the target. Waiting for the
- command's completion is later done on the top event loop (using
- continuations). */
-extern int interpreter_async;
-
extern void clear_interpreter_hooks (void);

/* well-known interpreters */
diff --git a/gdb/main.c b/gdb/main.c
index 03d6bbd..d84340e 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -311,7 +311,7 @@ captured_command_loop (void *data)
{
/* Top-level execution commands can be run in the background from
here on. */
- interpreter_async = 1;
+ current_ui->async = 1;

current_interp_command_loop ();
/* FIXME: cagney/1999-11-05: A correct command_loop() implementaton
diff --git a/gdb/python/python.c b/gdb/python/python.c
index c706644..fa1c78e 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -321,8 +321,8 @@ python_interactive_command (char *arg, int from_tty)
struct cleanup *cleanup;
int err;

- cleanup = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ cleanup = make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

arg = skip_spaces (arg);

@@ -466,8 +466,8 @@ python_command (char *arg, int from_tty)

cleanup = ensure_python_env (get_current_arch (), current_language);

- make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

arg = skip_spaces (arg);
if (arg && *arg)
@@ -650,8 +650,8 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
struct cleanup *cleanup = make_cleanup (xfree, copy);
struct interp *interp;

- make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

make_cleanup_restore_ui_out (&current_uiout);
/* Use the console interpreter uiout to have the same print format
diff --git a/gdb/top.c b/gdb/top.c
index a34635b..3842f0c 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -407,7 +407,7 @@ maybe_wait_sync_command_done (int was_sync)
command's list, running command hooks or similars), and we
just ran a synchronous command that started the target, wait
for that command to end. */
- if (!interpreter_async && !was_sync && sync_execution)
+ if (!current_ui->async && !was_sync && sync_execution)
wait_sync_command_done ();
}

@@ -525,8 +525,8 @@ execute_command_to_string (char *p, int from_tty)
restoration callbacks. */
cleanup = set_batch_flag_and_make_cleanup_restore_page_info ();

- make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
+ make_cleanup_restore_integer (&current_ui->async);
+ current_ui->async = 0;

str_file = mem_fileopen ();

diff --git a/gdb/top.h b/gdb/top.h
index d404427..f18b79e 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -23,6 +23,8 @@
#include "buffer.h"
#include "event-loop.h"

+struct tl_interp_info;
+
/* All about a user interface instance. Each user interface has its
own I/O files/streams, readline state, its own top level
interpreter (for the main UI, this is the interpreter specified
@@ -50,6 +52,19 @@ struct ui
processing. */
void (*input_handler) (char *);

+ /* Each UI has its own independent set of interpreters. */
+ struct ui_interp_info *interp_info;
+
+ /* True if the UI is in async mode, false if in sync mode. If in
+ sync mode, a synchronous execution command (e.g, "next") does not
+ return until the command is finished. If in async mode, then
+ running a synchronous command returns right after resuming the
+ target. Waiting for the command's completion is later done on
+ the top event loop. For the main UI, this starts out disabled,
+ until all the explicit command line arguments (e.g., `gdb -ex
+ "start" -ex "next"') are processed. */
+ int async;
+
/* The fields below that start with "m_" are "private". They're
meant to be accessed through wrapper macros that make them look
like globals. */
--
2.5.5