ODR warnings for "struct insn_info"
[binutils-gdb.git] / gdb / utils.c
index a86d2c4d38658617fbbe59934b115aad7d874e4d..f9dc4f234310c6bda1807a27507ee56f05472e13 100644 (file)
 #include "bt-utils.h"
 #include "gdbsupport/buildargv.h"
 #include "pager.h"
+#include "run-on-main-thread.h"
 
 void (*deprecated_error_begin_hook) (void);
 
 /* Prototypes for local functions */
 
-static void vfprintf_maybe_filtered (struct ui_file *, const char *,
-                                    va_list, bool)
-  ATTRIBUTE_PRINTF (2, 0);
-
 static void set_screen_size (void);
 static void set_width (void);
 
@@ -111,9 +108,9 @@ static void
 show_sevenbit_strings (struct ui_file *file, int from_tty,
                       struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("Printing of 8-bit characters "
-                           "in strings as \\nnn is %s.\n"),
-                   value);
+  gdb_printf (file, _("Printing of 8-bit characters "
+                     "in strings as \\nnn is %s.\n"),
+             value);
 }
 
 /* String to be printed before warning messages, if any.  */
@@ -125,7 +122,7 @@ static void
 show_pagination_enabled (struct ui_file *file, int from_tty,
                         struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("State of pagination is %s.\n"), value);
+  gdb_printf (file, _("State of pagination is %s.\n"), value);
 }
 
 \f
@@ -150,13 +147,10 @@ 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)
-       fputs_unfiltered (warning_pre_print, gdb_stderr);
-      vfprintf_unfiltered (gdb_stderr, string, args);
-      fprintf_unfiltered (gdb_stderr, "\n");
+       gdb_puts (warning_pre_print, gdb_stderr);
+      gdb_vprintf (gdb_stderr, string, args);
+      gdb_printf (gdb_stderr, "\n");
     }
 }
 
@@ -184,7 +178,7 @@ abort_with_message (const char *msg)
   if (current_ui == NULL)
     fputs (msg, stderr);
   else
-    fputs_unfiltered (msg, gdb_stderr);
+    gdb_puts (msg, gdb_stderr);
 
   abort ();            /* ARI: abort */
 }
@@ -244,10 +238,10 @@ can_dump_core (enum resource_limit_kind limit_kind)
 void
 warn_cant_dump_core (const char *reason)
 {
-  fprintf_unfiltered (gdb_stderr,
-                     _("%s\nUnable to dump core, use `ulimit -c"
-                       " unlimited' before executing GDB next time.\n"),
-                     reason);
+  gdb_printf (gdb_stderr,
+             _("%s\nUnable to dump core, use `ulimit -c"
+               " unlimited' before executing GDB next time.\n"),
+             reason);
 }
 
 /* Check whether GDB will be able to dump core using the dump_core
@@ -312,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.  */
@@ -384,8 +388,9 @@ 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)
-    fprintf_unfiltered (gdb_stderr, "%s\n", reason.c_str ());
+    gdb_printf (gdb_stderr, "%s\n", reason.c_str ());
 
   if (problem->should_print_backtrace)
     gdb_internal_backtrace ();
@@ -395,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? "),
@@ -408,17 +414,19 @@ internal_vproblem (struct internal_problem *problem,
   else
     internal_error (__FILE__, __LINE__, _("bad switch"));
 
-  fputs_unfiltered (_("\nThis is a bug, please report it."), gdb_stderr);
+  gdb_puts (_("\nThis is a bug, please report it."), gdb_stderr);
   if (REPORT_BUGS_TO[0])
-    fprintf_unfiltered (gdb_stderr, _("  For instructions, see:\n%s."),
-                       REPORT_BUGS_TO);
-  fputs_unfiltered ("\n\n", gdb_stderr);
+    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
        {
@@ -654,10 +662,7 @@ 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);
-  fprintf_unfiltered (gdb_stderr, "%s: %s.\n", string, err);
+  gdb_printf (gdb_stderr, "%s: %s.\n", string, err);
 }
 
 /* Control C eventually causes this to be called, at a convenient time.  */
