/* The highest UI number ever assigned. */
static int highest_ui_num;
+/* Unbuffer STREAM. This is a wrapper around setbuf(STREAM, nullptr)
+ which applies some special rules for MS-Windows hosts. */
+
+static void
+unbuffer_stream (FILE *stream)
+{
+ /* Unbuffer the input stream so that in gdb_readline_no_editing_callback,
+ the calls to fgetc fetch only one char at the time from STREAM.
+
+ This is important because gdb_readline_no_editing_callback will read
+ from STREAM up to the first '\n' character, after this GDB returns to
+ the event loop and relies on a select on STREAM indicating that more
+ input is pending.
+
+ If STREAM is buffered then the fgetc calls may have moved all the
+ pending input from the kernel into a local buffer, after which the
+ select will not indicate that more input is pending, and input after
+ the first '\n' will not be processed immediately.
+
+ Please ensure that any changes in this area run the MI tests with the
+ FORCE_SEPARATE_MI_TTY=1 flag being passed. */
+
+#ifdef __MINGW32__
+ /* With MS-Windows runtime, making stdin unbuffered when it's
+ connected to the terminal causes it to misbehave. */
+ if (!ISATTY (stream))
+ setbuf (stream, nullptr);
+#else
+ /* On GNU/Linux the issues described above can impact GDB even when
+ dealing with input from a terminal. For now we unbuffer the input
+ stream for everyone except MS-Windows. */
+ setbuf (stream, nullptr);
+#endif
+}
+
/* See top.h. */
ui::ui (FILE *instream_, FILE *outstream_, FILE *errstream_)
outstream (outstream_),
errstream (errstream_),
input_fd (fileno (instream)),
- input_interactive_p (ISATTY (instream)),
+ m_input_interactive_p (ISATTY (instream)),
prompt_state (PROMPT_NEEDED),
m_gdb_stdout (new pager_file (new stdio_file (outstream))),
m_gdb_stdin (new stdio_file (instream)),
{
buffer_init (&line_buffer);
+ unbuffer_stream (instream_);
+
if (ui_list == NULL)
ui_list = this;
else
{
struct ui *ui = current_ui;
+ unbuffer_stream (stream);
+
scoped_restore save_instream
= make_scoped_restore (&ui->instream, stream);
current_ui->secondary_prompt_depth++;
if (m_target_is_async_orig)
- target_async (0);
+ target_async (false);
}
~gdb_readline_wrapper_cleanup ()
saved_after_char_processing_hook = NULL;
if (m_target_is_async_orig)
- target_async (1);
+ target_async (true);
}
DISABLE_COPY_AND_ASSIGN (gdb_readline_wrapper_cleanup);
/* Don't use fancy stuff if not talking to stdin. */
if (deprecated_readline_hook
&& from_tty
- && input_interactive_p (current_ui))
+ && current_ui->input_interactive_p ())
{
rl.reset ((*deprecated_readline_hook) (prompt));
}
else if (command_editing_p
&& from_tty
- && input_interactive_p (current_ui))
+ && current_ui->input_interactive_p ())
{
rl.reset (gdb_readline_wrapper (prompt));
}
--enable-threading\n\
"));
#else
- gdb_print (stream, _("\
+ gdb_printf (stream, _("\
--disable-threading\n\
"));
#endif
any UI with a terminal, save history. */
for (ui *ui : all_uis ())
{
- if (input_interactive_p (ui))
+ if (ui->input_interactive_p ())
{
save = 1;
break;
if (interactive_mode == AUTO_BOOLEAN_AUTO)
gdb_printf (file, "Debugger's interactive mode "
"is %s (currently %s).\n",
- value, input_interactive_p (current_ui) ? "on" : "off");
+ value, current_ui->input_interactive_p () ? "on" : "off");
else
gdb_printf (file, "Debugger's interactive mode is %s.\n", value);
}
/* Returns whether GDB is running on an interactive terminal. */
-int
-input_interactive_p (struct ui *ui)
+bool
+ui::input_interactive_p () const
{
if (batch_flag)
- return 0;
+ return false;
if (interactive_mode != AUTO_BOOLEAN_AUTO)
return interactive_mode == AUTO_BOOLEAN_TRUE;
- return ui->input_interactive_p;
+ return m_input_interactive_p;
}
\f
static void
that was read. */
if (!history_filename.empty ()
&& !IS_ABSOLUTE_PATH (history_filename.c_str ()))
- {
- gdb::unique_xmalloc_ptr<char> temp
- (gdb_abspath (history_filename.c_str ()));
-
- history_filename = temp.get ();
- }
+ history_filename = gdb_abspath (history_filename.c_str ());
}
/* Whether we're in quiet startup mode. */
rl_completion_display_matches_hook = cli_display_match_list;
rl_readline_name = "gdb";
rl_terminal_name = getenv ("TERM");
+ rl_deprep_term_function = gdb_rl_deprep_term_function;
/* The name for this defun comes from Bash, where it originated.
15 is Control-o, the same binding this function has in Bash. */
const char *fname = ".gdb_history";
#endif
- gdb::unique_xmalloc_ptr<char> temp (gdb_abspath (fname));
- history_filename = temp.get ();
+ history_filename = gdb_abspath (fname);
}
}