gdb/
[deliverable/binutils-gdb.git] / gdb / ui-file.c
index f40bfdb89f0674d4bca60f6de98766c0d6a59050..ce270f6cce03172d3289bd4b79d023d4959db1ff 100644 (file)
@@ -1,6 +1,6 @@
 /* UI_FILE - a generic STDIO like output stream.
 
-   Copyright (C) 1999, 2000, 2001, 2002, 2007, 2008, 2009, 2010
+   Copyright (C) 1999, 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -18,7 +18,7 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-/* Implement the ``struct ui_file'' object. */
+/* Implement the ``struct ui_file'' object.  */
 
 #include "defs.h"
 #include "ui-file.h"
@@ -30,6 +30,7 @@
 
 static ui_file_isatty_ftype null_file_isatty;
 static ui_file_write_ftype null_file_write;
+static ui_file_write_ftype null_file_write_async_safe;
 static ui_file_fputs_ftype null_file_fputs;
 static ui_file_read_ftype null_file_read;
 static ui_file_flush_ftype null_file_flush;
@@ -42,6 +43,7 @@ struct ui_file
     int *magic;
     ui_file_flush_ftype *to_flush;
     ui_file_write_ftype *to_write;
+    ui_file_write_async_safe_ftype *to_write_async_safe;
     ui_file_fputs_ftype *to_fputs;
     ui_file_read_ftype *to_read;
     ui_file_delete_ftype *to_delete;
@@ -61,6 +63,7 @@ ui_file_new (void)
   set_ui_file_data (file, NULL, null_file_delete);
   set_ui_file_flush (file, null_file_flush);
   set_ui_file_write (file, null_file_write);
+  set_ui_file_write_async_safe (file, null_file_write_async_safe);
   set_ui_file_fputs (file, null_file_fputs);
   set_ui_file_read (file, null_file_read);
   set_ui_file_isatty (file, null_file_isatty);
