[gdb/testsuite] Prevent timeout in gdb.ada/float-bits.exp
[binutils-gdb.git] / gdb / ui-file.c
index 57352e44a34f140f201b6bea1585c7b59ab878b9..3343b6b8fc586ee9652b48b3cb9664c8da89395b 100644 (file)
 
 #include "defs.h"
 #include "ui-file.h"
-#include "gdb_obstack.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;
 
@@ -40,32 +42,121 @@ ui_file::printf (const char *format, ...)
   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 (&copy, 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
@@ -261,8 +352,7 @@ stdio_file::isatty ()
 bool
 stdio_file::can_emit_style_escape ()
 {
-  return ((this == gdb_stdout || this == gdb_stderr)
-         && this->isatty ()
+  return (this->isatty ()
          && term_cli_styling ());
 }
 
@@ -294,9 +384,9 @@ stderr_file::stderr_file (FILE *stream)
 
 \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 ()
@@ -350,8 +440,7 @@ tee_file::term_out ()
 bool
 tee_file::can_emit_style_escape ()
 {
-  return ((this == gdb_stdout || this == gdb_stderr)
-         && m_one->term_out ()
+  return (m_one->term_out ()
          && term_cli_styling ());
 }
 
@@ -386,3 +475,31 @@ no_terminal_escape_file::puts (const char *buf)
   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);
+}