ODR warnings for "struct insn_info"
[binutils-gdb.git] / gdb / utils.c
index bf6f4fb9b89298525506443aea45b21a014169d3..f9dc4f234310c6bda1807a27507ee56f05472e13 100644 (file)
@@ -78,6 +78,7 @@
 #include "bt-utils.h"
 #include "gdbsupport/buildargv.h"
 #include "pager.h"
+#include "run-on-main-thread.h"
 
 void (*deprecated_error_begin_hook) (void);
 
@@ -146,9 +147,6 @@ vwarning (const char *string, va_list args)
          term_state.emplace ();
          target_terminal::ours_for_output ();
        }
-      if (filtered_printing_initialized ())
-       gdb_stdout->wrap_here (0);      /* Force out any buffered output.  */
-      gdb_flush (gdb_stdout);
       if (warning_pre_print)
        gdb_puts (warning_pre_print, gdb_stderr);
       gdb_vprintf (gdb_stderr, string, args);
@@ -308,6 +306,16 @@ struct internal_problem
   bool should_print_backtrace;
 };
 
+/* Return true if the readline callbacks have been initialized for UI.
+   This is always true once GDB is fully initialized, but during the early
+   startup phase this is initially false.  */
+
+static bool
+readline_initialized (struct ui *ui)
+{
+  return ui->call_readline != nullptr;
+}
+
 /* Report a problem, internal to GDB, to the user.  Once the problem
    has been reported, and assuming GDB didn't quit, the caller can
    either allow execution to resume or throw an error.  */
