summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2020-01-31 14:58:07 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2020-01-31 14:58:07 (GMT)
commitbfad7e731e065f729b1b29430eadc5599fed2221 (patch)
treee70de8a0b599ae989b87e4991c3da262f6ea1d33
parentff4989d1928248d02e222c2590088c0a5dbb6f46 (diff)
downloadtcl-bfad7e731e065f729b1b29430eadc5599fed2221.zip
tcl-bfad7e731e065f729b1b29430eadc5599fed2221.tar.gz
tcl-bfad7e731e065f729b1b29430eadc5599fed2221.tar.bz2
Make Tcl_ChannelCloseProc() deprecated too. Implement close2Proc and wideSeekProc for all internal channel types.
-rw-r--r--generic/tcl.decls2
-rw-r--r--generic/tcl.h10
-rw-r--r--generic/tclDecls.h5
-rw-r--r--generic/tclIO.c68
-rw-r--r--generic/tclIOGT.c13
-rw-r--r--generic/tclIORChan.c13
-rw-r--r--generic/tclIORTrans.c13
-rw-r--r--generic/tclStubInit.c1
-rw-r--r--generic/tclZipfs.c13
-rw-r--r--generic/tclZlib.c13
-rw-r--r--unix/tclUnixChan.c27
-rw-r--r--unix/tclUnixSock.c4
-rw-r--r--win/tclWinChan.c14
-rw-r--r--win/tclWinConsole.c14
-rw-r--r--win/tclWinSerial.c16
-rw-r--r--win/tclWinSock.c4
16 files changed, 147 insertions, 83 deletions
diff --git a/generic/tcl.decls b/generic/tcl.decls
index 8a88a04..1e124a4 100644
--- a/generic/tcl.decls
+++ b/generic/tcl.decls
@@ -1415,7 +1415,7 @@ declare 400 {
Tcl_DriverBlockModeProc *Tcl_ChannelBlockModeProc(
const Tcl_ChannelType *chanTypePtr)
}
-declare 401 {
+declare 401 {deprecated {Use Tcl_ChannelClose2Proc}} {
Tcl_DriverCloseProc *Tcl_ChannelCloseProc(
const Tcl_ChannelType *chanTypePtr)
}
diff --git a/generic/tcl.h b/generic/tcl.h
index d8a28a5..18a56dc 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -1428,12 +1428,8 @@ typedef int (Tcl_DriverInputProc) (ClientData instanceData, char *buf,
int toRead, int *errorCodePtr);
typedef int (Tcl_DriverOutputProc) (ClientData instanceData,
const char *buf, int toWrite, int *errorCodePtr);
-#ifndef TCL_NO_DEPRECATED
typedef int (Tcl_DriverSeekProc) (ClientData instanceData, long offset,
int mode, int *errorCodePtr);
-#else
-#define Tcl_DriverSeekProc Tcl_DriverWideSeekProc
-#endif
typedef int (Tcl_DriverSetOptionProc) (ClientData instanceData,
Tcl_Interp *interp, const char *optionName,
const char *value);
@@ -1478,19 +1474,15 @@ typedef struct Tcl_ChannelType {
/* Version of the channel type. */
Tcl_DriverCloseProc *closeProc;
/* Function to call to close the channel, or
- * TCL_CLOSE2PROC if the close2Proc should be
+ * NULL or TCL_CLOSE2PROC if the close2Proc should be
* used instead. */
Tcl_DriverInputProc *inputProc;
/* Function to call for input on channel. */
Tcl_DriverOutputProc *outputProc;
/* Function to call for output on channel. */
-#ifdef TCL_NO_DEPRECATED
- struct something_undefined *notUsed;
-#else
Tcl_DriverSeekProc *seekProc;
/* Function to call to seek on the channel.
* May be NULL. */
-#endif
Tcl_DriverSetOptionProc *setOptionProc;
/* Set an option on a channel. */
Tcl_DriverGetOptionProc *getOptionProc;
diff --git a/generic/tclDecls.h b/generic/tclDecls.h
index 6e9b391..6cb7547 100644
--- a/generic/tclDecls.h
+++ b/generic/tclDecls.h
@@ -1206,7 +1206,8 @@ EXTERN Tcl_ChannelTypeVersion Tcl_ChannelVersion(
EXTERN Tcl_DriverBlockModeProc * Tcl_ChannelBlockModeProc(
const Tcl_ChannelType *chanTypePtr);
/* 401 */
-EXTERN Tcl_DriverCloseProc * Tcl_ChannelCloseProc(
+TCL_DEPRECATED("Use Tcl_ChannelClose2Proc")
+Tcl_DriverCloseProc * Tcl_ChannelCloseProc(
const Tcl_ChannelType *chanTypePtr);
/* 402 */
EXTERN Tcl_DriverClose2Proc * Tcl_ChannelClose2Proc(
@@ -2356,7 +2357,7 @@ typedef struct TclStubs {
const char * (*tcl_ChannelName) (const Tcl_ChannelType *chanTypePtr); /* 398 */
Tcl_ChannelTypeVersion (*tcl_ChannelVersion) (const Tcl_ChannelType *chanTypePtr); /* 399 */
Tcl_DriverBlockModeProc * (*tcl_ChannelBlockModeProc) (const Tcl_ChannelType *chanTypePtr); /* 400 */
- Tcl_DriverCloseProc * (*tcl_ChannelCloseProc) (const Tcl_ChannelType *chanTypePtr); /* 401 */
+ TCL_DEPRECATED_API("Use Tcl_ChannelClose2Proc") Tcl_DriverCloseProc * (*tcl_ChannelCloseProc) (const Tcl_ChannelType *chanTypePtr); /* 401 */
Tcl_DriverClose2Proc * (*tcl_ChannelClose2Proc) (const Tcl_ChannelType *chanTypePtr); /* 402 */
Tcl_DriverInputProc * (*tcl_ChannelInputProc) (const Tcl_ChannelType *chanTypePtr); /* 403 */
Tcl_DriverOutputProc * (*tcl_ChannelOutputProc) (const Tcl_ChannelType *chanTypePtr); /* 404 */
diff --git a/generic/tclIO.c b/generic/tclIO.c
index fccc989..370508d 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -374,11 +374,12 @@ ChanClose(
Channel *chanPtr,
Tcl_Interp *interp)
{
- if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) {
+#ifndef TCL_NO_DEPRECATED
+ if ((chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) && (chanPtr->typePtr->closeProc != NULL)) {
return chanPtr->typePtr->closeProc(chanPtr->instanceData, interp);
- } else {
- return chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, 0);
}
+#endif
+ return chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, 0);
}
static inline int
@@ -1630,9 +1631,18 @@ Tcl_CreateChannel(
assert(sizeof(Tcl_ChannelTypeVersion) == sizeof(Tcl_DriverBlockModeProc *));
assert(typePtr->typeName != NULL);
- if (NULL == typePtr->closeProc) {
- Tcl_Panic("channel type %s must define closeProc", typePtr->typeName);
+#ifndef TCL_NO_DEPRECATED
+ if (((NULL == typePtr->closeProc) || (TCL_CLOSE2PROC == typePtr->closeProc)) && (typePtr->close2Proc == NULL)) {
+ Tcl_Panic("channel type %s must define closeProc or close2Proc", typePtr->typeName);
+ }
+#else
+ if (Tcl_ChannelVersion(typePtr) < TCL_CHANNEL_VERSION_5) {
+ Tcl_Panic("channel type %s must be version TCL_CHANNEL_VERSION_5", typePtr->typeName);
+ }
+ if (typePtr->close2Proc == NULL) {
+ Tcl_Panic("channel type %s must define close2Proc", typePtr->typeName);
}
+#endif
if ((TCL_READABLE & mask) && (NULL == typePtr->inputProc)) {
Tcl_Panic("channel type %s must define inputProc when used for reader channel", typePtr->typeName);
}
@@ -1643,17 +1653,9 @@ Tcl_CreateChannel(
Tcl_Panic("channel type %s must define watchProc", typePtr->typeName);
}
#ifndef TCL_NO_DEPRECATED
- if ((NULL!=typePtr->wideSeekProc) && (NULL == typePtr->seekProc)) {
+ if ((NULL != typePtr->wideSeekProc) && (NULL == typePtr->seekProc)) {
Tcl_Panic("channel type %s must define seekProc if defining wideSeekProc", typePtr->typeName);
}
-#elif 1 /* TODO: Too strict for backwards compatibility, just make sure for the Tcl core for now. */
- if (NULL != typePtr->notUsed) {
- Tcl_Panic("channel type %s cannot have seekProc", typePtr->typeName);
- }
-#else
- if ((NULL!=typePtr->notUsed) && (NULL == typePtr->wideSeekProc)) {
- Tcl_Panic("channel type %s must define wideSeekProc if defining seekProc", typePtr->typeName);
- }
#endif
/*
@@ -3396,7 +3398,7 @@ Tcl_Close(
* channel. */
Channel *chanPtr; /* The real IO channel. */
ChannelState *statePtr; /* State of real IO channel. */
- int result; /* Of calling FlushChannel. */
+ int result = 0; /* Of calling FlushChannel. */
int flushcode;
int stickyError;
@@ -3497,12 +3499,14 @@ Tcl_Close(
* it anymore and this will help avoid deadlocks on some channel types.
*/
- if (chanPtr->typePtr->closeProc == TCL_CLOSE2PROC) {
- result = chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp,
- TCL_CLOSE_READ);
- } else {
- result = 0;
+#ifndef TCL_NO_DEPRECATED
+ if ((chanPtr->typePtr->closeProc == TCL_CLOSE2PROC) || (chanPtr->typePtr->closeProc == NULL)) {
+ /* If this half-close fails, just continue the full close */
+ (void)chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, TCL_CLOSE_READ);
}
+#else
+ (void)chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, TCL_CLOSE_READ);
+#endif
/*
* The call to FlushChannel will flush any queued output and invoke the
@@ -3562,19 +3566,17 @@ Tcl_Close(
*
* Tcl_CloseEx --
*
- * Closes one side of a channel, read or write.
+ * Closes one side of a channel, read or write, close all.
*
* Results:
* A standard Tcl result.
*
* Side effects:
- * Closes one direction of the channel.
+ * Closes one direction of the channel, or do a full close.
*
* NOTE:
* Tcl_CloseEx closes the specified direction of the channel as far as
- * the user is concerned. The channel keeps existing however. You cannot
- * calls this function to close the last possible direction of the
- * channel. Use Tcl_Close for that.
+ * the user is concerned. If flags = 0, this is equivalent to Tcl_Close.
*
*----------------------------------------------------------------------
*/
@@ -3594,18 +3596,26 @@ Tcl_CloseEx(
return TCL_OK;
}
- /* TODO: assert flags validity ? */
-
chanPtr = (Channel *) chan;
statePtr = chanPtr->state;
+ if ((flags & (TCL_READABLE | TCL_WRITABLE)) == 0) {
+ return Tcl_Close(interp, chan);
+ }
+ if ((flags & (TCL_READABLE | TCL_WRITABLE)) == (TCL_READABLE | TCL_WRITABLE)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "double-close of channels not supported by %ss",
+ chanPtr->typePtr->typeName));
+ return TCL_ERROR;
+ }
+
/*
* Does the channel support half-close anyway? Error if not.
*/
if (!chanPtr->typePtr->close2Proc) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "half-close of channels not supported by %ss",
+ "half-close of channels not supported by %ss",
chanPtr->typePtr->typeName));
return TCL_ERROR;
}
@@ -10585,6 +10595,7 @@ Tcl_ChannelBlockModeProc(
*----------------------------------------------------------------------
*/
+#ifndef TCL_NO_DEPRECATED
Tcl_DriverCloseProc *
Tcl_ChannelCloseProc(
const Tcl_ChannelType *chanTypePtr)
@@ -10592,6 +10603,7 @@ Tcl_ChannelCloseProc(
{
return chanTypePtr->closeProc;
}
+#endif
/*
*----------------------------------------------------------------------
diff --git a/generic/tclIOGT.c b/generic/tclIOGT.c
index 4195256..c983434 100644
--- a/generic/tclIOGT.c
+++ b/generic/tclIOGT.c
@@ -22,7 +22,7 @@
static int TransformBlockModeProc(ClientData instanceData,
int mode);
static int TransformCloseProc(ClientData instanceData,
- Tcl_Interp *interp);
+ Tcl_Interp *interp, int flags);
static int TransformInputProc(ClientData instanceData, char *buf,
int toRead, int *errorCodePtr);
static int TransformOutputProc(ClientData instanceData,
@@ -121,7 +121,7 @@ static inline void ResultAdd(ResultBuffer *r, unsigned char *buf,
static const Tcl_ChannelType transformChannelType = {
"transform", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
- TransformCloseProc, /* Close proc. */
+ TCL_CLOSE2PROC, /* Close proc. */
TransformInputProc, /* Input proc. */
TransformOutputProc, /* Output proc. */
#ifndef TCL_NO_DEPRECATED
@@ -133,7 +133,7 @@ static const Tcl_ChannelType transformChannelType = {
TransformGetOptionProc, /* Get option proc. */
TransformWatchProc, /* Initialize notifier. */
TransformGetFileHandleProc, /* Get OS handles out of channel. */
- NULL, /* close2proc */
+ TransformCloseProc, /* close2proc */
TransformBlockModeProc, /* Set blocking/nonblocking mode.*/
NULL, /* Flush proc. */
TransformNotifyProc, /* Handling of events bubbling up. */
@@ -539,10 +539,15 @@ TransformBlockModeProc(
static int
TransformCloseProc(
ClientData instanceData,
- Tcl_Interp *interp)
+ Tcl_Interp *interp,
+ int flags)
{
TransformChannelData *dataPtr = instanceData;
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
+
/*
* Important: In this procedure 'dataPtr->self' already points to the
* underlying channel.
diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c
index 3baf8f3..ebe2f7e 100644
--- a/generic/tclIORChan.c
+++ b/generic/tclIORChan.c
@@ -32,7 +32,7 @@
*/
static int ReflectClose(ClientData clientData,
- Tcl_Interp *interp);
+ Tcl_Interp *interp, int flags);
static int ReflectInput(ClientData clientData, char *buf,
int toRead, int *errorCodePtr);
static int ReflectOutput(ClientData clientData, const char *buf,
@@ -67,7 +67,7 @@ static void TimerRunWrite(ClientData clientData);
static const Tcl_ChannelType tclRChannelType = {
"tclrchannel", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
- ReflectClose, /* Close channel, clean instance data */
+ TCL_CLOSE2PROC, /* Close channel, clean instance data */
ReflectInput, /* Handle read request */
ReflectOutput, /* Handle write request */
#ifndef TCL_NO_DEPRECATED
@@ -79,7 +79,7 @@ static const Tcl_ChannelType tclRChannelType = {
ReflectGetOption, /* Get options. NULL'able */
ReflectWatch, /* Initialize notifier */
NULL, /* Get OS handle from the channel. NULL'able */
- NULL, /* No close2 support. NULL'able */
+ ReflectClose, /* No close2 support. NULL'able */
ReflectBlock, /* Set blocking/nonblocking. NULL'able */
NULL, /* Flush channel. Not used by core. NULL'able */
NULL, /* Handle events. NULL'able */
@@ -1158,7 +1158,8 @@ TclChanCaughtErrorBypass(
static int
ReflectClose(
ClientData clientData,
- Tcl_Interp *interp)
+ Tcl_Interp *interp,
+ int flags)
{
ReflectedChannel *rcPtr = clientData;
int result; /* Result code for 'close' */
@@ -1168,6 +1169,10 @@ ReflectClose(
Tcl_HashEntry *hPtr; /* Entry in the above map */
const Tcl_ChannelType *tctPtr;
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
+
if (TclInThreadExit()) {
/*
* This call comes from TclFinalizeIOSystem. There are no
diff --git a/generic/tclIORTrans.c b/generic/tclIORTrans.c
index 70dd640..316378f 100644
--- a/generic/tclIORTrans.c
+++ b/generic/tclIORTrans.c
@@ -32,7 +32,7 @@
*/
static int ReflectClose(ClientData clientData,
- Tcl_Interp *interp);
+ Tcl_Interp *interp, int flags);
static int ReflectInput(ClientData clientData, char *buf,
int toRead, int *errorCodePtr);
static int ReflectOutput(ClientData clientData, const char *buf,
@@ -62,7 +62,7 @@ static int ReflectNotify(ClientData clientData, int mask);
static const Tcl_ChannelType tclRTransformType = {
"tclrtransform", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel. */
- ReflectClose, /* Close channel, clean instance data. */
+ TCL_CLOSE2PROC, /* Close channel, clean instance data. */
ReflectInput, /* Handle read request. */
ReflectOutput, /* Handle write request. */
#ifndef TCL_NO_DEPRECATED
@@ -74,7 +74,7 @@ static const Tcl_ChannelType tclRTransformType = {
ReflectGetOption, /* Get options. */
ReflectWatch, /* Initialize notifier. */
ReflectHandle, /* Get OS handle from the channel. */
- NULL, /* No close2 support. NULL'able. */
+ ReflectClose, /* No close2 support. NULL'able. */
ReflectBlock, /* Set blocking/nonblocking. */
NULL, /* Flush channel. Not used by core.
* NULL'able. */
@@ -885,7 +885,8 @@ UnmarshallErrorResult(
static int
ReflectClose(
ClientData clientData,
- Tcl_Interp *interp)
+ Tcl_Interp *interp,
+ int flags)
{
ReflectedTransform *rtPtr = clientData;
int errorCode, errorCodeSet = 0;
@@ -896,6 +897,10 @@ ReflectClose(
* in this interp. */
Tcl_HashEntry *hPtr; /* Entry in the above map */
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
+
if (TclInThreadExit()) {
/*
* This call comes from TclFinalizeIOSystem. There are no
diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c
index 927f1d0..971d42d 100644
--- a/generic/tclStubInit.c
+++ b/generic/tclStubInit.c
@@ -257,6 +257,7 @@ mp_err TclBN_mp_mul_d(const mp_int *a, unsigned int b, mp_int *c) {
# define Tcl_BackgroundError 0
# define Tcl_FreeResult 0
# define Tcl_ChannelSeekProc 0
+# define Tcl_ChannelCloseProc 0
#else
mp_err TclBN_mp_div_3(const mp_int *a, mp_int *c, unsigned int *d) {
diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c
index b45d86e..ee87af0 100644
--- a/generic/tclZipfs.c
+++ b/generic/tclZipfs.c
@@ -385,7 +385,7 @@ static int ZipFSLoadFile(Tcl_Interp *interp, Tcl_Obj *path,
static void ZipfsExitHandler(ClientData clientData);
static void ZipfsSetup(void);
static int ZipChannelClose(void *instanceData,
- Tcl_Interp *interp);
+ Tcl_Interp *interp, int flags);
static int ZipChannelGetFile(void *instanceData,
int direction, void **handlePtr);
static int ZipChannelRead(void *instanceData, char *buf,
@@ -446,7 +446,7 @@ static const Tcl_Filesystem zipfsFilesystem = {
static Tcl_ChannelType ZipChannelType = {
"zip", /* Type name. */
TCL_CHANNEL_VERSION_5,
- ZipChannelClose, /* Close channel, clean instance data */
+ TCL_CLOSE2PROC, /* Close channel, clean instance data */
ZipChannelRead, /* Handle read request */
ZipChannelWrite, /* Handle write request */
#ifndef TCL_NO_DEPRECATED
@@ -458,7 +458,7 @@ static Tcl_ChannelType ZipChannelType = {
NULL, /* Get options, NULL'able */
ZipChannelWatchChannel, /* Initialize notifier */
ZipChannelGetFile, /* Get OS handle from the channel */
- NULL, /* 2nd version of close channel, NULL'able */
+ ZipChannelClose, /* 2nd version of close channel, NULL'able */
NULL, /* Set blocking mode for raw channel, NULL'able */
NULL, /* Function to flush channel, NULL'able */
NULL, /* Function to handle event, NULL'able */
@@ -3318,10 +3318,15 @@ ZipFSTclLibraryObjCmd(
static int
ZipChannelClose(
void *instanceData,
- Tcl_Interp *dummy) /* Current interpreter. */
+ Tcl_Interp *dummy, /* Current interpreter. */
+ int flags)
{
ZipChannel *info = instanceData;
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
+
if (info->iscompr && info->ubuf) {
ckfree(info->ubuf);
info->ubuf = NULL;
diff --git a/generic/tclZlib.c b/generic/tclZlib.c
index 49f1c39..44451e2 100644
--- a/generic/tclZlib.c
+++ b/generic/tclZlib.c
@@ -160,7 +160,7 @@ typedef struct {
static Tcl_CmdDeleteProc ZlibStreamCmdDelete;
static Tcl_DriverBlockModeProc ZlibTransformBlockMode;
-static Tcl_DriverCloseProc ZlibTransformClose;
+static Tcl_DriverClose2Proc ZlibTransformClose;
static Tcl_DriverGetHandleProc ZlibTransformGetHandle;
static Tcl_DriverGetOptionProc ZlibTransformGetOption;
static Tcl_DriverHandlerProc ZlibTransformEventHandler;
@@ -205,7 +205,7 @@ static void ZlibTransformTimerRun(void *clientData);
static const Tcl_ChannelType zlibChannelType = {
"zlib",
TCL_CHANNEL_VERSION_5,
- ZlibTransformClose,
+ TCL_CLOSE2PROC,
ZlibTransformInput,
ZlibTransformOutput,
NULL, /* seekProc */
@@ -213,7 +213,7 @@ static const Tcl_ChannelType zlibChannelType = {
ZlibTransformGetOption,
ZlibTransformWatch,
ZlibTransformGetHandle,
- NULL, /* close2Proc */
+ ZlibTransformClose, /* close2Proc */
ZlibTransformBlockMode,
NULL, /* flushProc */
ZlibTransformEventHandler,
@@ -2895,11 +2895,16 @@ ZlibStreamHeaderCmd(
static int
ZlibTransformClose(
void *instanceData,
- Tcl_Interp *interp)
+ Tcl_Interp *interp,
+ int flags)
{
ZlibChannelData *cd = instanceData;
int e, written, result = TCL_OK;
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
+
/*
* Delete the support timer.
*/
diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c
index 56a0276..e1b7223 100644
--- a/unix/tclUnixChan.c
+++ b/unix/tclUnixChan.c
@@ -121,7 +121,7 @@ typedef struct {
static int FileBlockModeProc(ClientData instanceData, int mode);
static int FileCloseProc(ClientData instanceData,
- Tcl_Interp *interp);
+ Tcl_Interp *interp, int flags);
static int FileGetHandleProc(ClientData instanceData,
int direction, ClientData *handlePtr);
static int FileInputProc(ClientData instanceData, char *buf,
@@ -139,7 +139,7 @@ static Tcl_WideInt FileWideSeekProc(ClientData instanceData,
static void FileWatchProc(ClientData instanceData, int mask);
#ifdef SUPPORTS_TTY
static int TtyCloseProc(ClientData instanceData,
- Tcl_Interp *interp);
+ Tcl_Interp *interp, int flags);
static void TtyGetAttributes(int fd, TtyAttrs *ttyPtr);
static int TtyGetOptionProc(ClientData instanceData,
Tcl_Interp *interp, const char *optionName,
@@ -163,7 +163,7 @@ static int TtySetOptionProc(ClientData instanceData,
static const Tcl_ChannelType fileChannelType = {
"file", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
- FileCloseProc, /* Close proc. */
+ TCL_CLOSE2PROC, /* Close proc. */
FileInputProc, /* Input proc. */
FileOutputProc, /* Output proc. */
#ifndef TCL_NO_DEPRECATED
@@ -175,7 +175,7 @@ static const Tcl_ChannelType fileChannelType = {
NULL, /* Get option proc. */
FileWatchProc, /* Initialize notifier. */
FileGetHandleProc, /* Get OS handles out of channel. */
- NULL, /* close2proc. */
+ FileCloseProc, /* close2proc. */
FileBlockModeProc, /* Set blocking or non-blocking mode.*/
NULL, /* flush proc. */
NULL, /* handler proc. */
@@ -193,7 +193,7 @@ static const Tcl_ChannelType fileChannelType = {
static const Tcl_ChannelType ttyChannelType = {
"tty", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
- TtyCloseProc, /* Close proc. */
+ TCL_CLOSE2PROC, /* Close proc. */
FileInputProc, /* Input proc. */
FileOutputProc, /* Output proc. */
NULL, /* Seek proc. */
@@ -201,7 +201,7 @@ static const Tcl_ChannelType ttyChannelType = {
TtyGetOptionProc, /* Get option proc. */
FileWatchProc, /* Initialize notifier. */
FileGetHandleProc, /* Get OS handles out of channel. */
- NULL, /* close2proc. */
+ TtyCloseProc, /* close2proc. */
FileBlockModeProc, /* Set blocking or non-blocking mode.*/
NULL, /* flush proc. */
NULL, /* handler proc. */
@@ -359,11 +359,16 @@ FileOutputProc(
static int
FileCloseProc(
ClientData instanceData, /* File state. */
- Tcl_Interp *interp) /* For error reporting - unused. */
+ Tcl_Interp *dummy, /* For error reporting - unused. */
+ int flags)
{
FileState *fsPtr = instanceData;
int errorCode = 0;
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
+
Tcl_DeleteFileHandler(fsPtr->fd);
/*
@@ -384,10 +389,14 @@ FileCloseProc(
static int
TtyCloseProc(
ClientData instanceData,
- Tcl_Interp *interp)
+ Tcl_Interp *interp,
+ int flags)
{
TtyState *ttyPtr = instanceData;
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
/*
* If we've been asked by the user to drain or flush, do so now.
*/
@@ -416,7 +425,7 @@ TtyCloseProc(
* Delegate to close for files.
*/
- return FileCloseProc(instanceData, interp);
+ return FileCloseProc(instanceData, interp, flags);
}
#endif /* SUPPORTS_TTY */
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
index 57735da..e9c552e 100644
--- a/unix/tclUnixSock.c
+++ b/unix/tclUnixSock.c
@@ -157,7 +157,11 @@ static void WrapNotify(ClientData clientData, int mask);
static const Tcl_ChannelType tcpChannelType = {
"tcp", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
+#ifndef TCL_NO_DEPRECATED
TcpCloseProc, /* Close proc. */
+#else
+ TCL_CLOSE2PROC, /* Close proc. */
+#endif
TcpInputProc, /* Input proc. */
TcpOutputProc, /* Output proc. */
NULL, /* Seek proc. */
diff --git a/win/tclWinChan.c b/win/tclWinChan.c
index 829cc74..b7f5c04 100644
--- a/win/tclWinChan.c
+++ b/win/tclWinChan.c
@@ -76,7 +76,7 @@ static int FileBlockProc(ClientData instanceData, int mode);
static void FileChannelExitHandler(ClientData clientData);
static void FileCheckProc(ClientData clientData, int flags);
static int FileCloseProc(ClientData instanceData,
- Tcl_Interp *interp);
+ Tcl_Interp *interp, int flags);
static int FileEventProc(Tcl_Event *evPtr, int flags);
static int FileGetHandleProc(ClientData instanceData,
int direction, ClientData *handlePtr);
@@ -107,7 +107,7 @@ static int NativeIsComPort(const WCHAR *nativeName);
static const Tcl_ChannelType fileChannelType = {
"file", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
- FileCloseProc, /* Close proc. */
+ TCL_CLOSE2PROC, /* Close proc. */
FileInputProc, /* Input proc. */
FileOutputProc, /* Output proc. */
#ifndef TCL_NO_DEPRECATED
@@ -119,7 +119,7 @@ static const Tcl_ChannelType fileChannelType = {
NULL, /* Get option proc. */
FileWatchProc, /* Set up the notifier to watch the channel. */
FileGetHandleProc, /* Get an OS handle from channel. */
- NULL, /* close2proc. */
+ FileCloseProc, /* close2proc. */
FileBlockProc, /* Set blocking or non-blocking mode.*/
NULL, /* flush proc. */
NULL, /* handler proc. */
@@ -392,12 +392,18 @@ FileBlockProc(
static int
FileCloseProc(
ClientData instanceData, /* Pointer to FileInfo structure. */
- Tcl_Interp *interp) /* Not used. */
+ Tcl_Interp *dummy, /* Not used. */
+ int flags)
{
FileInfo *fileInfoPtr = instanceData;
FileInfo *infoPtr;
ThreadSpecificData *tsdPtr;
int errorCode = 0;
+ (void)dummy;
+
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
/*
* Remove the file from the watch list.
diff --git a/win/tclWinConsole.c b/win/tclWinConsole.c
index 7de425b..632f0e7 100644
--- a/win/tclWinConsole.c
+++ b/win/tclWinConsole.c
@@ -142,7 +142,7 @@ static int ConsoleBlockModeProc(ClientData instanceData,
int mode);
static void ConsoleCheckProc(ClientData clientData, int flags);
static int ConsoleCloseProc(ClientData instanceData,
- Tcl_Interp *interp);
+ Tcl_Interp *interp, int flags);
static int ConsoleEventProc(Tcl_Event *evPtr, int flags);
static void ConsoleExitHandler(ClientData clientData);
static int ConsoleGetHandleProc(ClientData instanceData,
@@ -180,7 +180,7 @@ static BOOL WriteConsoleBytes(HANDLE hConsole,
static const Tcl_ChannelType consoleChannelType = {
"console", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
- ConsoleCloseProc, /* Close proc. */
+ TCL_CLOSE2PROC, /* Close proc. */
ConsoleInputProc, /* Input proc. */
ConsoleOutputProc, /* Output proc. */
NULL, /* Seek proc. */
@@ -188,7 +188,7 @@ static const Tcl_ChannelType consoleChannelType = {
ConsoleGetOptionProc, /* Get option proc. */
ConsoleWatchProc, /* Set up notifier to watch the channel. */
ConsoleGetHandleProc, /* Get an OS handle from channel. */
- NULL, /* close2proc. */
+ ConsoleCloseProc, /* close2proc. */
ConsoleBlockModeProc, /* Set blocking or non-blocking mode. */
NULL, /* Flush proc. */
NULL, /* Handler proc. */
@@ -531,12 +531,18 @@ ConsoleBlockModeProc(
static int
ConsoleCloseProc(
ClientData instanceData, /* Pointer to ConsoleInfo structure. */
- Tcl_Interp *interp) /* For error reporting. */
+ Tcl_Interp *dummy, /* For error reporting. */
+ int flags)
{
ConsoleInfo *consolePtr = instanceData;
int errorCode = 0;
ConsoleInfo *infoPtr, **nextPtrPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ (void)dummy;
+
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
/*
* Clean up the background thread if necessary. Note that this must be
diff --git a/win/tclWinSerial.c b/win/tclWinSerial.c
index e945055..ec5d17b 100644
--- a/win/tclWinSerial.c
+++ b/win/tclWinSerial.c
@@ -168,7 +168,7 @@ static COMMTIMEOUTS no_timeout = {
static int SerialBlockProc(ClientData instanceData, int mode);
static void SerialCheckProc(ClientData clientData, int flags);
static int SerialCloseProc(ClientData instanceData,
- Tcl_Interp *interp);
+ Tcl_Interp *interp, int flags);
static int SerialEventProc(Tcl_Event *evPtr, int flags);
static void SerialExitHandler(ClientData clientData);
static int SerialGetHandleProc(ClientData instanceData,
@@ -204,7 +204,7 @@ static int SerialBlockingWrite(SerialInfo *infoPtr, LPVOID buf,
static const Tcl_ChannelType serialChannelType = {
"serial", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
- SerialCloseProc, /* Close proc. */
+ TCL_CLOSE2PROC, /* Close proc. */
SerialInputProc, /* Input proc. */
SerialOutputProc, /* Output proc. */
NULL, /* Seek proc. */
@@ -212,7 +212,7 @@ static const Tcl_ChannelType serialChannelType = {
SerialGetOptionProc, /* Get option proc. */
SerialWatchProc, /* Set up notifier to watch the channel. */
SerialGetHandleProc, /* Get an OS handle from channel. */
- NULL, /* close2proc. */
+ SerialCloseProc, /* close2proc. */
SerialBlockProc, /* Set blocking or non-blocking mode.*/
NULL, /* flush proc. */
NULL, /* handler proc. */
@@ -597,14 +597,18 @@ SerialBlockProc(
static int
SerialCloseProc(
ClientData instanceData, /* Pointer to SerialInfo structure. */
- Tcl_Interp *interp) /* For error reporting. */
+ Tcl_Interp *interp, /* For error reporting. */
+ int flags)
{
SerialInfo *serialPtr = (SerialInfo *) instanceData;
- int errorCode, result = 0;
+ int errorCode = 0, result = 0;
SerialInfo *infoPtr, **nextPtrPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- errorCode = 0;
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
+
if (serialPtr->validMask & TCL_READABLE) {
PurgeComm(serialPtr->handle, PURGE_RXABORT | PURGE_RXCLEAR);
diff --git a/win/tclWinSock.c b/win/tclWinSock.c
index 8b42b9b..8213fde 100644
--- a/win/tclWinSock.c
+++ b/win/tclWinSock.c
@@ -280,7 +280,11 @@ static Tcl_DriverGetHandleProc TcpGetHandleProc;
static const Tcl_ChannelType tcpChannelType = {
"tcp", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
+#ifndef TCL_NO_DEPRECATED
TcpCloseProc, /* Close proc. */
+#else
+ TCL_CLOSE2PROC, /* Close proc. */
+#endif
TcpInputProc, /* Input proc. */
TcpOutputProc, /* Output proc. */
NULL, /* Seek proc. */