Merge branch 'master' into mingw
[fw/stlink] / mingw / mingw.c
1 #ifdef __MINGW32__
2
3 #include "mingw.h"
4
5 #undef socket
6 #undef connect
7 #undef accept
8 #undef shutdown
9
10 #include <string.h>
11 #include <errno.h>
12 #include <assert.h>
13
14 int win32_poll(struct pollfd *fds, unsigned int nfds, int timo)
15 {
16     struct timeval timeout, *toptr;
17     fd_set ifds, ofds, efds, *ip, *op;
18     unsigned int i, rc;
19
20     /* Set up the file-descriptor sets in ifds, ofds and efds. */
21     FD_ZERO(&ifds);
22     FD_ZERO(&ofds);
23     FD_ZERO(&efds);
24     for (i = 0, op = ip = 0; i < nfds; ++i) {
25         fds[i].revents = 0;
26         if(fds[i].events & (POLLIN|POLLPRI)) {
27                 ip = &ifds;
28                 FD_SET(fds[i].fd, ip);
29         }
30         if(fds[i].events & POLLOUT) {
31                 op = &ofds;
32                 FD_SET(fds[i].fd, op);
33         }
34         FD_SET(fds[i].fd, &efds);
35     } 
36
37     /* Set up the timeval structure for the timeout parameter */
38     if(timo < 0) {
39         toptr = 0;
40     } else {
41         toptr = &timeout;
42         timeout.tv_sec = timo / 1000;
43         timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000;
44     }
45
46 #ifdef DEBUG_POLL
47     printf("Entering select() sec=%ld usec=%ld ip=%lx op=%lx\n",
48            (long)timeout.tv_sec, (long)timeout.tv_usec, (long)ip, (long)op);
49 #endif
50     rc = select(0, ip, op, &efds, toptr);
51 #ifdef DEBUG_POLL
52     printf("Exiting select rc=%d\n", rc);
53 #endif
54
55     if(rc <= 0)
56         return rc;
57
58     if(rc > 0) {
59         for ( i = 0; i < nfds; ++i) {
60             int fd = fds[i].fd;
61         if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds))
62                 fds[i].revents |= POLLIN;
63         if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds))
64                 fds[i].revents |= POLLOUT;
65         if(FD_ISSET(fd, &efds))
66                 /* Some error was detected ... should be some way to know. */
67                 fds[i].revents |= POLLHUP;
68 #ifdef DEBUG_POLL
69         printf("%d %d %d revent = %x\n", 
70                 FD_ISSET(fd, &ifds), FD_ISSET(fd, &ofds), FD_ISSET(fd, &efds), 
71                 fds[i].revents
72         );
73 #endif
74         }
75     }
76     return rc;
77 }
78 static void
79 set_connect_errno(int winsock_err)
80 {
81     switch(winsock_err) {
82         case WSAEINVAL:
83         case WSAEALREADY:
84         case WSAEWOULDBLOCK:
85             errno = EINPROGRESS;
86             break;
87         default:
88             errno = winsock_err;
89             break;
90     }
91 }
92
93 static void
94 set_socket_errno(int winsock_err)
95 {
96     switch(winsock_err) {
97         case WSAEWOULDBLOCK:
98             errno = EAGAIN;
99             break;
100         default:
101             errno = winsock_err;
102             break;
103     }
104 }
105 /*
106  * A wrapper around the socket() function. The purpose of this wrapper
107  * is to ensure that the global errno symbol is set if an error occurs,
108  * even if we are using winsock.
109  */
110 SOCKET
111 win32_socket(int domain, int type, int protocol)
112 {
113     SOCKET fd = socket(domain, type, protocol);
114     if(fd == INVALID_SOCKET) {
115         set_socket_errno(WSAGetLastError());
116     }
117     return fd;
118 }
119 /*
120  * A wrapper around the connect() function. The purpose of this wrapper
121  * is to ensure that the global errno symbol is set if an error occurs,
122  * even if we are using winsock.
123  */
124 int
125 win32_connect(SOCKET fd, struct sockaddr *addr, socklen_t addr_len)
126 {
127     int rc = connect(fd, addr, addr_len);
128     assert(rc == 0 || rc == SOCKET_ERROR);
129     if(rc == SOCKET_ERROR) {
130         set_connect_errno(WSAGetLastError());
131     }
132     return rc;
133 }
134
135 /*
136  * A wrapper around the accept() function. The purpose of this wrapper
137  * is to ensure that the global errno symbol is set if an error occurs,
138  * even if we are using winsock.
139  */
140 SOCKET
141 win32_accept(SOCKET fd, struct sockaddr *addr, socklen_t *addr_len)
142 {
143     SOCKET newfd = accept(fd, addr, addr_len);
144     if(newfd == INVALID_SOCKET) {
145         set_socket_errno(WSAGetLastError());
146         newfd = -1;
147     }
148     return newfd;
149 }
150
151 /*
152  * A wrapper around the shutdown() function. The purpose of this wrapper
153  * is to ensure that the global errno symbol is set if an error occurs,
154  * even if we are using winsock.
155  */
156 int
157 win32_shutdown(SOCKET fd, int mode)
158 {
159     int rc = shutdown(fd, mode);
160     assert(rc == 0 || rc == SOCKET_ERROR);
161     if(rc == SOCKET_ERROR) {
162         set_socket_errno(WSAGetLastError());
163     }
164     return rc;
165 }
166 int win32_close_socket(SOCKET fd) {
167     int rc;
168
169     rc = closesocket(fd);
170     return rc;
171 }
172
173
174 ssize_t win32_write_socket(SOCKET fd, void *buf, int n)
175 {
176     int rc = send(fd, buf, n, 0);
177     if(rc == SOCKET_ERROR) {
178         set_socket_errno(WSAGetLastError());
179     }
180     return rc;
181 }
182
183 ssize_t win32_read_socket(SOCKET fd, void *buf, int n)
184 {
185     int rc = recv(fd, buf, n, 0);
186     if(rc == SOCKET_ERROR) {
187         set_socket_errno(WSAGetLastError());
188     }
189     return rc;
190 }
191
192
193 char * win32_strtok_r(char *s, const char *delim, char **lasts)
194 {
195         register char *spanp;
196         register int c, sc;
197         char *tok;
198
199
200         if (s == NULL && (s = *lasts) == NULL)
201                 return (NULL);
202
203         /*
204          * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
205          */
206 cont:
207         c = *s++;
208         for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
209                 if (c == sc)
210                         goto cont;
211         }
212
213         if (c == 0) {           /* no non-delimiter characters */
214                 *lasts = NULL;
215                 return (NULL);
216         }
217         tok = s - 1;
218
219         /*
220          * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
221          * Note that delim must have one NUL; we stop if we see that, too.
222          */
223         for (;;) {
224                 c = *s++;
225                 spanp = (char *)delim;
226                 do {
227                         if ((sc = *spanp++) == c) {
228                                 if (c == 0)
229                                         s = NULL;
230                                 else
231                                         s[-1] = 0;
232                                 *lasts = s;
233                                 return (tok);
234                         }
235                 } while (sc != 0);
236         }
237         /* NOTREACHED */
238 }
239
240 char *win32_strsep (char **stringp, const char *delim)
241 {
242         register char *s;
243         register const char *spanp;
244         register int c, sc;
245         char *tok;
246
247         if ((s = *stringp) == NULL)
248                 return (NULL);
249         for (tok = s;;) {
250                 c = *s++;
251                 spanp = delim;
252                 do {
253                         if ((sc = *spanp++) == c) {
254                                 if (c == 0)
255                                         s = NULL;
256                                 else
257                                         s[-1] = 0;
258                                 *stringp = s;
259                                 return (tok);
260                         }
261                 } while (sc != 0);
262         }
263         /* NOTREACHED */
264 }
265
266 #endif
267
268