1/*
2
3Copyright 1994, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29/*
30 * Copyright © 2005 Daniel Stone
31 * 
32 * Permission to use, copy, modify, distribute, and sell this software and its
33 * documentation for any purpose is hereby granted without fee, provided that
34 * the above copyright notice appear in all copies and that both that
35 * copyright notice and this permission notice appear in supporting
36 * documentation, and that the name of Daniel Stone not be used in advertising
37 * or publicity pertaining to distribution of the software without specific,
38 * written prior permission.  Daniel Stone makes no representations about the
39 * suitability of this software for any purpose.  It is provided "as is"
40 * without express or implied warranty.
41 *
42 * DANIEL STONE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
43 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
44 * DANIEL STONE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
45 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
46 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
47 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48*/
49
50#ifndef _XPOLL_H_
51#define _XPOLL_H_
52
53#if !defined(WIN32) || defined(__CYGWIN__)
54
55#ifndef USE_POLL
56
57#if defined(FD_SETSIZE) && FD_SETSIZE < 512
58# define XFD_SETSIZE	FD_SETSIZE
59#else
60# define XFD_SETSIZE	512
61# ifndef FD_SETSIZE
62#  define FD_SETSIZE	XFD_SETSIZE
63# endif
64#endif
65
66#include <X11/Xos.h>
67
68#include <sys/select.h>  /* Get the FD_* macros. */
69
70#include <X11/Xmd.h>
71
72#ifdef CSRG_BASED
73#include <sys/param.h>
74# if BSD < 199103
75typedef long fd_mask;
76# endif
77#endif
78
79#ifndef NBBY
80#define NBBY	8		/* number of bits in a byte */
81#endif
82
83#ifndef NFDBITS
84#define NFDBITS (sizeof(fd_mask) * NBBY)	/* bits per mask */
85#endif
86
87#ifndef howmany
88#define howmany(x,y)	(((x)+((y)-1))/(y))
89#endif
90
91#if defined(BSD) && BSD < 198911 
92typedef struct fd_set {
93	fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
94} fd_set;
95#endif
96
97# define Select(n,r,w,e,t) select(n,(fd_set*)r,(fd_set*)w,(fd_set*)e,(struct timeval*)t)
98
99#define __X_FDS_BITS @USE_FDS_BITS@
100
101#ifndef __FDS_BITS
102# define __FDS_BITS(p)  ((p)->__X_FDS_BITS)
103#endif
104
105#define __XFDS_BITS(p, n) (__FDS_BITS(p))[n]
106
107#ifndef FD_SET
108#define FD_SET(n, p)    (__XFDS_BITS(p, ((n)/NFDBITS)) |= ((fd_mask)1 << ((n) % NFDBITS)))
109#endif
110#ifndef FD_CLR
111#define FD_CLR(n, p)    (__XFDS_BITS((p), ((n)/NFDBITS)) &= ~((fd_mask)1 << ((n) % NFDBITS)))
112#endif
113#ifndef FD_ISSET
114#define FD_ISSET(n, p)  ((__XFDS_BITS((p), ((n)/NFDBITS))) & ((fd_mask)1 << ((n) % NFDBITS)))
115#endif
116#ifndef FD_ZERO
117#define FD_ZERO(p)      bzero((char *)(p), sizeof(*(p)))
118#endif
119
120/*
121 * The howmany(FD_SETSIZE, NFDBITS) computes the number of elements in the
122 * array. before accessing an element in the array we check it exists.
123 * If it does not exist then the compiler discards the code to access it. 
124 */
125#define XFD_ANYSET(p) \
126        ((howmany(FD_SETSIZE, NFDBITS) > 0 && (__XFDS_BITS(p, 0))) || \
127        (howmany(FD_SETSIZE, NFDBITS) > 1 && (__XFDS_BITS(p, 1))) || \
128        (howmany(FD_SETSIZE, NFDBITS) > 2 && (__XFDS_BITS(p, 2))) || \
129        (howmany(FD_SETSIZE, NFDBITS) > 3 && (__XFDS_BITS(p, 3))) || \
130        (howmany(FD_SETSIZE, NFDBITS) > 4 && (__XFDS_BITS(p, 4))) || \
131        (howmany(FD_SETSIZE, NFDBITS) > 5 && (__XFDS_BITS(p, 5))) || \
132        (howmany(FD_SETSIZE, NFDBITS) > 6 && (__XFDS_BITS(p, 6))) || \
133        (howmany(FD_SETSIZE, NFDBITS) > 7 && (__XFDS_BITS(p, 7))) || \
134        (howmany(FD_SETSIZE, NFDBITS) > 8 && (__XFDS_BITS(p, 8))) || \
135        (howmany(FD_SETSIZE, NFDBITS) > 9 && (__XFDS_BITS(p, 9))) || \
136        (howmany(FD_SETSIZE, NFDBITS) > 10 && (__XFDS_BITS(p, 10))) || \
137        (howmany(FD_SETSIZE, NFDBITS) > 11 && (__XFDS_BITS(p, 11))) || \
138        (howmany(FD_SETSIZE, NFDBITS) > 12 && (__XFDS_BITS(p, 12))) || \
139        (howmany(FD_SETSIZE, NFDBITS) > 13 && (__XFDS_BITS(p, 13))) || \
140        (howmany(FD_SETSIZE, NFDBITS) > 14 && (__XFDS_BITS(p, 14))) || \
141        (howmany(FD_SETSIZE, NFDBITS) > 15 && (__XFDS_BITS(p, 15))))
142
143
144#define XFD_COPYSET(src,dst) { \
145        int __i__; \
146		for (__i__ = 0; __i__ < howmany(FD_SETSIZE, NFDBITS); __i__++) \
147            __XFDS_BITS((dst), __i__) = __XFDS_BITS((src), __i__); \
148        }
149#define XFD_ANDSET(dst,b1,b2) { \
150        int __i__; \
151        for (__i__ = 0; __i__ < howmany(FD_SETSIZE, NFDBITS); __i__++) \
152            __XFDS_BITS((dst), __i__) = ((__XFDS_BITS((b1), __i__)) & (__XFDS_BITS((b2), __i__))); \
153        }
154#define XFD_ORSET(dst,b1,b2) { \
155        int __i__; \
156        for (__i__ = 0; __i__ < howmany(FD_SETSIZE, NFDBITS); __i__++) \
157		__XFDS_BITS((dst), __i__) = ((__XFDS_BITS((b1), __i__)) | (__XFDS_BITS((b2), __i__))); \
158        }        
159#define XFD_UNSET(dst,b1) { \
160        int __i__; \
161        for (__i__ = 0; __i__ < howmany(FD_SETSIZE, NFDBITS); __i__++) \
162    		__XFDS_BITS((dst), __i__) &= ~(__XFDS_BITS((b1), __i__)); \
163        }
164
165#else /* USE_POLL */
166#include <sys/poll.h>
167#endif /* USE_POLL */
168
169#else /* WIN32 */
170
171#define XFD_SETSIZE	512
172#ifndef FD_SETSIZE
173#define FD_SETSIZE	XFD_SETSIZE
174#endif
175#include <X11/Xwinsock.h>
176
177#define Select(n,r,w,e,t) select(0,(fd_set*)r,(fd_set*)w,(fd_set*)e,(struct timeval*)t)
178
179#define XFD_SETCOUNT(p)	(((fd_set FAR *)(p))->fd_count)
180#define XFD_FD(p,i) (((fd_set FAR *)(p))->fd_array[i])
181#define XFD_ANYSET(p)	XFD_SETCOUNT(p)
182
183#define XFD_COPYSET(src,dst) { \
184    u_int __i; \
185    FD_ZERO(dst); \
186    for (__i = 0; __i < XFD_SETCOUNT(src) ; __i++) { \
187        XFD_FD(dst,__i) = XFD_FD(src,__i); \
188    } \
189    XFD_SETCOUNT(dst) = XFD_SETCOUNT(src); \
190}
191
192#define XFD_ANDSET(dst,b1,b2) { \
193    u_int __i; \
194    FD_ZERO(dst); \
195    for (__i = 0; __i < XFD_SETCOUNT(b1) ; __i++) { \
196        if (FD_ISSET(XFD_FD(b1,__i), b2)) \
197	   FD_SET(XFD_FD(b1,__i), dst); \
198    } \
199}
200
201#define XFD_ORSET(dst,b1,b2) { \
202    u_int __i; \
203    if (dst != b1) XFD_COPYSET(b1,dst); \
204    for (__i = 0; __i < XFD_SETCOUNT(b2) ; __i++) { \
205        if (!FD_ISSET(XFD_FD(b2,__i), dst)) \
206	   FD_SET(XFD_FD(b2,__i), dst); \
207    } \
208}
209
210/* this one is really sub-optimal */
211#define XFD_UNSET(dst,b1) { \
212    u_int __i; \
213    for (__i = 0; __i < XFD_SETCOUNT(b1) ; __i++) { \
214	FD_CLR(XFD_FD(b1,__i), dst); \
215    } \
216}
217
218/* we have to pay the price of having an array here, unlike with bitmasks
219   calling twice FD_SET with the same fd is not transparent, so be careful */
220#undef FD_SET
221#define FD_SET(fd,set) do { \
222    if (XFD_SETCOUNT(set) < FD_SETSIZE && !FD_ISSET(fd,set)) \
223        XFD_FD(set,XFD_SETCOUNT(set)++)=(fd); \
224} while(0)
225
226#define getdtablesize() FD_SETSIZE 
227
228#endif /* WIN32 */
229
230#endif /* _XPOLL_H_ */
231