@@ -691,6 +696,9 @@ quit (void)
 void
 maybe_quit (void)
 {
+  if (!is_main_thread ())
+    return;
+
   if (sync_quit_force_run)
     quit ();
 
@@ -879,11 +887,11 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
       target_terminal::scoped_restore_terminal_state term_state;
       target_terminal::ours_for_output ();
       gdb_stdout->wrap_here (0);
-      vfprintf_filtered (gdb_stdout, ctlstr, args);
+      gdb_vprintf (gdb_stdout, ctlstr, args);
 
-      printf_filtered (_("(%s or %s) [answered %c; "
-                        "input not from terminal]\n"),
-                      y_string, n_string, def_answer);
+      gdb_printf (_("(%s or %s) [answered %c; "
+                   "input not from terminal]\n"),
+                 y_string, n_string, def_answer);
 
       return def_value;
     }
@@ -918,7 +926,7 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
 
       if (response == NULL)    /* C-d  */
        {
-         printf_filtered ("EOF [assumed %c]\n", def_answer);
+         gdb_printf ("EOF [assumed %c]\n", def_answer);
          retval = def_value;
          break;
        }
@@ -945,15 +953,15 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
          break;
        }
       /* Invalid entries are not defaulted and require another selection.  */
-      printf_filtered (_("Please answer %s or %s.\n"),
-                      y_string, n_string);
+      gdb_printf (_("Please answer %s or %s.\n"),
+                 y_string, n_string);
     }
 
   /* Add time spend in this routine to prompt_for_continue_wait_time.  */
   prompt_for_continue_wait_time += steady_clock::now () - prompt_started;
 
   if (annotation_level > 1)
-    printf_filtered (("\n\032\032post-query\n"));
+    gdb_printf (("\n\032\032post-query\n"));
   return retval;
 }
 \f
@@ -1134,9 +1142,9 @@ static void
 show_lines_per_page (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file,
-                   _("Number of lines gdb thinks are in a page is %s.\n"),
-                   value);
+  gdb_printf (file,
+             _("Number of lines gdb thinks are in a page is %s.\n"),
+             value);
 }
 
 /* Number of chars per line or UINT_MAX if line folding is disabled.  */
@@ -1145,10 +1153,10 @@ static void
 show_chars_per_line (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file,
-                   _("Number of characters gdb thinks "
-                     "are in a line is %s.\n"),
-                   value);
+  gdb_printf (file,
+             _("Number of characters gdb thinks "
+               "are in a line is %s.\n"),
+             value);
 }
 
 /* Current count of lines printed on this page, chars on this line.  */
@@ -1160,7 +1168,7 @@ static bool pagination_disabled_for_command;
 
 /* Buffer and start column of buffered text, for doing smarter word-
    wrapping.  When someone calls wrap_here(), we start buffering output
-   that comes through fputs_filtered().  If we see a newline, we just
+   that comes through gdb_puts().  If we see a newline, we just
    spit it out and forget about the wrap_here().  If we see another
    wrap_here(), we spit it out and remember the newer one.  If we see
    the end of the line, we spit out a newline, the indent, and then
@@ -1508,15 +1516,14 @@ pager_file::wrap_here (int indent)
     }
 }
 
-/* Print input string to gdb_stdout, filtered, with wrap, 
-   arranging strings in columns of n chars.  String can be
-   right or left justified in the column.  Never prints 
-   trailing spaces.  String should never be longer than
-   width.  FIXME: this could be useful for the EXAMINE 
-   command, which currently doesn't tabulate very well.  */
+/* Print input string to gdb_stdout arranging strings in columns of n
+   chars.  String can be right or left justified in the column.  Never
+   prints trailing spaces.  String should never be longer than width.
+   FIXME: this could be useful for the EXAMINE command, which
+   currently doesn't tabulate very well.  */
 
 void
