#include "gdbsupport/gdb-safe-ctype.h"
#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 fputs_maybe_filtered (const char *, struct ui_file *, int);
-
-static void prompt_for_continue (void);
-
static void set_screen_size (void);
static void set_width (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. */
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
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");
}
}
if (current_ui == NULL)
fputs (msg, stderr);
else
- fputs_unfiltered (msg, gdb_stderr);
+ gdb_puts (msg, gdb_stderr);
abort (); /* ARI: abort */
}
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
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. */
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 ();
/* 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? "),
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
{
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. */
void
maybe_quit (void)
{
+ if (!is_main_thread ())
+ return;
+
if (sync_quit_force_run)
quit ();
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;
}
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;
}
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
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. */
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. */
/* 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
static bool filter_initialized = false;
-/* Contains characters which are waiting to be output (they have
- already been counted in chars_printed). */
-static std::string wrap_buffer;
-
-/* String to indent by if the wrap occurs. */
-static int wrap_indent;
-
-/* Column number on the screen where wrap_buffer begins, or 0 if wrapping
- is not in effect. */
-static int wrap_column;
-
-/* The style applied at the time that wrap_here was called. */
-static ui_file_style wrap_style;
\f
/* Initialize the number of lines per page and chars per line. */
if (chars_per_line == 0)
init_page_info ();
- wrap_buffer.clear ();
filter_initialized = true;
}
set_width ();
}
-/* The currently applied style. */
-
-static ui_file_style applied_style;
-
-/* Emit an ANSI style escape for STYLE. If STREAM is nullptr, emit to
- the wrap buffer; otherwise emit to STREAM. */
-
-static void
-emit_style_escape (const ui_file_style &style,
- struct ui_file *stream = nullptr)
+void
+pager_file::emit_style_escape (const ui_file_style &style)
{
- if (applied_style != style)
+ if (can_emit_style_escape () && style != m_applied_style)
{
- applied_style = style;
-
- if (stream == nullptr)
- wrap_buffer.append (style.to_ansi ());
+ m_applied_style = style;
+ if (m_paging)
+ m_stream->emit_style_escape (style);
else
- stream->puts (style.to_ansi ().c_str ());
+ m_wrap_buffer.append (style.to_ansi ());
}
}
-/* Set the current output style. This will affect future uses of the
- _filtered output functions. */
-
-static void
-set_output_style (struct ui_file *stream, const ui_file_style &style)
-{
- if (!stream->can_emit_style_escape ())
- return;
-
- /* Note that we may not pass STREAM here, when we want to emit to
- the wrap buffer, not directly to STREAM. */
- if (stream == gdb_stdout)
- stream = nullptr;
- emit_style_escape (style, stream);
-}
-
-/* See utils.h. */
+/* See pager.h. */
void
-reset_terminal_style (struct ui_file *stream)
+pager_file::reset_style ()
{
- if (stream->can_emit_style_escape ())
+ if (can_emit_style_escape ())
{
- /* Force the setting, regardless of what we think the setting
- might already be. */
- applied_style = ui_file_style ();
- wrap_buffer.append (applied_style.to_ansi ());
+ m_applied_style = ui_file_style ();
+ m_wrap_buffer.append (m_applied_style.to_ansi ());
}
}
telling users what to do in the prompt is more user-friendly than
expecting them to think of Ctrl-C/SIGINT. */
-static void
-prompt_for_continue (void)
+void
+pager_file::prompt_for_continue ()
{
char cont_prompt[120];
/* Used to add duration we waited for user to respond to
steady_clock::time_point prompt_started = steady_clock::now ();
bool disable_pagination = pagination_disabled_for_command;
+ scoped_restore save_paging = make_scoped_restore (&m_paging, true);
+
/* Clear the current styling. */
- if (gdb_stdout->can_emit_style_escape ())
- emit_style_escape (ui_file_style (), gdb_stdout);
+ m_stream->emit_style_escape (ui_file_style ());
if (annotation_level > 1)
- printf_unfiltered (("\n\032\032pre-prompt-for-continue\n"));
+ m_stream->puts (("\n\032\032pre-prompt-for-continue\n"));
strcpy (cont_prompt,
"--Type <RET> for more, q to quit, "
prompt_for_continue_wait_time += steady_clock::now () - prompt_started;
if (annotation_level > 1)
- printf_unfiltered (("\n\032\032post-prompt-for-continue\n"));
+ m_stream->puts (("\n\032\032post-prompt-for-continue\n"));
if (ignore != NULL)
{
pagination_disabled_for_command = false;
}
-/* Flush the wrap buffer to STREAM, if necessary. */
-
-static void
-flush_wrap_buffer (struct ui_file *stream)
+void
+pager_file::flush_wrap_buffer ()
{
- if (stream == gdb_stdout && !wrap_buffer.empty ())
+ if (!m_paging && !m_wrap_buffer.empty ())
{
- stream->puts (wrap_buffer.c_str ());
- wrap_buffer.clear ();
+ m_stream->puts (m_wrap_buffer.c_str ());
+ m_wrap_buffer.clear ();
}
}
+void
+pager_file::flush ()
+{
+ flush_wrap_buffer ();
+ m_stream->flush ();
+}
+
/* See utils.h. */
void
gdb_flush (struct ui_file *stream)
{
- flush_wrap_buffer (stream);
stream->flush ();
}
/* See ui-file.h. */
void
-ui_file::wrap_here (int indent)
+pager_file::wrap_here (int indent)
{
/* This should have been allocated, but be paranoid anyway. */
gdb_assert (filter_initialized);
- flush_wrap_buffer (this);
+ flush_wrap_buffer ();
if (chars_per_line == UINT_MAX) /* No line overflow checking. */
{
- wrap_column = 0;
+ m_wrap_column = 0;
}
else if (chars_printed >= chars_per_line)
{
- puts_filtered ("\n");
+ this->puts ("\n");
if (indent != 0)
- puts_filtered (n_spaces (indent));
- wrap_column = 0;
+ this->puts (n_spaces (indent));
+ m_wrap_column = 0;
}
else
{
- wrap_column = chars_printed;
- wrap_indent = indent;
- wrap_style = applied_style;
+ m_wrap_column = chars_printed;
+ m_wrap_indent = indent;
+ m_wrap_style = m_applied_style;
}
}
-/* 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;
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;
while (spaces--)
spacebuf[spaces] = ' ';
- puts_filtered (spacebuf);
- puts_filtered (string);
+ gdb_puts (spacebuf);
+ gdb_puts (string);
}
{
if (chars_printed > 0)
{
- puts_filtered ("\n");
+ gdb_puts ("\n");
}
}
-
-/* Like fputs but if FILTER is true, pause after every screenful.
-
- Regardless of FILTER can wrap at points other than the final
- character of a line.
-
- Unlike fputs, fputs_maybe_filtered does not return a value.
- It is OK for LINEBUFFER to be NULL, in which case just don't print
- anything.
-
- Note that a longjmp to top level may occur in this routine (only if
- FILTER is true) (since prompt_for_continue may do so) so this
- routine should not be called when cleanups are not in place. */
-
-static void
-fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream,
- int filter)
+void
+pager_file::puts (const char *linebuffer)
{
const char *lineptr;
if (linebuffer == 0)
return;
- /* Don't do any filtering if it is disabled. */
- if (!stream->can_page ()
- || stream != gdb_stdout
- || !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 ())
{
- flush_wrap_buffer (stream);
- stream->puts (linebuffer);
+ flush_wrap_buffer ();
+ m_stream->puts (linebuffer);
return;
}
auto buffer_clearer
= make_scope_exit ([&] ()
{
- wrap_buffer.clear ();
- wrap_column = 0;
- wrap_indent = 0;
+ m_wrap_buffer.clear ();
+ m_wrap_column = 0;
+ 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. */
/* Possible new page. Note that PAGINATION_DISABLED_FOR_COMMAND
might be set during this loop, so we must continue to check
it here. */
- if (filter && (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')
/* Print a single line. */
if (*lineptr == '\t')
{
- wrap_buffer.push_back ('\t');
+ m_wrap_buffer.push_back ('\t');
/* Shifting right by 3 produces the number of tab stops
we have already passed, and then adding one and
shifting left 3 advances to the next tab stop. */
else if (*lineptr == '\033'
&& skip_ansi_escape (lineptr, &skip_bytes))
{
- wrap_buffer.append (lineptr, skip_bytes);
+ m_wrap_buffer.append (lineptr, skip_bytes);
/* Note that we don't consider this a character, so we
don't increment chars_printed here. */
lineptr += skip_bytes;
}
else if (*lineptr == '\r')
{
- wrap_buffer.push_back (*lineptr);
+ m_wrap_buffer.push_back (*lineptr);
chars_printed = 0;
lineptr++;
}
else
{
- wrap_buffer.push_back (*lineptr);
+ m_wrap_buffer.push_back (*lineptr);
chars_printed++;
lineptr++;
}
prompt is given; and to avoid emitting style
sequences in the middle of a run of text, we track
this as well. */
- ui_file_style save_style = applied_style;
+ ui_file_style save_style = m_applied_style;
bool did_paginate = false;
chars_printed = 0;
lines_printed++;
- if (wrap_column)
+ if (m_wrap_column)
{
/* We are about to insert a newline at an historic
location in the WRAP_BUFFER. Before we do we want to
need to insert an escape sequence we must restore the
current applied style to how it was at the WRAP_COLUMN
location. */
- applied_style = wrap_style;
- if (stream->can_emit_style_escape ())
- emit_style_escape (ui_file_style (), stream);
+ m_applied_style = m_wrap_style;
+ m_stream->emit_style_escape (ui_file_style ());
/* If we aren't actually wrapping, don't output
newline -- if chars_per_line is right, we
probably just overflowed anyway; if it's wrong,
let us keep going. */
- /* XXX: The ideal thing would be to call
- 'stream->putc' here, but we can't because it
- currently calls 'fputc_unfiltered', which ends up
- calling us, which generates an infinite
- recursion. */
- stream->puts ("\n");
+ m_stream->puts ("\n");
}
else
- flush_wrap_buffer (stream);
+ this->flush_wrap_buffer ();
/* Possible new page. Note that
PAGINATION_DISABLED_FOR_COMMAND might be set during
this loop, so we must continue to check it here. */
- if (filter
- && 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;
}
/* Now output indentation and wrapped string. */
- if (wrap_column)
+ if (m_wrap_column)
{
- stream->puts (n_spaces (wrap_indent));
+ m_stream->puts (n_spaces (m_wrap_indent));
/* Having finished inserting the wrapping we should
restore the style as it was at the WRAP_COLUMN. */
- if (stream->can_emit_style_escape ())
- emit_style_escape (wrap_style, stream);
+ m_stream->emit_style_escape (m_wrap_style);
/* The WRAP_BUFFER will still contain content, and that
content might set some alternative style. Restore
APPLIED_STYLE as it was before we started wrapping,
this reflects the current style for the last character
in WRAP_BUFFER. */
- applied_style = save_style;
+ m_applied_style = save_style;
/* Note that this can set chars_printed > chars_per_line
if we are printing a long string. */
- chars_printed = wrap_indent + (save_chars - wrap_column);
- wrap_column = 0; /* And disable fancy wrap */
+ chars_printed = m_wrap_indent + (save_chars - m_wrap_column);
+ m_wrap_column = 0; /* And disable fancy wrap */
}
- else if (did_paginate && stream->can_emit_style_escape ())
- emit_style_escape (save_style, stream);
+ else if (did_paginate)
+ m_stream->emit_style_escape (save_style);
}
}
if (*lineptr == '\n')
{
chars_printed = 0;
- stream->wrap_here (0); /* Spit out chars, cancel
- further wraps. */
+ wrap_here (0); /* Spit out chars, cancel further wraps. */
lines_printed++;
- /* XXX: The ideal thing would be to call
- 'stream->putc' here, but we can't because it
- currently calls 'fputc_unfiltered', which ends up
- calling us, which generates an infinite
- recursion. */
- stream->puts ("\n");
+ m_stream->puts ("\n");
lineptr++;
}
}
}
void
-fputs_filtered (const char *linebuffer, struct ui_file *stream)
+pager_file::write (const char *buf, long length_buf)
{
- fputs_maybe_filtered (linebuffer, stream, 1);
+ /* We have to make a string here because the pager uses
+ skip_ansi_escape, which requires NUL-termination. */
+ std::string str (buf, 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 ()
{
- fputs_maybe_filtered (linebuffer, stream, 0);
+ 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");
}
-/* See utils.h. */
+#endif /* GDB_SELF_TEST */
void
-fputs_styled (const char *linebuffer, const ui_file_style &style,
- struct ui_file *stream)
+gdb_puts (const char *linebuffer, struct ui_file *stream)
{
- set_output_style (stream, style);
- fputs_maybe_filtered (linebuffer, stream, 1);
- set_output_style (stream, ui_file_style ());
+ stream->puts (linebuffer);
}
/* See utils.h. */
void
-fputs_styled_unfiltered (const char *linebuffer, const ui_file_style &style,
- struct ui_file *stream)
+fputs_styled (const char *linebuffer, const ui_file_style &style,
+ struct ui_file *stream)
{
- set_output_style (stream, style);
- fputs_maybe_filtered (linebuffer, stream, 0);
- set_output_style (stream, ui_file_style ());
+ stream->emit_style_escape (style);
+ gdb_puts (linebuffer, stream);
+ stream->emit_style_escape (ui_file_style ());
}
/* See utils.h. */
/* 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++;
}
/* Output pmatch with the highlight style. */
- set_output_style (stream, highlight_style.style ());
+ stream->emit_style_escape (highlight_style.style ());
while (n_highlight > 0)
{
- fputc_filtered (*str, stream);
+ gdb_putc (*str, stream);
n_highlight--;
str++;
}
- set_output_style (stream, ui_file_style ());
+ stream->emit_style_escape (ui_file_style ());
}
/* Output the trailing part of STR not matching HIGHLIGHT. */
if (*str)
- fputs_filtered (str, stream);
-}
-
-int
-putchar_unfiltered (int c)
-{
- return fputc_unfiltered (c, gdb_stdout);
-}
-
-/* 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);
+ gdb_puts (str, stream);
}
-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)
-{
- ui_out_flags flags = disallow_ui_out_field;
- if (!filter)
- flags |= unfiltered_output;
- cli_ui_out (stream, flags).vmessage (applied_style, format, args);
-}
-
-
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)
{
- if (debug_timestamp && stream == gdb_stdlog)
- {
- static bool needs_timestamp = true;
-
- /* Print timestamp if previous print ended with a \n. */
- if (needs_timestamp)
- {
- using namespace std::chrono;
-
- steady_clock::time_point now = steady_clock::now ();
- seconds s = duration_cast<seconds> (now.time_since_epoch ());
- microseconds us = duration_cast<microseconds> (now.time_since_epoch () - s);
- std::string timestamp = string_printf ("%ld.%06ld ",
- (long) s.count (),
- (long) us.count ());
- fputs_unfiltered (timestamp.c_str (), stream);
- }
-
- /* Print the message. */
- string_file sfile;
- cli_ui_out (&sfile, 0).vmessage (ui_file_style (), format, args);
- const std::string &linebuffer = sfile.string ();
- fputs_unfiltered (linebuffer.c_str (), stream);
-
- size_t len = linebuffer.length ();
- needs_timestamp = (len > 0 && linebuffer[len - 1] == '\n');
- }
- else
- 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);
+ stream->vprintf (format, args);
}
void
-vprintf_unfiltered (const char *format, va_list args)
+gdb_vprintf (const char *format, va_list args)
{
- vfprintf_unfiltered (gdb_stdout, format, args);
+ gdb_stdout->vprintf (format, args);
}
void
-fprintf_filtered (struct ui_file *stream, const char *format, ...)
+gdb_printf (struct ui_file *stream, const char *format, ...)
{
va_list args;
va_start (args, format);
- vfprintf_filtered (stream, format, args);
- va_end (args);
-}
-
-void
-fprintf_unfiltered (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);
}
{
va_list args;
- set_output_style (stream, style);
+ stream->emit_style_escape (style);
va_start (args, format);
- vfprintf_filtered (stream, format, args);
+ gdb_vprintf (stream, format, args);
va_end (args);
- set_output_style (stream, ui_file_style ());
-}
-
-/* See utils.h. */
-
-void
-vfprintf_styled (struct ui_file *stream, const ui_file_style &style,
- const char *format, va_list args)
-{
- set_output_style (stream, style);
- vfprintf_filtered (stream, format, args);
- set_output_style (stream, ui_file_style ());
+ stream->emit_style_escape (ui_file_style ());
}
-/* See utils.h. */
-
void
-vfprintf_styled_no_gdbfmt (struct ui_file *stream, const ui_file_style &style,
- bool filter, const char *format, va_list args)
-{
- std::string str = string_vprintf (format, args);
- if (!str.empty ())
- {
- set_output_style (stream, style);
- fputs_maybe_filtered (str.c_str (), stream, filter);
- set_output_style (stream, 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);
}
va_list args;
va_start (args, format);
- vfprintf_unfiltered (gdb_stdout, format, args);
+ string_file file (gdb_stdout->can_emit_style_escape ());
+ file.vprintf (format, args);
+ gdb_stdout->puts_unfiltered (file.string ().c_str ());
va_end (args);
}
This one doesn't, and had better not! */
void
-puts_filtered (const char *string)
-{
- fputs_filtered (string, gdb_stdout);
-}
-
-void
-puts_unfiltered (const char *string)
+gdb_puts (const char *string)
{
- fputs_unfiltered (string, gdb_stdout);
+ gdb_stdout->puts (string);
}
/* Return a pointer to N spaces and a null. The pointer is good
/* 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);
}
}
}
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
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
}