* configure.ac: On MinGW, define USE_WIN32API and link with

-lws2_32.
	* ser-tcp.c (<winsock2.h>): Include, for Windows.
	(ETIMEDOUT): Define, for Windows.
	(ioctl): Likewise.
	(closesocket): Define, for POSIX.
	(net_open): Adjust for differences in socket functions between
	Windows and UNIX.
	(net_close): Likweise.
	(net_read_prim): New function.
	(net_write_prim): Likewise.
	(_initialize_ser_tcp): Initialize winsock.  Fill in read_prim and
	write_prim.
	* ser-unix.h (ser_unix_readcchar): Remove.
	(ser_unix_read_prim): Declare.
	(ser_unix_write_prim): Likewise.
	* ser-unix.c (generic_readchar): Move to ser-base.c.
	(ser_unix_wait_for): Likewise.
	(do_unix_readchar): Likewise.
	(ser_unix_readchar): Likewise.
	(_initialize_ser_hardwire): Initialize read_prim and write_prim.
	(ser_unix_read_prim): New function.
	(ser_unix_write_prim): Likewise.
	* ser-base.h (generic_readchar): Declare.
	(ser_base_readchar): Likewise.
	* ser-base.c (<winsock2.h>): Include, for windows.
	(fd_event): Use the read primitive specified by the serial
	interface.
	(ser_base_wait_for): Moved from ser-unix.c
	(do_ser_base_read_char): Likewise.
	(generic_readchar): Likewise.
	(ser_base_readchar): Likewise.
	(ser_base_write): Use the write primitive specified by the serial
	interface.
	* ser-pipe.c (_initialize_ser_pipe): Use ser_base_readchar, not
	ser_unix_readchar.  Initialize read_prim and write_prim.
	* serial.c (struct serial_ops): Add read_prim and write_prim.
	* configure: Regenerate.
This commit is contained in:
Mark Mitchell 2005-04-21 05:34:33 +00:00
parent 20b26460df
commit b450502905
10 changed files with 347 additions and 208 deletions

View file

@ -1,3 +1,44 @@
2005-04-20 Mark Mitchell <mark@codesourcery.com>
* configure.ac: On MinGW, define USE_WIN32API and link with
-lws2_32.
* ser-tcp.c (<winsock2.h>): Include, for Windows.
(ETIMEDOUT): Define, for Windows.
(ioctl): Likewise.
(closesocket): Define, for POSIX.
(net_open): Adjust for differences in socket functions between
Windows and UNIX.
(net_close): Likweise.
(net_read_prim): New function.
(net_write_prim): Likewise.
(_initialize_ser_tcp): Initialize winsock. Fill in read_prim and
write_prim.
* ser-unix.h (ser_unix_readcchar): Remove.
(ser_unix_read_prim): Declare.
(ser_unix_write_prim): Likewise.
* ser-unix.c (generic_readchar): Move to ser-base.c.
(ser_unix_wait_for): Likewise.
(do_unix_readchar): Likewise.
(ser_unix_readchar): Likewise.
(_initialize_ser_hardwire): Initialize read_prim and write_prim.
(ser_unix_read_prim): New function.
(ser_unix_write_prim): Likewise.
* ser-base.h (generic_readchar): Declare.
(ser_base_readchar): Likewise.
* ser-base.c (<winsock2.h>): Include, for windows.
(fd_event): Use the read primitive specified by the serial
interface.
(ser_base_wait_for): Moved from ser-unix.c
(do_ser_base_read_char): Likewise.
(generic_readchar): Likewise.
(ser_base_readchar): Likewise.
(ser_base_write): Use the write primitive specified by the serial
interface.
* ser-pipe.c (_initialize_ser_pipe): Use ser_base_readchar, not
ser_unix_readchar. Initialize read_prim and write_prim.
* serial.c (struct serial_ops): Add read_prim and write_prim.
* configure: Regenerate.
2005-04-19 Ben Elliston <bje@au.ibm.com>
* c-lang.c (c_create_fundamental_type): Comment fix.

12
gdb/configure vendored
View file