-puts_filtered_tabular (char *string, int width, int right)
+puts_tabular (char *string, int width, int right)
 {
   int spaces = 0;
   int stringlen;
@@ -1525,13 +1532,13 @@ puts_filtered_tabular (char *string, int width, int right)
   gdb_assert (chars_per_line > 0);
   if (chars_per_line == UINT_MAX)
     {
-      puts_filtered (string);
-      puts_filtered ("\n");
+      gdb_puts (string);
+      gdb_puts ("\n");
       return;
     }
 
   if (((chars_printed - 1) / width + 2) * width >= chars_per_line)
-    puts_filtered ("\n");
+    gdb_puts ("\n");
 
   if (width >= chars_per_line)
     width = chars_per_line - 1;
@@ -1548,8 +1555,8 @@ puts_filtered_tabular (char *string, int width, int right)
   while (spaces--)
     spacebuf[spaces] = ' ';
 
-  puts_filtered (spacebuf);
-  puts_filtered (string);
+  gdb_puts (spacebuf);
+  gdb_puts (string);
 }
 
 
@@ -1563,7 +1570,7 @@ begin_line (void)
 {
   if (chars_printed > 0)
     {
-      puts_filtered ("\n");
+      gdb_puts ("\n");
     }
 }
 
@@ -1575,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 ())
@@ -1596,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.  */
@@ -1606,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')
@@ -1682,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;
@@ -1737,14 +1750,43 @@ pager_file::write (const char *buf, long length_buf)
   this->puts (str.c_str ());
 }
 
