--- doc/refchan.n.orig +++ doc/refchan.n @@ -53,8 +53,8 @@ here, then the \fBfinalize\fR subcommand .PP The \fImode\fR argument tells the handler whether the channel was opened for reading, writing, or both. It is a list containing any of -the strings \fBread\fR or \fBwrite\fR. The list will always -contain at least one element. +the strings \fBread\fR or \fBwrite\fR. The list may be empty, but +will usually contain at least one element. .PP The subcommand must throw an error if the chosen mode is not supported by the \fIcmdPrefix\fR. --- generic/tclIORChan.c.orig +++ generic/tclIORChan.c @@ -425,7 +425,7 @@ static void UnmarshallErrorResult(Tcl_I */ static int EncodeEventMask(Tcl_Interp *interp, - const char *objName, Tcl_Obj *obj, int *mask); + const char *objName, Tcl_Obj *obj, int *mask, int needed); static Tcl_Obj * DecodeEventMask(int mask); static ReflectedChannel * NewReflectedChannel(Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj); @@ -532,11 +532,11 @@ TclChanCreateObjCmd( /* * First argument is a list of modes. Allowed entries are "read", "write". - * Expect at least one list element. Abbreviations are ok. + * Empty list is uncommon, but allowed. Abbreviations are ok. */ modeObj = objv[MODE]; - if (EncodeEventMask(interp, "mode", objv[MODE], &mode) != TCL_OK) { + if (EncodeEventMask(interp, "mode", objv[MODE], &mode, 0) != TCL_OK) { return TCL_ERROR; } @@ -902,7 +902,7 @@ TclChanPostEventObjCmd( * "write". Expect at least one list element. Abbreviations are ok. */ - if (EncodeEventMask(interp, "event", objv[EVENT], &events) != TCL_OK) { + if (EncodeEventMask(interp, "event", objv[EVENT], &events, 1) != TCL_OK) { return TCL_ERROR; } @@ -2007,8 +2007,9 @@ ReflectGetOption( * EncodeEventMask -- * * This function takes a list of event items and constructs the - * equivalent internal bitmask. The list must contain at least one - * element. Elements are "read", "write", or any unique abbreviation of + * equivalent internal bitmask. The list may be empty if the last + * argument is 0, otherwise it must contain at least one element. + * Elements are "read", "write", or any unique abbreviation of * them. Note that the bitmask is not changed if problems are * encountered. * @@ -2028,7 +2029,8 @@ EncodeEventMask( Tcl_Interp *interp, const char *objName, Tcl_Obj *obj, - int *mask) + int *mask, + int needed) { int events; /* Mask of events to post */ int listc; /* #elements in eventspec list */ @@ -2040,7 +2042,7 @@ EncodeEventMask( return TCL_ERROR; } - if (listc < 1) { + if (needed && listc < 1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad %s list: is empty", objName)); return TCL_ERROR; --- tests/ioCmd.test.orig +++ tests/ioCmd.test @@ -670,12 +670,12 @@ test iocmd-21.1 {chan create, wrong#args catch {chan create a b c} msg set msg } {wrong # args: should be "chan create mode cmdprefix"} -test iocmd-21.2 {chan create, invalid r/w mode, empty} { - proc foo {} {} - catch {chan create {} foo} msg +test iocmd-21.2 {chan create, r/w mode empty} { + proc foo {cmd args} { return "initialize finalize watch" } + set chan [chan create {} foo] + close $chan rename foo {} - set msg -} {bad mode list: is empty} +} {} test iocmd-21.3 {chan create, invalid r/w mode, bad string} { proc foo {} {} catch {chan create {c} foo} msg