@@ -380,6 +388,7 @@ internal_vproblem (struct internal_problem *problem,
   if (problem->should_quit != internal_problem_ask
       || !confirm
       || !filtered_printing_initialized ()
+      || !readline_initialized (current_ui)
       || problem->should_print_backtrace)
     gdb_printf (gdb_stderr, "%s\n", reason.c_str ());
 
@@ -391,7 +400,8 @@ internal_vproblem (struct internal_problem *problem,
       /* Default (yes/batch case) is to quit GDB.  When in batch mode
         this lessens the likelihood of GDB going into an infinite
         loop.  */
-      if (!confirm || !filtered_printing_initialized ())
+      if (!confirm || !filtered_printing_initialized ()
+         || !readline_initialized (current_ui))
        quit_p = 1;
       else
        quit_p = query (_("%s\nQuit this debugging session? "),
@@ -406,15 +416,17 @@ internal_vproblem (struct internal_problem *problem,
 
   gdb_puts (_("\nThis is a bug, please report it."), gdb_stderr);
   if (REPORT_BUGS_TO[0])
-    gdb_printf (gdb_stderr, _("  For instructions, see:\n%s."),
-               REPORT_BUGS_TO);
+    gdb_printf (gdb_stderr, _("  For instructions, see:\n%ps."),
+               styled_string (file_name_style.style (),
+                              REPORT_BUGS_TO));
   gdb_puts ("\n\n", gdb_stderr);
 
   if (problem->should_dump_core == internal_problem_ask)
     {
       if (!can_dump_core_warn (LIMIT_MAX, reason.c_str ()))
        dump_core_p = 0;
-      else if (!filtered_printing_initialized ())
+      else if (!filtered_printing_initialized ()
+              || !readline_initialized (current_ui))
        dump_core_p = 1;
       else
        {
@@ -650,9 +662,6 @@ void
 print_sys_errmsg (const char *string, int errcode)
 {
   const char *err = safe_strerror (errcode);
-  /* We want anything which was printed on stdout to come out first, before
-     this message.  */
-  gdb_flush (gdb_stdout);
   gdb_printf (gdb_stderr, "%s: %s.\n", string, err);
 }
 
@@ -687,6 +696,9 @@ quit (void)
 void
 maybe_quit (void)
 {
+  if (!is_main_thread ())
+    return;
+
   if (sync_quit_force_run)
     quit ();
 
@@ -1570,10 +1582,8 @@ pager_file::puts (const char *linebuffer)
   if (linebuffer == 0)
     return;
 
-  /* Don't do any filtering if it is disabled.  */
-  if (!pagination_enabled
-      || pagination_disabled_for_command
-      || batch_flag
+  /* Don't do any filtering or wrapping if both are disabled.  */
+  if (batch_flag
       || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX)
       || top_level_interpreter () == NULL
       || top_level_interpreter ()->interp_ui_out ()->is_mi_like_p ())
@@ -1591,6 +1601,12 @@ pager_file::puts (const char *linebuffer)
                         m_wrap_indent = 0;
                       });
 
+  /* If the user does "set height 1" then the pager will exhibit weird
+     behavior.  This is pathological, though, so don't allow it.  */
+  const unsigned int lines_allowed = (lines_per_page > 1
+                                     ? lines_per_page - 1
+                                     : 1);
+
   /* Go through and output each character.  Show line extension
      when this is necessary; prompt user for new page when this is
      necessary.  */
@@ -1601,8 +1617,9 @@ pager_file::puts (const char *linebuffer)
       /* Possible new page.  Note that PAGINATION_DISABLED_FOR_COMMAND
         might be set during this loop, so we must continue to check
         it here.  */
-      if ((lines_printed >= lines_per_page - 1)
-         && !pagination_disabled_for_command)
+      if (pagination_enabled
+         && !pagination_disabled_for_command
+         && lines_printed >= lines_allowed)
        prompt_for_continue ();
 
       while (*lineptr && *lineptr != '\n')
@@ -1677,8 +1694,9 @@ pager_file::puts (const char *linebuffer)
              /* Possible new page.  Note that
                 PAGINATION_DISABLED_FOR_COMMAND might be set during
                 this loop, so we must continue to check it here.  */
-             if (lines_printed >= lines_per_page - 1
-                 && !pagination_disabled_for_command)
+             if (pagination_enabled
+                 && !pagination_disabled_for_command
+                 && lines_printed >= lines_allowed)
                {
                  prompt_for_continue ();
                  did_paginate = true;
@@ -1732,6 +1750,41 @@ pager_file::write (const char *buf, long length_buf)
   this->puts (str.c_str ());
 }
 
+#if GDB_SELF_TEST
+
+/* Test that disabling the pager does not also disable word
+   wrapping.  */
+
+static void
+test_pager ()
+{
+  string_file *strfile = new string_file ();
+  pager_file pager (strfile);
+
+  /* Make sure the pager is disabled.  */
+  scoped_restore save_enabled
+    = make_scoped_restore (&pagination_enabled, false);
+  scoped_restore save_disabled
+    = make_scoped_restore (&pagination_disabled_for_command, false);
+  scoped_restore save_batch
+    = make_scoped_restore (&batch_flag, false);
+  scoped_restore save_lines
+    = make_scoped_restore (&lines_per_page, 50);
+  /* Make it easy to word wrap.  */
+  scoped_restore save_chars
+    = make_scoped_restore (&chars_per_line, 15);
+  scoped_restore save_printed
+    = make_scoped_restore (&chars_printed, 0);
+
+  pager.puts ("aaaaaaaaaaaa");
+  pager.wrap_here (2);
+  pager.puts ("bbbbbbbbbbbb\n");
+
+  SELF_CHECK (strfile->string () == "aaaaaaaaaaaa\n  bbbbbbbbbbbb\n");
+}
+
+#endif /* GDB_SELF_TEST */
+
 void
 gdb_puts (const char *linebuffer, struct ui_file *stream)
 {
@@ -1785,16 +1838,13 @@ fputs_highlighted (const char *str, const compiled_regex &highlight,
     gdb_puts (str, stream);
 }
 
-/* Write character C to gdb_stdout using GDB's paging mechanism and return C.
-   May return nonlocally.  */
-
-int
+void
 gdb_putc (int c)
 {
   return gdb_stdout->putc (c);
 }
 
-int
+void
 gdb_putc (int c, struct ui_file *stream)
 {
   return stream->putc (c);
@@ -1837,17 +1887,6 @@ fprintf_styled (struct ui_file *stream, const ui_file_style &style,
   stream->emit_style_escape (ui_file_style ());
 }
 
-/* See utils.h.  */
-
-void
-vfprintf_styled (struct ui_file *stream, const ui_file_style &style,
-                const char *format, va_list args)
-{
-  stream->emit_style_escape (style);
-  gdb_vprintf (stream, format, args);
-  stream->emit_style_escape (ui_file_style ());
-}
-
 void
 gdb_printf (const char *format, ...)
 {
@@ -1913,14 +1952,14 @@ print_spaces (int n, struct ui_file *stream)
 \f
 /* C++/ObjC demangler stuff.  */
 
-/* fprintf_symbol_filtered attempts to demangle NAME, a symbol in language
+/* fprintf_symbol attempts to demangle NAME, a symbol in language
    LANG, using demangling args ARG_MODE, and print it filtered to STREAM.
    If the name is not mangled, or the language for the name is unknown, or
    demangling is off, the name is printed in its "raw" form.  */
 
 void
-fprintf_symbol_filtered (struct ui_file *stream, const char *name,
-                        enum language lang, int arg_mode)
+fprintf_symbol (struct ui_file *stream, const char *name,
+               enum language lang, int arg_mode)
 {
   if (name != NULL)
     {
@@ -3695,5 +3734,6 @@ When set, debugging messages will be marked with seconds and microseconds."),
   selftests::register_test ("gdb_argv_array_view", gdb_argv_as_array_view_test);
   selftests::register_test ("strncmp_iw_with_mode",
                            strncmp_iw_with_mode_tests);
+  selftests::register_test ("pager", test_pager);
 #endif
 }