-void
-fputs_unfiltered (const char *linebuffer, struct ui_file *stream)
+#if GDB_SELF_TEST
+
+/* Test that disabling the pager does not also disable word
+   wrapping.  */
+
+static void
+test_pager ()
 {
-  stream->puts_unfiltered (linebuffer);
+  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
-fputs_filtered (const char *linebuffer, struct ui_file *stream)
+gdb_puts (const char *linebuffer, struct ui_file *stream)
 {
   stream->puts (linebuffer);
 }
@@ -1756,7 +1798,7 @@ fputs_styled (const char *linebuffer, const ui_file_style &style,
              struct ui_file *stream)
 {
   stream->emit_style_escape (style);
-  fputs_filtered (linebuffer, stream);
+  gdb_puts (linebuffer, stream);
   stream->emit_style_escape (ui_file_style ());
 }
 
@@ -1775,7 +1817,7 @@ fputs_highlighted (const char *str, const compiled_regex &highlight,
       /* Output the part before pmatch with current style.  */
       while (pmatch.rm_so > 0)
        {
-         fputc_filtered (*str, stream);
+         gdb_putc (*str, stream);
          pmatch.rm_so--;
          str++;
        }
@@ -1784,7 +1826,7 @@ fputs_highlighted (const char *str, const compiled_regex &highlight,
       stream->emit_style_escape (highlight_style.style ());
       while (n_highlight > 0)
        {
-         fputc_filtered (*str, stream);
+         gdb_putc (*str, stream);
          n_highlight--;
          str++;
        }
@@ -1793,102 +1835,40 @@ fputs_highlighted (const char *str, const compiled_regex &highlight,
 
   /* Output the trailing part of STR not matching HIGHLIGHT.  */
   if (*str)
-    fputs_filtered (str, stream);
-}
-
-/* Write character C to gdb_stdout using GDB's paging mechanism and return C.
-   May return nonlocally.  */
-
-int
-putchar_filtered (int c)
-{
-  return fputc_filtered (c, gdb_stdout);
-}
-
-int
-fputc_unfiltered (int c, struct ui_file *stream)
-{
-  char buf[2];
-
-  buf[0] = c;
-  buf[1] = 0;
-  fputs_unfiltered (buf, stream);
-  return c;
-}
-
-int
-fputc_filtered (int c, struct ui_file *stream)
-{
-  char buf[2];
-
-  buf[0] = c;
-  buf[1] = 0;
-  fputs_filtered (buf, stream);
-  return c;
-}
-
-/* Print a variable number of ARGS using format FORMAT.  If this
-   information is going to put the amount written (since the last call
-   to REINITIALIZE_MORE_FILTER or the last page break) over the page size,
-   call prompt_for_continue to get the users permission to continue.
-
-   Unlike fprintf, this function does not return a value.
-
-   We implement three variants, vfprintf (takes a vararg list and stream),
-   fprintf (takes a stream to write on), and printf (the usual).
-
-   Note also that this may throw a quit (since prompt_for_continue may
-   do so).  */
-
-static void
-vfprintf_maybe_filtered (struct ui_file *stream, const char *format,
-                        va_list args, bool filter)
-{
-  stream->vprintf (format, args);
+    gdb_puts (str, stream);
 }
 
-
 void
-vfprintf_filtered (struct ui_file *stream, const char *format, va_list args)
+gdb_putc (int c)
 {
-  vfprintf_maybe_filtered (stream, format, args, true);
+  return gdb_stdout->putc (c);
 }
 
 void
-vfprintf_unfiltered (struct ui_file *stream, const char *format, va_list args)
+gdb_putc (int c, struct ui_file *stream)
 {
-  vfprintf_maybe_filtered (stream, format, args, false);
+  return stream->putc (c);
 }
 
 void
-vprintf_filtered (const char *format, va_list args)
+gdb_vprintf (struct ui_file *stream, const char *format, va_list args)
 {
-  vfprintf_filtered (gdb_stdout, format, args);
-}
-
-void
-vprintf_unfiltered (const char *format, va_list args)
-{
-  vfprintf_unfiltered (gdb_stdout, format, args);
+  stream->vprintf (format, args);
 }
 
 void
-fprintf_filtered (struct ui_file *stream, const char *format, ...)
+gdb_vprintf (const char *format, va_list args)
 {
-  va_list args;
-
-  va_start (args, format);
-  vfprintf_filtered (stream, format, args);
-  va_end (args);
+  gdb_stdout->vprintf (format, args);
 }
 
 void
-fprintf_unfiltered (struct ui_file *stream, const char *format, ...)
+gdb_printf (struct ui_file *stream, const char *format, ...)
 {
   va_list args;
 
   va_start (args, format);
-  vfprintf_unfiltered (stream, format, args);
+  gdb_vprintf (stream, format, args);
   va_end (args);
 }
 
@@ -1902,29 +1882,18 @@ fprintf_styled (struct ui_file *stream, const ui_file_style &style,
 
   stream->emit_style_escape (style);
   va_start (args, format);
-  vfprintf_filtered (stream, format, args);
+  gdb_vprintf (stream, format, args);
   va_end (args);
   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);
-  vfprintf_filtered (stream, format, args);
-  stream->emit_style_escape (ui_file_style ());
-}
-
 void
-printf_filtered (const char *format, ...)
+gdb_printf (const char *format, ...)
 {
   va_list args;
 
   va_start (args, format);
-  vfprintf_filtered (gdb_stdout, format, args);
+  gdb_vprintf (gdb_stdout, format, args);
   va_end (args);
 }
 
@@ -1947,9 +1916,9 @@ printf_unfiltered (const char *format, ...)
    This one doesn't, and had better not!  */
 
 void
-puts_filtered (const char *string)
+gdb_puts (const char *string)
 {
-  fputs_filtered (string, gdb_stdout);
+  gdb_stdout->puts (string);
 }
 
 /* Return a pointer to N spaces and a null.  The pointer is good
@@ -1976,34 +1945,34 @@ n_spaces (int n)
 
 /* Print N spaces.  */
 void
-print_spaces_filtered (int n, struct ui_file *stream)
+print_spaces (int n, struct ui_file *stream)
 {
-  fputs_filtered (n_spaces (n), stream);
+  gdb_puts (n_spaces (n), 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)
     {
       /* If user wants to see raw output, no problem.  */
       if (!demangle)
        {
-         fputs_filtered (name, stream);
+         gdb_puts (name, stream);
        }
       else
        {
          gdb::unique_xmalloc_ptr<char> demangled
            = language_demangle (language_def (lang), name, arg_mode);
-         fputs_filtered (demangled ? demangled.get () : name, stream);
+         gdb_puts (demangled ? demangled.get () : name, stream);
        }
     }
 }
@@ -3165,8 +3134,8 @@ static void
 show_debug_timestamp (struct ui_file *file, int from_tty,
                      struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("Timestamping debugging messages is %s.\n"),
-                   value);
+  gdb_printf (file, _("Timestamping debugging messages is %s.\n"),
+             value);
 }
 \f
 
@@ -3765,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
 }