Make stdin be per UI

This commit makes each UI have its own "stdin" stream pointer.  This
is used to determine whether the "from_tty" argument to
execute_command, etc. should be true.

Related, this commit makes input_from_terminal_p take an UI parameter,
and then avoids the gdb_has_a_terminal in it.  gdb_has_a_terminal only
returns info on gdb's own main/primary terminal (the real stdin).
However, the places that call input_from_terminal_p really want to
know is whether the command came from an interactive tty.  This patch
thus renames input_from_terminal_p to input_interactive_p for clarity,
and then makes input_interactive_p check for "set interactive" itself,
along with ISATTY, instead of calling gdb_has_a_terminal.  Actually,
quit_force wants to call input_interactive_p _after_ stdin is closed,
we can't call ISATTY that late.  So instead we save the result of
ISATTY in a field of the UI.

gdb/ChangeLog:
2016-06-21  Pedro Alves  <palves@redhat.com>

	* cli/cli-script.c (read_next_line): Adjust to per-UI stdin.
	(read_command_lines): Use input_interactive_p instead of
	input_from_terminal_p.
	* defs.h (struct ui): Forward declare.
	(input_from_terminal_p): Rename to ...
	(input_interactive_p): ... this.
	* event-top.c (stdin_event_handler): Pass 0 as from_tty argument
	to quit_command.
	(command_handler): Adjust to per-UI stdin.
	(handle_line_of_input): Adjust to per-UI stdin and use
	input_interactive_p instead of ISATTY and input_from_terminal_p.
	(gdb_readline_no_editing_callback): Adjust to per-UI stdin.
	(command_line_handler): Always pass true as "from_tty" parameter
	of handle_line_of_input and execute_command.
	(async_sigterm_handler): Pass 0 as from_tty argument to
	quit_command.
	* inflow.c (interactive_mode, show_interactive_mode): Moved to ...
	(gdb_has_a_terminal): Don't check interactive_mode here.
	(_initialize_inflow): Don't install "set interactive-mode" here.
	* main.c (captured_command_loop): Adjust to per-UI stdin.
	* mi/mi-interp.c (mi_execute_command_wrapper): Adjust to per-UI
	stdin.
	* top.c (new_ui): Save the stdin stream and whether it's a tty.
	(dont_repeat): Adjust to per-UI stdin.
	(command_line_input): Adjust to per-UI stdin and to use
	input_interactive_p.
	(quit_force): Write history if any UI supports interactive input.
	(interactive_mode, show_interactive_mode): Move here, from
	inflow.c.
	(input_from_terminal_p): Rename to ...
	(input_interactive_p): ... this, and check the "interactive_mode"
	global instead of calling gdb_has_a_terminal.
	(_initialize_top): Install "set interactive-mode" here.
	* top.h (struct ui) <stdin_stream, input_interactive_p>: New
	fields.
	* utils.c (quit): Pass 0 as from_tty argument to quit_force.
	(defaulted_query): Adjust to per-UI stdin and to use
	input_interactive_p.
This commit is contained in:
Pedro Alves
2016-06-21 01:11:54 +01:00
parent 07169ff772
commit 268a799a45
10 changed files with 144 additions and 79 deletions

View File

