summaryrefslogtreecommitdiff
path: root/do/select
blob: 38211931156e95aae15101bb7c4e91e426314561 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#ifdef HAS_SELECT
int
do_select(gimme,arglast)
int gimme;
int *arglast;
{
    register STR **st = stack->ary_array;
    register int sp = arglast[0];
    register int i;
    register int j;
    register char *s;
    register STR *TARG;
    double value;
    int maxlen = 0;
    int nfound;
    struct timeval timebuf;
    struct timeval *tbuf = &timebuf;
    int growsize;
#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
    int masksize;
    int offset;
    char *fd_sets[4];
    int k;

#if BYTEORDER & 0xf0000
#define ORDERBYTE (0x88888888 - BYTEORDER)
#else
#define ORDERBYTE (0x4444 - BYTEORDER)
#endif

#endif

    for (i = 1; i <= 3; i++) {
	j = st[sp+i]->str_cur;
	if (maxlen < j)
	    maxlen = j;
    }

#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
    growsize = maxlen;		/* little endians can use vecs directly */
#else
#ifdef NFDBITS

#ifndef NBBY
#define NBBY 8
#endif

    masksize = NFDBITS / NBBY;
#else
    masksize = sizeof(long);	/* documented int, everyone seems to use long */
#endif
    growsize = maxlen + (masksize - (maxlen % masksize));
    Zero(&fd_sets[0], 4, char*);
#endif

    for (i = 1; i <= 3; i++) {
	TARG = st[sp+i];
	j = TARG->str_len;
	if (j < growsize) {
	    if (TARG->str_pok) {
		Str_Grow(TARG,growsize);
		s = str_get(TARG) + j;
		while (++j <= growsize) {
		    *s++ = '\0';
		}
	    }
	    else if (TARG->str_ptr) {
		Safefree(TARG->str_ptr);
		TARG->str_ptr = Nullch;
	    }
	}
#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
	s = TARG->str_ptr;
	if (s) {
	    New(403, fd_sets[i], growsize, char);
	    for (offset = 0; offset < growsize; offset += masksize) {
		for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
		    fd_sets[i][j+offset] = s[(k % masksize) + offset];
	    }
	}
#endif
    }
    TARG = st[sp+4];
    if (TARG->str_nok || TARG->str_pok) {
	value = str_gnum(TARG);
	if (value < 0.0)
	    value = 0.0;
	timebuf.tv_sec = (long)value;
	value -= (double)timebuf.tv_sec;
	timebuf.tv_usec = (long)(value * 1000000.0);
    }
    else
	tbuf = Null(struct timeval*);

#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
    nfound = select(
	maxlen * 8,
	st[sp+1]->str_ptr,
	st[sp+2]->str_ptr,
	st[sp+3]->str_ptr,
	tbuf);
#else
    nfound = select(
	maxlen * 8,
	fd_sets[1],
	fd_sets[2],
	fd_sets[3],
	tbuf);
    for (i = 1; i <= 3; i++) {
	if (fd_sets[i]) {
	    TARG = st[sp+i];
	    s = TARG->str_ptr;
	    for (offset = 0; offset < growsize; offset += masksize) {
		for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
		    s[(k % masksize) + offset] = fd_sets[i][j+offset];
	    }
	    Safefree(fd_sets[i]);
	}
    }
#endif

    st[++sp] = str_mortal(&str_no);
    str_numset(st[sp], (double)nfound);
    if (gimme == G_ARRAY && tbuf) {
	value = (double)(timebuf.tv_sec) +
		(double)(timebuf.tv_usec) / 1000000.0;
	st[++sp] = str_mortal(&str_no);
	str_numset(st[sp], value);
    }
    return sp;
}
#endif /* SELECT */