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