[PATCH v2 07/25] Make instream and serial_stdin be per UI

Pedro Alves
2016-03-21T15:30:37Z

Note that in inflow.c, we always use the _main_ UI, not the current
UI. What this means is that the inferior is always run on gdb's tty,
unless you use "set inferior-tty ..."
---
gdb/cli/cli-script.c | 11 +++++----
gdb/event-top.c | 34 +++++++++++++++-------------
gdb/inflow.c | 23 ++++++++++++++-----
gdb/main.c | 7 ++++--
gdb/mi/mi-interp.c | 4 +++-
gdb/python/python.c | 3 ++-
gdb/terminal.h | 6 +++--
gdb/testsuite/gdb.gdb/selftest.exp | 4 ++++
gdb/top.c | 46 +++++++++++++++++++++-----------------
gdb/top.h | 7 +++++-
gdb/utils.c | 4 +++-
11 files changed, 95 insertions(+), 54 deletions(-)

diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 5fc01b3..0507c55 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -352,6 +352,7 @@ do_restore_user_call_depth (void * call_depth)
void
execute_user_command (struct cmd_list_element *c, char *args)
{
+ struct ui *ui = current_ui;
struct command_line *cmdlines;
struct cleanup *old_chain;
enum command_control_type ret;
@@ -372,8 +373,8 @@ execute_user_command (struct cmd_list_element *c, char *args)

/* Set the instream to 0, indicating execution of a
user-defined function. */
- make_cleanup (do_restore_instream_cleanup, instream);
- instream = (FILE *) 0;
+ make_cleanup (do_restore_instream_cleanup, ui->instream);
+ ui->instream = NULL;

/* Also set the global in_user_command, so that NULL instream is
not confused with Insight. */
@@ -931,6 +932,7 @@ realloc_body_list (struct command_line *command, int new_length)
static char *
read_next_line (void)
{
+ struct ui *ui = current_ui;
char *prompt_ptr, control_prompt[256];
int i = 0;

@@ -938,7 +940,8 @@ read_next_line (void)
error (_("Control nesting too deep!"));

/* Set a prompt based on the nesting of the control commands. */
- if (instream == stdin || (instream == 0 && deprecated_readline_hook != NULL))
+ if (ui->instream == stdin
+ || (ui->instream == 0 && deprecated_readline_hook != NULL))
{
for (i = 0; i < control_level; i++)
control_prompt[i] = ' ';
@@ -949,7 +952,7 @@ read_next_line (void)
else
prompt_ptr = NULL;

- return command_line_input (prompt_ptr, instream == stdin, "commands");
+ return command_line_input (prompt_ptr, ui->instream == stdin, "commands");
}

/* Process one input line. If the command is an "end", return such an
diff --git a/gdb/event-top.c b/gdb/event-top.c
index b40ae93..1ca2901 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -418,7 +418,7 @@ stdin_event_handler (int error, gdb_client_data client_data)
printf_unfiltered (_("error detected on stdin\n"));
delete_file_handler (input_fd);
/* If stdin died, we may as well kill gdb. */
- quit_command ((char *) 0, stdin == instream);
+ quit_command ((char *) 0, stdin == ui->instream);
}
else
{
@@ -465,11 +465,12 @@ async_disable_stdin (void)
void
command_handler (char *command)
{
+ struct ui *ui = current_ui;
struct cleanup *stat_chain;
char *c;

clear_quit_flag ();
- if (instream == stdin)
+ if (ui->instream == stdin)
reinitialize_more_filter ();

stat_chain = make_command_stats_cleanup (1);
@@ -479,7 +480,7 @@ command_handler (char *command)
;
if (c[0] != '#')
{
- execute_command (command, instream == stdin);
+ execute_command (command, ui->instream == stdin);

/* Do any commands attached to breakpoint we stopped at. */
bpstat_do_actions ();
@@ -546,6 +547,7 @@ char *
handle_line_of_input (struct buffer *cmd_line_buffer,
char *rl, int repeat, char *annotation_suffix)
{
+ struct ui *ui = current_ui;
char *p1;
char *cmd;

@@ -560,7 +562,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
command, but leave ownership of memory to the buffer . */
cmd_line_buffer->used_size = 0;

- if (annotation_level > 1 && instream == stdin)
+ if (annotation_level > 1 && ui->instream == stdin)
{
printf_unfiltered (("\n\032\032post-"));
puts_unfiltered (annotation_suffix);
@@ -577,8 +579,8 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
}

/* Do history expansion if that is wished. */
- if (history_expansion_p && instream == stdin
- && ISATTY (instream))
+ if (history_expansion_p && ui->instream == stdin
+ && ISATTY (ui->instream))
{
char *history_value;
int expanded;
@@ -648,9 +650,11 @@ void
command_line_handler (char *rl)
{
struct buffer *line_buffer = get_command_line_buffer ();
+ struct ui *ui = current_ui;
char *cmd;

- cmd = handle_line_of_input (line_buffer, rl, instream == stdin, "prompt");
+ cmd = handle_line_of_input (line_buffer, rl, ui->instream == stdin,
+ "prompt");
if (cmd == (char *) EOF)
{
/* stdin closed. The connection with the terminal is gone.
@@ -658,7 +662,7 @@ command_line_handler (char *rl)
hung up but GDB is still alive. In such a case, we just quit
gdb killing the inferior program too. */
printf_unfiltered ("quit\n");
- execute_command ("quit", stdin == instream);
+ execute_command ("quit", stdin == ui->instream);
}
else if (cmd == NULL)
{
@@ -693,9 +697,9 @@ gdb_readline_no_editing_callback (gdb_client_data client_data)
stream after '\n'. If we buffer the input and fgetc drains the
stream, getting stuff beyond the newline as well, a select, done
afterwards will not trigger. */
- if (!done_once && !ISATTY (instream))
+ if (!done_once && !ISATTY (ui->instream))
{
- setbuf (instream, NULL);
+ setbuf (ui->instream, NULL);
done_once = 1;
}

@@ -711,7 +715,7 @@ gdb_readline_no_editing_callback (gdb_client_data client_data)
{
/* Read from stdin if we are executing a user defined command.
This is the right thing for prompt_for_continue, at least. */
- c = fgetc (instream ? instream : stdin);
+ c = fgetc (ui->instream ? ui->instream : stdin);

if (c == EOF)
{
@@ -833,7 +837,7 @@ handle_sigint (int sig)
static void
async_sigterm_handler (gdb_client_data arg)
{
- quit_force (NULL, stdin == instream);
+ quit_force (NULL, stdin == current_ui->instream);
}

/* See defs.h. */
@@ -1015,7 +1019,7 @@ gdb_setup_readline (void)

/* If the input stream is connected to a terminal, turn on
editing. */
- if (ISATTY (instream))
+ if (ISATTY (ui->instream))
{
/* Tell gdb that we will be using the readline library. This
could be overwritten by a command in .gdbinit like 'set
@@ -1038,11 +1042,11 @@ gdb_setup_readline (void)
ui->input_handler = command_line_handler;

/* Tell readline to use the same input stream that gdb uses. */
- rl_instream = instream;
+ rl_instream = ui->instream;

/* Get a file descriptor for the input stream, so that we can
register it with the event loop. */
- input_fd = fileno (instream);
+ input_fd = fileno (ui->instream);

/* Now we need to create the event sources for the input file
descriptor. */
diff --git a/gdb/inflow.c b/gdb/inflow.c
index 4c80dbd..2b12090 100644
--- a/gdb/inflow.c
+++ b/gdb/inflow.c
@@ -31,6 +31,7 @@

#include "inflow.h"
#include "gdbcmd.h"
+#include "top.h"

#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
@@ -172,6 +173,8 @@ set_initial_gdb_ttystate (void)
int
gdb_has_a_terminal (void)
{
+ struct ui *ui = main_ui;
+
if (interactive_mode != AUTO_BOOLEAN_AUTO)
return interactive_mode == AUTO_BOOLEAN_TRUE;

@@ -194,7 +197,8 @@ gdb_has_a_terminal (void)
gdb_has_a_terminal_flag = no;
if (stdin_serial != NULL)
{
- our_terminal_info.ttystate = serial_get_tty_state (stdin_serial);
+ our_terminal_info.ttystate
+ = serial_get_tty_state (stdin_serial);

if (our_terminal_info.ttystate != NULL)
{
@@ -225,6 +229,7 @@ gdb_has_a_terminal (void)
void
child_terminal_init_with_pgrp (int pgrp)
{
+ struct ui *ui = main_ui;
struct inferior *inf = current_inferior ();
struct terminal_info *tinfo = get_inflow_inferior_data (inf);

@@ -255,6 +260,8 @@ child_terminal_init_with_pgrp (int pgrp)
void
gdb_save_tty_state (void)
{
+ struct ui *ui = main_ui;
+
if (gdb_has_a_terminal ())
{
xfree (our_terminal_info.ttystate);
@@ -286,6 +293,7 @@ child_terminal_init (struct target_ops *self)
void
child_terminal_inferior (struct target_ops *self)
{
+ struct ui *ui = main_ui;
struct inferior *inf;
struct terminal_info *tinfo;

@@ -313,8 +321,7 @@ child_terminal_inferior (struct target_ops *self)
/* Because we were careful to not change in or out of raw mode in
terminal_ours, we will not change in our out of raw mode with
this call, so we don't flush any input. */
- result = serial_set_tty_state (stdin_serial,
- tinfo->ttystate);
+ result = serial_set_tty_state (stdin_serial, tinfo->ttystate);
OOPSY ("setting tty state");

if (!job_control)
@@ -394,6 +401,7 @@ child_terminal_ours (struct target_ops *self)
static void
child_terminal_ours_1 (int output_only)
{
+ struct ui *ui = main_ui;
struct inferior *inf;
struct terminal_info *tinfo;

@@ -451,7 +459,8 @@ child_terminal_ours_1 (int output_only)
though, since readline will deal with raw mode when/if it needs
to. */

- serial_noflush_set_tty_state (stdin_serial, our_terminal_info.ttystate,
+ serial_noflush_set_tty_state (stdin_serial,
+ our_terminal_info.ttystate,
tinfo->ttystate);

if (job_control)
@@ -555,6 +564,7 @@ inflow_inferior_exit (struct inferior *inf)
void
copy_terminal_info (struct inferior *to, struct inferior *from)
{
+ struct ui *ui = main_ui;
struct terminal_info *tinfo_to, *tinfo_from;

tinfo_to = get_inflow_inferior_data (to);
@@ -583,6 +593,7 @@ term_info (char *arg, int from_tty)
void
child_terminal_info (struct target_ops *self, const char *args, int from_tty)
{
+ struct ui *ui = main_ui;
struct inferior *inf;
struct terminal_info *tinfo;

@@ -888,9 +899,9 @@ gdb_setpgid (void)
that we can guarantee stdin_serial is opened if there is
a terminal. */
void
-initialize_stdin_serial (void)
+initialize_stdin_serial (struct ui *ui)
{
- stdin_serial = serial_fdopen (0);
+ stdin_serial = serial_fdopen (fileno (ui->instream));
}

void
diff --git a/gdb/main.c b/gdb/main.c
index 72d0369..89037cf 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -307,6 +307,8 @@ setup_alternate_signal_stack (void)
static int
captured_command_loop (void *data)
{
+ struct ui *ui = current_ui;
+
/* Top-level execution commands can be run in the background from
here on. */
current_ui->async = 1;
@@ -324,7 +326,7 @@ captured_command_loop (void *data)
error) we try to quit. If the quit is aborted, catch_errors()
which called this catch the signal and restart the command
loop. */
- quit_command (NULL, instream == stdin);
+ quit_command (NULL, ui->instream == stdin);
return 1;
}

@@ -433,6 +435,7 @@ DEF_VEC_O (cmdarg_s);
static int
captured_main (void *data)
{
+ struct ui *ui = current_ui;
struct captured_main_args *context = (struct captured_main_args *) data;
int argc = context->argc;
char **argv = context->argv;
@@ -503,7 +506,7 @@ captured_main (void *data)

clear_quit_flag ();
saved_command_line = (char *) xstrdup ("");
- instream = stdin;
+ ui->instream = stdin;

#ifdef __MINGW32__
/* Ensure stderr is unbuffered. A Cygwin pty or pipe is implemented
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 149f920..f7003d0 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -280,7 +280,9 @@ mi_interp_query_hook (const char *ctlstr, va_list ap)
static void
mi_execute_command_wrapper (const char *cmd)
{
- mi_execute_command (cmd, stdin == instream);
+ struct ui *ui = current_ui;
+
+ mi_execute_command (cmd, stdin == ui->instream);
}

/* Observer for the synchronous_command_done notification. */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index a164e37..5d45093 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -328,6 +328,7 @@ eval_python_command (const char *command)
static void
python_interactive_command (char *arg, int from_tty)
{
+ struct ui *ui = current_ui;
struct cleanup *cleanup;
int err;

@@ -351,7 +352,7 @@ python_interactive_command (char *arg, int from_tty)
}
else
{
- err = PyRun_InteractiveLoop (instream, "<stdin>");
+ err = PyRun_InteractiveLoop (ui->instream, "<stdin>");
dont_repeat ();
}

diff --git a/gdb/terminal.h b/gdb/terminal.h
index 4a00716..60a7e6d 100644
--- a/gdb/terminal.h
+++ b/gdb/terminal.h
@@ -77,6 +77,7 @@
#endif

struct inferior;
+struct ui;

extern void new_tty_prefork (const char *);

@@ -96,8 +97,9 @@ extern pid_t create_tty_session (void);
we lack job control. */
extern int gdb_setpgid (void);

-/* Set up a serial structure describing standard input. In inflow.c. */
-extern void initialize_stdin_serial (void);
+/* Set up a serial structure describing the UI's input. In
+ inflow.c. */
+extern void initialize_stdin_serial (struct ui *ui);

extern int gdb_has_a_terminal (void);

diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp
index 969797a..af0026c 100644
--- a/gdb/testsuite/gdb.gdb/selftest.exp
+++ b/gdb/testsuite/gdb.gdb/selftest.exp
@@ -205,6 +205,10 @@ proc do_steps_and_nexts {} {
set description "step over gdb_stderr initialization"
set command "step"
}
+ -re "ui = current_ui.*$gdb_prompt $" {
+ set description "step over top_level initialization"
+ set command "step"
+ }
-re ".*main.c.*No such file or directory.*$gdb_prompt $" {
setup_xfail "rs6000-*-aix3*"
fail "must be able to list source lines"
diff --git a/gdb/top.c b/gdb/top.c
index 19b50c2..4ecc99d 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -122,13 +122,6 @@ show_confirm (struct ui_file *file, int from_tty,
value);
}

-/* stdio stream that command input is being read from. Set to stdin
- normally. Set by source_command to the file we are sourcing. Set
- to NULL if we are executing a user-defined command or interacting
- via a GUI. */
-
-FILE *instream;
-
/* Flag to indicate whether a user defined command is currently running. */

int in_user_command;
@@ -285,18 +278,21 @@ quit_cover (void)
void
do_restore_instream_cleanup (void *stream)
{
+ struct ui *ui = current_ui;
+
/* Restore the previous input stream. */
- instream = (FILE *) stream;
+ ui->instream = (FILE *) stream;
}

/* Read commands from STREAM. */
void
read_command_file (FILE *stream)
{
+ struct ui *ui = current_ui;
struct cleanup *cleanups;

- cleanups = make_cleanup (do_restore_instream_cleanup, instream);
- instream = stream;
+ cleanups = make_cleanup (do_restore_instream_cleanup, ui->instream);
+ ui->instream = stream;
command_loop ();
do_cleanups (cleanups);
}
@@ -548,14 +544,16 @@ execute_command_to_string (char *p, int from_tty)
void
command_loop (void)
{
- while (instream && !feof (instream))
+ struct ui *ui = current_ui;
+
+ while (ui->instream && !feof (ui->instream))
{
char *command;

/* Get a command-line. This calls the readline package. */
- command = command_line_input (instream == stdin ?
- get_prompt () : (char *) NULL,
- instream == stdin, "prompt");
+ command = command_line_input (ui->instream == stdin
+ ? get_prompt () : (char *) NULL,
+ ui->instream == stdin, "prompt");
if (command == NULL)
return;
command_handler (command);
@@ -572,13 +570,15 @@ static int suppress_dont_repeat = 0;
void
dont_repeat (void)
{
+ struct ui *ui = current_ui;
+
if (suppress_dont_repeat || server_command)
return;

/* If we aren't reading from standard input, we are saving the last
thing read from stdin in line and don't want to delete it. Null
lines won't repeat here in any case. */
- if (instream == stdin)
+ if (ui->instream == stdin)
*saved_command_line = 0;
}

@@ -607,6 +607,7 @@ static char *
gdb_readline_no_editing (const char *prompt)
{
struct buffer line_buffer;
+ struct ui *ui = current_ui;

buffer_init (&line_buffer);

@@ -625,7 +626,7 @@ gdb_readline_no_editing (const char *prompt)

/* Read from stdin if we are executing a user defined command.
This is the right thing for prompt_for_continue, at least. */
- c = fgetc (instream ? instream : stdin);
+ c = fgetc (ui->instream ? ui->instream : stdin);

if (c == EOF)
{
@@ -1031,6 +1032,7 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
{
static struct buffer cmd_line_buffer;
static int cmd_line_buffer_initialized;
+ struct ui *ui = current_ui;
const char *prompt = prompt_arg;
char *cmd;

@@ -1038,7 +1040,7 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
if (annotation_suffix == NULL)
annotation_suffix = "";

- if (annotation_level > 1 && instream == stdin)
+ if (annotation_level > 1 && ui->instream == stdin)
{
char *local_prompt;

@@ -1088,7 +1090,7 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
if (source_file_name != NULL)
++source_line_number;

- if (annotation_level > 1 && instream == stdin)
+ if (annotation_level > 1 && ui->instream == stdin)
{
puts_unfiltered ("\n\032\032pre-");
puts_unfiltered (annotation_suffix);
@@ -1500,16 +1502,18 @@ quit_force (char *args, int from_tty)
int
input_from_terminal_p (void)
{
+ struct ui *ui = current_ui;
+
if (batch_flag)
return 0;

- if (gdb_has_a_terminal () && instream == stdin)
+ if (gdb_has_a_terminal () && ui->instream == stdin)
return 1;

/* If INSTREAM is unset, and we are not in a user command, we
must be in Insight. That's like having a terminal, for our
purposes. */
- if (instream == NULL && !in_user_command)
+ if (ui->instream == NULL && !in_user_command)
return 1;

return 0;
@@ -1945,7 +1949,7 @@ gdb_init (char *argv0)
init_cli_cmds();
init_main (); /* But that omits this file! Do it now. */

- initialize_stdin_serial ();
+ initialize_stdin_serial (current_ui);

/* Take a snapshot of our tty state before readline/ncurses have had a chance
to alter it. */
diff --git a/gdb/top.h b/gdb/top.h
index ef05942..d9322bd 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -67,6 +67,12 @@ struct ui
"start" -ex "next"') are processed. */
int async;

+ /* stdio stream that command input is being read from. Set to stdin
+ normally. Set by source_command to the file we are sourcing.
+ Set to NULL if we are executing a user-defined command or
+ interacting via a GUI. */
+ FILE *instream;
+
/* The fields below that start with "m_" are "private". They're
meant to be accessed through wrapper macros that make them look
like globals. */
@@ -108,7 +114,6 @@ extern void switch_thru_all_uis_next (struct switch_thru_all_uis *state);

/* From top.c. */
extern char *saved_command_line;
-extern FILE *instream;
extern int in_user_command;
extern int confirm;
extern char gdb_dirbuf[1024];
diff --git a/gdb/utils.c b/gdb/utils.c
index 97e5133..d1a56ef 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1021,10 +1021,12 @@ print_sys_errmsg (const char *string, int errcode)
void
quit (void)
{
+ struct ui *ui = current_ui;
+
if (sync_quit_force_run)
{
sync_quit_force_run = 0;
- quit_force (NULL, stdin == instream);
+ quit_force (NULL, stdin == ui->instream);
}

#ifdef __MSDOS__
--
2.5.0