@ -20034,6 +20034,18 @@ if test x$gdb_cv_os_cygwin = xyes; then
esac
fi
# The ser-tcp.c module requires sockets.
case ${host} in
*mingw32*)
cat >>confdefs.h <<\_ACEOF
#define USE_WIN32API 1
_ACEOF
WIN32LIBS="$WIN32LIBS -lws2_32"
;;
esac
LIBGUI="../libgui/src/libgui.a"
GUI_CFLAGS_X="-I${srcdir}/../libgui/src"

View file

@ -1187,6 +1187,18 @@ if test x$gdb_cv_os_cygwin = xyes; then
;;
esac
fi
# The ser-tcp.c module requires sockets.
case ${host} in
*mingw32*)
AC_DEFINE(USE_WIN32API, 1,
[Define if we should use the Windows API, instead of the
POSIX API. On Windows, we use the Windows API when
building for MinGW, but the POSIX API when building
for Cygwin.])
WIN32LIBS="$WIN32LIBS -lws2_32"
;;
esac
AC_SUBST(WIN32LIBS)
LIBGUI="../libgui/src/libgui.a"

View file

@ -24,6 +24,9 @@
#include "serial.h"
#include "ser-unix.h"
#include "event-loop.h"
#ifdef USE_WIN32API
#include <winsock2.h>
#endif
static timer_handler_func push_event;
static handler_func fd_event;
@ -136,11 +139,7 @@ fd_event (int error, void *context)
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);
nr = scb->ops->read_prim (scb, BUFSIZ);
if (nr == 0)
{
scb->bufcnt = SERIAL_EOF;
@ -174,6 +173,181 @@ push_event (void *context)
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)
/* 0 chars means timeout. (We may need to distinguish between EOF
& timeouts someday.) */
return SERIAL_TIMEOUT;
else
/* Got an error from read. */
return SERIAL_ERROR;
}
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)
{
@ -181,7 +355,7 @@ ser_base_write (struct serial *scb, const char *str, int len)
while (len > 0)
{
cc = write (scb->fd, str, len);
cc = scb->ops->write_prim (scb, str, len);
if (cc < 0)
return 1;

View file

@ -25,6 +25,9 @@
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);
@ -46,5 +49,6 @@ 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

View file

@ -144,7 +144,7 @@ _initialize_ser_pipe (void)
ops->next = 0;
ops->open = pipe_open;
ops->close = pipe_close;
ops->readchar = ser_unix_readchar;
ops->readchar = ser_base_readchar;
ops->write = ser_base_write;
ops->flush_output = ser_base_flush_output;
ops->flush_input = ser_base_flush_input;
@ -158,5 +158,7 @@ _initialize_ser_pipe (void)
ops->setstopbits = ser_base_setstopbits;
ops->drain_output = ser_base_drain_output;
ops->async = ser_base_async;
ops->read_prim = ser_unix_read_prim;
ops->write_prim = ser_unix_write_prim;
serial_add_interface (ops);
}

View file

