/* UI_FILE - a generic STDIO like output stream.
- Copyright (C) 1999-2019 Free Software Foundation, Inc.
+ Copyright (C) 1999-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "ui-file.h"
-#include "gdb_obstack.h"
-#include "gdb_select.h"
+#include "gdbsupport/gdb_obstack.h"
+#include "gdbsupport/gdb_select.h"
#include "gdbsupport/filestuff.h"
+#include "cli-out.h"
#include "cli/cli-style.h"
+#include <chrono>
null_file null_stream;
va_list args;
va_start (args, format);
- vfprintf_unfiltered (this, format, args);
+ vprintf (format, args);
va_end (args);
}
void
ui_file::putstr (const char *str, int quoter)
{
- fputstr_unfiltered (str, quoter, this);
+ while (*str)
+ printchar (*str++, quoter, false);
}
void
-ui_file::putstrn (const char *str, int n, int quoter)
+ui_file::putstrn (const char *str, int n, int quoter, bool async_safe)
{
- fputstrn_unfiltered (str, n, quoter, fputc_unfiltered, this);
+ for (int i = 0; i < n; i++)
+ printchar (str[i], quoter, async_safe);
}
-int
+void
ui_file::putc (int c)
{
- return fputc_unfiltered (c, this);
+ char copy = (char) c;
+ write (©, 1);
}
void
ui_file::vprintf (const char *format, va_list args)
{
- vfprintf_unfiltered (this, format, args);
+ ui_out_flags flags = disallow_ui_out_field;
+ cli_ui_out (this, flags).vmessage (m_applied_style, format, args);
+}
+
+/* See ui-file.h. */
+
+void
+ui_file::emit_style_escape (const ui_file_style &style)
+{
+ if (can_emit_style_escape () && style != m_applied_style)
+ {
+ m_applied_style = style;
+ this->puts (style.to_ansi ().c_str ());
+ }
+}
+
+/* See ui-file.h. */
+
+void
+ui_file::reset_style ()
+{
+ if (can_emit_style_escape ())
+ {
+ m_applied_style = ui_file_style ();
+ this->puts (m_applied_style.to_ansi ().c_str ());
+ }
+}
+
+/* See ui-file.h. */
+
+void
+ui_file::printchar (int c, int quoter, bool async_safe)
+{
+ char buf[4];
+ int out = 0;
+
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if (c < 0x20 /* Low control chars */
+ || (c >= 0x7F && c < 0xA0) /* DEL, High controls */
+ || (sevenbit_strings && c >= 0x80))
+ { /* high order bit set */
+ buf[out++] = '\\';
+
+ switch (c)
+ {
+ case '\n':
+ buf[out++] = 'n';
+ break;
+ case '\b':
+ buf[out++] = 'b';
+ break;
+ case '\t':
+ buf[out++] = 't';
+ break;
+ case '\f':
+ buf[out++] = 'f';
+ break;
+ case '\r':
+ buf[out++] = 'r';
+ break;
+ case '\033':
+ buf[out++] = 'e';
+ break;
+ case '\007':
+ buf[out++] = 'a';
+ break;
+ default:
+ {
+ buf[out++] = '0' + ((c >> 6) & 0x7);
+ buf[out++] = '0' + ((c >> 3) & 0x7);
+ buf[out++] = '0' + ((c >> 0) & 0x7);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (quoter != 0 && (c == '\\' || c == quoter))
+ buf[out++] = '\\';
+ buf[out++] = c;
+ }
+
+ if (async_safe)
+ this->write_async_safe (buf, out);
+ else
+ this->write (buf, out);
}
\f
\f
-void
-gdb_flush (struct ui_file *file)
-{
- file->flush ();
-}
-
-int
-ui_file_isatty (struct ui_file *file)
-{
- return file->isatty ();
-}
-
/* true if the gdb terminal supports styling, and styling is enabled. */
static bool
return true;
}
-
-void
-ui_file_write (struct ui_file *file,
- const char *buf,
- long length_buf)
-{
- file->write (buf, length_buf);
-}
-
-void
-ui_file_write_async_safe (struct ui_file *file,
- const char *buf,
- long length_buf)
-{
- file->write_async_safe (buf, length_buf);
-}
-
-long
-ui_file_read (struct ui_file *file, char *buf, long length_buf)
-{
- return file->read (buf, length_buf);
-}
-
-void
-fputs_unfiltered (const char *buf, struct ui_file *file)
-{
- file->puts (buf);
-}
-
\f
string_file::~string_file ()
bool
stdio_file::can_emit_style_escape ()
{
- return (this == gdb_stdout
- && this->isatty ()
+ return (this->isatty ()
&& term_cli_styling ());
}
void
stderr_file::write (const char *buf, long length_buf)
{
- gdb_flush (gdb_stdout);
+ gdb_stdout->flush ();
stdio_file::write (buf, length_buf);
}
void
stderr_file::puts (const char *linebuffer)
{
- gdb_flush (gdb_stdout);
+ gdb_stdout->flush ();
stdio_file::puts (linebuffer);
}
\f
-tee_file::tee_file (ui_file *one, ui_file_up &&two)
+tee_file::tee_file (ui_file *one, ui_file *two)
: m_one (one),
- m_two (std::move (two))
+ m_two (two)
{}
tee_file::~tee_file ()
bool
tee_file::can_emit_style_escape ()
{
- return (this == gdb_stdout
- && m_one->term_out ()
+ return (m_one->term_out ()
&& term_cli_styling ());
}
if (*buf != '\0')
this->stdio_file::write (buf, strlen (buf));
}
+
+void
+timestamped_file::write (const char *buf, long len)
+{
+ if (debug_timestamp)
+ {
+ /* Print timestamp if previous print ended with a \n. */
+ if (m_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 ());
+ m_stream->puts (timestamp.c_str ());
+ }
+
+ /* Print the message. */
+ m_stream->write (buf, len);
+
+ m_needs_timestamp = (len > 0 && buf[len - 1] == '\n');
+ }
+ else
+ m_stream->write (buf, len);
+}