@@ -1,3 +1,44 @@
2016-06-21 Pedro Alves <palves@redhat.com>
* cli/cli-script.c (read_next_line): Adjust to per-UI stdin.
(read_command_lines): Use input_interactive_p instead of
input_from_terminal_p.
* defs.h (struct ui): Forward declare.
(input_from_terminal_p): Rename to ...
(input_interactive_p): ... this.
* event-top.c (stdin_event_handler): Pass 0 as from_tty argument
to quit_command.
(command_handler): Adjust to per-UI stdin.
(handle_line_of_input): Adjust to per-UI stdin and use
input_interactive_p instead of ISATTY and input_from_terminal_p.
(gdb_readline_no_editing_callback): Adjust to per-UI stdin.
(command_line_handler): Always pass true as "from_tty" parameter
of handle_line_of_input and execute_command.
(async_sigterm_handler): Pass 0 as from_tty argument to
quit_command.
* inflow.c (interactive_mode, show_interactive_mode): Moved to ...
(gdb_has_a_terminal): Don't check interactive_mode here.
(_initialize_inflow): Don't install "set interactive-mode" here.
* main.c (captured_command_loop): Adjust to per-UI stdin.
* mi/mi-interp.c (mi_execute_command_wrapper): Adjust to per-UI
stdin.
* top.c (new_ui): Save the stdin stream and whether it's a tty.
(dont_repeat): Adjust to per-UI stdin.
(command_line_input): Adjust to per-UI stdin and to use
input_interactive_p.
(quit_force): Write history if any UI supports interactive input.
(interactive_mode, show_interactive_mode): Move here, from
inflow.c.
(input_from_terminal_p): Rename to ...
(input_interactive_p): ... this, and check the "interactive_mode"
global instead of calling gdb_has_a_terminal.
(_initialize_top): Install "set interactive-mode" here.
* top.h (struct ui) <stdin_stream, input_interactive_p>: New
fields.
* utils.c (quit): Pass 0 as from_tty argument to quit_force.
(defaulted_query): Adjust to per-UI stdin and to use
input_interactive_p.
2016-06-21 Pedro Alves <palves@redhat.com> 2016-06-21 Pedro Alves <palves@redhat.com>
* event-top.c (stdin_event_handler): Don't quit gdb if it was a * event-top.c (stdin_event_handler): Don't quit gdb if it was a

View File