@ -34,11 +34,19 @@
#endif
#include <sys/time.h>
#ifdef USE_WIN32API
#include <winsock2.h>
#define ETIMEDOUT WSAETIMEDOUT
#define close closesocket
#define ioctl ioctlsocket
#else
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#endif
#include <signal.h>
#include "gdb_string.h"
@ -62,6 +70,11 @@ net_open (struct serial *scb, const char *name)
int use_udp;
struct hostent *hostent;
struct sockaddr_in sockaddr;
#ifdef USE_WIN32API
u_long ioarg;
#else
int ioarg;
#endif
use_udp = 0;
if (strncmp (name, "udp:", 4) == 0)
@ -108,14 +121,25 @@ net_open (struct serial *scb, const char *name)
sizeof (struct in_addr));
/* set socket nonblocking */
tmp = 1;
ioctl (scb->fd, FIONBIO, &tmp);
ioarg = 1;
ioctl (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 && errno != EINPROGRESS)
if (n < 0
#ifdef USE_WIN32API
/* Under Windows, calling "connect" with a non-blocking socket
results in WSAEWOULDBLOCK, not WSAEINPROGRESS. */
&& WSAGetLastError() != WSAEWOULDBLOCK
#else
&& errno != EINPROGRESS
#endif
)
{
#ifdef USE_WIN32API
errno = WSAGetLastError();
#endif
net_close (scb);
return -1;
}
@ -165,7 +189,11 @@ net_open (struct serial *scb, const char *name)
{
int res, err, len;
len = sizeof(err);
res = getsockopt (scb->fd, SOL_SOCKET, SO_ERROR, &err, &len);
/* 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)
@ -176,8 +204,8 @@ net_open (struct serial *scb, const char *name)
}
/* turn off nonblocking */
tmp = 0;
ioctl (scb->fd, FIONBIO, &tmp);
ioarg = 0;
ioctl (scb->fd, FIONBIO, &ioarg);
if (use_udp == 0)
{
@ -206,16 +234,35 @@ net_close (struct serial *scb)
scb->fd = -1;
}
static int
net_read_prim (struct serial *scb, size_t count)
{
return recv (scb->fd, scb->buf, count, 0);
}
static int
net_write_prim (struct serial *scb, const void *buf, size_t count)
{
return send (scb->fd, buf, count, 0);
}
void
_initialize_ser_tcp (void)
{
struct serial_ops *ops = XMALLOC (struct serial_ops);
struct serial_ops *ops;
#ifdef USE_WIN32API
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_unix_readchar;
ops->readchar = ser_base_readchar;
ops->write = ser_base_write;
ops->flush_output = ser_base_flush_output;
ops->flush_input = ser_base_flush_input;
@ -229,5 +276,7 @@ _initialize_ser_tcp (void)
ops->setstopbits = ser_base_setstopbits;
ops->drain_output = ser_base_drain_output;
ops->async = ser_base_async;
ops->read_prim = net_read_prim;
ops->write_prim = net_write_prim;
serial_add_interface (ops);
}

View file

@ -70,9 +70,6 @@ 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);
@ -422,7 +419,7 @@ hardwire_raw (struct serial *scb)
*/
/* FIXME: cagney/1999-09-16: Don't replace this with the equivalent
ser_unix*() until the old TERMIOS/SGTTY/... timer code has been
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
@ -542,13 +539,13 @@ wait_for (struct serial *scb, int timeout)
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
ser_base*() 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*()
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_unix_readchar() doesn't expect
times out due to no data while ser_base_readchar() doesn't expect
that. */
static int
@ -863,191 +860,7 @@ hardwire_close (struct serial *scb)
close (scb->fd);
scb->fd = -1;
}
/* 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);
}
void
_initialize_ser_hardwire (void)
@ -1058,7 +871,7 @@ _initialize_ser_hardwire (void)
ops->next = 0;
ops->open = hardwire_open;
ops->close = hardwire_close;
/* FIXME: Don't replace this with the equivalent ser_unix*() until
/* 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;
@ -1075,5 +888,29 @@ _initialize_ser_hardwire (void)
ops->setstopbits = hardwire_setstopbits;
ops->drain_output = hardwire_drain_output;
ops->async = ser_base_async;
ops->read_prim = ser_unix_read_prim;
ops->write_prim = ser_unix_write_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;
}
int
ser_unix_write_prim (struct serial *scb, const void *buf, size_t len)
{
/* ??? Historically, GDB has not retried calls to "write" that
result in EINTR. */
return write (scb->fd, buf, len);
}

View file

@ -22,6 +22,8 @@
#ifndef SER_UNIX_H
#define SER_UNIX_H
extern int ser_unix_readchar (struct serial *scb, int timeout);
extern int ser_unix_read_prim (struct serial *scb, size_t count);
extern int ser_unix_write_prim (struct serial *scb, const void *buf,
size_t count);
#endif

View file

@ -232,6 +232,12 @@ struct serial_ops
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);
/* Perform a low-level write operation, writing (at most) COUNT
bytes from BUF. */
int (*write_prim)(struct serial *scb, const void *buf, size_t count);
};
/* Add a new serial interface to the interface list */