NEWS: Mention new sim --map-info flag.
[deliverable/binutils-gdb.git] / gdb / ser-base.c
index 07ec503b89f893da41ce7ba8d4d4a27d9fd226bc..c17a38903026867d96199f34a465934ce7aec6e3 100644 (file)
@@ -1,13 +1,13 @@
 /* Generic serial interface functions.
 
-   Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-   2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2003,
+   2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "serial.h"
-#include "ser-unix.h"
+#include "ser-base.h"
 #include "event-loop.h"
+
+#include "gdb_select.h"
+#include "gdb_string.h"
+#include <sys/time.h>
 #ifdef USE_WIN32API
 #include <winsock2.h>
 #endif
 
+
 static timer_handler_func push_event;
 static handler_func fd_event;
 
@@ -60,12 +63,13 @@ enum {
    the need to make redundant calls into the event-loop - the next
    scheduled task is only changed when needed. */
 
-void
+static void
 reschedule (struct serial *scb)
 {
   if (serial_is_async_p (scb))
     {
       int next_state;
+
       switch (scb->async_state)
        {
        case FD_SCHEDULED:
@@ -167,6 +171,7 @@ static void
 push_event (void *context)
 {
   struct serial *scb = context;
+
   scb->async_state = NOTHING_SCHEDULED; /* Timers are one-off */
   scb->async_handler (scb, scb->async_context);
   /* re-schedule */
@@ -198,9 +203,9 @@ ser_base_wait_for (struct serial *scb, int timeout)
       FD_SET (scb->fd, &exceptfds);
 
       if (timeout >= 0)
-       numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
+       numfds = gdb_select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
       else
-       numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0);
+       numfds = gdb_select (scb->fd + 1, &readfds, 0, &exceptfds, 0);
 
       if (numfds <= 0)
        {
@@ -276,9 +281,7 @@ do_ser_base_readchar (struct serial *scb, int timeout)
   if (status <= 0)
     {
       if (status == 0)
-       /* 0 chars means timeout.  (We may need to distinguish between EOF
-          & timeouts someday.)  */
-       return SERIAL_TIMEOUT;  
+        return SERIAL_EOF;
       else
        /* Got an error from read.  */
        return SERIAL_ERROR;    
@@ -338,6 +341,55 @@ generic_readchar (struct serial *scb, int timeout,
            }
        }
     }
+  /* Read any error output we might have.  */
+  if (scb->error_fd != -1)
+    {
+      ssize_t s;
+      char buf[81];
+
+      for (;;)
+        {
+         char *current;
+         char *newline;
+         int to_read = 80;
+
+         int num_bytes = -1;
+         if (scb->ops->avail)
+           num_bytes = (scb->ops->avail)(scb, scb->error_fd);
+         if (num_bytes != -1)
+           to_read = (num_bytes < to_read) ? num_bytes : to_read;
+
+         if (to_read == 0)
+           break;
+
+         s = read (scb->error_fd, &buf, to_read);
+         if (s == -1)
+           break;
+         if (s == 0)
+           {
+             /* EOF */
+             close (scb->error_fd);
+             scb->error_fd = -1;
+             break;
+           }
+
+         /* In theory, embedded newlines are not a problem.
+            But for MI, we want each output line to have just
+            one newline for legibility.  So output things
+            in newline chunks.  */
+         buf[s] = '\0';
+         current = buf;
+         while ((newline = strstr (current, "\n")) != NULL)
+           {
+             *newline = '\0';
+             fputs_unfiltered (current, gdb_stderr);
+             fputs_unfiltered ("\n", gdb_stderr);
+             current = newline + 1;
+           }
+         fputs_unfiltered (current, gdb_stderr);
+       }
+    }
+
   reschedule (scb);
   return ch;
 }
This page took 0.024765 seconds and 4 git commands to generate.