Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* PATCH: Windows sockets
@ 2005-03-26  1:27 Mark Mitchell
  2005-03-26  2:09 ` Christopher Faylor
  2005-03-26  8:47 ` Mark Kettenis
  0 siblings, 2 replies; 9+ messages in thread
From: Mark Mitchell @ 2005-03-26  1:27 UTC (permalink / raw)
  To: gdb-patches


Here's the first "interesting" patch for Windows support.  This patch
modifies ser-tcp.c to support Windows, so that we can use a GDB
running on Windows to talk to a gdbserver process.  

Here is a sumary of the changes in this patch:

1. Link with -lws2_32 on MinGW so we can use sockets.

2. In defs.h, define WINAPI so that source files know whether they are
   supposed to use the Windows API.

3. Move ser_unix_readchar and friends (which were only barely
   UNIX-specific) into ser-base.c, renaming appropriately.

4. Add a new member (read_prim) to struct serial_ops, and use it from
   ser_base_readchar.  The reason for this is that sockets must be
   read with "recv" on Windows; plain "read" does not work.  So, we
   need a way to indicate which low-level primitive to use to read
   from a file descriptor.

5. Make a handful of minor changes to ter-tcp.c to account for
   differences in the BSD and Windows sockets APIs.

6. Tweak safe_strerror to deal with Windows sockets error codes.

Tested on x86_64-unknown-linux-gnu, to make sure I didn't break UNIX,
and cursorily on Windows (with other patches, not yet submitted).

OK to apply?

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2005-03-25  Mark Mitchell  <mark@codesourcery.com>

	* configure.ac: Link with -lws2_32 on mingw.
	* configure: Regenerated.
	* defs.h (WINAPI): Define, conditionally.
	* ser-base.c (winsock2.h): Include it.
	(fd_event): Use read_prim.
	(ser_base_wait_for): Moved here from ser-unix.c.
	(do_ser_base_readchar): Likewise.
	(generic_readchar): Likewise.
	(ser_base_readchar): Likewise.
	* ser-base.h (generic_readchar): Declare.
	(ser_base_readchar): Likewise.
	* ser-pipe.c (_initialize_ser_pipe): Adjust for name changes.
	* ser-tcp.c (winsock2.h): Include it.
	(ETIMEDOUT): Define on Windows.
	(closesocket): Define on UNIX.
	(ioctlsocket): Likewise.
	(net_open): Adjust for differences in socket functions between
	Windows and UNIX.
	(_initialize_ser_tcp): Adjust for name changes.
	(net_read_prim): New function.
	(net_write): Likewise.
	* ser-unix.c (generic_readchar): Remove.
	(ser_unix_wait_for): Likewise.
	(do_unix_readchar): Likewise.
	(ser_unix_readchar): Likewise.
	(_initialize_ser_hardwire): Adjust for name changes.
	(ser_unix_read_prim): New function.
	* ser-unix.h (ser_unix_readchar): Remove.
	(ser_unix_read_prim): Declare.
	* serial.h (struct serial_ops): Add read_prim.
	* utils.c (winerror.h): Include it.
	(safe_strerror): Handle winsock errors.

Index: configure.ac
===================================================================
RCS file: /cvs/src/src/gdb/configure.ac,v
retrieving revision 1.17
diff -c -5 -p -r1.17 configure.ac
*** configure.ac	25 Mar 2005 19:47:23 -0000	1.17
--- configure.ac	26 Mar 2005 01:00:29 -0000
*************** if test x$gdb_cv_os_cygwin = xyes; then
*** 1185,1194 ****
--- 1185,1201 ----
      case "${target}" in
  	*cygwin*) WIN32LIBS="$WIN32LIBS -limagehlp"
  	;;
      esac
  fi
+ 
+ # The ser-tcp.c module requires sockets.
+ case ${host} in
+   *mingw32*)
+     WIN32LIBS="$WIN32LIBS -lwsock32"
+     ;;
+ esac	    
  AC_SUBST(WIN32LIBS)
  
  LIBGUI="../libgui/src/libgui.a"
  GUI_CFLAGS_X="-I${srcdir}/../libgui/src"
  AC_SUBST(LIBGUI)
Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.182
diff -c -5 -p -r1.182 defs.h
*** defs.h	17 Mar 2005 22:11:09 -0000	1.182
--- defs.h	26 Mar 2005 01:00:29 -0000
*************** extern int use_windows;
*** 1149,1158 ****
--- 1149,1162 ----
  
  #ifndef SLASH_STRING
  #define SLASH_STRING "/"
  #endif
  
+ #if defined(__WIN32__) && !defined(__CYGWIN__)
+ #define WINAPI
+ #endif
+ 
  /* Provide default definitions of PIDGET, TIDGET, and MERGEPID.
     The name ``TIDGET'' is a historical accident.  Many uses of TIDGET
     in the code actually refer to a lightweight process id, i.e,
     something that can be considered a process id in its own right for
     certain purposes.  */
Index: ser-base.c
===================================================================
RCS file: /cvs/src/src/gdb/ser-base.c,v
retrieving revision 1.2
diff -c -5 -p -r1.2 ser-base.c
*** ser-base.c	25 Mar 2005 20:06:36 -0000	1.2
--- ser-base.c	26 Mar 2005 01:00:29 -0000
***************
*** 22,31 ****
--- 22,34 ----
  
  #include "defs.h"
  #include "serial.h"
  #include "ser-unix.h"
  #include "event-loop.h"
+ #ifdef WINAPI
+ #include <winsock2.h>
+ #endif
  
  static timer_handler_func push_event;
  static handler_func fd_event;
  
  /* Event handling for ASYNC serial code.
*************** fd_event (int error, void *context)
*** 134,148 ****
      {
        /* Prime the input FIFO.  The readchar() function is used to
           pull characters out of the buffer.  See also
           generic_readchar(). */
        int nr;
!       do
! 	{
! 	  nr = read (scb->fd, scb->buf, BUFSIZ);
! 	}
!       while (nr == -1 && errno == EINTR);
        if (nr == 0)
  	{
  	  scb->bufcnt = SERIAL_EOF;
  	}
        else if (nr > 0)
--- 137,147 ----
      {
        /* Prime the input FIFO.  The readchar() function is used to
           pull characters out of the buffer.  See also
           generic_readchar(). */
        int nr;
!       nr = scb->ops->read_prim (scb, BUFSIZ);
        if (nr == 0)
  	{
  	  scb->bufcnt = SERIAL_EOF;
  	}
        else if (nr > 0)
*************** push_event (void *context)
*** 172,181 ****
--- 171,359 ----
    scb->async_handler (scb, scb->async_context);
    /* re-schedule */
    reschedule (scb);
  }
  
