Hi! ----
Attached (as "astksh_20130913_poll1_update004.diff.txt") is the (long awaited) update for the poll(1) builtin. * Changes: - Mostly code cleanup - use of "bool" in the "events" variable is now mandatory to simplify some code - poll(1) now has a -s option (similar to sleep(1)) to exit when poll(2) was interupted by a signal or similar event. poll(1) (like poll(2)) will return an error, but with exit code 2 instead of exit code 1 as for normal errors Comments/rants/etc. welcome... ---- Bye, Roland -- __ . . __ (o.\ \/ /.o) [email protected] \__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer /O /==\ O\ TEL +49 641 3992797 (;O/ \/ \O;)
diff -r -u original/src/cmd/ksh93/bltins/poll.c build_poll/src/cmd/ksh93/bltins/poll.c --- src/cmd/ksh93/bltins/poll.c 2013-04-11 21:48:39.000000000 +0200 +++ src/cmd/ksh93/bltins/poll.c 2013-09-16 23:52:21.140525532 +0200 @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 2007-2012 AT&T Intellectual Property * +* Copyright (c) 2012-2013 AT&T Intellectual Property * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -40,7 +40,7 @@ static const char sh_optpoll[] = -"[-?\n@(#)$Id: poll (AT&T Labs Research) 2012-08-16 $\n]" +"[-?\n@(#)$Id: poll (AT&T Labs Research) 2013-09-14 $\n]" "[-author?Roland Mainz <[email protected]>]" "[-license?http://www.eclipse.org/org/documents/epl-v10.html]" "[+NAME? poll - input/output multiplexing]" @@ -110,7 +110,7 @@ "This flag is only valid in the \brevents\b compound " "variable; it is not used in the \bevents\b " "compound variable.]" - "}" + "}" "]" "[+?If the value fd is less than 0, events is ignored and " @@ -146,17 +146,17 @@ "to other types of file is unspecified.]" "[+?The poll utility supports sockets.]" -#ifdef __SunOS -"[+?The poll utility may be used on Solaris on directory fds of " + +"[+?The poll utility may be used on Solaris/Illumos on directory fds of " "/proc/$pid/ to get a \bpollhup='true'\b when the process quits.]" -#endif + "[+?A file descriptor for a socket that is listening for connections " "will indicate that it is ready for reading, once connections " "are available. A file descriptor for a socket that " "is connecting asynchronously will indicate that it is ready " "for writing, once a connection has been established.]" -"[+?Regular files always poll TRUE for reading and writing.]" +"[+?Regular files always poll 'true' for reading and writing.]" "[e:eventarray]:[fdcount?Upon successful completion, an indexed array " "of strings is returned which contains a list of array " @@ -164,7 +164,8 @@ "[S!:pollsfio?Look into sfio streams for buffered information and set " "pollin/pollout to reflect sfio stream state.]" "[R:pollttyraw?Put tty connections into raw mode when polling. The " - "fd is returned to tty cooked mode before poll(1) exits.]" + "fd is returned to tty cooked mode before \bpoll\b(1) exits.]" +"[s:sleep?Sleep until a signal, poll event or a timeout is received.]" "[t:timeout]:[seconds?Timeout in seconds. If the value timeout is 0, " "poll returns immediately. If the value of timeout is -1, " "poll blocks until a requested event occurs or until the " @@ -185,6 +186,10 @@ "may appear in the \brevents\b compound variable even if " "they were not requested in \bevents\b.]" + "[+?It is recommended to use the \bbool\b type for the \bevents\b " + "variables (it can currently not be enforced for " + "backwards-compatibility reasons but may be done in the future).]" + "[+?Using the value of variables in \brevents\b which are " "not set in \bevents\b can be done by putting a '-' suffix " "after the variable name, e.g. use " @@ -192,19 +197,30 @@ "\bar[x]].revents.pollhup\b or an empty string if the variable " "was not set.]" + "[+?If any of the \bpoll*\b variables in \bevents\b uses the " + "\b_Bool\b type all \bpoll*\b variables in \revents\b will be " + "of type \b_Bool\b, too.]" + "[+?Like \bpoll\b(2) it is legal to poll on the same fd in " "multiple entries, for exanple to listen for different events " "or to allow multiple callers to pool their poll lists " "together into one \bpoll\b(1) call.]" "}" +"[+KNOWN BUGS?]{" + "[+?Multidimensional (typeset -a ar=( [4]][16]]=... )) indexed " + "arrays are currently not supported.]" +"}" + /* quoting: ']' must be quoted as "]]" and '?' must be quoted as "//" */ "[+EXAMPLES?]{" "[+?The following example will wait for 10 seconds for input " "on fd 0, variable \bp[fd0]].revents.pollin\b will be 'true' " "or 'false' depening on whether the stream 0 is ready for " "reading:]{" - "[+?compound -A p=( [fd0]]=( fd=0 events=( pollin='true' ) ) ) ; poll -t10 p ; print -v p]" + "[+?compound -A p=( [fd0]]=( integer fd=0 ; compound events=( bool pollin='true' ) ) ) ; " + "poll -t10 p ; " + "print -v p]" "}" "[+?The following example will wait for 2 seconds for input " @@ -212,7 +228,11 @@ "\bp[0]].revents.pollhup\b will be 'true' after polling ends " "because there is both input data available and the end of " "the stream was reached:]{" - "[+?printf '\\n' | ksh -c 'compound -a p=( ( fd=0 events=( pollin=\"true\" pollhup=\"true\" ) ) ) ; poll -t2 p ; print -v p']" + "[+?printf '\\n' | " + "ksh -c 'compound -a p=( ( integer fd=0 ; " + "compound events=( bool pollin=\"true\" pollhup=\"true\" ) ) ) ; " + "poll -t2 p ; " + "print -v p']" "}" "}" @@ -231,9 +251,39 @@ vsnprintf(varnamebuff, sizeof(varnamebuff), namefmt, ap); va_end(ap); - return nv_open(varnamebuff, dict, flags); + return(nv_open(varnamebuff, dict, flags)); +} + + +static +bool nv_is_bool_t(Namval_t *np) +{ + Namval_t *nv; + const char *np_tn; /* type name */ + + nv=nv_type(np); + if (!nv) + return(false); + np_tn=nv->nvname; + if (!np_tn) + return(false); + if (strcmp(np_tn, "_Bool")) + return(false); + return(true); +} + + +static +Namval_t *nv_get_bool_t(Shell_t *shp) +{ + Namval_t *b; + b = nv_search("_Bool", shp->bltin_tree,0); + if (!b) + return(NULL); + return(nv_type(b)); } + /* Name/value mapping table for POLL*-flags */ struct pollflagnamemap { @@ -300,9 +350,19 @@ int eventvar_found; }; +typedef struct State_s /* program state */ +{ + Shbltin_t *context; + Shell_t *shp; + Namval_t *bool_t; /* handle to the _Bool type */ + bool eagain; + int poll_errno; /* errno returned by |poll()| */ +} State_t; + + /* poll on given |fds| data and retry after EINTR/EAGAIN while adjusting timeout */ static -int poll_loop(Shbltin_t* context, struct pollfd *fds, nfds_t nfds, int timeout) +int poll_loop(State_t *state, struct pollfd *fds, nfds_t nfds, int timeout) { /* nanoseconds to milliseconds */ #define TIME_NS2MS(t) ((t)/(1000UL*1000UL)) @@ -324,98 +384,109 @@ do { while(((n = poll(fds, nfds, timeout)) < 0) && - ((errno == EINTR) || (errno == EAGAIN)) && - (!context->sigset)) - errno=0; - - timeout_ns=timeout_ns-(tmxgettime()-starttime); - timeout=TIME_NS2MS(timeout_ns); - } while((timeout > 0) && (!context->sigset)); + (((errno == EINTR) || (errno == EAGAIN)) && state->eagain) && + (!state->context->sigset)) + errno = 0; + state->poll_errno = errno; + + timeout_ns = timeout_ns-(tmxgettime()-starttime); + timeout = TIME_NS2MS(timeout_ns); + } while((timeout > 0) && (!state->context->sigset)); } else { while(((n = poll(fds, nfds, timeout)) < 0) && - ((errno == EINTR) || (errno == EAGAIN)) && - (!context->sigset)) - errno=0; + (((errno == EINTR) || (errno == EAGAIN)) && state->eagain) && + (!state->context->sigset)) + errno = 0; + state->poll_errno = errno; } - return n; + return(n); } /* get ".poll*"-variables in "ar[i].events" and store data in |currpollfd| and |currps| */ static -bool get_compound_revents(Shell_t *shp, const char *parrayname, struct pollstat *currps, struct pollfd *currpollfd) +bool get_compound_revents(State_t *state, const char *parrayname, struct pollstat *currps, struct pollfd *currpollfd) { - const char *subname=currps->array_subscript; + const char *subname = currps->array_subscript; Namval_t *np; int fd; int pi; + bool success = true; - np = nv_open_fmt(shp->var_tree, NV_VARNAME|NV_NOFAIL|NV_NOADD, "%s[%s].fd", parrayname, subname); + np = nv_open_fmt(state->shp->var_tree, NV_VARNAME|NV_NOFAIL|NV_NOADD, "%s[%s].fd", parrayname, subname); if (!np) { errormsg(SH_DICT, ERROR_ERROR, "missing pollfd %s[%s].fd", parrayname, subname); - return false; + return(false); } fd = (int)nv_getnum(np); nv_close(np); + + /* fd==-1 means "ignore entry" */ if ((fd < -1) || (fd > OPEN_MAX)) { errormsg(SH_DICT, ERROR_ERROR, "invalid pollfd %s[%s].fd %d", parrayname, subname, fd); - return false; + return(false); } currpollfd->fd = fd; - np = nv_open_fmt(shp->var_tree, NV_VARNAME|NV_COMVAR|NV_NOFAIL|NV_NOADD, "%s[%s].events", parrayname, subname); + np = nv_open_fmt(state->shp->var_tree, NV_VARNAME|NV_COMVAR|NV_NOFAIL|NV_NOADD, "%s[%s].events", parrayname, subname); if (!np) { errormsg(SH_DICT, ERROR_ERROR, "missing pollfd %s[%s].events", parrayname, subname); - return false; + return(false); } nv_close(np); - currpollfd->events=0; - currpollfd->revents=0; - currps->eventvar_found=0; + currpollfd->events = 0; + currpollfd->revents = 0; + currps->eventvar_found = 0; + for (pi=0 ; pfnm[pi].name != NULL ; pi++) { - const char *s; - - np = nv_open_fmt(shp->var_tree, NV_VARNAME|NV_NOFAIL|NV_NOADD, "%s[%s].events.%s", parrayname, subname, pfnm[pi].name); + np = nv_open_fmt(state->shp->var_tree, NV_VARNAME|NV_NOFAIL|NV_NOADD, "%s[%s].events.%s", parrayname, subname, pfnm[pi].name); if (!np) + { + /* ignore this, it may be a sparse array */ continue; + } - currps->eventvar_found |= pfnm[pi].flag; - s=nv_getval(np); - if (s != NULL) + if (nv_is_bool_t(np)) { - if (!strcmp(s, "true")) + currps->eventvar_found |= pfnm[pi].flag; + if (((bool)nv_getnum(np)) == true) currpollfd->events |= pfnm[pi].flag; - else if (!strcmp(s, "false")) - ; - else - errormsg(SH_DICT, ERROR_ERROR, "invalid boolean value % in variable %s[%s].events", s, parrayname, subname); + } + else + { + errormsg(SH_DICT, ERROR_ERROR, "%s[%s].events.%s is not of type _Bool", parrayname, subname, pfnm[pi].name); + success = false; + } + nv_close(np); } - return true; + return(success); } + /* set ".poll*"-variables in "ar[i].revents" per data in |currpollfd| and |currps| */ static -void set_compound_revents(Shell_t *shp, const char *parrayname, struct pollstat *currps, struct pollfd *currpollfd) +bool set_compound_revents(State_t *state, const char *parrayname, struct pollstat *currps, struct pollfd *currpollfd) { - const char *subname=currps->array_subscript; - Namval_t *np; - int pi; + const char *subname = currps->array_subscript; + Namval_t *np; + int pi; + bool success = true; - np = nv_open_fmt(shp->var_tree, NV_VARNAME|NV_NOFAIL|NV_COMVAR, "%s[%s].revents", parrayname, subname); + np = nv_open_fmt(state->shp->var_tree, NV_VARNAME|NV_NOFAIL|NV_COMVAR, "%s[%s].revents", parrayname, subname); if (!np) { errormsg(SH_DICT, ERROR_ERROR, "could not create pollfd %s[%s].revents", parrayname, subname); - return; + return(false); } nv_setvtree(np); /* make "revents" really a compound variable */ nv_close(np); @@ -429,21 +500,29 @@ if ((currps->eventvar_found & pfnm[pi].flag) || ((currpollfd->revents & (POLLHUP|POLLNVAL|POLLERR)) & pfnm[pi].flag)) { - np = nv_open_fmt(shp->var_tree, NV_VARNAME|NV_NOFAIL, "%s[%s].revents.%s", parrayname, subname, pfnm[pi].name); + np = nv_open_fmt(state->shp->var_tree, NV_VARNAME|NV_NOFAIL, "%s[%s].revents.%s", parrayname, subname, pfnm[pi].name); if (!np) + { + success = false; continue; + } + nv_settype(np, state->bool_t, 0); nv_putval(np, ((currpollfd->revents & pfnm[pi].flag)?"true":"false"), 0); + nv_close(np); } } + + return(success); } + /* |main()| for poll(1) builtin */ extern int b_poll(int argc, char *argv[], Shbltin_t* context) { - Shell_t *shp = sh_contexttoshell(context); + State_t state; Namval_t *np, *array_np, *array_np_sub; @@ -453,7 +532,7 @@ *subname, /* current subscript */ *s; int n; - nfds_t numpollfd = 0; /* number of entries to poll */ + nfds_t numpollfd = 0; /* number of entries to poll */ int i, j; double timeout = -1.; @@ -467,6 +546,11 @@ *currps; /* current |pollstat| we are working on */ int retval = 0; /* return value of builtin */ + state.context = context; + state.shp = sh_contexttoshell(context); + state.eagain = true; + state.poll_errno = 0; + while (n = optget(argv, sh_optpoll)) switch (n) { case 't': @@ -476,12 +560,15 @@ errormsg(SH_DICT, ERROR_system(1), "%s: invalid timeout", opt_info.arg); /* -t uses seconds */ - if (timeout >=0) + if (timeout >= 0) timeout *= 1000.; break; case 'e': eventarrayname = opt_info.arg; break; + case 's': + state.eagain=opt_info.num?false:true; + break; case 'S': pollsfio=opt_info.num?true:false; break; @@ -502,11 +589,15 @@ parrayname = argv[0]; + state.bool_t = nv_get_bool_t(state.shp); + if (!state.bool_t) + errormsg(SH_DICT, ERROR_system(1), "internal error: _Bool type not found"); + strstk = stkopen(0); if (!strstk) errormsg(SH_DICT, ERROR_system(1), e_nospace); - array_np = nv_open(parrayname, shp->var_tree, NV_VARNAME|NV_NOFAIL|NV_NOADD); + array_np = nv_open(parrayname, state.shp->var_tree, NV_VARNAME|NV_NOFAIL|NV_NOADD); if (!array_np) { stkclose(strstk); @@ -551,7 +642,7 @@ i = 0; do { - if (!(subname=nv_getsub(array_np_sub))) + if (!(subname = nv_getsub(array_np_sub))) break; pollstat[i].array_subscript=stkcopy(strstk, subname); @@ -561,14 +652,14 @@ goto done_error; } - if (!get_compound_revents(shp, parrayname, &pollstat[i], &pollfd[i])) + if (!get_compound_revents(&state, parrayname, &pollstat[i], &pollfd[i])) goto done_error; i++; } while(array_np_sub && nv_nextsub(array_np_sub)); nv_close(array_np); - array_np=NULL; + array_np = NULL; /* * If sfio handles fds we need to check whether there are @@ -592,11 +683,11 @@ for (i=0 ; i < numpollfd ; i++) { - currps=&pollstat[i]; - fd=pollfd[i].fd; + currps = &pollstat[i]; + fd = pollfd[i].fd; - currps->sfio.sfd=(fd>=0)?sh_fd2sfio(shp, fd):NULL; - currps->sfio.flags=0; + currps->sfio.sfd = (fd>=0)?sh_fd2sfio(state.shp, fd):NULL; + currps->sfio.flags = 0; if (currps->sfio.sfd!=NULL) { /* Only add |currps->sfio.sfd| to the @@ -618,7 +709,7 @@ break; } if (j == num_sfd) - sfd[num_sfd++]=currps->sfio.sfd; + sfd[num_sfd++] = currps->sfio.sfd; } } @@ -640,7 +731,7 @@ for (j=0 ; j < numpollfd ; j++) { if (pollstat[j].sfio.sfd == sfd[i]) - pollstat[j].sfio.flags=sfpoll_flags; + pollstat[j].sfio.flags = sfpoll_flags; } } } @@ -651,7 +742,7 @@ */ if (eventarrayname) { - np = nv_open_fmt(shp->var_tree, NV_VARNAME|NV_ARRAY|NV_NOFAIL, "%s", eventarrayname); + np = nv_open_fmt(state.shp->var_tree, NV_VARNAME|NV_ARRAY|NV_NOFAIL, "%s", eventarrayname); if (!np) { errormsg(SH_DICT, ERROR_ERROR, "could not create eventarray variable %s", eventarrayname); @@ -659,6 +750,10 @@ } nv_close(np); + + /* Clear array */ + sfsprintf(buff, sizeof(buff), "%s=()", eventarrayname); + sh_trap(state.shp, buff, 0); } /* @@ -670,8 +765,8 @@ for (i=0 ; i < numpollfd ; i++) { - fd=pollfd[i].fd; - if ((fd >=0) && (shp->fdstatus[fd]&IOTTY)) + fd = pollfd[i].fd; + if ((fd >= 0) && (state.shp->fdstatus[fd]&IOTTY)) tty_raw(fd, 1); } } @@ -679,7 +774,7 @@ /* * ... then poll for events... */ - n = poll_loop(context, pollfd, numpollfd, timeout); + n = poll_loop(&state, pollfd, numpollfd, timeout); /* * ... and restore the tty's to "cooked" mode @@ -690,17 +785,19 @@ for (i=0 ; i < numpollfd ; i++) { - fd=pollfd[i].fd; - if ((fd >=0) && (shp->fdstatus[fd]&IOTTY)) + fd = pollfd[i].fd; + if ((fd >= 0) && (state.shp->fdstatus[fd]&IOTTY)) tty_cooked(fd); } } if (n < 0) { + retval = (state.poll_errno==EAGAIN || state.poll_errno==EINTR)?2:1; + errno = state.poll_errno; /* |ERROR_system(0)| won't quit the builtin */ errormsg(SH_DICT, ERROR_system(0), "poll(2) failure"); - retval=1; + } /* @@ -717,20 +814,21 @@ pollfd[i].revents |= POLLOUT; } - set_compound_revents(shp, parrayname, &pollstat[i], &pollfd[i]); + if (!set_compound_revents(&state, parrayname, &pollstat[i], &pollfd[i])) + retval = 1; /* Add array index to eventarray if this pollfd entry had any events */ if (eventarrayname && pollfd[i].revents) { sfsprintf(buff, sizeof(buff), "%s+=( '%s' )", eventarrayname, pollstat[i].array_subscript); - sh_trap(shp, buff, 0); + sh_trap(state.shp, buff, 0); } } goto done; done_error: - retval=1; + retval = 1; done: if (array_np) nv_close(array_np); diff -r -u original/src/cmd/ksh93/tests/builtin_poll.sh build_poll/src/cmd/ksh93/tests/builtin_poll.sh --- src/cmd/ksh93/tests/builtin_poll.sh 2013-05-11 22:23:48.000000000 +0200 +++ src/cmd/ksh93/tests/builtin_poll.sh 2013-09-16 22:32:11.545232157 +0200 @@ -1,26 +1,7 @@ ######################################################################## # # # This software is part of the ast package # -# Copyright (c) 1982-2013 AT&T Intellectual Property # -# and is licensed under the # -# Eclipse Public License, Version 1.0 # -# by AT&T Intellectual Property # -# # -# A copy of the License is available at # -# http://www.eclipse.org/org/documents/epl-v10.html # -# (with md5 checksum b35adb5213ca9657e911e9befb180842) # -# # -# Information and Software Systems Research # -# AT&T Research # -# Florham Park NJ # -# # -# David Korn <[email protected]> # -# # -######################################################################## -######################################################################## -# # -# This software is part of the ast package # -# Copyright (c) 2009-2012 Roland Mainz # +# Copyright (c) 2009-2013 Roland Mainz # # and is licensed under the # # Eclipse Public License, Version 1.0 # # by AT&T Intellectual Property # @@ -35,7 +16,7 @@ ######################################################################## # -# Copyright (c) 2009, 2012, Roland Mainz. All rights reserved. +# Copyright (c) 2009, 2013, Roland Mainz. All rights reserved. # # @@ -70,8 +51,8 @@ { compound d1=( compound -A u=( - [y]=( integer fd=5 ; compound events=( pollin='true' ) revents=() ) - [x]=( integer fd=5 ; compound events=( pollin='true' ) revents=() ) + [y]=( integer fd=5 ; compound events=( bool pollin='true' ) revents=() ) + [x]=( integer fd=5 ; compound events=( bool pollin='true' ) revents=() ) ) ) @@ -88,7 +69,7 @@ # test 2: unset d1.res - d1.u[z]=( integer fd=5 ; compound events=( pollout='true' ) revents=() ) + d1.u[z]=( integer fd=5 ; compound events=( bool pollout='true' ) revents=() ) print -C d1 >'testdata.cpv' $SHELL -o errexit -c 'builtin poll ; read -C <"testdata.cpv" d1 ; { poll -e d1.res -t 5. d1.u ; } 5<"/dev/null" 5>"/dev/null" ; print -C d1 >"testdata.cpv"' >'log.txt' 2>&1 || err_exit "poll returned non-zero exit code $?" @@ -120,19 +101,19 @@ $'integer i maxfd=$(getconf "OPEN_MAX")\n' $'(( maxfd-=10 )) # space for stdin/stdout/stderr/dirfd\n' $'for (( i=0 ; i < maxfd ; i++ )) ; do\n' - $' pl[$((i*17))]=( fd=0 events=( pollin=true ) )\n' + $' pl[$((i*17))]=( fd=0 events=( bool pollin=true ) )\n' $'done\n' $'poll -R -t2 pl\n' $'print -v pl\n' $'print "OK"\n' ) - expected_output_pattern='~(E)([[:space:]]*?\([[:space:]]*?\[.+\]=\([[:space:]]*?events=\([[:space:]]*?pollin=true[[:space:]]*?\)[[:space:]]*?fd=0[[:space:]]*?revents=\([[:space:]]*?pollhup=true[[:space:]]*?pollin=true[[:space:]]*?\)[[:space:]]*?\)[[:space:]]*?\)[[:space:]]*?)+OK' + expected_output_pattern='~(E)([[:space:]]*?\([[:space:]]*?\[.+\]=\([[:space:]]*?events=\([[:space:]]*?(_Bool|)[[:space:]]*?pollin=true[[:space:]]*?\)[[:space:]]*?fd=0[[:space:]]*?revents=\([[:space:]]*?(_Bool|)[[:space:]]*?pollhup=true[[:space:]]*?(_Bool|)[[:space:]]*?pollin=true[[:space:]]*?\)[[:space:]]*?\)[[:space:]]*?\)[[:space:]]*?)+OK' ) ( name='sparse_type_array1' typeset -r -a script=( $'builtin poll\n' - $'typeset -T p_t=( typeset -l -i fd ; \n' + $'typeset -T p_t=( typeset fd=-1 ; \n' # fixme: This should be "integer fd=-1" but ast-ksh.2013-09-13 crashes # fixme: In theory we only have to list the events we want # in the compound variable "events" ... and the same events # plus pollerr, pollnval and pollup in "revents" (since @@ -141,8 +122,8 @@ # which triggers fatal errors in case we try to read a # non-existing type variable member - see # http://marc.info/?l=ast-developers&m=134526131905059&w=2 - $' compound events=( typeset pollin=false pollpri=false pollout=false pollrdnorm=false pollwrnorm=false pollrdband=false pollwrband=false pollmsg=false pollremove=false pollrdhup=false pollerr=false pollhup=false pollnval=false ; )\n' - $' compound revents=( typeset pollin=false pollpri=false pollout=false pollrdnorm=false pollwrnorm=false pollrdband=false pollwrband=false pollmsg=false pollremove=false pollrdhup=false pollerr=false pollhup=false pollnval=false ; )\n' + $' compound events=( bool pollin=false pollpri=false pollout=false pollrdnorm=false pollwrnorm=false pollrdband=false pollwrband=false pollmsg=false pollremove=false pollrdhup=false pollerr=false pollhup=false pollnval=false ; )\n' + $' compound revents=( bool pollin=false pollpri=false pollout=false pollrdnorm=false pollwrnorm=false pollrdband=false pollwrband=false pollmsg=false pollremove=false pollrdhup=false pollerr=false pollhup=false pollnval=false ; )\n' $' function pinit { _.fd=$1 ; _.events.pollin=true ; } ;\n' $')\n' $'compound c ; p_t -a c.pl\n' @@ -158,13 +139,13 @@ $'print -v c\n' $'print "OK"\n' ) - expected_output_pattern='~(Xlr)\([[:space:]]+?p_t[[:space:]]+?-a[[:space:]]+?pl=\([[:space:]]+?([[:space:]]+?\[[[:alnum:]]+\]=\([[:space:]]+?typeset[[:space:]]+?-l[[:space:]]+?-i[[:space:]]+?fd=0[[:space:]]+?events=\((([^\x28\x29]+?pollin=true[^\x28\x29]+?)&([^\x28\x29]+?pollhup=false[^\x28\x29]+?))[[:space:]]+?\)[[:space:]]+?revents=\((([^\x28\x29]+?pollin=true[^\x28\x29]+?)&([^\x28\x29]+?pollhup=true[^\x28\x29]+?))\)[[:space:]]+?\)[[:space:]]+?)+?[[:space:]]+?\)[[:space:]]+?\)[[:space:]]+?OK' + expected_output_pattern='~(Xlr)\([[:space:]]+?p_t[[:space:]]+?-a[[:space:]]+?pl=\([[:space:]]+?([[:space:]]+?\[[[:alnum:]]+\]=\(([[:space:]]+?typeset[[:space:]]+?-l[[:space:]]+?-i)*?[[:space:]]+?fd=0[[:space:]]+?events=\((([^\x28\x29]+?(_Bool|)[[:space:]]*?pollin=true[^\x28\x29]+?)&([^\x28\x29]+?(_Bool|)[[:space:]]*?pollhup=false[^\x28\x29]+?))[[:space:]]+?\)[[:space:]]+?revents=\((([^\x28\x29]+?(_Bool|)[[:space:]]*?pollin=true[^\x28\x29]+?)&([^\x28\x29]+?(_Bool|)[[:space:]]*?pollhup=true[^\x28\x29]+?))\)[[:space:]]+?\)[[:space:]]+?)+?[[:space:]]+?\)[[:space:]]+?\)[[:space:]]+?OK' ) ( name='associative_type_array1' typeset -r -a script=( $'builtin poll\n' - $'typeset -T p_t=( typeset -l -i fd ; \n' + $'typeset -T p_t=( typeset fd=-1 ; \n' # fixme: This should be "integer fd=-1" but ast-ksh.2013-09-13 crashes # fixme: In theory we only have to list the events we want # in the compound variable "events" ... and the same events # plus pollerr, pollnval and pollup in "revents" (since @@ -173,8 +154,8 @@ # which triggers fatal errors in case we try to read a # non-existing type variable member - see # http://marc.info/?l=ast-developers&m=134526131905059&w=2 - $' compound events=( typeset pollin=false pollpri=false pollout=false pollrdnorm=false pollwrnorm=false pollrdband=false pollwrband=false pollmsg=false pollremove=false pollrdhup=false pollerr=false pollhup=false pollnval=false ; )\n' - $' compound revents=( typeset pollin=false pollpri=false pollout=false pollrdnorm=false pollwrnorm=false pollrdband=false pollwrband=false pollmsg=false pollremove=false pollrdhup=false pollerr=false pollhup=false pollnval=false ; )\n' + $' compound events=( bool pollin=false pollpri=false pollout=false pollrdnorm=false pollwrnorm=false pollrdband=false pollwrband=false pollmsg=false pollremove=false pollrdhup=false pollerr=false pollhup=false pollnval=false ; )\n' + $' compound revents=( bool pollin=false pollpri=false pollout=false pollrdnorm=false pollwrnorm=false pollrdband=false pollwrband=false pollmsg=false pollremove=false pollrdhup=false pollerr=false pollhup=false pollnval=false ; )\n' $' function pinit { _.fd=$1 ; _.events.pollin=true ; } ;\n' $')\n' $'compound c ; p_t -A c.pl\n' @@ -190,7 +171,7 @@ $'print -v c\n' $'print "OK"\n' ) - expected_output_pattern='~(Xlr)\([[:space:]]+?p_t[[:space:]]+?-A[[:space:]]+?pl=\([[:space:]]+?([[:space:]]+?\[[[:alnum:]]+\]=\([[:space:]]+?typeset[[:space:]]+?-l[[:space:]]+?-i[[:space:]]+?fd=0[[:space:]]+?events=\((([^\x28\x29]+?pollin=true[^\x28\x29]+?)&([^\x28\x29]+?pollhup=false[^\x28\x29]+?))[[:space:]]+?\)[[:space:]]+?revents=\((([^\x28\x29]+?pollin=true[^\x28\x29]+?)&([^\x28\x29]+?pollhup=true[^\x28\x29]+?))\)[[:space:]]+?\)[[:space:]]+?)+?[[:space:]]+?\)[[:space:]]+?\)[[:space:]]+?OK' + expected_output_pattern='~(Xlr)\([[:space:]]+?p_t[[:space:]]+?-A[[:space:]]+?pl=\([[:space:]]+?([[:space:]]+?\[[[:alnum:]]+\]=\(([[:space:]]+?typeset[[:space:]]+?-l[[:space:]]+?-i)*?[[:space:]]+?fd=0[[:space:]]+?events=\((([^\x28\x29]+?(_Bool|)[[:space:]]*?pollin=true[^\x28\x29]+?)&([^\x28\x29]+?(_Bool|)[[:space:]]*?pollhup=false[^\x28\x29]+?))[[:space:]]+?\)[[:space:]]+?revents=\((([^\x28\x29]+?(_Bool|)[[:space:]]*?pollin=true[^\x28\x29]+?)&([^\x28\x29]+?(_Bool|)[[:space:]]*?pollhup=true[^\x28\x29]+?))\)[[:space:]]+?\)[[:space:]]+?)+?[[:space:]]+?\)[[:space:]]+?\)[[:space:]]+?OK' ) ) @@ -219,17 +200,16 @@ integer i typeset testname cat >'poll_circus.sh' <<EOF +# fixme: add com.kornshell.tests.builtin_poll.fifo_circus1 namespace +# namespaces unfortunately don't work with "shcomp" from ast-ksh.2013-09-13 typeset -T circus_t=( typeset fifo_name - integer in_fd - integer out_fd + integer in_fd=-1 + integer out_fd=-1 function fifo_init { integer pid - # fixme: we can't assign fd directly because ast-ksh.2012-08-13 has a bug - # with "redirect" - integer fd _.fifo_name="\$1" rm -f "\${_.fifo_name}" @@ -241,14 +221,12 @@ { redirect {dummy}<"\${_.fifo_name}" ; for (( ;; )) ; do sleep 15 ; done ; } & (( pid=\$! )) - redirect {fd}>"\${_.fifo_name}" - (( _.out_fd=fd )) + redirect {_.out_fd}>"\${_.fifo_name}" #printf '%s: outfd=%d\n' "\${_.fifo_name}" _.out_fd kill \$pid ; wait \$pid 2>'/dev/null' - redirect {fd}<"\${_.fifo_name}" - (( _.in_fd=fd )) + redirect {_.in_fd}<"\${_.fifo_name}" #printf '%s: infd=%d\n' "\${_.fifo_name}" _.in_fd return 0 @@ -278,9 +256,9 @@ compound -A pollfd for name in "\${!ar[@]}" ; do subname="fifo_\${name}_in" - pollfd[\${subname}]=( fd=\${ar[\${name}].in_fd} events=( pollin='true' pollerr='false' pollhup='false' pollnval='false' ) revents=() ) + pollfd[\${subname}]=( integer fd=\${ar[\${name}].in_fd} ; compound events=( bool pollin='true' pollerr='false' pollhup='false' pollnval='false' ) revents=() ) subname="fifo_\${name}_out" - pollfd[\${subname}]=( fd=\${ar[\${name}].out_fd} events=( pollout='true' pollerr='false' pollhup='false' pollnval='false' ) revents=() ) + pollfd[\${subname}]=( integer fd=\${ar[\${name}].out_fd} ; compound events=( bool pollout='true' pollerr='false' pollhup='false' pollnval='false' ) revents=() ) done # main event loop @@ -293,36 +271,36 @@ up="\$name" subname="fifo_\${name}_in" - if \${pollfd[\${subname}].revents.pollin} ; then printf '%sI+' "\${up}" ; else printf '...' ; fi - if \${pollfd[\${subname}].revents.pollhup} ; then printf '%sIH' "\${up}" ; else printf '...' ; fi - if \${pollfd[\${subname}].revents.pollerr} ; then printf '%sIE' "\${up}" ; else printf '...' ; fi - if \${pollfd[\${subname}].revents.pollnval} ; then printf '%sIN' "\${up}" ; else printf '...' ; fi + if (( pollfd[\${subname}].revents.pollin )) ; then printf '%sI+' "\${up}" ; else printf '...' ; fi + if (( pollfd[\${subname}].revents.pollhup )) ; then printf '%sIH' "\${up}" ; else printf '...' ; fi + if (( pollfd[\${subname}].revents.pollerr )) ; then printf '%sIE' "\${up}" ; else printf '...' ; fi + if (( pollfd[\${subname}].revents.pollnval )) ; then printf '%sIN' "\${up}" ; else printf '...' ; fi subname="fifo_\${name}_out" - if \${pollfd[\${subname}].revents.pollout} ; then printf '%sO+' "\${up}" ; else printf '...' ; fi - if \${pollfd[\${subname}].revents.pollhup} ; then printf '%sOH' "\${up}" ; else printf '...' ; fi - if \${pollfd[\${subname}].revents.pollerr} ; then printf '%sOE' "\${up}" ; else printf '...' ; fi - if \${pollfd[\${subname}].revents.pollnval} ; then printf '%sON' "\${up}" ; else printf '...' ; fi + if (( pollfd[\${subname}].revents.pollout )) ; then printf '%sO+' "\${up}" ; else printf '...' ; fi + if (( pollfd[\${subname}].revents.pollhup )) ; then printf '%sOH' "\${up}" ; else printf '...' ; fi + if (( pollfd[\${subname}].revents.pollerr )) ; then printf '%sOE' "\${up}" ; else printf '...' ; fi + if (( pollfd[\${subname}].revents.pollnval )) ; then printf '%sON' "\${up}" ; else printf '...' ; fi printf '|' done printf '\n' # pass token around - if \${pollfd[fifo_a_in].revents.pollin} && \${pollfd[fifo_b_out].revents.pollout}; then + if (( pollfd[fifo_a_in].revents.pollin && pollfd[fifo_b_out].revents.pollout )) ; then if read -u\${pollfd[fifo_a_in].fd} -N1 x ; then print -u\${pollfd[fifo_b_out].fd} -f "%s" "\$x" 2>'/dev/null' fi fi - if \${pollfd[fifo_b_in].revents.pollin} && \${pollfd[fifo_c_out].revents.pollout}; then + if (( pollfd[fifo_b_in].revents.pollin && pollfd[fifo_c_out].revents.pollout )) ; then if read -u\${pollfd[fifo_b_in].fd} -N1 x ; then print -u\${pollfd[fifo_c_out].fd} -f "%s" "\$x" 2>'/dev/null' fi fi - if \${pollfd[fifo_c_in].revents.pollin} && \${pollfd[fifo_d_out].revents.pollout}; then + if (( pollfd[fifo_c_in].revents.pollin && pollfd[fifo_d_out].revents.pollout )) ; then if read -u\${pollfd[fifo_c_in].fd} -N1 x ; then print -u\${pollfd[fifo_d_out].fd} -f "%s" "\$x" 2>'/dev/null' fi fi - if \${pollfd[fifo_d_in].revents.pollin} && \${pollfd[fifo_a_out].revents.pollout}; then + if (( pollfd[fifo_d_in].revents.pollin && pollfd[fifo_a_out].revents.pollout )) ; then if read -u\${pollfd[fifo_d_in].fd} -N1 x ; then print -u\${pollfd[fifo_a_out].fd} -f "%s" "\$x" 2>'/dev/null' fi @@ -331,19 +309,19 @@ # send HUP around # we explicitly do NOT close the file descriptors here # to force poll(1) to set revents.pollnval=true - if \${pollfd[fifo_a_in].revents.pollhup} ; then + if (( pollfd[fifo_a_in].revents.pollhup )) ; then redirect {pollfd[fifo_a_in].fd}<&-; redirect {pollfd[fifo_b_out].fd}<&-; fi - if \${pollfd[fifo_b_in].revents.pollhup} ; then + if (( pollfd[fifo_b_in].revents.pollhup )) ; then redirect {pollfd[fifo_b_in].fd}<&-; redirect {pollfd[fifo_c_out].fd}<&-; fi - if \${pollfd[fifo_c_in].revents.pollhup} ; then + if (( pollfd[fifo_c_in].revents.pollhup )) ; then redirect {pollfd[fifo_c_in].fd}<&-; redirect {pollfd[fifo_d_out].fd}<&-; fi - if \${pollfd[fifo_d_in].revents.pollhup} ; then + if (( pollfd[fifo_d_in].revents.pollhup )) ; then redirect {pollfd[fifo_d_in].fd}<&-; redirect {pollfd[fifo_a_out].fd}<&-; fi @@ -357,23 +335,26 @@ # - real applications may just use something like # \$ unset pollfd[fifo_a_in] # to remove the whole # array node - \${pollfd[fifo_a_in].revents.pollnval} && (( pollfd[fifo_a_in].fd=-1 )) - \${pollfd[fifo_a_out].revents.pollnval} && (( pollfd[fifo_a_out].fd=-1 )) - \${pollfd[fifo_b_in].revents.pollnval} && (( pollfd[fifo_b_in].fd=-1 )) - \${pollfd[fifo_b_out].revents.pollnval} && (( pollfd[fifo_b_out].fd=-1 )) - \${pollfd[fifo_c_in].revents.pollnval} && (( pollfd[fifo_c_in].fd=-1 )) - \${pollfd[fifo_c_out].revents.pollnval} && (( pollfd[fifo_c_out].fd=-1 )) - \${pollfd[fifo_d_in].revents.pollnval} && (( pollfd[fifo_d_in].fd=-1 )) - \${pollfd[fifo_d_out].revents.pollnval} && (( pollfd[fifo_d_out].fd=-1 )) + (( pollfd[fifo_a_in].revents.pollnval && (pollfd[fifo_a_in].fd=-1) )) + (( pollfd[fifo_a_out].revents.pollnval && (pollfd[fifo_a_out].fd=-1) )) + (( pollfd[fifo_b_in].revents.pollnval && (pollfd[fifo_b_in].fd=-1) )) + (( pollfd[fifo_b_out].revents.pollnval && (pollfd[fifo_b_out].fd=-1) )) + (( pollfd[fifo_c_in].revents.pollnval && (pollfd[fifo_c_in].fd=-1) )) + (( pollfd[fifo_c_out].revents.pollnval && (pollfd[fifo_c_out].fd=-1) )) + (( pollfd[fifo_d_in].revents.pollnval && (pollfd[fifo_d_in].fd=-1) )) + (( pollfd[fifo_d_out].revents.pollnval && (pollfd[fifo_d_out].fd=-1) )) # send start token if (( i==0 )) ; then # Use the Euro symbol (\u[20ac]) if the locale - # uses a UTF-8 encoding - typeset -r utf8_euro_char1=\$'\u[20ac]' - typeset -r utf8_euro_char2=\$'\342\202\254' - if (( (\${#utf8_euro_char1} == 1) && (\${#utf8_euro_char2} == 1) )) ; then - print -u\${pollfd[fifo_a_out].fd} -f '\u[20ac]' + # supports it. + # \$'\u[20ac-]' (note the trailing '-') returns an + # empty string if the unicode codepoint 0x20ac + # cannot be represented in the current locle + if [[ \$'\u[20ac-]' != '' ]] ; then + [[ "\${ wc -C <<<\$'\u[20ac-]' ;}" == ~(Er)[[:space:]]+2 ]] || \ + print -u2 'ASSERT: Unicode 0x20ac is not a character' + print -u\${pollfd[fifo_a_out].fd} -f \$'\u[20ac]' else print -u\${pollfd[fifo_a_out].fd} -f 'X' fi @@ -398,6 +379,7 @@ builtin mkfifo builtin poll builtin rm +builtin wc main exit $? @@ -445,6 +427,7 @@ # run tests builtin poll || { err_exit 'poll builtin not found.'; exit 1; } +builtin rm || { err_exit 'rm builtin not found.'; exit 1; } builtin rmdir || { err_exit 'rmdir builtin not found.'; exit 1; } test1
_______________________________________________ ast-developers mailing list [email protected] http://lists.research.att.com/mailman/listinfo/ast-developers
