[gdb/testsuite] Fix gdb.opt/inline-small-func.exp with clang
[binutils-gdb.git] / gdb / top.c
index c7ff6744694281ae0d5d8bc3bbe73a81cc16be2e..453fa236db1aa79c35da6847055a428bcbb2e5a1 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -257,6 +257,41 @@ void (*deprecated_context_hook) (int id);
 /* 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_)
@@ -273,7 +308,7 @@ 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)),
@@ -283,6 +318,8 @@ ui::ui (FILE *instream_, FILE *outstream_, FILE *errstream_)
 {
   buffer_init (&line_buffer);
 
+  unbuffer_stream (instream_);
+
   if (ui_list == NULL)
     ui_list = this;
   else
@@ -412,6 +449,8 @@ read_command_file (FILE *stream)
 {
   struct ui *ui = current_ui;
 
+  unbuffer_stream (stream);
+
   scoped_restore save_instream
     = make_scoped_restore (&ui->instream, stream);
 
@@ -1070,7 +1109,7 @@ public:
     current_ui->secondary_prompt_depth++;
 
     if (m_target_is_async_orig)
-      target_async (0);
+      target_async (false);
   }
 
   ~gdb_readline_wrapper_cleanup ()
@@ -1099,7 +1138,7 @@ public:
     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);
@@ -1366,13 +1405,13 @@ command_line_input (const char *prompt_arg, const char *annotation_suffix)
       /* 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));
        }
@@ -1629,7 +1668,7 @@ This GDB was configured as follows:\n\
             --enable-threading\n\
 "));
 #else
-  gdb_print (stream, _("\
+  gdb_printf (stream, _("\
             --disable-threading\n\
 "));
 #endif
@@ -1836,7 +1875,7 @@ quit_force (int *exit_arg, int from_tty)
             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;
@@ -1884,23 +1923,23 @@ show_interactive_mode (struct ui_file *file, int from_tty,
   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
@@ -2167,12 +2206,7 @@ set_history_filename (const char *args,
      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.  */
@@ -2230,6 +2264,7 @@ init_main (void)
   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.  */
@@ -2444,7 +2479,6 @@ _initialize_top ()
       const char *fname = ".gdb_history";
 #endif
 
-      gdb::unique_xmalloc_ptr<char> temp (gdb_abspath (fname));
-      history_filename = temp.get ();
+      history_filename = gdb_abspath (fname);
     }
 }