+ /* Wait for input on scb, with timeout seconds.  Returns 0 on success,
+    otherwise SERIAL_TIMEOUT or SERIAL_ERROR. */
+ 
+ static int
+ ser_base_wait_for (struct serial *scb, int timeout)
+ {
+   while (1)
+     {
+       int numfds;
+       struct timeval tv;
+       fd_set readfds, exceptfds;
+ 
+       /* NOTE: Some OS's can scramble the READFDS when the select()
+          call fails (ex the kernel with Red Hat 5.2).  Initialize all
+          arguments before each call. */
+ 
+       tv.tv_sec = timeout;
+       tv.tv_usec = 0;
+ 
+       FD_ZERO (&readfds);
+       FD_ZERO (&exceptfds);
+       FD_SET (scb->fd, &readfds);
+       FD_SET (scb->fd, &exceptfds);
+ 
+       if (timeout >= 0)
+ 	numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
+       else
+ 	numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0);
+ 
+       if (numfds <= 0)
+ 	{
+ 	  if (numfds == 0)
+ 	    return SERIAL_TIMEOUT;
+ 	  else if (errno == EINTR)
+ 	    continue;
+ 	  else
+ 	    return SERIAL_ERROR;	/* Got an error from select or poll */
+ 	}
+ 
+       return 0;
+     }
+ }
+ 
+ /* Read a character with user-specified timeout.  TIMEOUT is number of seconds
+    to wait, or -1 to wait forever.  Use timeout of 0 to effect a poll.  Returns
+    char if successful.  Returns -2 if timeout expired, EOF if line dropped
+    dead, or -3 for any other error (see errno in that case). */
+ 
+ static int
+ do_ser_base_readchar (struct serial *scb, int timeout)
+ {
+   int status;
+   int delta;
+ 
+   /* We have to be able to keep the GUI alive here, so we break the
+      original timeout into steps of 1 second, running the "keep the
+      GUI alive" hook each time through the loop.
+ 
+      Also, timeout = 0 means to poll, so we just set the delta to 0,
+      so we will only go through the loop once.  */
+ 
+   delta = (timeout == 0 ? 0 : 1);
+   while (1)
+     {
+ 
+       /* N.B. The UI may destroy our world (for instance by calling
+          remote_stop,) in which case we want to get out of here as
+          quickly as possible.  It is not safe to touch scb, since
+          someone else might have freed it.  The
+          deprecated_ui_loop_hook signals that we should exit by
+          returning 1.  */
+ 
+       if (deprecated_ui_loop_hook)
+ 	{
+ 	  if (deprecated_ui_loop_hook (0))
+ 	    return SERIAL_TIMEOUT;
+ 	}
+ 
+       status = ser_base_wait_for (scb, delta);
+       if (timeout > 0)
+         timeout -= delta;
+ 
+       /* If we got a character or an error back from wait_for, then we can 
+          break from the loop before the timeout is completed. */
+ 
+       if (status != SERIAL_TIMEOUT)
+ 	{
+ 	  break;
+ 	}
+ 
+       /* If we have exhausted the original timeout, then generate
+          a SERIAL_TIMEOUT, and pass it out of the loop. */
+ 
+       else if (timeout == 0)
+ 	{
+ 	  status = SERIAL_TIMEOUT;
+ 	  break;
+ 	}
+     }
+ 
+   if (status < 0)
+     return status;
+ 
+   status = scb->ops->read_prim (scb, BUFSIZ);
+ 
+   if (status <= 0)
+     {
+       if (status == 0)
+ 	return SERIAL_TIMEOUT;	/* 0 chars means timeout [may need to
+ 				   distinguish between EOF & timeouts
+ 				   someday] */
+       else
+ 	return SERIAL_ERROR;	/* Got an error from read */
+     }
+ 
+   scb->bufcnt = status;
+   scb->bufcnt--;
+   scb->bufp = scb->buf;
+   return *scb->bufp++;
+ }
+ 
+ /* Perform operations common to both old and new readchar. */
+ 
+ /* Return the next character from the input FIFO.  If the FIFO is
+    empty, call the SERIAL specific routine to try and read in more
+    characters.
+ 
+    Initially data from the input FIFO is returned (fd_event()
+    pre-reads the input into that FIFO.  Once that has been emptied,
+    further data is obtained by polling the input FD using the device
+    specific readchar() function.  Note: reschedule() is called after
+    every read.  This is because there is no guarentee that the lower
+    level fd_event() poll_event() code (which also calls reschedule())
+    will be called. */
+ 
+ int
+ generic_readchar (struct serial *scb, int timeout,
+ 		  int (do_readchar) (struct serial *scb, int timeout))
+ {
+   int ch;
+   if (scb->bufcnt > 0)
+     {
+       ch = *scb->bufp;
+       scb->bufcnt--;
+       scb->bufp++;
+     }
+   else if (scb->bufcnt < 0)
+     {
+       /* Some errors/eof are are sticky. */
+       ch = scb->bufcnt;
+     }
+   else
+     {
+       ch = do_readchar (scb, timeout);
+       if (ch < 0)
+ 	{
+ 	  switch ((enum serial_rc) ch)
+ 	    {
+ 	    case SERIAL_EOF:
+ 	    case SERIAL_ERROR:
+ 	      /* Make the error/eof stick. */
+ 	      scb->bufcnt = ch;
+ 	      break;
+ 	    case SERIAL_TIMEOUT:
+ 	      scb->bufcnt = 0;
+ 	      break;
+ 	    }
+ 	}
+     }
+   reschedule (scb);
+   return ch;
+ }
+ 
+ int
+ ser_base_readchar (struct serial *scb, int timeout)
+ {
+   return generic_readchar (scb, timeout, do_ser_base_readchar);
+ }
+ 
  int
  ser_base_write (struct serial *scb, const char *str, int len)
  {
    int cc;
  
Index: ser-base.h
===================================================================
RCS file: /cvs/src/src/gdb/ser-base.h,v
retrieving revision 1.2
diff -c -5 -p -r1.2 ser-base.h
*** ser-base.h	25 Mar 2005 20:06:36 -0000	1.2
--- ser-base.h	26 Mar 2005 01:00:29 -0000
***************
*** 23,32 ****
--- 23,35 ----
  #define SER_BASE_H
  
  struct serial;
  struct ui_file;
  
+ extern int generic_readchar (struct serial *scb, int timeout,
+ 			     int (*do_readchar) (struct serial *scb,
+ 						 int timeout));
  extern void reschedule (struct serial *scb);
  extern int ser_base_flush_output (struct serial *scb);
  extern int ser_base_flush_input (struct serial *scb);
  extern int ser_base_send_break (struct serial *scb);
  extern void ser_base_raw (struct serial *scb);
*************** extern int ser_base_setstopbits (struct 
*** 44,50 ****
--- 47,54 ----
  extern int ser_base_drain_output (struct serial *scb);
  
  extern int ser_base_write (struct serial *scb, const char *str, int len);
  
  extern void ser_base_async (struct serial *scb, int async_p);
+ extern int ser_base_readchar (struct serial *scb, int timeout);
  
  #endif
Index: ser-pipe.c
===================================================================
RCS file: /cvs/src/src/gdb/ser-pipe.c,v
retrieving revision 1.15
diff -c -5 -p -r1.15 ser-pipe.c
*** ser-pipe.c	25 Mar 2005 20:06:36 -0000	1.15
--- ser-pipe.c	26 Mar 2005 01:00:29 -0000
*************** _initialize_ser_pipe (void)
*** 142,152 ****
    memset (ops, 0, sizeof (struct serial_ops));
    ops->name = "pipe";
    ops->next = 0;
    ops->open = pipe_open;
    ops->close = pipe_close;
!   ops->readchar = ser_unix_readchar;
    ops->write = ser_base_write;
    ops->flush_output = ser_base_flush_output;
    ops->flush_input = ser_base_flush_input;
    ops->send_break = ser_base_send_break;
    ops->go_raw = ser_base_raw;
--- 142,152 ----
    memset (ops, 0, sizeof (struct serial_ops));
    ops->name = "pipe";
    ops->next = 0;
    ops->open = pipe_open;
    ops->close = pipe_close;
!   ops->readchar = ser_base_readchar;
    ops->write = ser_base_write;
    ops->flush_output = ser_base_flush_output;
    ops->flush_input = ser_base_flush_input;
    ops->send_break = ser_base_send_break;
    ops->go_raw = ser_base_raw;
*************** _initialize_ser_pipe (void)
*** 156,162 ****
--- 156,163 ----
    ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
    ops->setbaudrate = ser_base_setbaudrate;
    ops->setstopbits = ser_base_setstopbits;
    ops->drain_output = ser_base_drain_output;
    ops->async = ser_base_async;
+   ops->read_prim = ser_unix_read_prim;
    serial_add_interface (ops);
  }
Index: ser-tcp.c
===================================================================
RCS file: /cvs/src/src/gdb/ser-tcp.c,v
retrieving revision 1.20
diff -c -5 -p -r1.20 ser-tcp.c
*** ser-tcp.c	25 Mar 2005 20:06:36 -0000	1.20
--- ser-tcp.c	26 Mar 2005 01:00:29 -0000
***************
*** 32,46 ****
--- 32,54 ----
  #ifdef HAVE_SYS_IOCTL_H
  #include <sys/ioctl.h>  /* For FIONBIO. */
  #endif
  
  #include <sys/time.h>
+ 
+ #ifdef WINAPI
+ #include <winsock2.h>
+ #define ETIMEDOUT WSAETIMEDOUT
+ #else
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <netdb.h>
  #include <sys/socket.h>
  #include <netinet/tcp.h>
+ #define closesocket close
+ #define ioctlsocket ioctl 
+ #endif
  
  #include <signal.h>
  #include "gdb_string.h"
  
  static int net_open (struct serial *scb, const char *name);
*************** net_open (struct serial *scb, const char
*** 60,69 ****
--- 68,82 ----
    char *port_str, hostname[100];
    int n, port, tmp;
    int use_udp;
    struct hostent *hostent;
    struct sockaddr_in sockaddr;
+ #ifdef WINAPI
+   u_long ioarg;
+ #else
+   int ioarg;
+ #endif
  
    use_udp = 0;
    if (strncmp (name, "udp:", 4) == 0)
      {
        use_udp = 1;
*************** net_open (struct serial *scb, const char
*** 106,123 ****
    sockaddr.sin_port = htons (port);
    memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
  	  sizeof (struct in_addr));
  
    /* set socket nonblocking */
!   tmp = 1;
!   ioctl (scb->fd, FIONBIO, &tmp);
  
    /* Use Non-blocking connect.  connect() will return 0 if connected already. */
    n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
  
!   if (n < 0 && errno != EINPROGRESS)
      {
        net_close (scb);
        return -1;
      }
  
    if (n)
--- 119,147 ----
    sockaddr.sin_port = htons (port);
    memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
  	  sizeof (struct in_addr));
  
    /* set socket nonblocking */
!   ioarg = 1;
!   ioctlsocket (scb->fd, FIONBIO, &ioarg);
  
    /* Use Non-blocking connect.  connect() will return 0 if connected already. */
    n = connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
  
!   if (n < 0
! #ifdef WINAPI
!       /* Under Windows, calling "connect" with a non-blocking socket
! 	 results in WSAEWOULDBLOCK, not WSAEINPROGRESS.  */
!       && WSAGetLastError() != WSAEWOULDBLOCK
! #else
!       && errno != EINPROGRESS
! #endif
!       )
      {
+ #ifdef WINAPI
+       errno = WSAGetLastError();
+ #endif
        net_close (scb);
        return -1;
      }
  
    if (n)
*************** net_open (struct serial *scb, const char
*** 163,185 ****
  
    /* Got something.  Is it an error? */
    {
      int res, err, len;
      len = sizeof(err);
!     res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, &err, &len);
      if (res < 0 || err)
        {
  	if (err)
  	  errno = err;
  	net_close (scb);
  	return -1;
        }
    } 
  
    /* turn off nonblocking */
!   tmp = 0;
!   ioctl (scb->fd, FIONBIO, &tmp);
  
    if (use_udp == 0)
      {
        /* Disable Nagle algorithm. Needed in some cases. */
        tmp = 1;
--- 187,213 ----
  
    /* Got something.  Is it an error? */
    {
      int res, err, len;
      len = sizeof(err);
!     /* On Windows, the fourth parameter to getsockopt is a "char *";
!        on UNIX systems it is generally "void *".  The cast to "void *"
!        is OK everywhere, since in C "void *" can be implicitly
!        converted to any pointer type.  */
!     res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len);
      if (res < 0 || err)
        {
  	if (err)
  	  errno = err;
  	net_close (scb);
  	return -1;
        }
    } 
  
    /* turn off nonblocking */
!   ioarg = 0;
!   ioctlsocket (scb->fd, FIONBIO, &ioarg);
  
    if (use_udp == 0)
      {
        /* Disable Nagle algorithm. Needed in some cases. */
        tmp = 1;
*************** static void
*** 200,224 ****
  net_close (struct serial *scb)
  {
    if (scb->fd < 0)
      return;
  
!   close (scb->fd);
    scb->fd = -1;
  }
  
  void
  _initialize_ser_tcp (void)
  {
!   struct serial_ops *ops = XMALLOC (struct serial_ops);
    memset (ops, 0, sizeof (struct serial_ops));
    ops->name = "tcp";
    ops->next = 0;
    ops->open = net_open;
    ops->close = net_close;
!   ops->readchar = ser_unix_readchar;
!   ops->write = ser_base_write;
    ops->flush_output = ser_base_flush_output;
    ops->flush_input = ser_base_flush_input;
    ops->send_break = ser_base_send_break;
    ops->go_raw = ser_base_raw;
    ops->get_tty_state = ser_base_get_tty_state;
--- 228,293 ----
  net_close (struct serial *scb)
  {
    if (scb->fd < 0)
      return;
  
!   closesocket (scb->fd);
    scb->fd = -1;
  }
  
+ static int
+ net_read_prim (struct serial *scb, size_t count)
+ {
+ #ifdef WINAPI
+   /* Under Windows, we must use "recv" to read data from sockets.  */
+   return recv (scb->fd, scb->buf, count, 0);
+ #else
+   return ser_unix_read_prim (scb, count);
+ #endif
+ }
+ 
+ static int
+ net_write (struct serial *scb, const char *str, int len)
+ {
+ #ifdef WINAPI
+   /* Under Windows, we must use "send" to send data to and from
+      sockets.  */
+   int cc;
+ 
+   while (len > 0)
+     {
+       cc = send (scb->fd, str, len, 0);
+ 
+       if (cc < 0)
+ 	return 1;
+       len -= cc;
+       str += cc;
+     }
+   return 0;
+ #else
+   return ser_base_write (scb, str, len);
+ #endif
+ }
+ 
  void
  _initialize_ser_tcp (void)
  {
!   struct serial_ops *ops;
! #ifdef WINAPI
!   WSADATA wsa_data;
!   if (WSAStartup (MAKEWORD (1, 0), &wsa_data) != 0)
!     /* WinSock is unavailable.  */
!     return;
! #endif
!   ops = XMALLOC (struct serial_ops);
    memset (ops, 0, sizeof (struct serial_ops));
    ops->name = "tcp";
    ops->next = 0;
    ops->open = net_open;
    ops->close = net_close;
!   ops->readchar = ser_base_readchar;
!   ops->write = net_write;
    ops->flush_output = ser_base_flush_output;
    ops->flush_input = ser_base_flush_input;
    ops->send_break = ser_base_send_break;
    ops->go_raw = ser_base_raw;
    ops->get_tty_state = ser_base_get_tty_state;
*************** _initialize_ser_tcp (void)
*** 227,233 ****
--- 296,303 ----
    ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
    ops->setbaudrate = ser_base_setbaudrate;
    ops->setstopbits = ser_base_setstopbits;
    ops->drain_output = ser_base_drain_output;
    ops->async = ser_base_async;
+   ops->read_prim = net_read_prim;
    serial_add_interface (ops);
  }
Index: ser-unix.c
===================================================================
RCS file: /cvs/src/src/gdb/ser-unix.c,v
retrieving revision 1.24
diff -c -5 -p -r1.24 ser-unix.c
*** ser-unix.c	25 Mar 2005 20:06:36 -0000	1.24
--- ser-unix.c	26 Mar 2005 01:00:30 -0000
*************** struct hardwire_ttystate
*** 68,80 ****
  static int hardwire_open (struct serial *scb, const char *name);
  static void hardwire_raw (struct serial *scb);
  static int wait_for (struct serial *scb, int timeout);
  static int hardwire_readchar (struct serial *scb, int timeout);
  static int do_hardwire_readchar (struct serial *scb, int timeout);
- static int generic_readchar (struct serial *scb, int timeout,
- 			     int (*do_readchar) (struct serial *scb,
- 						 int timeout));
  static int rate_to_code (int rate);
  static int hardwire_setbaudrate (struct serial *scb, int rate);
  static void hardwire_close (struct serial *scb);
  static int get_tty_state (struct serial *scb,
  			  struct hardwire_ttystate * state);
--- 68,77 ----
*************** hardwire_raw (struct serial *scb)
*** 420,430 ****
     For termio{s}, we actually just setup VTIME if necessary, and let the
     timeout occur in the read() in hardwire_read().
   */
  
  /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent
!    ser_unix*() until the old TERMIOS/SGTTY/... timer code has been
     flushed. . */
  
  /* NOTE: cagney/1999-09-30: Much of the code below is dead.  The only
     possible values of the TIMEOUT parameter are ONE and ZERO.
     Consequently all the code that tries to handle the possability of
--- 417,427 ----
     For termio{s}, we actually just setup VTIME if necessary, and let the
     timeout occur in the read() in hardwire_read().
   */
  
  /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent
!    ser_base*() until the old TERMIOS/SGTTY/... timer code has been
     flushed. . */
  
  /* NOTE: cagney/1999-09-30: Much of the code below is dead.  The only
     possible values of the TIMEOUT parameter are ONE and ZERO.
     Consequently all the code that tries to handle the possability of
*************** wait_for (struct serial *scb, int timeou
*** 540,556 ****
     to wait, or -1 to wait forever.  Use timeout of 0 to effect a poll.  Returns
     char if successful.  Returns SERIAL_TIMEOUT if timeout expired, EOF if line
     dropped dead, or SERIAL_ERROR for any other error (see errno in that case).  */
  
  /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent
!    ser_unix*() until the old TERMIOS/SGTTY/... timer code has been
     flushed. */
  
  /* NOTE: cagney/1999-09-16: This function is not identical to
!    ser_unix_readchar() as part of replacing it with ser_unix*()
     merging will be required - this code handles the case where read()
!    times out due to no data while ser_unix_readchar() doesn't expect
     that. */
  
  static int
  do_hardwire_readchar (struct serial *scb, int timeout)
  {
--- 537,553 ----
     to wait, or -1 to wait forever.  Use timeout of 0 to effect a poll.  Returns
     char if successful.  Returns SERIAL_TIMEOUT if timeout expired, EOF if line
     dropped dead, or SERIAL_ERROR for any other error (see errno in that case).  */
  
  /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent
!    ser_base*() until the old TERMIOS/SGTTY/... timer code has been
     flushed. */
  
  /* NOTE: cagney/1999-09-16: This function is not identical to
!    ser_base_readchar() as part of replacing it with ser_base*()
     merging will be required - this code handles the case where read()
!    times out due to no data while ser_base_readchar() doesn't expect
     that. */
  
  static int
  do_hardwire_readchar (struct serial *scb, int timeout)
  {
*************** hardwire_close (struct serial *scb)
*** 861,1066 ****
      return;
  
    close (scb->fd);
    scb->fd = -1;
  }
- 
  \f
- /* Wait for input on scb, with timeout seconds.  Returns 0 on success,
-    otherwise SERIAL_TIMEOUT or SERIAL_ERROR. */
- 
- static int
- ser_unix_wait_for (struct serial *scb, int timeout)
- {
-   while (1)
-     {
-       int numfds;
-       struct timeval tv;
-       fd_set readfds, exceptfds;
- 
-       /* NOTE: Some OS's can scramble the READFDS when the select()
-          call fails (ex the kernel with Red Hat 5.2).  Initialize all
-          arguments before each call. */
- 
-       tv.tv_sec = timeout;
-       tv.tv_usec = 0;
- 
-       FD_ZERO (&readfds);
-       FD_ZERO (&exceptfds);
-       FD_SET (scb->fd, &readfds);
-       FD_SET (scb->fd, &exceptfds);
- 
-       if (timeout >= 0)
- 	numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
-       else
- 	numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0);
- 
-       if (numfds <= 0)
- 	{
- 	  if (numfds == 0)
- 	    return SERIAL_TIMEOUT;
- 	  else if (errno == EINTR)
- 	    continue;
- 	  else
- 	    return SERIAL_ERROR;	/* Got an error from select or poll */
- 	}
- 
-       return 0;
-     }
- }
- 
- /* Read a character with user-specified timeout.  TIMEOUT is number of seconds
-    to wait, or -1 to wait forever.  Use timeout of 0 to effect a poll.  Returns
-    char if successful.  Returns -2 if timeout expired, EOF if line dropped
-    dead, or -3 for any other error (see errno in that case). */
- 
- static int
- do_unix_readchar (struct serial *scb, int timeout)
- {
-   int status;
-   int delta;
- 
-   /* We have to be able to keep the GUI alive here, so we break the
-      original timeout into steps of 1 second, running the "keep the
-      GUI alive" hook each time through the loop.
- 
-      Also, timeout = 0 means to poll, so we just set the delta to 0,
-      so we will only go through the loop once.  */
- 
-   delta = (timeout == 0 ? 0 : 1);
-   while (1)
-     {
- 
-       /* N.B. The UI may destroy our world (for instance by calling
-          remote_stop,) in which case we want to get out of here as
-          quickly as possible.  It is not safe to touch scb, since
-          someone else might have freed it.  The
-          deprecated_ui_loop_hook signals that we should exit by
-          returning 1.  */
- 
-       if (deprecated_ui_loop_hook)
- 	{
- 	  if (deprecated_ui_loop_hook (0))
- 	    return SERIAL_TIMEOUT;
- 	}
- 
-       status = ser_unix_wait_for (scb, delta);
-       if (timeout > 0)
-         timeout -= delta;
- 
-       /* If we got a character or an error back from wait_for, then we can 
-          break from the loop before the timeout is completed. */
- 
-       if (status != SERIAL_TIMEOUT)
- 	{
- 	  break;
- 	}
- 
-       /* If we have exhausted the original timeout, then generate
-          a SERIAL_TIMEOUT, and pass it out of the loop. */
- 
-       else if (timeout == 0)
- 	{
- 	  status = SERIAL_TIMEOUT;
- 	  break;
- 	}
-     }
- 
-   if (status < 0)
-     return status;
- 
-   while (1)
-     {
-       status = read (scb->fd, scb->buf, BUFSIZ);
-       if (status != -1 || errno != EINTR)
- 	break;
-     }
- 
-   if (status <= 0)
-     {
-       if (status == 0)
- 	return SERIAL_TIMEOUT;	/* 0 chars means timeout [may need to
- 				   distinguish between EOF & timeouts
- 				   someday] */
-       else
- 	return SERIAL_ERROR;	/* Got an error from read */
-     }
- 
-   scb->bufcnt = status;
-   scb->bufcnt--;
-   scb->bufp = scb->buf;
-   return *scb->bufp++;
- }
- 
- /* Perform operations common to both old and new readchar. */
- 
- /* Return the next character from the input FIFO.  If the FIFO is
-    empty, call the SERIAL specific routine to try and read in more
-    characters.
- 
-    Initially data from the input FIFO is returned (fd_event()
-    pre-reads the input into that FIFO.  Once that has been emptied,
-    further data is obtained by polling the input FD using the device
-    specific readchar() function.  Note: reschedule() is called after
-    every read.  This is because there is no guarentee that the lower
-    level fd_event() poll_event() code (which also calls reschedule())
-    will be called. */
- 
- static int
- generic_readchar (struct serial *scb, int timeout,
- 		  int (do_readchar) (struct serial *scb, int timeout))
- {
-   int ch;
-   if (scb->bufcnt > 0)
-     {
-       ch = *scb->bufp;
-       scb->bufcnt--;
-       scb->bufp++;
-     }
-   else if (scb->bufcnt < 0)
-     {
-       /* Some errors/eof are are sticky. */
-       ch = scb->bufcnt;
-     }
-   else
-     {
-       ch = do_readchar (scb, timeout);
-       if (ch < 0)
- 	{
- 	  switch ((enum serial_rc) ch)
- 	    {
- 	    case SERIAL_EOF:
- 	    case SERIAL_ERROR:
- 	      /* Make the error/eof stick. */
- 	      scb->bufcnt = ch;
- 	      break;
- 	    case SERIAL_TIMEOUT:
- 	      scb->bufcnt = 0;
- 	      break;
- 	    }
- 	}
-     }
-   reschedule (scb);
-   return ch;
- }
- 
- int
- ser_unix_readchar (struct serial *scb, int timeout)
- {
-   return generic_readchar (scb, timeout, do_unix_readchar);
- }
  \f
  void
  _initialize_ser_hardwire (void)
  {
    struct serial_ops *ops = XMALLOC (struct serial_ops);
    memset (ops, 0, sizeof (struct serial_ops));
    ops->name = "hardwire";
    ops->next = 0;
    ops->open = hardwire_open;
    ops->close = hardwire_close;
!   /* FIXME: Don't replace this with the equivalent ser_unix*() until
       the old TERMIOS/SGTTY/... timer code has been flushed. cagney
       1999-09-16. */
    ops->readchar = hardwire_readchar;
    ops->write = ser_base_write;
    ops->flush_output = hardwire_flush_output;
--- 858,879 ----
      return;
  
    close (scb->fd);
    scb->fd = -1;
  }
  \f
  \f
  void
  _initialize_ser_hardwire (void)
  {
    struct serial_ops *ops = XMALLOC (struct serial_ops);
    memset (ops, 0, sizeof (struct serial_ops));
    ops->name = "hardwire";
    ops->next = 0;
    ops->open = hardwire_open;
    ops->close = hardwire_close;
!   /* FIXME: Don't replace this with the equivalent ser_base*() until
       the old TERMIOS/SGTTY/... timer code has been flushed. cagney
       1999-09-16. */
    ops->readchar = hardwire_readchar;
    ops->write = ser_base_write;
    ops->flush_output = hardwire_flush_output;
*************** _initialize_ser_hardwire (void)
*** 1073,1079 ****
--- 886,907 ----
    ops->noflush_set_tty_state = hardwire_noflush_set_tty_state;
    ops->setbaudrate = hardwire_setbaudrate;
    ops->setstopbits = hardwire_setstopbits;
    ops->drain_output = hardwire_drain_output;
    ops->async = ser_base_async;
+   ops->read_prim = ser_unix_read_prim;
    serial_add_interface (ops);
  }
+ 
+ int
+ ser_unix_read_prim (struct serial *scb, size_t count)
+ {
+   int status;
+ 
+   while (1)
+     {
+       status = read (scb->fd, scb->buf, count);
+       if (status != -1 || errno != EINTR)
+ 	break;
+     }
+   return status;
+ }
Index: ser-unix.h
===================================================================
RCS file: /cvs/src/src/gdb/ser-unix.h,v
retrieving revision 1.5
diff -c -5 -p -r1.5 ser-unix.h
*** ser-unix.h	25 Mar 2005 19:47:23 -0000	1.5
--- ser-unix.h	26 Mar 2005 01:00:30 -0000
***************
*** 20,27 ****
     Boston, MA 02111-1307, USA.  */
  
  #ifndef SER_UNIX_H
  #define SER_UNIX_H
  
! extern int ser_unix_readchar (struct serial *scb, int timeout);
  
  #endif
--- 20,27 ----
     Boston, MA 02111-1307, USA.  */
  
  #ifndef SER_UNIX_H
  #define SER_UNIX_H
  
! extern int ser_unix_read_prim (struct serial *scb, size_t count);
  
  #endif
Index: serial.h
===================================================================
RCS file: /cvs/src/src/gdb/serial.h,v
retrieving revision 1.10
diff -c -5 -p -r1.10 serial.h
*** serial.h	14 Jan 2005 01:59:20 -0000	1.10
--- serial.h	26 Mar 2005 01:00:30 -0000
*************** struct serial_ops
*** 230,239 ****
--- 230,242 ----
      int (*drain_output) (struct serial *);
      /* Change the serial device into/out of asynchronous mode, call
         the specified function when ever there is something
         interesting.  */
      void (*async) (struct serial *scb, int async_p);
+     /* Perform a low-level read operation, reading (at most) COUNT
+        bytes into SCB->BUF.  */
+     int (*read_prim)(struct serial *scb, size_t count);
    };
  
  /* Add a new serial interface to the interface list */
  
  extern void serial_add_interface (struct serial_ops * optable);
Index: utils.c
===================================================================
RCS file: /cvs/src/src/gdb/utils.c,v
retrieving revision 1.160
diff -c -5 -p -r1.160 utils.c
*** utils.c	18 Mar 2005 20:46:38 -0000	1.160
--- utils.c	26 Mar 2005 01:00:30 -0000
***************
*** 56,65 ****
--- 56,69 ----
  
  #include "inferior.h"		/* for signed_pointer_to_address */
  
  #include <sys/param.h>		/* For MAXPATHLEN */
  
+ #ifdef WINAPI
+ #include <winerror.h>
+ #endif
+ 
  #include "gdb_curses.h"
  
  #include "readline/readline.h"
  
  #if !HAVE_DECL_MALLOC
*************** internal_warning (const char *file, int 
*** 844,861 ****
  
  char *
  safe_strerror (int errnum)
  {
    char *msg;
  
!   msg = strerror (errnum);
!   if (msg == NULL)
      {
!       static char buf[32];
!       xsnprintf (buf, sizeof buf, "(undocumented errno %d)", errnum);
        msg = buf;
      }
    return (msg);
  }
  
  /* Print the system error message for errno, and also mention STRING
     as the file name for which the error was encountered.
--- 848,879 ----
  
  char *
  safe_strerror (int errnum)
  {
    char *msg;
+   static char buf[32];
  
! #ifdef WINAPI
!   /* The strerror function only works for functions that set errno.
!      In the case of Windows sockets, we can get error numbers that
!      strerror cannot handle.  */
!   if (errnum > WSABASEERR)
      {
!       xsnprintf (buf, sizeof buf, "(winsock error %d)", errnum);
        msg = buf;
      }
+   else
+ #endif
+     {
+       msg = strerror (errnum);
+     
+       if (msg == NULL)
+ 	{
+ 	  xsnprintf (buf, sizeof buf, "(undocumented errno %d)", errnum);
+ 	  msg = buf;
+ 	}
+     }
    return (msg);
  }
  
  /* Print the system error message for errno, and also mention STRING
     as the file name for which the error was encountered.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: Windows sockets
  2005-03-26  1:27 PATCH: Windows sockets Mark Mitchell
@ 2005-03-26  2:09 ` Christopher Faylor
  2005-03-26  8:47 ` Mark Kettenis
  1 sibling, 0 replies; 9+ messages in thread
From: Christopher Faylor @ 2005-03-26  2:09 UTC (permalink / raw)
  To: Mark Mitchell, gdb-patches

On Fri, Mar 25, 2005 at 05:27:05PM -0800, Mark Mitchell wrote:
>Here's the first "interesting" patch for Windows support.  This patch
>modifies ser-tcp.c to support Windows, so that we can use a GDB
>running on Windows to talk to a gdbserver process.  
>
>Here is a sumary of the changes in this patch:
>
>1. Link with -lws2_32 on MinGW so we can use sockets.
>
>2. In defs.h, define WINAPI so that source files know whether they are
>   supposed to use the Windows API.
>
>3. Move ser_unix_readchar and friends (which were only barely
>   UNIX-specific) into ser-base.c, renaming appropriately.
>
>4. Add a new member (read_prim) to struct serial_ops, and use it from
>   ser_base_readchar.  The reason for this is that sockets must be
>   read with "recv" on Windows; plain "read" does not work.  So, we
>   need a way to indicate which low-level primitive to use to read
>   from a file descriptor.
>
>5. Make a handful of minor changes to ter-tcp.c to account for
>   differences in the BSD and Windows sockets APIs.
>
>6. Tweak safe_strerror to deal with Windows sockets error codes.
>
>Tested on x86_64-unknown-linux-gnu, to make sure I didn't break UNIX,
>and cursorily on Windows (with other patches, not yet submitted).
>
>OK to apply?

The windows-specific configury parts look ok to me.  That's all I
can approve, although the other bits look right too.

cgf


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: Windows sockets
  2005-03-26  1:27 PATCH: Windows sockets Mark Mitchell
  2005-03-26  2:09 ` Christopher Faylor
@ 2005-03-26  8:47 ` Mark Kettenis
  2005-03-26 17:38   ` Mark Mitchell
  1 sibling, 1 reply; 9+ messages in thread
From: Mark Kettenis @ 2005-03-26  8:47 UTC (permalink / raw)
  To: mark; +Cc: gdb-patches

   Date: Fri, 25 Mar 2005 17:27:05 -0800
   From: Mark Mitchell <mark@codesourcery.com>

   Here's the first "interesting" patch for Windows support.  This patch
   modifies ser-tcp.c to support Windows, so that we can use a GDB
   running on Windows to talk to a gdbserver process.

Yikes.  This is real ugly and I'm not too happy about this.

   Here is a sumary of the changes in this patch:

   1. Link with -lws2_32 on MinGW so we can use sockets.

Can't you just use a standard autoconf check to check for that library
instead of hardcoding it to be linked in on MinGW?

   2. In defs.h, define WINAPI so that source files know whether they are
      supposed to use the Windows API.

This is bad.  Yet another #ifdef WINDHOOS when we really are trying to
get rid of those.

   3. Move ser_unix_readchar and friends (which were only barely
      UNIX-specific) into ser-base.c, renaming appropriately.

Fair enough.

   4. Add a new member (read_prim) to struct serial_ops, and use it from
      ser_base_readchar.  The reason for this is that sockets must be
      read with "recv" on Windows; plain "read" does not work.  So, we
      need a way to indicate which low-level primitive to use to read
      from a file descriptor.

But write(2) does work and you don't need to use send(2).  Oh you do
but things are not quite symmetric.  Could you fix that?  Isn't it a
better idea to change the #ifdef WINAPI in a #ifdef HAVE_RECV, add an
autoconf check for recv(2), and always prefer it over read(2) if
available for reading from a socket?

   5. Make a handful of minor changes to ter-tcp.c to account for
      differences in the BSD and Windows sockets APIs.

You mean that Windows doesn't have the proper BSD socket API even
though Microsoft stole^Wused the BSD TCP stack?

I really think these changes are too pervasive and that you really
need to create a ser-win32.c that has all the Windows-specific cruft
in it.

   6. Tweak safe_strerror to deal with Windows sockets error codes.

I'm defenitely not thrilled by this tweak.  You're only changing
"undocumented" into "winsock".  I presume it helps with debugging this
stuff, but is it really worth the clutter it adds?

Sorry,

Mark


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: Windows sockets
  2005-03-26  8:47 ` Mark Kettenis
@ 2005-03-26 17:38   ` Mark Mitchell
  2005-03-26 17:48     ` Christopher Faylor
  2005-03-27 12:59     ` Kai Henningsen
  0 siblings, 2 replies; 9+ messages in thread
From: Mark Mitchell @ 2005-03-26 17:38 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches


Thanks for the quick review.

>    Here is a sumary of the changes in this patch:
> 
>    1. Link with -lws2_32 on MinGW so we can use sockets.
> 
> Can't you just use a standard autoconf check to check for that library
> instead of hardcoding it to be linked in on MinGW?

I could do that -- but I didn't because there are Windows configurations 
that do not want to use Winsock.  For example, we don't want to link in 
this library on Cygwin; we just want to let the Cygwin DLL take care of 
things.

>    2. In defs.h, define WINAPI so that source files know whether they are
>       supposed to use the Windows API.
> 
> This is bad.  Yet another #ifdef WINDHOOS when we really are trying to
> get rid of those.

This is the same problem as above; I could autoconf things for Windows, 
but those autoconf tests would fire under Cygwin as well.

>    3. Move ser_unix_readchar and friends (which were only barely
>       UNIX-specific) into ser-base.c, renaming appropriately.
> 
> Fair enough.
> 
>    4. Add a new member (read_prim) to struct serial_ops, and use it from
>       ser_base_readchar.  The reason for this is that sockets must be
>       read with "recv" on Windows; plain "read" does not work.  So, we
>       need a way to indicate which low-level primitive to use to read
>       from a file descriptor.
> 
> But write(2) does work and you don't need to use send(2).  Oh you do
> but things are not quite symmetric.  Could you fix that?  

I'm not sure what you mean.  Do you mean that you would like to create 
write_prim, and use that from the high-level serial "write" function? 
Sure, I can do that.

 > Isn't it a
> better idea to change the #ifdef WINAPI in a #ifdef HAVE_RECV, add an
> autoconf check for recv(2), and always prefer it over read(2) if
> available for reading from a socket?

I was confused about that.  I thought that using recv would not work as 
well as read on UNIX, but I've done some extra research, and I think 
send/recv should work fine everywhere.  Please consider the change you 
suggest made.

>    5. Make a handful of minor changes to ter-tcp.c to account for
>       differences in the BSD and Windows sockets APIs.
> 
> You mean that Windows doesn't have the proper BSD socket API even
> though Microsoft stole^Wused the BSD TCP stack?

Yes, there are a few minor differences.

> I really think these changes are too pervasive and that you really
> need to create a ser-win32.c that has all the Windows-specific cruft
> in it.

I can do that.

However, after making the changes you suggest above, there will only be 
the following Windows-specific changes:

1. Macro definitions at top-of-file to unify the Windows/UNIX spellings 
of ETIMEDOUT, closesocket, and ioctlsocket.

2. The change top net_open to use a "u_long *" argument as the last 
argument to ioctl, rather than an "int *".  (We could avoid the #ifdef 
with a typedef at the top of the file, if that's better than the way I 
have it now.)

3. The change to net_open to use WSAGetLastError() instead of errno on 
Windows.

4. The change to _initialize_ser_tcp to initialize the sockets library.

To me, it seems a shame to duplicate the entire file (in particular, 
net_open, which is the meat of the file) on account of these 
differences.  That function is mostly platform independent, including 
parsing the host/port specification, setting up the socket, connecting 
the socket, interacting with the UI during the connection delay, etc.

Would you please tell me definitively that you want this copied to 
another file?  I'm perfectly willing to do it, but I want to make sure 
that it's really the right thing before I do.  Or, perhaps you mean that 
you want hooks inserted at all the right places, and overridden in 
ser-win32.c?  I can also do that, but I think it will make the code 
harder to read.  Please let me know.

>    6. Tweak safe_strerror to deal with Windows sockets error codes.
> 
> I'm defenitely not thrilled by this tweak.  You're only changing
> "undocumented" into "winsock".  I presume it helps with debugging this
> stuff, but is it really worth the clutter it adds?

I think so, yes.  Windows strerror never returns NULL.  For unknown 
values, it returns "Unknown error" with no indication of *which* unknown 
error.  These errors are presented to users, so, if for example, a 
socket cannot be connected because the user entered the wrong port, or 
gdbserver is not running, the user would only see "Unknown error".  I 
agree that, from a user-experience point of view, "winsock error 12345" 
is not all that helpful -- but at least there is *some* method for 
figuring out what went wrong.

Thanks,

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
(916) 791-8304


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: Windows sockets
  2005-03-26 17:38   ` Mark Mitchell
@ 2005-03-26 17:48     ` Christopher Faylor
  2005-03-26 19:06       ` Mark Mitchell
  2005-03-27 12:59     ` Kai Henningsen
  1 sibling, 1 reply; 9+ messages in thread
From: Christopher Faylor @ 2005-03-26 17:48 UTC (permalink / raw)
  To: Mark Mitchell, gdb-patches

On Sat, Mar 26, 2005 at 09:38:15AM -0800, Mark Mitchell wrote:
>Thanks for the quick review.
>
>>   Here is a sumary of the changes in this patch:
>>
>>   1. Link with -lws2_32 on MinGW so we can use sockets.
>>
>>Can't you just use a standard autoconf check to check for that library
>>instead of hardcoding it to be linked in on MinGW?
>
>I could do that -- but I didn't because there are Windows configurations 
>that do not want to use Winsock.  For example, we don't want to link in 
>this library on Cygwin; we just want to let the Cygwin DLL take care of 
>things.
>
>>   2. In defs.h, define WINAPI so that source files know whether they are
>>      supposed to use the Windows API.
>>
>>This is bad.  Yet another #ifdef WINDHOOS when we really are trying to
>>get rid of those.
>
>This is the same problem as above; I could autoconf things for Windows, 
>but those autoconf tests would fire under Cygwin as well.

I guess you could only check for the existence of ws2_32 when the host
is mingw, but that seems sort of redundant given that there is a
preprocessor test which precisely tells what needs to be done.  While
I'm normally a big fan of using conditionals like "HAVE_WINSOCK", it
doesn't seem like it makes the code any clearer to use these types of
conditionals in this case unless we really anticipate that there will
be another OS out there with some of the pecularities os Windows but
not all of them.

One observation is that maybe you could do something like:

#if defined (__WIN32__) && !defined (__CYGWIN__)
# define MINGW
#endif

and use #ifdef MINGW where appropriate.

cgf


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: Windows sockets
  2005-03-26 17:48     ` Christopher Faylor
@ 2005-03-26 19:06       ` Mark Mitchell
  2005-03-26 21:03         ` Christopher Faylor
  2005-03-26 22:00         ` Eli Zaretskii
  0 siblings, 2 replies; 9+ messages in thread
From: Mark Mitchell @ 2005-03-26 19:06 UTC (permalink / raw)
  To: Christopher Faylor; +Cc: gdb-patches

Christopher Faylor wrote:

> I guess you could only check for the existence of ws2_32 when the host
> is mingw, but that seems sort of redundant given that there is a
> preprocessor test which precisely tells what needs to be done.

Right.

> While
> I'm normally a big fan of using conditionals like "HAVE_WINSOCK", it
> doesn't seem like it makes the code any clearer to use these types of
> conditionals in this case unless we really anticipate that there will
> be another OS out there with some of the pecularities os Windows but
> not all of them.
> 
> One observation is that maybe you could do something like:
> 
> #if defined (__WIN32__) && !defined (__CYGWIN__)
> # define MINGW
> #endif
> 
> and use #ifdef MINGW where appropriate.

If people would prefer that to WINAPI, that's fine by me.

(I'm not quite sure what we would call an environment in which the 
compiler was Visual C, or some other non-GCC Windows compiler.  Would 
that still be MinGW?  If not, then MINGW might not be as good a name, 
which is why I went with WINAPI.  But, I'm not concerned about how to 
spell the conditional; whatever seems best to people is fine with me!)

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
(916) 791-8304


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: Windows sockets
  2005-03-26 19:06       ` Mark Mitchell
@ 2005-03-26 21:03         ` Christopher Faylor
  2005-03-26 22:00         ` Eli Zaretskii
  1 sibling, 0 replies; 9+ messages in thread
From: Christopher Faylor @ 2005-03-26 21:03 UTC (permalink / raw)
  To: Mark Mitchell, gdb-patches

On Sat, Mar 26, 2005 at 11:06:03AM -0800, Mark Mitchell wrote:
>Christopher Faylor wrote:
>>While I'm normally a big fan of using conditionals like "HAVE_WINSOCK",
>>it doesn't seem like it makes the code any clearer to use these types
>>of conditionals in this case unless we really anticipate that there
>>will be another OS out there with some of the pecularities os Windows
>>but not all of them.
>>
>>One observation is that maybe you could do something like:
>>
>>#if defined (__WIN32__) && !defined (__CYGWIN__) # define MINGW #endif
>>
>>and use #ifdef MINGW where appropriate.
>
>If people would prefer that to WINAPI, that's fine by me.
>
>(I'm not quite sure what we would call an environment in which the
>compiler was Visual C, or some other non-GCC Windows compiler.  Would
>that still be MinGW?  If not, then MINGW might not be as good a name,
>which is why I went with WINAPI.  But, I'm not concerned about how to
>spell the conditional; whatever seems best to people is fine with me!)

Huh.  I don't know.  I didn't even consider that gdb would build with
Visual C.

Actually, for the last four or five years, Cygwin's gcc hasn't defined
__WIN32__, so just using __WIN32__ would probably be sufficient.

Otherwise, I guess you're right, WINAPI makes the most sense.

cgf


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: Windows sockets
  2005-03-26 19:06       ` Mark Mitchell
  2005-03-26 21:03         ` Christopher Faylor
@ 2005-03-26 22:00         ` Eli Zaretskii
  1 sibling, 0 replies; 9+ messages in thread
From: Eli Zaretskii @ 2005-03-26 22:00 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: me, gdb-patches

> Date: Sat, 26 Mar 2005 11:06:03 -0800
> From: Mark Mitchell <mark@codesourcery.com>
> CC: gdb-patches@sources.redhat.com
> 
> (I'm not quite sure what we would call an environment in which the 
> compiler was Visual C, or some other non-GCC Windows compiler.  Would 
> that still be MinGW?

No.  MinGW is the development environment that uses native Windows
ports of GNU tools.  So using MSVC is out.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: Windows sockets
  2005-03-26 17:38   ` Mark Mitchell
  2005-03-26 17:48     ` Christopher Faylor
@ 2005-03-27 12:59     ` Kai Henningsen
  1 sibling, 0 replies; 9+ messages in thread
From: Kai Henningsen @ 2005-03-27 12:59 UTC (permalink / raw)
  To: gdb-patches

mark@codesourcery.com (Mark Mitchell)  wrote on 26.03.05 in <42459E07.9020201@codesourcery.com>:

> >    6. Tweak safe_strerror to deal with Windows sockets error codes.
> >
> > I'm defenitely not thrilled by this tweak.  You're only changing
> > "undocumented" into "winsock".  I presume it helps with debugging this
> > stuff, but is it really worth the clutter it adds?
>
> I think so, yes.  Windows strerror never returns NULL.  For unknown
> values, it returns "Unknown error" with no indication of *which* unknown
> error.  These errors are presented to users, so, if for example, a
> socket cannot be connected because the user entered the wrong port, or
> gdbserver is not running, the user would only see "Unknown error".  I
> agree that, from a user-experience point of view, "winsock error 12345"
> is not all that helpful -- but at least there is *some* method for
> figuring out what went wrong.

Well ...

There *is* support in Win32 for getting error message text for OS error  
numbers (which are completely different from errno numbers). There's a  
slight complication in that until lately, these didn't cover Winsock  
codes, but on modern Windows versions they do.

So it might make sense to try that.

See <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ 
debug/base/retrieving_the_last_error_code.asp> for example code.

MfG Kai


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2005-03-27 12:59 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-26  1:27 PATCH: Windows sockets Mark Mitchell
2005-03-26  2:09 ` Christopher Faylor
2005-03-26  8:47 ` Mark Kettenis
2005-03-26 17:38   ` Mark Mitchell
2005-03-26 17:48     ` Christopher Faylor
2005-03-26 19:06       ` Mark Mitchell
2005-03-26 21:03         ` Christopher Faylor
2005-03-26 22:00         ` Eli Zaretskii
2005-03-27 12:59     ` Kai Henningsen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox