38211931156e95aae15101bb7c4e91e426314561
[perl.git] / do / select
1 #ifdef HAS_SELECT
2 int
3 do_select(gimme,arglast)
4 int gimme;
5 int *arglast;
6 {
7     register STR **st = stack->ary_array;
8     register int sp = arglast[0];
9     register int i;
10     register int j;
11     register char *s;
12     register STR *TARG;
13     double value;
14     int maxlen = 0;
15     int nfound;
16     struct timeval timebuf;
17     struct timeval *tbuf = &timebuf;
18     int growsize;
19 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
20     int masksize;
21     int offset;
22     char *fd_sets[4];
23     int k;
24
25 #if BYTEORDER & 0xf0000
26 #define ORDERBYTE (0x88888888 - BYTEORDER)
27 #else
28 #define ORDERBYTE (0x4444 - BYTEORDER)
29 #endif
30
31 #endif
32
33     for (i = 1; i <= 3; i++) {
34         j = st[sp+i]->str_cur;
35         if (maxlen < j)
36             maxlen = j;
37     }
38
39 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
40     growsize = maxlen;          /* little endians can use vecs directly */
41 #else
42 #ifdef NFDBITS
43
44 #ifndef NBBY
45 #define NBBY 8
46 #endif
47
48     masksize = NFDBITS / NBBY;
49 #else
50     masksize = sizeof(long);    /* documented int, everyone seems to use long */
51 #endif
52     growsize = maxlen + (masksize - (maxlen % masksize));
53     Zero(&fd_sets[0], 4, char*);
54 #endif
55
56     for (i = 1; i <= 3; i++) {
57         TARG = st[sp+i];
58         j = TARG->str_len;
59         if (j < growsize) {
60             if (TARG->str_pok) {
61                 Str_Grow(TARG,growsize);
62                 s = str_get(TARG) + j;
63                 while (++j <= growsize) {
64                     *s++ = '\0';
65                 }
66             }
67             else if (TARG->str_ptr) {
68                 Safefree(TARG->str_ptr);
69                 TARG->str_ptr = Nullch;
70             }
71         }
72 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
73         s = TARG->str_ptr;
74         if (s) {
75             New(403, fd_sets[i], growsize, char);
76             for (offset = 0; offset < growsize; offset += masksize) {
77                 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
78                     fd_sets[i][j+offset] = s[(k % masksize) + offset];
79             }
80         }
81 #endif
82     }
83     TARG = st[sp+4];
84     if (TARG->str_nok || TARG->str_pok) {
85         value = str_gnum(TARG);
86         if (value < 0.0)
87             value = 0.0;
88         timebuf.tv_sec = (long)value;
89         value -= (double)timebuf.tv_sec;
90         timebuf.tv_usec = (long)(value * 1000000.0);
91     }
92     else
93         tbuf = Null(struct timeval*);
94
95 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
96     nfound = select(
97         maxlen * 8,
98         st[sp+1]->str_ptr,
99         st[sp+2]->str_ptr,
100         st[sp+3]->str_ptr,
101         tbuf);
102 #else
103     nfound = select(
104         maxlen * 8,
105         fd_sets[1],
106         fd_sets[2],
107         fd_sets[3],
108         tbuf);
109     for (i = 1; i <= 3; i++) {
110         if (fd_sets[i]) {
111             TARG = st[sp+i];
112             s = TARG->str_ptr;
113             for (offset = 0; offset < growsize; offset += masksize) {
114                 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
115                     s[(k % masksize) + offset] = fd_sets[i][j+offset];
116             }
117             Safefree(fd_sets[i]);
118         }
119     }
120 #endif
121
122     st[++sp] = str_mortal(&str_no);
123     str_numset(st[sp], (double)nfound);
124     if (gimme == G_ARRAY && tbuf) {
125         value = (double)(timebuf.tv_sec) +
126                 (double)(timebuf.tv_usec) / 1000000.0;
127         st[++sp] = str_mortal(&str_no);
128         str_numset(st[sp], value);
129     }
130     return sp;
131 }
132 #endif /* SELECT */
133