@@ -935,12 +935,13 @@ read_next_line (void)
struct ui *ui = current_ui; struct ui *ui = current_ui;
char *prompt_ptr, control_prompt[256]; char *prompt_ptr, control_prompt[256];
int i = 0; int i = 0;
int from_tty = ui->instream == ui->stdin_stream;
if (control_level >= 254) if (control_level >= 254)
error (_("Control nesting too deep!")); error (_("Control nesting too deep!"));
/* Set a prompt based on the nesting of the control commands. */ /* Set a prompt based on the nesting of the control commands. */
if (ui->instream == stdin if (from_tty
|| (ui->instream == 0 && deprecated_readline_hook != NULL)) || (ui->instream == 0 && deprecated_readline_hook != NULL))
{ {
for (i = 0; i < control_level; i++) for (i = 0; i < control_level; i++)
@@ -952,7 +953,7 @@ read_next_line (void)
else else
prompt_ptr = NULL; prompt_ptr = NULL;
return command_line_input (prompt_ptr, ui->instream == stdin, "commands"); return command_line_input (prompt_ptr, from_tty, "commands");
} }
/* Process one input line. If the command is an "end", return such an /* Process one input line. If the command is an "end", return such an
@@ -1256,7 +1257,7 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands,
{ {
struct command_line *head; struct command_line *head;
if (from_tty && input_from_terminal_p ()) if (from_tty && input_interactive_p (current_ui))
{ {
if (deprecated_readline_begin_hook) if (deprecated_readline_begin_hook)
{ {
@@ -1287,7 +1288,8 @@ read_command_lines (char *prompt_arg, int from_tty, int parse_commands,
do_cleanups (old_chain); do_cleanups (old_chain);
} }
if (deprecated_readline_end_hook && from_tty && input_from_terminal_p ()) if (from_tty && input_interactive_p (current_ui)
&& deprecated_readline_end_hook)
{ {
(*deprecated_readline_end_hook) (); (*deprecated_readline_end_hook) ();
} }

View File

@@ -324,7 +324,9 @@ extern char *command_line_input (const char *, int, char *);
extern void print_prompt (void); extern void print_prompt (void);
extern int input_from_terminal_p (void); struct ui;
extern int input_interactive_p (struct ui *);
extern int info_verbose; extern int info_verbose;

View File

@@ -518,7 +518,7 @@ stdin_event_handler (int error, gdb_client_data client_data)
{ {
/* If stdin died, we may as well kill gdb. */ /* If stdin died, we may as well kill gdb. */
printf_unfiltered (_("error detected on stdin\n")); printf_unfiltered (_("error detected on stdin\n"));
quit_command ((char *) 0, stdin == ui->instream); quit_command ((char *) 0, 0);
} }
else else
{ {
@@ -589,7 +589,7 @@ command_handler (char *command)
struct cleanup *stat_chain; struct cleanup *stat_chain;
char *c; char *c;
if (ui->instream == stdin) if (ui->instream == ui->stdin_stream)
reinitialize_more_filter (); reinitialize_more_filter ();
stat_chain = make_command_stats_cleanup (1); stat_chain = make_command_stats_cleanup (1);
@@ -599,7 +599,7 @@ command_handler (char *command)
; ;
if (c[0] != '#') if (c[0] != '#')
{ {
execute_command (command, ui->instream == stdin); execute_command (command, ui->instream == ui->stdin_stream);
/* Do any commands attached to breakpoint we stopped at. */ /* Do any commands attached to breakpoint we stopped at. */
bpstat_do_actions (); bpstat_do_actions ();
@@ -667,6 +667,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
char *rl, int repeat, char *annotation_suffix) char *rl, int repeat, char *annotation_suffix)
{ {
struct ui *ui = current_ui; struct ui *ui = current_ui;
int from_tty = ui->instream == ui->stdin_stream;
char *p1; char *p1;
char *cmd; char *cmd;
@@ -681,7 +682,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
command, but leave ownership of memory to the buffer . */ command, but leave ownership of memory to the buffer . */
cmd_line_buffer->used_size = 0; cmd_line_buffer->used_size = 0;
if (annotation_level > 1 && ui->instream == stdin) if (from_tty && annotation_level > 1)
{ {
printf_unfiltered (("\n\032\032post-")); printf_unfiltered (("\n\032\032post-"));
puts_unfiltered (annotation_suffix); puts_unfiltered (annotation_suffix);
@@ -698,8 +699,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
} }
/* Do history expansion if that is wished. */ /* Do history expansion if that is wished. */
if (history_expansion_p && ui->instream == stdin if (history_expansion_p && from_tty && input_interactive_p (current_ui))
&& ISATTY (ui->instream))
{ {
char *history_value; char *history_value;
int expanded; int expanded;
@@ -743,7 +743,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
and then later fetch it from the value history and remove the and then later fetch it from the value history and remove the
'#'. The kill ring is probably better, but some people are in '#'. The kill ring is probably better, but some people are in
the habit of commenting things out. */ the habit of commenting things out. */
if (*cmd != '\0' && input_from_terminal_p ()) if (*cmd != '\0' && from_tty && input_interactive_p (current_ui))
gdb_add_history (cmd); gdb_add_history (cmd);
/* Save into global buffer if appropriate. */ /* Save into global buffer if appropriate. */
@@ -772,8 +772,7 @@ command_line_handler (char *rl)
struct ui *ui = current_ui; struct ui *ui = current_ui;
char *cmd; char *cmd;
cmd = handle_line_of_input (line_buffer, rl, ui->instream == stdin, cmd = handle_line_of_input (line_buffer, rl, 1, "prompt");
"prompt");
if (cmd == (char *) EOF) if (cmd == (char *) EOF)
{ {
/* stdin closed. The connection with the terminal is gone. /* stdin closed. The connection with the terminal is gone.
@@ -781,7 +780,7 @@ command_line_handler (char *rl)
hung up but GDB is still alive. In such a case, we just quit hung up but GDB is still alive. In such a case, we just quit
gdb killing the inferior program too. */ gdb killing the inferior program too. */
printf_unfiltered ("quit\n"); printf_unfiltered ("quit\n");
execute_command ("quit", stdin == ui->instream); execute_command ("quit", 1);
} }
else if (cmd == NULL) else if (cmd == NULL)
{ {
@@ -838,7 +837,7 @@ gdb_readline_no_editing_callback (gdb_client_data client_data)
{ {
/* Read from stdin if we are executing a user defined command. /* Read from stdin if we are executing a user defined command.
This is the right thing for prompt_for_continue, at least. */ This is the right thing for prompt_for_continue, at least. */
c = fgetc (ui->instream ? ui->instream : stdin); c = fgetc (ui->instream != NULL ? ui->instream : ui->stdin_stream);
if (c == EOF) if (c == EOF)
{ {
@@ -1086,7 +1085,7 @@ interruptible_select (int n,
static void static void
async_sigterm_handler (gdb_client_data arg) async_sigterm_handler (gdb_client_data arg)
{ {
quit_force (NULL, stdin == current_ui->instream); quit_force (NULL, 0);
} }
/* See defs.h. */ /* See defs.h. */

View File

@@ -142,24 +142,6 @@ enum gdb_has_a_terminal_flag_enum
} }
gdb_has_a_terminal_flag = have_not_checked; gdb_has_a_terminal_flag = have_not_checked;
/* The value of the "interactive-mode" setting. */
static enum auto_boolean interactive_mode = AUTO_BOOLEAN_AUTO;
/* Implement the "show interactive-mode" option. */
static void
show_interactive_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
if (interactive_mode == AUTO_BOOLEAN_AUTO)
fprintf_filtered (file, "Debugger's interactive mode "
"is %s (currently %s).\n",
value, gdb_has_a_terminal () ? "on" : "off");
else
fprintf_filtered (file, "Debugger's interactive mode is %s.\n", value);
}
/* Set the initial tty state that is to be inherited by new inferiors. */ /* Set the initial tty state that is to be inherited by new inferiors. */
void void
@@ -172,9 +154,6 @@ set_initial_gdb_ttystate (void)
int int
gdb_has_a_terminal (void) gdb_has_a_terminal (void)
{ {
if (interactive_mode != AUTO_BOOLEAN_AUTO)
return interactive_mode == AUTO_BOOLEAN_TRUE;
switch (gdb_has_a_terminal_flag) switch (gdb_has_a_terminal_flag)
{ {
case yes: case yes:
@@ -899,20 +878,6 @@ _initialize_inflow (void)
add_info ("terminal", term_info, add_info ("terminal", term_info,
_("Print inferior's saved terminal status.")); _("Print inferior's saved terminal status."));
add_setshow_auto_boolean_cmd ("interactive-mode", class_support,
&interactive_mode, _("\
Set whether GDB's standard input is a terminal."), _("\
Show whether GDB's standard input is a terminal."), _("\
If on, GDB assumes that standard input is a terminal. In practice, it\n\
means that GDB should wait for the user to answer queries associated to\n\
commands entered at the command prompt. If off, GDB assumes that standard\n\
input is not a terminal, and uses the default answer to all queries.\n\
If auto (the default), determine which mode to use based on the standard\n\
input settings."),
NULL,
show_interactive_mode,
&setlist, &showlist);
terminal_is_ours = 1; terminal_is_ours = 1;
/* OK, figure out whether we have job control. If neither termios nor /* OK, figure out whether we have job control. If neither termios nor

View File

@@ -334,7 +334,7 @@ captured_command_loop (void *data)
error) we try to quit. If the quit is aborted, catch_errors() error) we try to quit. If the quit is aborted, catch_errors()
which called this catch the signal and restart the command which called this catch the signal and restart the command
loop. */ loop. */
quit_command (NULL, ui->instream == stdin); quit_command (NULL, ui->instream == ui->stdin_stream);
return 1; return 1;
} }

View File

@@ -286,7 +286,7 @@ mi_execute_command_wrapper (const char *cmd)
{ {
struct ui *ui = current_ui; struct ui *ui = current_ui;
mi_execute_command (cmd, stdin == ui->instream); mi_execute_command (cmd, ui->instream == ui->stdin_stream);
} }
/* Observer for the synchronous_command_done notification. */ /* Observer for the synchronous_command_done notification. */

View File

@@ -259,12 +259,15 @@ new_ui (FILE *instream, FILE *outstream, FILE *errstream)
ui = XCNEW (struct ui); ui = XCNEW (struct ui);
ui->num = ++highest_ui_num; ui->num = ++highest_ui_num;
ui->stdin_stream = instream;
ui->instream = instream; ui->instream = instream;
ui->outstream = outstream; ui->outstream = outstream;
ui->errstream = errstream; ui->errstream = errstream;
ui->input_fd = fileno (ui->instream); ui->input_fd = fileno (ui->instream);
ui->input_interactive_p = ISATTY (ui->instream);
ui->m_gdb_stdin = stdio_fileopen (ui->instream); ui->m_gdb_stdin = stdio_fileopen (ui->instream);
ui->m_gdb_stdout = stdio_fileopen (ui->outstream); ui->m_gdb_stdout = stdio_fileopen (ui->outstream);
ui->m_gdb_stderr = stderr_fileopen (ui->errstream); ui->m_gdb_stderr = stderr_fileopen (ui->errstream);
@@ -646,7 +649,7 @@ dont_repeat (void)
/* If we aren't reading from standard input, we are saving the last /* 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 thing read from stdin in line and don't want to delete it. Null
lines won't repeat here in any case. */ lines won't repeat here in any case. */
if (ui->instream == stdin) if (ui->instream == ui->stdin_stream)
*saved_command_line = 0; *saved_command_line = 0;
} }
@@ -1108,7 +1111,7 @@ gdb_safe_append_history (void)
NULL is returned for end of file. NULL is returned for end of file.
*If* the instream == stdin & stdin is a terminal, the line read is *If* input is from an interactive stream (stdin), the line read is
copied into the global 'saved_command_line' so that it can be copied into the global 'saved_command_line' so that it can be
repeated. repeated.
@@ -1123,12 +1126,13 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
struct ui *ui = current_ui; struct ui *ui = current_ui;
const char *prompt = prompt_arg; const char *prompt = prompt_arg;
char *cmd; char *cmd;
int from_tty = ui->instream == ui->stdin_stream;
/* The annotation suffix must be non-NULL. */ /* The annotation suffix must be non-NULL. */
if (annotation_suffix == NULL) if (annotation_suffix == NULL)
annotation_suffix = ""; annotation_suffix = "";
if (annotation_level > 1 && ui->instream == stdin) if (from_tty && annotation_level > 1)
{ {
char *local_prompt; char *local_prompt;
@@ -1174,7 +1178,7 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
if (source_file_name != NULL) if (source_file_name != NULL)
++source_line_number; ++source_line_number;
if (annotation_level > 1 && ui->instream == stdin) if (from_tty && annotation_level > 1)
{ {
puts_unfiltered ("\n\032\032pre-"); puts_unfiltered ("\n\032\032pre-");
puts_unfiltered (annotation_suffix); puts_unfiltered (annotation_suffix);
@@ -1182,11 +1186,15 @@ command_line_input (const char *prompt_arg, int repeat, char *annotation_suffix)
} }
/* Don't use fancy stuff if not talking to stdin. */ /* Don't use fancy stuff if not talking to stdin. */
if (deprecated_readline_hook && input_from_terminal_p ()) if (deprecated_readline_hook
&& from_tty
&& input_interactive_p (current_ui))
{ {
rl = (*deprecated_readline_hook) (prompt); rl = (*deprecated_readline_hook) (prompt);
} }
else if (command_editing_p && input_from_terminal_p ()) else if (command_editing_p
&& from_tty
&& input_interactive_p (current_ui))
{ {
rl = gdb_readline_wrapper (prompt); rl = gdb_readline_wrapper (prompt);
} }
@@ -1561,9 +1569,25 @@ quit_force (char *args, int from_tty)
/* Save the history information if it is appropriate to do so. */ /* Save the history information if it is appropriate to do so. */
TRY TRY
{ {
if (write_history_p && history_filename if (write_history_p && history_filename)
&& input_from_terminal_p ()) {
gdb_safe_append_history (); struct ui *ui;
int save = 0;
/* History is currently shared between all UIs. If there's
any UI with a terminal, save history. */
ALL_UIS (ui)
{
if (input_interactive_p (ui))
{
save = 1;
break;
}
}
if (save)
gdb_safe_append_history ();
}
} }
CATCH (ex, RETURN_MASK_ALL) CATCH (ex, RETURN_MASK_ALL)
{ {
@@ -1585,27 +1609,36 @@ quit_force (char *args, int from_tty)
exit (exit_code); exit (exit_code);
} }
/* Returns whether GDB is running on a terminal and input is /* The value of the "interactive-mode" setting. */
currently coming from that terminal. */ static enum auto_boolean interactive_mode = AUTO_BOOLEAN_AUTO;
/* Implement the "show interactive-mode" option. */
static void
show_interactive_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
if (interactive_mode == AUTO_BOOLEAN_AUTO)
fprintf_filtered (file, "Debugger's interactive mode "
"is %s (currently %s).\n",
value, gdb_has_a_terminal () ? "on" : "off");
else
fprintf_filtered (file, "Debugger's interactive mode is %s.\n", value);
}
/* Returns whether GDB is running on an interactive terminal. */
int int
input_from_terminal_p (void) input_interactive_p (struct ui *ui)
{ {
struct ui *ui = current_ui;
if (batch_flag) if (batch_flag)
return 0; return 0;
if (gdb_has_a_terminal () && ui->instream == stdin) if (interactive_mode != AUTO_BOOLEAN_AUTO)
return 1; return interactive_mode == AUTO_BOOLEAN_TRUE;
/* If INSTREAM is unset, and we are not in a user command, we return ui->input_interactive_p;
must be in Insight. That's like having a terminal, for our
purposes. */
if (ui->instream == NULL && !in_user_command)
return 1;
return 0;
} }
static void static void
@@ -2013,6 +2046,20 @@ When set, GDB uses the specified path to search for data files."),
set_gdb_datadir, show_gdb_datadir, set_gdb_datadir, show_gdb_datadir,
&setlist, &setlist,
&showlist); &showlist);
add_setshow_auto_boolean_cmd ("interactive-mode", class_support,
&interactive_mode, _("\
Set whether GDB's standard input is a terminal."), _("\
Show whether GDB's standard input is a terminal."), _("\
If on, GDB assumes that standard input is a terminal. In practice, it\n\
means that GDB should wait for the user to answer queries associated to\n\
commands entered at the command prompt. If off, GDB assumes that standard\n\
input is not a terminal, and uses the default answer to all queries.\n\
If auto (the default), determine which mode to use based on the standard\n\
input settings."),
NULL,
show_interactive_mode,
&setlist, &showlist);
} }
void void

View File

@@ -98,6 +98,9 @@ struct ui
currently active. */ currently active. */
int secondary_prompt_depth; int secondary_prompt_depth;
/* The UI's stdin. Set to stdin for the main UI. */
FILE *stdin_stream;
/* stdio stream that command input is being read from. Set to stdin /* stdio stream that command input is being read from. Set to stdin
normally. Set by source_command to the file we are sourcing. normally. Set by source_command to the file we are sourcing.
Set to NULL if we are executing a user-defined command or Set to NULL if we are executing a user-defined command or
@@ -112,6 +115,11 @@ struct ui
it with the event loop. */ it with the event loop. */
int input_fd; int input_fd;
/* Whether ISATTY returns true on input_fd. Cached here because
quit_force needs to know this _after_ input_fd might be
closed. */
int input_interactive_p;
/* See enum prompt_state's description. */ /* See enum prompt_state's description. */
enum prompt_state prompt_state; enum prompt_state prompt_state;

View File

@@ -1052,7 +1052,7 @@ quit (void)
if (sync_quit_force_run) if (sync_quit_force_run)
{ {
sync_quit_force_run = 0; sync_quit_force_run = 0;
quit_force (NULL, stdin == ui->instream); quit_force (NULL, 0);
} }
#ifdef __MSDOS__ #ifdef __MSDOS__
@@ -1271,7 +1271,8 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
question we're asking, and then answer the default automatically. This question we're asking, and then answer the default automatically. This
way, important error messages don't get lost when talking to GDB way, important error messages don't get lost when talking to GDB
over a pipe. */ over a pipe. */
if (! input_from_terminal_p ()) if (current_ui->instream != current_ui->stdin_stream
|| !input_interactive_p (current_ui))
{ {
target_terminal_ours_for_output (); target_terminal_ours_for_output ();
wrap_here (""); wrap_here ("");