diff --git a/scsh/fdports1.c b/scsh/fdports1.c index 9b73a82..3a44cd5 100644 --- a/scsh/fdports1.c +++ b/scsh/fdports1.c @@ -28,6 +28,7 @@ #include "cstuff.h" #define NUM_FDPORTS 256 #include "fdports.h" +#include "machine/stdio_dep.h" /* Make sure our exports match up w/the implementation: */ #include "fdports1.h" diff --git a/scsh/select1.c b/scsh/select1.c index 0cdeb42..b790ee2 100644 --- a/scsh/select1.c +++ b/scsh/select1.c @@ -16,6 +16,7 @@ #include "cstuff.h" #include "fdports.h" /* Accessors for Scheme I/O port internals. */ #include "fdports1.h" /* Import fdes2fstar(). */ +#include "machine/stdio_dep.h" /* Import stdio buf-peeking ops. */ /* Make sure our exports match up w/the implementation: */ #include "select1.h" @@ -29,29 +30,25 @@ extern FILE *fdes2fstar(int fd); static void or2_fdset(fd_set *x, fd_set *y, int max_elt); static int copyback_fdvec(scheme_value portvec, fd_set *fdset); -/* RVEC, WVEC, and EVEC are Scheme vectors of integer file descriptors -** and I/O ports. NSECS is an integer timeout value, or #f for infinite wait. -** Do the select() call. Move every element we hit on to the front of -** its vector. The number of hits are returned in R_NUMRDY, W_NUMRDY, and -** E_NUMRDY. The principle return value is #f if we win, and a fixnum errno -** value if we error out. +/* RVEC, WVEC, and EVEC are Scheme vectors of integer file descriptors, +** I/O ports, and #f's. NSECS is an integer timeout value, or #f for +** infinite wait. Do the select() call, returning result fd_sets in the +** passed pointers. Return 0 for OK, otherwise error is in errno. */ -scheme_value scm_select(scheme_value rvec, scheme_value wvec, - scheme_value evec, scheme_value nsecs, - int *r_numrdy, int *w_numrdy, int *e_numrdy) +int do_select(scheme_value rvec, scheme_value wvec, + scheme_value evec, scheme_value nsecs, + fd_set *rset_ans, fd_set *wset_ans, fd_set *eset_ans) { struct timeval timeout, *tptr; fd_set rset_bufrdy, wset_bufrdy, eset_bufrdy; /* Buffered port hits. */ - fd_set rset_try, wset_try, eset_try; /* Real select() sets. */ int rbuf_rdy=0, wbuf_rdy=0, bufrdy; /* Set if we find buffered I/O hits. */ int max_fd = -1; /* Max fdes in the sets. */ int nelts, i; int nfound; - FD_ZERO(&rset_try); FD_ZERO(&wset_try); FD_ZERO(&eset_try); + FD_ZERO(rset_ans); FD_ZERO(wset_ans); FD_ZERO(eset_ans); FD_ZERO(&rset_bufrdy); FD_ZERO(&wset_bufrdy); FD_ZERO(&eset_bufrdy); - *r_numrdy = *w_numrdy = *e_numrdy = 0; /* Scan the readvec elts. */ nelts = VECTOR_LENGTH(rvec); @@ -61,21 +58,21 @@ scheme_value scm_select(scheme_value rvec, scheme_value wvec, if( FIXNUMP(elt) ) { /* It's an integer fdes. */ fd = EXTRACT_FIXNUM(elt); - FD_SET(fd, &rset_try); + FD_SET(fd, rset_ans); } - else { /* It better be a port. */ + else if( elt != SCHFALSE ) { /* It better be a port. */ FILE *f; scheme_value data = *Port_PortData(elt); fd = EXTRACT_FIXNUM(*PortData_Fd(data)); f = fdes2fstar(fd); - if( !f ) return ENTER_FIXNUM(errno); + if( !f ) return -1; else if( *PortData_Peek(data) != SCHFALSE /* Port has a peekchar */ || !ibuf_empty(f) ) { /* Stdio buf has chars. */ FD_SET(fd, &rset_bufrdy); rbuf_rdy = 1; /* Hit. */ } - else FD_SET(fd, &rset_try); /* No buffered data. */ + else FD_SET(fd, rset_ans); /* No buffered data. */ } max_fd = max(max_fd, fd); @@ -89,19 +86,19 @@ scheme_value scm_select(scheme_value rvec, scheme_value wvec, if( FIXNUMP(elt) ) { /* It's an integer fdes. */ fd = EXTRACT_FIXNUM(elt); - FD_SET(fd, &wset_try); + FD_SET(fd, wset_ans); } - else { /* It better be a port. */ + else if( elt != SCHFALSE ) { /* It better be a port. */ FILE *f; fd = EXTRACT_FIXNUM(*PortFd(elt)); f = fdes2fstar(fd); - if( !f ) return ENTER_FIXNUM(errno); + if( !f ) return -1; else if( !obuf_full(f) ) { /* I/O buf has room. */ FD_SET(fd, &wset_bufrdy); wbuf_rdy = 1; /* Hit. */ } - else FD_SET(fd, &wset_try); /* No room. */ + else FD_SET(fd, wset_ans); /* No room. */ } max_fd = max(max_fd, fd); @@ -115,12 +112,12 @@ scheme_value scm_select(scheme_value rvec, scheme_value wvec, if( FIXNUMP(elt) ) { /* It's an integer fdes. */ fd = EXTRACT_FIXNUM(elt); - FD_SET(fd, &rset_try); + FD_SET(fd, rset_ans); } - else { /* It better be a port. */ + else if( elt != SCHFALSE ) { /* It better be a port. */ fd = EXTRACT_FIXNUM(*PortFd(elt)); - FD_SET(fd, &rset_try); + FD_SET(fd, rset_ans); } max_fd = max(max_fd, fd); @@ -139,30 +136,38 @@ scheme_value scm_select(scheme_value rvec, scheme_value wvec, } else tptr = NULL; /* #f => Infinite wait. */ - nfound = select1(max_fd+1, &rset_try, &wset_try, &eset_try, tptr);/*Do it.*/ + nfound = select1(max_fd+1, rset_ans, wset_ans, eset_ans, tptr); /* Do it.*/ /* EINTR is not an error return if we have hits on buffered ports ** to report. */ if( nfound < 0 ) - if ( errno != EINTR || !bufrdy ) return ENTER_FIXNUM(errno); + if ( errno != EINTR || !bufrdy ) return -1; else { /* EINTR, but we have hits on buffered ports to report. */ - FD_ZERO(&rset_try); /* This should never happen -- */ - FD_ZERO(&wset_try); /* EINTR on a zero-sec select() */ - FD_ZERO(&eset_try); /* -- but I'm paranoid. */ + FD_ZERO(rset_ans); /* This should never happen -- */ + FD_ZERO(wset_ans); /* EINTR on a zero-sec select() */ + FD_ZERO(eset_ans); /* -- but I'm paranoid. */ } /* OR together the buffered-io ready sets and the fd ready sets. */ - if( rbuf_rdy ) or2_fdset(&rset_try, &rset_bufrdy, max_fd); - if( wbuf_rdy ) or2_fdset(&wset_try, &wset_bufrdy, max_fd); + if( rbuf_rdy ) or2_fdset(rset_ans, &rset_bufrdy, max_fd); + if( wbuf_rdy ) or2_fdset(wset_ans, &wset_bufrdy, max_fd); - *r_numrdy = copyback_fdvec(rvec, &rset_try); - *w_numrdy = copyback_fdvec(wvec, &wset_try); - *e_numrdy = copyback_fdvec(evec, &eset_try); - - return SCHFALSE; + return 0; } + + +/* x = x or y */ +static void or2_fdset(fd_set *x, fd_set *y, int max_elt) +{ + int i; + for(i=max_elt+1; --i >= 0;) + if( FD_ISSET(i,y) ) FD_SET(i,x); + } + + + /* PORTVEC is a vector of integer file descriptors and Scheme ports. ** Scan over the vector, and copy any elt whose file descriptor is in FDSET ** to the front of the vector. Return the number of elts thus copied. @@ -184,10 +189,73 @@ static int copyback_fdvec(scheme_value portvec, fd_set *fdset) } -/* x = x or y */ -static void or2_fdset(fd_set *x, fd_set *y, int max_elt) +/* Overwrite every inactive element in the vector with #f; +** Return count of active elements. +*/ + +static int clobber_inactives(scheme_value portvec, fd_set *fdset) { - int i; - for(i=max_elt+1; --i >= 0;) - if( FD_ISSET(i,y) ) FD_SET(i,x); + int count = 0; + int i = VECTOR_LENGTH(portvec); + + while( --i >= 0 ) { + scheme_value elt = VECTOR_REF(portvec, i); + if( elt != SCHFALSE ) { + int fd = EXTRACT_FIXNUM((FIXNUMP(elt)) ? elt : *PortFd(elt)); + if( FD_ISSET(fd,fdset) ) { + FD_CLR(fd,fdset); /* In case luser put elt in multiple times. */ + ++count; + } + else VECTOR_REF(portvec, i) = SCHFALSE; /* Clobber. */ + } + } + return count; + } + + +/* These two functions are the entry points to this file. +********************************************************* +*/ + +/* Copy active elts back to the front of their vector; +** Return error indicator & number of hits for each vector. +*/ + +scheme_value select_copyback(scheme_value rvec, scheme_value wvec, + scheme_value evec, scheme_value nsecs, + int *r_numrdy, int *w_numrdy, int *e_numrdy) +{ + fd_set rset, wset, eset; + + if( do_select(rvec, wvec, evec, nsecs, &rset, &wset, &eset) ) { + *r_numrdy = *w_numrdy = *e_numrdy = 0; + return ENTER_FIXNUM(errno); + } + + *r_numrdy = copyback_fdvec(rvec, &rset); + *w_numrdy = copyback_fdvec(wvec, &wset); + *e_numrdy = copyback_fdvec(evec, &eset); + return SCHFALSE; + } + + +/* Overwrite non-active elements in the vectors with #f; +** return error indicator & number of hits for each vector. +*/ + +scheme_value select_filter(scheme_value rvec, scheme_value wvec, + scheme_value evec, scheme_value nsecs, + int *r_numrdy, int *w_numrdy, int *e_numrdy) +{ + fd_set rset, wset, eset; + + if( do_select(rvec, wvec, evec, nsecs, &rset, &wset, &eset) ) { + *r_numrdy = *w_numrdy = *e_numrdy = 0; + return ENTER_FIXNUM(errno); + } + + *r_numrdy = clobber_inactives(rvec, &rset); + *w_numrdy = clobber_inactives(wvec, &wset); + *e_numrdy = clobber_inactives(evec, &eset); + return SCHFALSE; } diff --git a/scsh/syscalls1.c b/scsh/syscalls1.c index 945862c..4acb3df 100644 --- a/scsh/syscalls1.c +++ b/scsh/syscalls1.c @@ -22,6 +22,7 @@ #include #include "cstuff.h" +#include "machine/stdio_dep.h" /* Make sure our exports match up w/the implementation: */ #include "syscalls1.h" @@ -500,10 +501,11 @@ char *scm_gethostname(void) char *errno_msg(int i) { /* temp hack until we figure out what to do about losing sys_errlist's */ +extern #ifdef HAVE_CONST_SYS_ERRLIST const #endif - extern char *sys_errlist[]; + char *sys_errlist[]; extern int sys_nerr; return ( i < 0 || i > sys_nerr ) ? NULL /* i.e., #f */ : (char*) sys_errlist[i];