@@ -108,8 +111,8 @@ null_file_write (struct ui_file *file,
                 long sizeof_buf)
 {
   if (file->to_fputs == null_file_fputs)
-    /* Both the write and fputs methods are null. Discard the
-       request. */
+    /* Both the write and fputs methods are null.  Discard the
+       request.  */
     return;
   else
     {
@@ -144,16 +147,24 @@ static void
 null_file_fputs (const char *buf, struct ui_file *file)
 {
   if (file->to_write == null_file_write)
-    /* Both the write and fputs methods are null. Discard the
-       request. */
+    /* Both the write and fputs methods are null.  Discard the
+       request.  */
     return;
   else
     {
-      /* The write method was implemented, use that. */
+      /* The write method was implemented, use that.  */
       file->to_write (file, buf, strlen (buf));
     }
 }
 
+static void
+null_file_write_async_safe (struct ui_file *file,
+                           const char *buf,
+                           long sizeof_buf)
+{
+  return;
+}
+
 static void
 null_file_delete (struct ui_file *file)
 {
@@ -203,6 +214,14 @@ ui_file_write (struct ui_file *file,
   file->to_write (file, buf, length_buf);
 }
 
+void
+ui_file_write_async_safe (struct ui_file *file,
+                         const char *buf,
+                         long length_buf)
+{
+  file->to_write_async_safe (file, buf, length_buf);
+}
+
 long
 ui_file_read (struct ui_file *file, char *buf, long length_buf)
 {
@@ -246,6 +265,13 @@ set_ui_file_write (struct ui_file *file,
   file->to_write = write;
 }
 
+void
+set_ui_file_write_async_safe (struct ui_file *file,
+                             ui_file_write_async_safe_ftype *write_async_safe)
+{
+  file->to_write_async_safe = write_async_safe;
+}
+
 void
 set_ui_file_read (struct ui_file *file, ui_file_read_ftype *read)
 {
@@ -267,7 +293,7 @@ set_ui_file_data (struct ui_file *file, void *data,
 }
 
 /* ui_file utility function for converting a ``struct ui_file'' into
-   a memory buffer. */
+   a memory buffer.  */
 
 struct accumulated_ui_file
 {
@@ -323,8 +349,8 @@ ui_file_obsavestring (struct ui_file *file, struct obstack *obstack,
 }
 \f
 /* A pure memory based ``struct ui_file'' that can be used an output
-   buffer. The buffers accumulated contents are available via
-   ui_file_put(). */
+   buffer.  The buffers accumulated contents are available via
+   ui_file_put().  */
 
 struct mem_file
   {
@@ -434,14 +460,15 @@ mem_file_write (struct ui_file *file,
 }
 \f
 /* ``struct ui_file'' implementation that maps directly onto
-   <stdio.h>'s FILE. */
+   <stdio.h>'s FILE.  */
 
 static ui_file_write_ftype stdio_file_write;
+static ui_file_write_async_safe_ftype stdio_file_write_async_safe;
 static ui_file_fputs_ftype stdio_file_fputs;
 static ui_file_read_ftype stdio_file_read;
 static ui_file_isatty_ftype stdio_file_isatty;
 static ui_file_delete_ftype stdio_file_delete;
-static struct ui_file *stdio_file_new (FILE * file, int close_p);
+static struct ui_file *stdio_file_new (FILE *file, int close_p);
 static ui_file_flush_ftype stdio_file_flush;
 
 static int stdio_file_magic;
@@ -450,6 +477,9 @@ struct stdio_file
   {
     int *magic;
     FILE *file;
+    /* The associated file descriptor is extracted ahead of time for
+       stdio_file_write_async_safe's benefit, in case fileno isn't async-safe.  */
+    int fd;
     int close_p;
   };
 
@@ -461,10 +491,12 @@ stdio_file_new (FILE *file, int close_p)
 
   stdio->magic = &stdio_file_magic;
   stdio->file = file;
+  stdio->fd = fileno (file);
   stdio->close_p = close_p;
   set_ui_file_data (ui_file, stdio, stdio_file_delete);
   set_ui_file_flush (ui_file, stdio_file_flush);
   set_ui_file_write (ui_file, stdio_file_write);
+  set_ui_file_write_async_safe (ui_file, stdio_file_write_async_safe);
   set_ui_file_fputs (ui_file, stdio_file_fputs);
   set_ui_file_read (ui_file, stdio_file_read);
   set_ui_file_isatty (ui_file, stdio_file_isatty);
@@ -510,16 +542,14 @@ stdio_file_read (struct ui_file *file, char *buf, long length_buf)
      the file.  Wait until at least one byte of data is available.
      Control-C can interrupt gdb_select, but not read.  */
   {
-    int fd = fileno (stdio->file);
-
     fd_set readfds;
     FD_ZERO (&readfds);
-    FD_SET (fd, &readfds);
-    if (gdb_select (fd + 1, &readfds, NULL, NULL, NULL) == -1)
+    FD_SET (stdio->fd, &readfds);
+    if (gdb_select (stdio->fd + 1, &readfds, NULL, NULL, NULL) == -1)
       return -1;
   }
 
-  return read (fileno (stdio->file), buf, length_buf);
+  return read (stdio->fd, buf, length_buf);
 }
 
 static void
@@ -535,6 +565,28 @@ stdio_file_write (struct ui_file *file, const char *buf, long length_buf)
     ;
 }
 
+static void
+stdio_file_write_async_safe (struct ui_file *file,
+                            const char *buf, long length_buf)
+{
+  struct stdio_file *stdio = ui_file_data (file);
+
+  if (stdio->magic != &stdio_file_magic)
+    {
+      /* gettext isn't necessarily async safe, so we can't use _("error message") here.
+        We could extract the correct translation ahead of time, but this is an extremely
+        rare event, and one of the other stdio_file_* routines will presumably catch
+        the problem anyway.  For now keep it simple and ignore the error here.  */
+      return;
+    }
+
+  /* This is written the way it is to avoid a warning from gcc about not using the
+     result of write (since it can be declared with attribute warn_unused_result).
+     Alas casting to void doesn't work for this.  */
+  if (write (stdio->fd, buf, length_buf))
+    ;
+}
+
 static void
 stdio_file_fputs (const char *linebuffer, struct ui_file *file)
 {
@@ -556,10 +608,10 @@ stdio_file_isatty (struct ui_file *file)
   if (stdio->magic != &stdio_file_magic)
     internal_error (__FILE__, __LINE__,
                    _("stdio_file_isatty: bad magic number"));
-  return (isatty (fileno (stdio->file)));
+  return (isatty (stdio->fd));
 }
 
-/* Like fdopen().  Create a ui_file from a previously opened FILE. */
+/* Like fdopen().  Create a ui_file from a previously opened FILE.  */
 
 struct ui_file *
 stdio_fileopen (FILE *file)
This page took 0.027732 seconds and 4 git commands to generate.