*** doc/CrtChannel.3	1 Jul 2002 18:24:39 -0000	1.16
--- doc/CrtChannel.3	14 Jan 2004 02:18:02 -0000
***************
*** 7,17 ****
  '\"
  '\" RCS: @(#) $Id: CrtChannel.3,v 1.16 2002/07/01 18:24:39 jenglish Exp $
  .so man.macros
! .TH Tcl_CreateChannel 3 8.3 Tcl "Tcl Library Procedures"
  .BS
  '\" Note:  do not modify the .SH NAME line immediately below!
  .SH NAME
! Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption, Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelWideSeekProc, Tcl_ChannelSetOptionProc, Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, Tcl_ChannelHandlerProc, Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting, Tcl_ClearChannelHandlers, Tcl_GetChannelThread, Tcl_ChannelBuffered \- procedures for creating and manipulating channels
  .SH SYNOPSIS
  .nf
  \fB#include <tcl.h>\fR
--- 7,17 ----
  '\"
  '\" RCS: @(#) $Id: CrtChannel.3,v 1.16 2002/07/01 18:24:39 jenglish Exp $
  .so man.macros
! .TH Tcl_CreateChannel 3 8.5 Tcl "Tcl Library Procedures"
  .BS
  '\" Note:  do not modify the .SH NAME line immediately below!
  .SH NAME
! Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption, Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelWideSeekProc, Tcl_ChannelSetOptionProc, Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, Tcl_ChannelHandlerProc,  Tcl_ChannelCutProc,  Tcl_ChannelSpliceProc, Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting, Tcl_ClearChannelHandlers, Tcl_GetChannelThread, Tcl_ChannelBuffered \- procedures for creating and manipulating channels
  .SH SYNOPSIS
  .nf
  \fB#include <tcl.h>\fR
***************
*** 98,103 ****
--- 98,113 ----
  \fBTcl_ChannelWideSeekProc\fR(\fItypePtr\fR)
  .VE 8.4
  .sp
+ .VS 8.5
+ Tcl_DriverCutProc *
+ \fBTcl_ChannelCutProc\fR(\fItypePtr\fR)
+ .VE 8.5
+ .sp
+ .VS 8.5
+ Tcl_DriverSpliceProc *
+ \fBTcl_ChannelSpliceProc\fR(\fItypePtr\fR)
+ .VE 8.5
+ .sp
  Tcl_DriverSetOptionProc *
  \fBTcl_ChannelSetOptionProc\fR(\fItypePtr\fR)
  .sp
***************
*** 286,295 ****
--- 296,313 ----
  (thread)global list of all channels (of the current thread).
  Application to a channel still registered in some interpreter
  is not allowed.
+ .VS 8.5
+ Also notifiers the driver if the \fBTcl_ChannelType\fR version is
+ \fBTCL_CHANNEL_VERSION_4\fR (or higher).
+ .VE 8.5
  .PP
  \fBTcl_SpliceChannel\fR adds the specified \fIchannel\fR to the
  (thread)global list of all channels (of the current thread).
  Application to a channel registered in some interpreter is not allowed.
+ .VS 8.5
+ Also notifiers the driver if the \fBTcl_ChannelType\fR version is
+ \fBTCL_CHANNEL_VERSION_4\fR (or higher).
+ .VE 8.5
  .PP
  \fBTcl_ClearChannelHandlers\fR removes all channelhandlers and event
  scripts associated with the specified \fIchannel\fR, thus shutting
***************
*** 323,328 ****
--- 341,348 ----
  	Tcl_DriverFlushProc *\fIflushProc\fR;	
  	Tcl_DriverHandlerProc *\fIhandlerProc\fR;	
  	Tcl_DriverWideSeekProc *\fIwideSeekProc\fR;
+ 	Tcl_DriverCutProc *\fIcutProc\fR;
+ 	Tcl_DriverSpliceProc *\fIspliceProc\fR;
  } Tcl_ChannelType;
  .CE
  .PP
***************
*** 344,349 ****
--- 364,372 ----
  .VS 8.4
  \fBTcl_ChannelWideSeekProc\fR,
  .VE 8.4
+ .VS 8.5
+ \fBTcl_ChannelCutProc\fR, \fBTcl_ChannelSpliceProc\fR,
+ .VE 8.5
  \fBTcl_ChannelSetOptionProc\fR, \fBTcl_ChannelGetOptionProc\fR,
  \fBTcl_ChannelWatchProc\fR, \fBTcl_ChannelGetHandleProc\fR,
  \fBTcl_ChannelFlushProc\fR, or \fBTcl_ChannelHandlerProc\fR.
***************
*** 364,377 ****
  
  .SH VERSION
  .PP
! The \fIversion\fR field should be set to \fBTCL_CHANNEL_VERSION_2\fR.
! If it is not set to this value \fBTCL_CHANNEL_VERSION_3\fR, then this
! \fBTcl_ChannelType\fR is assumed to have the older structure.  See
  \fBOLD CHANNEL TYPES\fR for more details.  While Tcl will recognize
! and function with either structure, stacked channels must be of at
  least \fBTCL_CHANNEL_VERSION_2\fR to function correctly.
  .PP
  This value can be retrieved with \fBTcl_ChannelVersion\fR, which returns
  .VS 8.4
  one of \fBTCL_CHANNEL_VERSION_3\fR,
  .VE 8.4
--- 387,411 ----
  
  .SH VERSION
  .PP
! The \fIversion\fR field should be set to the version of the structure
! that you require.  \fBTCL_CHANNEL_VERSION_2\fR is the minimum recommended.
! .VS 8.4
! \fBTCL_CHANNEL_VERSION_3\fR must be set to specifiy the \fIwideSeekProc\fR member.
! .VE 8.4
! .VS 8.5
! \fBTCL_CHANNEL_VERSION_4\fR must be set to specifiy the \fIcutProc\fR and
! \fIspliceProc\fR members (includes \fIwideSeekProc\fR).
! .VE 8.5
! If it is not set to any of these, then this
! \fBTcl_ChannelType\fR is assumed to have the original structure.  See
  \fBOLD CHANNEL TYPES\fR for more details.  While Tcl will recognize
! and function with either structures, stacked channels must be of at
  least \fBTCL_CHANNEL_VERSION_2\fR to function correctly.
  .PP
  This value can be retrieved with \fBTcl_ChannelVersion\fR, which returns
+ .VS 8.5
+ one of \fBTCL_CHANNEL_VERSION_4\fR,
+ .VE 8.5
  .VS 8.4
  one of \fBTCL_CHANNEL_VERSION_3\fR,
  .VE 8.4
***************
*** 779,784 ****
--- 813,847 ----
  This value can be retrieved with \fBTcl_ChannelHandlerProc\fR, which returns
  a pointer to the function.
  
+ .VS 8.5
+ .SH "CUTPROC AND SPLICEPROC"
+ .PP
+ The \fIcutProc\fR and \fIspliceProc\fR fields contain the addresses of
+ the functions called by the generic layer when a channel is to move to
+ a different thread and can be NULL.  \fIcutProc\fR is used to notify the
+ driver that it should remove any thread-specific references it might be
+ maintaining. \fIcutProc\fR can also be called when the channel is closing,
+ too.  \fIspliceProc\fR is used to notify the driver that it should update
+ any thread-specific references it might be maintaining using the calling
+ thread as the associate. See \fBTcl_CutChannel\fR and \fBTcl_SpliceChannel\fR
+ for more detail.
+ .PP
+ .CS
+ typedef void Tcl_DriverCutProc(
+ 	ClientData \fIinstanceData\fR);
+ .CE
+ .CS
+ typedef void Tcl_DriverSpliceProc(
+ 	ClientData \fIinstanceData\fR);
+ .CE
+ .PP
+ \fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR
+ when this channel was created.
+ .PP
+ These values can be retrieved with \fBTcl_ChannelCutProc\fR and
+ \fBTcl_ChannelCutProc\fR, which returns a pointer to the function.
+ .VE 8.5
+ 
  .SH TCL_BADCHANNELOPTION
  .PP
  This procedure generates a "bad option" error message in an

*** generic/tcl.decls	29 Sep 2003 21:38:49 -0000	1.101
--- generic/tcl.decls	14 Jan 2004 02:18:05 -0000
***************
*** 1860,1865 ****
--- 1860,1873 ----
      Tcl_ExitProc *Tcl_SetExitProc(Tcl_ExitProc *proc)
  }
  
+ # davygrvy channelType ver 4 TIP#{unassigned}
+ declare 520 generic {
+     Tcl_DriverCutProc *Tcl_ChannelCutProc(Tcl_ChannelType *chanTypePtr)
+ }
+ declare 521 generic {
+     Tcl_DriverSpliceProc *Tcl_ChannelSpliceProc(Tcl_ChannelType *chanTypePtr)
+ }
+ 
  ##############################################################################
  
  # Define the platform specific public Tcl interface.  These functions are

*** generic/tcl.h	9 Jan 2004 20:55:26 -0000	1.170
--- generic/tcl.h	14 Jan 2004 02:18:09 -0000
***************
*** 1434,1440 ****
   * should be closed.
   */
  #define TCL_CLOSE_READ		(1<<1)
! #define TCL_CLOSE_WRITE	(1<<2)
  
  /*
   * Value to use as the closeProc for a channel that supports the
--- 1434,1440 ----
   * should be closed.
   */
  #define TCL_CLOSE_READ		(1<<1)
! #define TCL_CLOSE_WRITE		(1<<2)
  
  /*
   * Value to use as the closeProc for a channel that supports the
***************
*** 1448,1453 ****
--- 1448,1454 ----
  #define TCL_CHANNEL_VERSION_1	((Tcl_ChannelTypeVersion) 0x1)
  #define TCL_CHANNEL_VERSION_2	((Tcl_ChannelTypeVersion) 0x2)
  #define TCL_CHANNEL_VERSION_3	((Tcl_ChannelTypeVersion) 0x3)
+ #define TCL_CHANNEL_VERSION_4	((Tcl_ChannelTypeVersion) 0x4)
  
  /*
   * Typedefs for the various operations in a channel type:
***************
*** 1482,1487 ****
--- 1483,1492 ----
  typedef Tcl_WideInt (Tcl_DriverWideSeekProc) _ANSI_ARGS_((
  		    ClientData instanceData, Tcl_WideInt offset,
  		    int mode, int *errorCodePtr));
+ typedef void	(Tcl_DriverCutProc) _ANSI_ARGS_((
+ 		    ClientData instanceData));
+ typedef void	(Tcl_DriverSpliceProc) _ANSI_ARGS_((
+ 		    ClientData instanceData));
  
  
  /*
***************
*** 1573,1578 ****
--- 1578,1594 ----
  					 * handle 64-bit offsets. May be
  					 * NULL, and must be NULL if
  					 * seekProc is NULL. */
+     /*
+      * Only valid in TCL_CHANNEL_VERSION_4 channels or later
+      */
+     Tcl_DriverCutProc *cutProc;		/* Procedure to call to allow the
+ 					 * driver to remove any thread
+ 					 * specific data. */
+     Tcl_DriverSpliceProc *spliceProc;	/* Procedure to call to allow the
+ 					 * driver to insert new thread
+ 					 * specific data on the moved
+ 					 * channel. */
+ 
  } Tcl_ChannelType;
  
  /*
***************
*** 1580,1587 ****
   * set the channel into blocking or nonblocking mode. They are passed
   * as arguments to the blockModeProc procedure in the above structure.
   */
! #define TCL_MODE_BLOCKING 0		/* Put channel into blocking mode. */
! #define TCL_MODE_NONBLOCKING 1		/* Put channel into nonblocking
  					 * mode. */
  
  /*
--- 1596,1603 ----
   * set the channel into blocking or nonblocking mode. They are passed
   * as arguments to the blockModeProc procedure in the above structure.
   */
! #define TCL_MODE_BLOCKING	0	/* Put channel into blocking mode. */
! #define TCL_MODE_NONBLOCKING	1	/* Put channel into nonblocking
  					 * mode. */
  
  /*

*** generic/tclInt.h	13 Jan 2004 23:15:03 -0000	1.140
--- generic/tclInt.h	14 Jan 2004 02:18:17 -0000
***************
*** 1786,1795 ****
  EXTERN Tcl_Channel	TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp *interp,
  			    Tcl_Obj *pathPtr, int mode,
  			    int permissions));
- EXTERN void		TclpCutFileChannel _ANSI_ARGS_((Tcl_Channel chan));
- EXTERN void		TclpCutSockChannel _ANSI_ARGS_((Tcl_Channel chan));
- EXTERN void		TclpSpliceFileChannel _ANSI_ARGS_((Tcl_Channel chan));
- EXTERN void		TclpSpliceSockChannel _ANSI_ARGS_((Tcl_Channel chan));
  EXTERN void		TclpPanic _ANSI_ARGS_(TCL_VARARGS(CONST char *,
  			    format));
  EXTERN char *		TclpReadlink _ANSI_ARGS_((CONST char *fileName,
--- 1786,1791 ----

*** generic/tclIO.c	24 Dec 2003 04:18:19 -0000	1.69
--- generic/tclIO.c	14 Jan 2004 02:18:24 -0000
***************
*** 2388,2393 ****
--- 2388,2394 ----
                                           * channel out of the list on close. */
      ChannelState *statePtr = ((Channel *) chan)->state;
  					/* state of the channel stack. */
+     Tcl_DriverCutProc *cutProc;
  
      /*
       * Remove this channel from of the list of all channels
***************
*** 2410,2417 ****
  
      statePtr->nextCSPtr = (ChannelState *) NULL;
  
!     TclpCutFileChannel(chan);
!     TclpCutSockChannel(chan);
  }
  
  /*
--- 2411,2420 ----
  
      statePtr->nextCSPtr = (ChannelState *) NULL;
  
!     cutProc = Tcl_ChannelCutProc(Tcl_GetChannelType(chan));
!     if (cutProc != NULL) {
! 	(*cutProc)(Tcl_GetChannelInstanceData(chan));
!     }
  }
  
  /*
***************
*** 2448,2453 ****
--- 2451,2457 ----
  {
      ThreadSpecificData	*tsdPtr = TCL_TSD_INIT(&dataKey);
      ChannelState	*statePtr = ((Channel *) chan)->state;
+     Tcl_DriverSpliceProc *spliceProc;
  
      if (statePtr->nextCSPtr != (ChannelState *) NULL) {
          Tcl_Panic("Tcl_SpliceChannel: trying to add channel used in different list");
***************
*** 2462,2471 ****
       *          values even for a non-threaded core.
       */
  
!     statePtr->managingThread = Tcl_GetCurrentThread ();
! 
!     TclpSpliceFileChannel(chan);
!     TclpSpliceSockChannel(chan);
  }
  
  /*
--- 2466,2476 ----
       *          values even for a non-threaded core.
       */
  
!     statePtr->managingThread = Tcl_GetCurrentThread();
!     spliceProc = Tcl_ChannelSpliceProc(Tcl_GetChannelType(chan));
!     if (spliceProc != NULL) {
! 	(*spliceProc)(Tcl_GetChannelInstanceData(chan));
!     }
  }
  
  /*
***************
*** 8826,8831 ****
--- 8831,8838 ----
  	return TCL_CHANNEL_VERSION_2;
      } else if (chanTypePtr->version == TCL_CHANNEL_VERSION_3) {
  	return TCL_CHANNEL_VERSION_3;
+     } else if (chanTypePtr->version == TCL_CHANNEL_VERSION_4) {
+ 	return TCL_CHANNEL_VERSION_4;
      } else {
  	/*
  	 * In <v2 channel versions, the version field is occupied
***************
*** 9178,9180 ****
--- 9185,9241 ----
  	return NULL;
      }
  }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * Tcl_ChannelCutProc --
+  *
+  *	Return the Tcl_DriverCutProc of the channel type.
+  *
+  * Results:
+  *	A pointer to the proc.
+  *
+  * Side effects:
+  *	None.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ Tcl_DriverCutProc *
+ Tcl_ChannelCutProc(chanTypePtr)
+     Tcl_ChannelType *chanTypePtr;	/* Pointer to channel type. */
+ {
+     if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_4)) {
+ 	return chanTypePtr->cutProc;
+     } else {
+ 	return NULL;
+     }
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * Tcl_ChannelSpliceProc --
+  *
+  *	Return the Tcl_DriverSpliceProc of the channel type.
+  *
+  * Results:
+  *	A pointer to the proc.
+  *
+  * Side effects:
+  *	None.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ Tcl_DriverSpliceProc *
+ Tcl_ChannelSpliceProc(chanTypePtr)
+     Tcl_ChannelType *chanTypePtr;	/* Pointer to channel type. */
+ {
+     if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_4)) {
+ 	return chanTypePtr->spliceProc;
+     } else {
+ 	return NULL;
+     }
+ }

*** generic/tclIOGT.c	24 May 2002 21:19:06 -0000	1.7
--- generic/tclIOGT.c	14 Jan 2004 02:18:26 -0000
***************
*** 131,137 ****
  
  static Tcl_ChannelType transformChannelType = {
      "transform",			/* Type name. */
!     TCL_CHANNEL_VERSION_2,
      TransformCloseProc,			/* Close proc. */
      TransformInputProc,			/* Input proc. */
      TransformOutputProc,		/* Output proc. */
--- 131,137 ----
  
  static Tcl_ChannelType transformChannelType = {
      "transform",			/* Type name. */
!     TCL_CHANNEL_VERSION_3,
      TransformCloseProc,			/* Close proc. */
      TransformInputProc,			/* Input proc. */
      TransformOutputProc,		/* Output proc. */

*** mac/tclMacChan.c	24 Dec 2003 04:18:21 -0000	1.22
--- mac/tclMacChan.c	14 Jan 2004 02:18:30 -0000
***************
*** 79,129 ****
   * Static routines for this file:
   */
  
! static int		CommonGetHandle _ANSI_ARGS_((ClientData instanceData,
! 		            int direction, ClientData *handlePtr));
! static void		CommonWatch _ANSI_ARGS_((ClientData instanceData,
! 		            int mask));
! static int		FileBlockMode _ANSI_ARGS_((ClientData instanceData,
! 			    int mode));
! static void		FileChannelExitHandler _ANSI_ARGS_((
! 		            ClientData clientData));
! static void		FileCheckProc _ANSI_ARGS_((ClientData clientData,
! 			    int flags));
! static int		FileClose _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_Interp *interp));
! static int		FileEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
! 			    int flags));
! static ThreadSpecificData *FileInit _ANSI_ARGS_((void));
! static int		FileInput _ANSI_ARGS_((ClientData instanceData,
! 			    char *buf, int toRead, int *errorCode));
! static int		FileOutput _ANSI_ARGS_((ClientData instanceData,
! 			    CONST char *buf, int toWrite, int *errorCode));
! static int		FileSeek _ANSI_ARGS_((ClientData instanceData,
! 			    long offset, int mode, int *errorCode));
! static void		FileSetupProc _ANSI_ARGS_((ClientData clientData,
! 			    int flags));
! static Tcl_Channel	OpenFileChannel _ANSI_ARGS_((CONST char *fileName, 
! 			    int mode, int permissions, int *errorCodePtr));
! static int		StdIOBlockMode _ANSI_ARGS_((ClientData instanceData,
! 			    int mode));
! static int		StdIOClose _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_Interp *interp));
! static int		StdIOInput _ANSI_ARGS_((ClientData instanceData,
! 			    char *buf, int toRead, int *errorCode));
! static int		StdIOOutput _ANSI_ARGS_((ClientData instanceData,
! 			    CONST char *buf, int toWrite, int *errorCode));
! static int		StdIOSeek _ANSI_ARGS_((ClientData instanceData,
! 			    long offset, int mode, int *errorCode));
! static int		StdReady _ANSI_ARGS_((ClientData instanceData,
! 		            int mask));
  
  /*
   * This structure describes the channel type structure for file based IO:
   */
  
  static Tcl_ChannelType consoleChannelType = {
!     "file",			/* Type name. */
!     (Tcl_ChannelTypeVersion)StdIOBlockMode,		/* Set blocking/nonblocking mode.*/
      StdIOClose,			/* Close proc. */
      StdIOInput,			/* Input proc. */
      StdIOOutput,		/* Output proc. */
--- 79,117 ----
   * Static routines for this file:
   */
  
! static Tcl_DriverCutProc	CommonCutProc;
! static Tcl_DriverGetHandleProc	CommonGetHandle;
! static Tcl_DriverSpliceProc	CommonSpliceProc;
! static Tcl_DriverWatchProc	CommonWatch;
! 
! static Tcl_DriverBlockModeProc	FileBlockMode;
! static Tcl_ExitProc		FileChannelExitHandler;
! static Tcl_EventCheckProc	FileCheckProc;
! static Tcl_DriverCloseProc	FileClose;
! static Tcl_EventProc		FileEventProc;
! static ThreadSpecificData *	FileInit _ANSI_ARGS_((void));
! static Tcl_DriverInputProc	FileInput;
! static Tcl_DriverOutputProc	FileOutput;
! static Tcl_DriverSeekProc	FileSeek;
! static Tcl_EventSetupProc	FileSetupProc;
! static Tcl_Channel		OpenFileChannel _ANSI_ARGS_((
! 				    CONST char *fileName, int mode,
! 				    int permissions, int *errorCodePtr));
! static Tcl_DriverBlockModeProc	StdIOBlockMode;
! static Tcl_DriverCloseProc	StdIOClose;
! static Tcl_DriverInputProc	StdIOInput;
! static Tcl_DriverOutputProc	StdIOOutput;
! static Tcl_DriverSeekProc	StdIOSeek;
! static int			StdReady _ANSI_ARGS_((
! 				    ClientData instanceData, int mask));
  
  /*
   * This structure describes the channel type structure for file based IO:
   */
  
  static Tcl_ChannelType consoleChannelType = {
!     "console",			/* Type name. */
!     TCL_CHANNEL_VERSION_4,	/* v2 channel */
      StdIOClose,			/* Close proc. */
      StdIOInput,			/* Input proc. */
      StdIOOutput,		/* Output proc. */
***************
*** 131,137 ****
      NULL,			/* Set option proc. */
      NULL,			/* Get option proc. */
      CommonWatch,		/* Initialize notifier. */
!     CommonGetHandle		/* Get OS handles out of channel. */
  };
  
  /*
--- 119,132 ----
      NULL,			/* Set option proc. */
      NULL,			/* Get option proc. */
      CommonWatch,		/* Initialize notifier. */
!     CommonGetHandle,		/* Get OS handles out of channel. */
!     NULL,			/* close2 proc. */
!     StdIOBlockMode,		/* Set blocking/nonblocking mode.*/
!     NULL,			/* flush proc. */
!     NULL,			/* handler proc. */
!     NULL,			/* wide seek proc. */
!     CommonCutProc,		/* cut proc. */
!     CommonSpliceProc,		/* splice proc. */
  };
  
  /*
***************
*** 140,147 ****
  
  static Tcl_ChannelType fileChannelType = {
      "file",			/* Type name. */
!     (Tcl_ChannelTypeVersion)FileBlockMode,		/* Set blocking or
!                                  * non-blocking mode.*/
      FileClose,			/* Close proc. */
      FileInput,			/* Input proc. */
      FileOutput,			/* Output proc. */
--- 135,141 ----
  
  static Tcl_ChannelType fileChannelType = {
      "file",			/* Type name. */
!     TCL_CHANNEL_VERSION_4,	/* v4 channel */
      FileClose,			/* Close proc. */
      FileInput,			/* Input proc. */
      FileOutput,			/* Output proc. */
***************
*** 149,155 ****
      NULL,			/* Set option proc. */
      NULL,			/* Get option proc. */
      CommonWatch,		/* Initialize notifier. */
!     CommonGetHandle		/* Get OS handles out of channel. */
  };
  
  
--- 143,156 ----
      NULL,			/* Set option proc. */
      NULL,			/* Get option proc. */
      CommonWatch,		/* Initialize notifier. */
!     CommonGetHandle,		/* Get OS handles out of channel. */
!     NULL,			/* close2 proc. */
!     FileBlockMode,		/* Set blocking or non-blocking mode. */
!     NULL,			/* flush proc. */
!     NULL,			/* handler proc. */
!     NULL,			/* wide seek proc. */
!     CommonCutProc,		/* cut proc. */
!     CommonSpliceProc,		/* splice proc. */
  };
  
  
***************
*** 241,247 ****
  {
      FileState *infoPtr;
      Tcl_Time blockTime = { 0, 0 };
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
--- 242,250 ----
  {
      FileState *infoPtr;
      Tcl_Time blockTime = { 0, 0 };
!     ThreadSpecificData *tsdPtr;
!     
!     tsdPtr = FileInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
***************
*** 286,292 ****
      FileState *infoPtr;
      int sentMsg = 0;
      Tcl_Time blockTime = { 0, 0 };
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
--- 289,297 ----
      FileState *infoPtr;
      int sentMsg = 0;
      Tcl_Time blockTime = { 0, 0 };
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = FileInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
***************
*** 338,344 ****
  {
      FileEvent *fileEvPtr = (FileEvent *)evPtr;
      FileState *infoPtr;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return 0;
--- 343,351 ----
  {
      FileEvent *fileEvPtr = (FileEvent *)evPtr;
      FileState *infoPtr;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = FileInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return 0;
***************
*** 416,422 ****
      Tcl_Interp *interp)		/* Unused. */
  {
      int fd, errorCode = 0;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      /*
       * Invalidate the stdio cache if necessary.  Note that we assume that
--- 423,431 ----
      Tcl_Interp *interp)		/* Unused. */
  {
      int fd, errorCode = 0;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = FileInit();
  
      /*
       * Invalidate the stdio cache if necessary.  Note that we assume that
***************
*** 673,678 ****
--- 682,690 ----
      char channelName[16 + TCL_INTEGER_SPACE];
      int channelPermissions;
      FileState *fileState;
+     ThreadSpecificData *tsdPtr;
+     
+     tsdPtr = FileInit();
  
      /*
       * If the channels were not created yet, create them now and
***************
*** 706,711 ****
--- 718,725 ----
  	    (ClientData) fileState, channelPermissions);
      fileState->fileChan = channel;
      fileState->fileRef = fd;
+     fileState->nextPtr = tsdPtr->firstFilePtr;
+     tsdPtr->firstFilePtr = fileState;
  
      /*
       * Set up the normal channel options for stdio handles.
***************
*** 1212,1221 ****
  /*
   *----------------------------------------------------------------------
   *
!  * TclpCutFileChannel --
   *
!  *	Remove any thread local refs to this channel. See
!  *	Tcl_CutChannel for more info.
   *
   * Results:
   *	None.
--- 1226,1235 ----
  /*
   *----------------------------------------------------------------------
   *
!  * CommonCutProc --
   *
!  *	Driver procedure to remove any thread local refs to this
!  *	channel.  See Tcl_CutChannel for more info.
   *
   * Results:
   *	None.
***************
*** 1226,1247 ****
   *----------------------------------------------------------------------
   */
  
! void
! TclpCutFileChannel(chan)
!     Tcl_Channel chan;			/* The channel being removed. Must
!                                          * not be referenced in any
!                                          * interpreter. */
  {
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
!     Channel *chanPtr = (Channel *) chan;
!     FileState *infoPtr;
      FileState **nextPtrPtr;
      int removed = 0;
  
!     if (chanPtr->typePtr != &fileChannelType)
!         return;
! 
!     infoPtr = (FileState *) chanPtr->instanceData;
  
      for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL;
  	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
--- 1240,1255 ----
   *----------------------------------------------------------------------
   */
  
! static void
! CommonCutProc(instanceData)
!     ClientData instanceData,		/* The file state. */
  {
!     ThreadSpecificData *tsdPtr;
!     FileState *infoPtr = (FileState *) chanPtr->instanceData;
      FileState **nextPtrPtr;
      int removed = 0;
  
!     tsdPtr = FileInit();
  
      for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL;
  	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
***************
*** 1259,1275 ****
       */
  
      if (!removed) {
!         Tcl_Panic("file info ptr not on thread channel list");
      }
  }
  
  /*
   *----------------------------------------------------------------------
   *
!  * TclpSpliceFileChannel --
   *
!  *	Insert thread local ref for this channel.
!  *	Tcl_SpliceChannel for more info.
   *
   * Results:
   *	None.
--- 1267,1283 ----
       */
  
      if (!removed) {
!         Tcl_Panic("FileState ptr not on thread channel list");
      }
  }
  
  /*
   *----------------------------------------------------------------------
   *
!  * CommonSpliceProc --
   *
!  *	Driver procedure to insert thread local ref for this channel.
!  *	See Tcl_SpliceChannel for more info.
   *
   * Results:
   *	None.
***************
*** 1280,1299 ****
   *----------------------------------------------------------------------
   */
  
! void
! TclpSpliceFileChannel(chan)
!     Tcl_Channel chan;			/* The channel being removed. Must
!                                          * not be referenced in any
!                                          * interpreter. */
  {
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
!     Channel *chanPtr = (Channel *) chan;
!     FileState *infoPtr;
! 
!     if (chanPtr->typePtr != &fileChannelType)
!         return;
  
!     infoPtr = (FileState *) chanPtr->instanceData;
  
      infoPtr->nextPtr = tsdPtr->firstFilePtr;
      tsdPtr->firstFilePtr = infoPtr;
--- 1288,1301 ----
   *----------------------------------------------------------------------
   */
  
! static void
! CommonSpliceProc(instanceData)
!     ClientData instanceData,		/* The file state. */
  {
!     ThreadSpecificData *tsdPtr;
!     FileState *infoPtr = (FileState *) chanPtr->instanceData;
  
!     tsdPtr = FileInit();
  
      infoPtr->nextPtr = tsdPtr->firstFilePtr;
      tsdPtr->firstFilePtr = infoPtr;

*** mac/tclMacSock.c	24 Dec 2003 04:18:21 -0000	1.16
--- mac/tclMacSock.c	14 Jan 2004 02:18:34 -0000
***************
*** 130,186 ****
      StreamPtr tcpStream;	/* Low level Macintosh stream. */
  } SocketEvent;
  
  /*
   * Static routines for this file:
   */
  
! static pascal void	CleanUpExitProc _ANSI_ARGS_((void));
! static void		ClearZombieSockets _ANSI_ARGS_((void));
! static void		CloseCompletionRoutine _ANSI_ARGS_((TCPiopb *pb));
! static TcpState *	CreateSocket _ANSI_ARGS_((Tcl_Interp *interp,
! 			    int port, CONST char *host, CONST char *myAddr,
! 			    int myPort, int server, int async));
! static pascal void	DNRCompletionRoutine _ANSI_ARGS_((
! 			    struct hostInfo *hostinfoPtr,
! 			    DNRState *dnrStatePtr));
! static void		FreeSocketInfo _ANSI_ARGS_((TcpState *statePtr));
! static long		GetBufferSize _ANSI_ARGS_((void));
! static OSErr		GetHostFromString _ANSI_ARGS_((CONST char *name,
! 			    ip_addr *address));
! static OSErr		GetLocalAddress _ANSI_ARGS_((unsigned long *addr));
! static void		IOCompletionRoutine _ANSI_ARGS_((TCPiopb *pb));
! static void		InitMacTCPParamBlock _ANSI_ARGS_((TCPiopb *pBlock,
! 			    int csCode));
! static void		InitSockets _ANSI_ARGS_((void));
! static TcpState *	NewSocketInfo _ANSI_ARGS_((StreamPtr stream));
! static OSErr		ResolveAddress _ANSI_ARGS_((ip_addr tcpAddress,
! 			    Tcl_DString *dsPtr));
! static void		SocketCheckProc _ANSI_ARGS_((ClientData clientData,
! 			    int flags));
! static int		SocketEventProc _ANSI_ARGS_((Tcl_Event *evPtr,
! 			    int flags));
! static void		SocketExitHandler _ANSI_ARGS_((ClientData clientData));
! static void		SocketFreeProc _ANSI_ARGS_((ClientData clientData));
! static int		SocketReady _ANSI_ARGS_((TcpState *statePtr));
! static void		SocketSetupProc _ANSI_ARGS_((ClientData clientData,
! 			    int flags));
! static void		TcpAccept _ANSI_ARGS_((TcpState *statePtr));
! static int		TcpBlockMode _ANSI_ARGS_((ClientData instanceData, int mode));
! static int		TcpClose _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_Interp *interp));
! static int		TcpGetHandle _ANSI_ARGS_((ClientData instanceData,
! 		            int direction, ClientData *handlePtr));
! static int		TcpGetOptionProc _ANSI_ARGS_((ClientData instanceData,
!                             Tcl_Interp *interp, CONST char *optionName,
! 			    Tcl_DString *dsPtr));
! static int		TcpInput _ANSI_ARGS_((ClientData instanceData,
! 			    char *buf, int toRead, int *errorCodePtr));
! static int		TcpOutput _ANSI_ARGS_((ClientData instanceData,
! 			    CONST char *buf, int toWrite, int *errorCodePtr));
! static void		TcpWatch _ANSI_ARGS_((ClientData instanceData,
! 		            int mask));
! static int		WaitForSocketEvent _ANSI_ARGS_((TcpState *infoPtr,
! 		            int mask, int *errorCodePtr));
  
  pascal void NotifyRoutine (
      StreamPtr tcpStream,
--- 130,201 ----
      StreamPtr tcpStream;	/* Low level Macintosh stream. */
  } SocketEvent;
  
+ typedef struct ThreadSpecificData {
+     /*
+      * Every open socket has an entry on the following list.
+      */
+     
+     TcpState *socketList;
+ } ThreadSpecificData;
+ 
+ static Tcl_ThreadDataKey dataKey;
+ 
  /*
   * Static routines for this file:
   */
  
! static pascal void		CleanUpExitProc _ANSI_ARGS_((void));
! static void			ClearZombieSockets _ANSI_ARGS_((void));
! static void			CloseCompletionRoutine _ANSI_ARGS_((
! 				    TCPiopb *pb));
! static TcpState *		CreateSocket _ANSI_ARGS_((
! 				    Tcl_Interp *interp, int port,
! 				    CONST char *host, CONST char *myAddr,
! 				    int myPort, int server, int async));
! static pascal void		DNRCompletionRoutine _ANSI_ARGS_((
! 				    struct hostInfo *hostinfoPtr,
! 				    DNRState *dnrStatePtr));
! static void			FreeSocketInfo _ANSI_ARGS_((
! 				    TcpState *statePtr));
! static long			GetBufferSize _ANSI_ARGS_((void));
! static OSErr			GetHostFromString _ANSI_ARGS_((
! 				    CONST char *name, ip_addr *address));
! static OSErr			GetLocalAddress _ANSI_ARGS_((
! 				    unsigned long *addr));
! static void			IOCompletionRoutine _ANSI_ARGS_((
! 				    TCPiopb *pb));
! static void			InitMacTCPParamBlock _ANSI_ARGS_((
! 				    TCPiopb *pBlock, int csCode));
! static ThreadSpecificData *	InitSockets _ANSI_ARGS_((void));
! static TcpState *		NewSocketInfo _ANSI_ARGS_((
! 				    StreamPtr stream));
! static OSErr			ResolveAddress _ANSI_ARGS_((
! 				    ip_addr tcpAddress,
! 				    Tcl_DString *dsPtr));
! static Tcl_EventCheckProc	SocketCheckProc;
! static Tcl_EventProc		SocketEventProc;
! static Tcl_ExitProc		SocketExitHandler;
! static void			SocketFreeProc _ANSI_ARGS_((
! 				    ClientData clientData));
! static int			SocketReady _ANSI_ARGS_((
! 				    TcpState *statePtr));
! static void			SocketSetupProc _ANSI_ARGS_((
! 				    ClientData clientData, int flags));
! static void			TcpAccept _ANSI_ARGS_((
! 				    TcpState *statePtr));
! static Tcl_DriverBlockModeProc	TcpBlockMode;
! static Tcl_DriverCloseProc	TcpClose;
! static Tcl_DriverCutProc	TcpCutProc;
! static Tcl_DriverGetHandleProc	TcpGetHandle;
! static Tcl_DriverGetOptionProc	TcpGetOptionProc;
! static Tcl_DriverInputProc	TcpInput;
! static Tcl_DriverOutputProc	TcpOutput;
! static Tcl_DriverSpliceProc	TcpSpliceProc;
! static Tcl_DriverWatchProc	TcpWatch;
! 
! static int			WaitForSocketEvent _ANSI_ARGS_((
! 				    TcpState *infoPtr, int mask,
! 				    int *errorCodePtr));
  
  pascal void NotifyRoutine (
      StreamPtr tcpStream,
***************
*** 196,203 ****
  
  static Tcl_ChannelType tcpChannelType = {
      "tcp",			/* Type name. */
!     (Tcl_ChannelTypeVersion)TcpBlockMode,		/* Set blocking or
!                                  * non-blocking mode.*/
      TcpClose,			/* Close proc. */
      TcpInput,			/* Input proc. */
      TcpOutput,			/* Output proc. */
--- 211,217 ----
  
  static Tcl_ChannelType tcpChannelType = {
      "tcp",			/* Type name. */
!     TCL_CHANNEL_VERSION_4,
      TcpClose,			/* Close proc. */
      TcpInput,			/* Input proc. */
      TcpOutput,			/* Output proc. */
***************
*** 205,211 ****
      NULL,			/* Set option proc. */
      TcpGetOptionProc,		/* Get option proc. */
      TcpWatch,			/* Initialize notifier. */
!     TcpGetHandle		/* Get handles out of channel. */
  };
  
  /*
--- 219,232 ----
      NULL,			/* Set option proc. */
      TcpGetOptionProc,		/* Get option proc. */
      TcpWatch,			/* Initialize notifier. */
!     TcpGetHandle,		/* Get handles out of channel. */
!     NULL,			/* close2 proc. */
!     TcpBlockMode,		/* Set blocking or non-blocking mode.*/
!     NULL,			/* flush proc. */
!     NULL,			/* handler proc. */
!     NULL,			/* wide seek proc. */
!     TcpCutProc,			/* cut proc. */
!     TcpSpliceProc,		/* splice proc. */
  };
  
  /*
***************
*** 251,266 ****
      {NULL,		0},
  };
  
- typedef struct ThreadSpecificData {
-     /*
-      * Every open socket has an entry on the following list.
-      */
-     
-     TcpState *socketList;
- } ThreadSpecificData;
- 
- static Tcl_ThreadDataKey dataKey;
- 
  /*
   * Globals for holding information about OS support for sockets.
   */
--- 272,277 ----
***************
*** 293,299 ****
   */
  
  #define gestaltMacTCPVersion 'mtcp'
! static void
  InitSockets()
  {
      ParamBlockRec pb; 
--- 304,310 ----
   */
  
  #define gestaltMacTCPVersion 'mtcp'
! static ThreadSpecificData *
  InitSockets()
  {
      ParamBlockRec pb; 
***************
*** 371,376 ****
--- 382,388 ----
  	Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL);
  	Tcl_CreateThreadExitHandler(SocketExitHandler, (ClientData) NULL);
      }
+     return tsdPtr;
  }
  
  /*
***************
*** 460,466 ****
  {
      TcpState *statePtr;
      Tcl_Time blockTime = { 0, 0 };
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
--- 472,480 ----
  {
      TcpState *statePtr;
      Tcl_Time blockTime = { 0, 0 };
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = InitSockets();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
***************
*** 507,513 ****
      TcpState *statePtr;
      SocketEvent *evPtr;
      TcpState dummyState;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
--- 521,529 ----
      TcpState *statePtr;
      SocketEvent *evPtr;
      TcpState dummyState;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = InitSockets();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
***************
*** 869,875 ****
      }
  
      /*
!      * It's very bad if the statePtr is nNULL - we should probably panic...
       */
  
      if (statePtr == NULL) {
--- 885,891 ----
      }
  
      /*
!      * It's very bad if the statePtr is NULL - we should probably panic...
       */
  
      if (statePtr == NULL) {
***************
*** 1096,1102 ****
  	    switch (err) {
  		case noErr:
  		    /*
! 		     * The channel remains readable only if this read succeds
  		     * and we had more data then the size of the buffer we were
  		     * trying to fill.  Use the info from the call to status to
  		     * determine this.
--- 1112,1118 ----
  	    switch (err) {
  		case noErr:
  		    /*
! 		     * The channel remains readable only if this read succeeds
  		     * and we had more data then the size of the buffer we were
  		     * trying to fill.  Use the info from the call to status to
  		     * determine this.
***************
*** 1542,1547 ****
--- 1558,1640 ----
  /*
   *----------------------------------------------------------------------
   *
+  * TcpCutProc --
+  *
+  *	Driver procedure to remove any thread local refs to this
+  *	channel. See Tcl_CutChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ TcpCutProc(instanceData)
+     ClientData instanceData;		/* Socket state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     TcpState *infoPtr = (TcpState *) instanceData;
+     TcpState **nextPtrPtr;
+     int removed = 0;
+ 
+     tsdPtr = InitSockets();
+ 
+     for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL;
+ 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
+ 	if ((*nextPtrPtr) == infoPtr) {
+ 	    (*nextPtrPtr) = infoPtr->nextPtr;
+ 	    removed = 1;
+ 	    break;
+ 	}
+     }
+ 
+     /*
+      * This could happen if the channel was created in one thread
+      * and then moved to another without updating the thread
+      * local data in each thread.
+      */
+ 
+     if (!removed)
+         Tcl_Panic("TcpState info ptr not on thread channel list");
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * TcpSpliceProc --
+  *
+  *	Driver procedure to insert thread local ref for this channel.
+  *	See Tcl_SpliceChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ TcpSpliceProc(instanceData)
+     ClientData instanceData;		/* Socket state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     TcpState *infoPtr = (TcpState *) instanceData;
+ 
+     tsdPtr = InitSockets();
+ 
+     infoPtr->nextPtr   = tsdPtr->socketList;
+     tsdPtr->socketList = infoPtr;
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
   * NewSocketInfo --
   *
   *	This function allocates and initializes a new SocketInfo
***************
*** 1561,1567 ****
      StreamPtr tcpStream)
  {
      TcpState *statePtr;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState));
      statePtr->tcpStream = tcpStream;
--- 1654,1662 ----
      StreamPtr tcpStream)
  {
      TcpState *statePtr;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = InitSockets();
  
      statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState));
      statePtr->tcpStream = tcpStream;
***************
*** 1599,1605 ****
  FreeSocketInfo(
      TcpState *statePtr)		/* The state pointer to free. */
  {
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (statePtr == tsdPtr->socketList) {
  	tsdPtr->socketList = statePtr->nextPtr;
--- 1694,1702 ----
  FreeSocketInfo(
      TcpState *statePtr)		/* The state pointer to free. */
  {
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = InitSockets();
  
      if (statePtr == tsdPtr->socketList) {
  	tsdPtr->socketList = statePtr->nextPtr;
***************
*** 1987,1993 ****
      TcpState *statePtr;
      SocketEvent *eventPtr = (SocketEvent *) evPtr;
      int mask = 0;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return 0;
--- 2084,2092 ----
      TcpState *statePtr;
      SocketEvent *eventPtr = (SocketEvent *) evPtr;
      int mask = 0;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = InitSockets();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return 0;
***************
*** 2743,2749 ****
  ClearZombieSockets()
  {
      TcpState *statePtr;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      for (statePtr = tsdPtr->socketList; statePtr != NULL;
  	    statePtr = statePtr->nextPtr) {
--- 2842,2850 ----
  ClearZombieSockets()
  {
      TcpState *statePtr;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = InitSockets();
  
      for (statePtr = tsdPtr->socketList; statePtr != NULL;
  	    statePtr = statePtr->nextPtr) {
***************
*** 2790,2881 ****
      localIcmpMsg = *icmpMsg;
          
  }
- 
- /*
-  *----------------------------------------------------------------------
-  *
-  * TclpCutSockChannel --
-  *
-  *	Remove any thread local refs to this channel. See
-  *	Tcl_CutChannel for more info.
-  *
-  * Results:
-  *	None.
-  *
-  * Side effects:
-  *	Changes thread local list of valid channels.
-  *
-  *----------------------------------------------------------------------
-  */
- 
- void
- TclpCutSockChannel(chan)
-     Tcl_Channel chan;
- {
-     ThreadSpecificData *tsdPtr;
-     TcpState *infoPtr;
-     TcpState **nextPtrPtr;
-     int removed = 0;
- 
-     if (Tcl_GetChannelType(chan) != &tcpChannelType)
-         return;
- 
-     tsdPtr  = TCL_TSD_INIT(&dataKey);
-     infoPtr = (TcpState *) Tcl_GetChannelInstanceData (chan);
- 
-     for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL;
- 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
- 	if ((*nextPtrPtr) == infoPtr) {
- 	    (*nextPtrPtr) = infoPtr->nextPtr;
- 	    removed = 1;
- 	    break;
- 	}
-     }
- 
-     /*
-      * This could happen if the channel was created in one thread
-      * and then moved to another without updating the thread
-      * local data in each thread.
-      */
- 
-     if (!removed)
-         Tcl_Panic("file info ptr not on thread channel list");
-     return;
- }
- 
- /*
-  *----------------------------------------------------------------------
-  *
-  * TclpSpliceSockChannel --
-  *
-  *	Insert thread local ref for this channel.
-  *	Tcl_SpliceChannel for more info.
-  *
-  * Results:
-  *	None.
-  *
-  * Side effects:
-  *	Changes thread local list of valid channels.
-  *
-  *----------------------------------------------------------------------
-  */
- 
- void
- TclpSpliceSockChannel(chan)
-     Tcl_Channel chan;
- {
-     ThreadSpecificData *tsdPtr;
-     TcpState *infoPtr;
- 
-     if (Tcl_GetChannelType(chan) != &tcpChannelType)
-         return;
- 
-     InitSockets ();
- 
-     tsdPtr  = TCL_TSD_INIT(&dataKey);
-     infoPtr = (TcpState *) Tcl_GetChannelInstanceData (chan);
- 
-     infoPtr->nextPtr   = tsdPtr->socketList;
-     tsdPtr->socketList = infoPtr;
- }
- 
--- 2891,2893 ----

*** unix/tclUnixChan.c	24 Dec 2003 04:18:22 -0000	1.45
--- unix/tclUnixChan.c	14 Jan 2004 02:18:37 -0000
***************
*** 231,302 ****
   * Static routines for this file:
   */
  
! static TcpState *	CreateSocket _ANSI_ARGS_((Tcl_Interp *interp,
! 			    int port, CONST char *host, int server,
! 			    CONST char *myaddr, int myport, int async));
! static int		CreateSocketAddress _ANSI_ARGS_(
! 			    (struct sockaddr_in *sockaddrPtr,
! 			    CONST char *host, int port));
! static int		FileBlockModeProc _ANSI_ARGS_((
! 			    ClientData instanceData, int mode));
! static int		FileCloseProc _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_Interp *interp));
! static int		FileGetHandleProc _ANSI_ARGS_((ClientData instanceData,
! 			    int direction, ClientData *handlePtr));
! static int		FileInputProc _ANSI_ARGS_((ClientData instanceData,
! 			    char *buf, int toRead, int *errorCode));
! static int		FileOutputProc _ANSI_ARGS_((
! 			    ClientData instanceData, CONST char *buf,
! 			    int toWrite, int *errorCode));
! static int		FileSeekProc _ANSI_ARGS_((ClientData instanceData,
! 			    long offset, int mode, int *errorCode));
! static Tcl_WideInt	FileWideSeekProc _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_WideInt offset, int mode, int *errorCode));
! static void		FileWatchProc _ANSI_ARGS_((ClientData instanceData,
! 			    int mask));
! static void		TcpAccept _ANSI_ARGS_((ClientData data, int mask));
! static int		TcpBlockModeProc _ANSI_ARGS_((ClientData data,
! 			    int mode));
! static int		TcpCloseProc _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_Interp *interp));
! static int		TcpGetHandleProc _ANSI_ARGS_((ClientData instanceData,
! 			    int direction, ClientData *handlePtr));
! static int		TcpGetOptionProc _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_Interp *interp, CONST char *optionName,
! 			    Tcl_DString *dsPtr));
! static int		TcpInputProc _ANSI_ARGS_((ClientData instanceData,
! 			    char *buf, int toRead,  int *errorCode));
! static int		TcpOutputProc _ANSI_ARGS_((ClientData instanceData,
! 			    CONST char *buf, int toWrite, int *errorCode));
! static void		TcpWatchProc _ANSI_ARGS_((ClientData instanceData,
! 			    int mask));
  #ifdef SUPPORTS_TTY
! static int		TtyCloseProc _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_Interp *interp));
! static void		TtyGetAttributes _ANSI_ARGS_((int fd,
! 			    TtyAttrs *ttyPtr));
! static int		TtyGetOptionProc _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_Interp *interp, CONST char *optionName,
! 			    Tcl_DString *dsPtr));
! static FileState *	TtyInit _ANSI_ARGS_((int fd, int initialize));
  #if BAD_TIP35_FLUSH
! static int		TtyOutputProc _ANSI_ARGS_((ClientData instanceData,
! 			    CONST char *buf, int toWrite, int *errorCode));
  #endif /* BAD_TIP35_FLUSH */
! static int		TtyParseMode _ANSI_ARGS_((Tcl_Interp *interp,
! 			    CONST char *mode, int *speedPtr, int *parityPtr,
! 			    int *dataPtr, int *stopPtr));
! static void		TtySetAttributes _ANSI_ARGS_((int fd,
! 			    TtyAttrs *ttyPtr));
! static int		TtySetOptionProc _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_Interp *interp, CONST char *optionName, 
! 			    CONST char *value));
  #endif	/* SUPPORTS_TTY */
! static int		WaitForConnect _ANSI_ARGS_((TcpState *statePtr,
! 			    int *errorCodePtr));
! static Tcl_Channel	MakeTcpClientChannelMode _ANSI_ARGS_(
! 			    (ClientData tcpSocket,
! 			    int mode));
  
  
  /*
--- 231,286 ----
   * Static routines for this file:
   */
  
! static TcpState *		CreateSocket _ANSI_ARGS_((
! 				    Tcl_Interp *interp, int port,
! 				    CONST char *host, int server,
! 				    CONST char *myaddr, int myport,
! 				    int async));
! static int			CreateSocketAddress _ANSI_ARGS_(
! 				    (struct sockaddr_in *sockaddrPtr,
! 				    CONST char *host, int port));
! static Tcl_DriverBlockModeProc	FileBlockModeProc;
! static Tcl_DriverCloseProc	FileCloseProc;
! static Tcl_DriverCutProc	FileCutProc;
! static Tcl_DriverGetHandleProc	FileGetHandleProc;
! static Tcl_DriverInputProc	FileInputProc;
! static Tcl_DriverOutputProc	FileOutputProc);
! static Tcl_DriverSeekProc	FileSeekProc;
! static Tcl_DriverSpliceProc	FileSpliceProc;
! static Tcl_DriverWideSeekProc	FileWideSeekProc;
! static Tcl_DriverWatchProc	FileWatchProc;
! static void			TcpAccept _ANSI_ARGS_((ClientData data,
! 				    int mask));
! static Tcl_DriverBlockModeProc	TcpBlockModeProc;
! static Tcl_DriverCloseProc	TcpCloseProc;
! static Tcl_DriverGetHandleProc	TcpGetHandleProc;
! static Tcl_DriverGetOptionProc	TcpGetOptionProc;
! static Tcl_DriverInputProc	TcpInputProc;
! static Tcl_DriverOutputProc	TcpOutputProc;
! static Tcl_DriverWatchProc	TcpWatchProc;
  #ifdef SUPPORTS_TTY
! static Tcl_DriverCloseProc	TtyCloseProc;
! static void			TtyGetAttributes _ANSI_ARGS_((int fd,
! 				    TtyAttrs *ttyPtr));
! static Tcl_DriverGetOptionProc	TtyGetOptionProc;
! static FileState *		TtyInit _ANSI_ARGS_((int fd,
! 				    int initialize));
  #if BAD_TIP35_FLUSH
! static Tcl_DriverOutputProc	TtyOutputProc;
  #endif /* BAD_TIP35_FLUSH */
! static int			TtyParseMode _ANSI_ARGS_((
! 				    Tcl_Interp *interp, CONST char *mode,
! 				    int *speedPtr, int *parityPtr,
! 				    int *dataPtr, int *stopPtr));
! static void			TtySetAttributes _ANSI_ARGS_((int fd,
! 				    TtyAttrs *ttyPtr));
! static Tcl_DriverSetOptionProc	TtySetOptionProc;
  #endif	/* SUPPORTS_TTY */
! static int			WaitForConnect _ANSI_ARGS_((
! 				    TcpState *statePtr,
! 				    int *errorCodePtr));
! static Tcl_Channel		MakeTcpClientChannelMode _ANSI_ARGS_((
! 				    ClientData tcpSocket, int mode));
  
  
  /*
***************
*** 305,311 ****
  
  static Tcl_ChannelType fileChannelType = {
      "file",			/* Type name. */
!     TCL_CHANNEL_VERSION_3,	/* v3 channel */
      FileCloseProc,		/* Close proc. */
      FileInputProc,		/* Input proc. */
      FileOutputProc,		/* Output proc. */
--- 289,295 ----
  
  static Tcl_ChannelType fileChannelType = {
      "file",			/* Type name. */
!     TCL_CHANNEL_VERSION_4,	/* v4 channel */
      FileCloseProc,		/* Close proc. */
      FileInputProc,		/* Input proc. */
      FileOutputProc,		/* Output proc. */
***************
*** 319,324 ****
--- 303,310 ----
      NULL,			/* flush proc. */
      NULL,			/* handler proc. */
      FileWideSeekProc,		/* wide seek proc. */
+     FileCutProc,		/* cut proc. */
+     FileSpliceProc,		/* splice proc. */
  };
  
  #ifdef SUPPORTS_TTY
***************
*** 735,740 ****
--- 721,805 ----
  	return TCL_ERROR;
      }
  }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * FileCutProc --
+  *
+  *	Driver procedure to remove any thread local refs to this
+  *	channel. See Tcl_CutChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ FileCutProc(instanceData)
+     ClientData instanceData;		/* The file state. */
+ {
+ #ifdef DEPRECATED
+     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+     FileState *fsPtr = (FileState *) instanceData;;
+     FileState **nextPtrPtr;
+     int removed = 0;
+ 
+     for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL;
+ 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
+ 	if ((*nextPtrPtr) == fsPtr) {
+ 	    (*nextPtrPtr) = fsPtr->nextPtr;
+ 	    removed = 1;
+ 	    break;
+ 	}
+     }
+ 
+     /*
+      * This could happen if the channel was created in one thread
+      * and then moved to another without updating the thread
+      * local data in each thread.
+      */
+ 
+     if (!removed) {
+         Tcl_Panic("FileState ptr not on thread channel list");
+     }
+ 
+ #endif /* DEPRECATED */
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * FileSpliceProc --
+  *
+  *	Driver procedure to insert thread local ref for this channel.
+  *	Tcl_SpliceChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ FileSpliceProc(instanceData)
+     ClientData instanceData;		/* The file state. */
+ {
+ #ifdef DEPRECATED
+     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+     FileState *fsPtr = (FileState *) instanceData;
+ 
+     fsPtr->nextPtr = tsdPtr->firstFilePtr;
+     tsdPtr->firstFilePtr = fsPtr;
+ #endif /* DEPRECATED */
+ }
  
  #ifdef SUPPORTS_TTY 
  
***************
*** 3272,3369 ****
      }
      return result;
  }
- 
- /*
-  *----------------------------------------------------------------------
-  *
-  * TclpCutFileChannel --
-  *
-  *	Remove any thread local refs to this channel. See
-  *	Tcl_CutChannel for more info.
-  *
-  * Results:
-  *	None.
-  *
-  * Side effects:
-  *	Changes thread local list of valid channels.
-  *
-  *----------------------------------------------------------------------
-  */
- 
- void
- TclpCutFileChannel(chan)
-     Tcl_Channel chan;			/* The channel being removed. Must
-                                          * not be referenced in any
-                                          * interpreter. */
- {
- #ifdef DEPRECATED
-     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-     Channel *chanPtr = (Channel *) chan;
-     FileState *fsPtr;
-     FileState **nextPtrPtr;
-     int removed = 0;
- 
-     if (chanPtr->typePtr != &fileChannelType)
-         return;
- 
-     fsPtr = (FileState *) chanPtr->instanceData;
- 
-     for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL;
- 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
- 	if ((*nextPtrPtr) == fsPtr) {
- 	    (*nextPtrPtr) = fsPtr->nextPtr;
- 	    removed = 1;
- 	    break;
- 	}
-     }
- 
-     /*
-      * This could happen if the channel was created in one thread
-      * and then moved to another without updating the thread
-      * local data in each thread.
-      */
- 
-     if (!removed) {
-         Tcl_Panic("file info ptr not on thread channel list");
-     }
- 
- #endif /* DEPRECATED */
- }
- 
- /*
-  *----------------------------------------------------------------------
-  *
-  * TclpSpliceFileChannel --
-  *
-  *	Insert thread local ref for this channel.
-  *	Tcl_SpliceChannel for more info.
-  *
-  * Results:
-  *	None.
-  *
-  * Side effects:
-  *	Changes thread local list of valid channels.
-  *
-  *----------------------------------------------------------------------
-  */
- 
- void
- TclpSpliceFileChannel(chan)
-     Tcl_Channel chan;			/* The channel being removed. Must
-                                          * not be referenced in any
-                                          * interpreter. */
- {
- #ifdef DEPRECATED
-     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-     Channel *chanPtr = (Channel *) chan;
-     FileState *fsPtr;
- 
-     if (chanPtr->typePtr != &fileChannelType)
-         return;
- 
-     fsPtr = (FileState *) chanPtr->instanceData;
- 
-     fsPtr->nextPtr = tsdPtr->firstFilePtr;
-     tsdPtr->firstFilePtr = fsPtr;
- #endif /* DEPRECATED */
- }
--- 3337,3339 ----

*** unix/tclUnixSock.c	22 Apr 2003 23:20:43 -0000	1.7
--- unix/tclUnixSock.c	14 Jan 2004 02:18:39 -0000
***************
*** 148,196 ****
  {
      return TCL_OK;
  }
- 
- /*
-  *----------------------------------------------------------------------
-  *
-  * TclpCutSockChannel --
-  *
-  *	Remove any thread local refs to this channel. See
-  *	Tcl_CutChannel for more info. Dummy definition.
-  *
-  * Results:
-  *	None.
-  *
-  * Side effects:
-  *	None.
-  *
-  *----------------------------------------------------------------------
-  */
- 
- void
- TclpCutSockChannel(chan)
-     Tcl_Channel chan;
- {
- }
- 
- /*
-  *----------------------------------------------------------------------
-  *
-  * TclpSpliceSockChannel --
-  *
-  *	Insert thread local ref for this channel.
-  *	Tcl_SpliceChannel for more info. Dummy definition.
-  *
-  * Results:
-  *	None.
-  *
-  * Side effects:
-  *	None.
-  *
-  *----------------------------------------------------------------------
-  */
- 
- void
- TclpSpliceSockChannel(chan)
-     Tcl_Channel chan;
- {
- }
--- 148,150 ----

*** win/tclWinChan.c	24 Dec 2003 04:18:22 -0000	1.33
--- win/tclWinChan.c	14 Jan 2004 02:18:41 -0000
***************
*** 73,103 ****
   * Static routines for this file:
   */
  
! static int		FileBlockProc _ANSI_ARGS_((ClientData instanceData,
! 			    int mode));
! static void		FileChannelExitHandler _ANSI_ARGS_((
! 		            ClientData clientData));
! static void		FileCheckProc _ANSI_ARGS_((ClientData clientData,
! 			    int flags));
! static int		FileCloseProc _ANSI_ARGS_((ClientData instanceData,
! 		            Tcl_Interp *interp));
! static int		FileEventProc _ANSI_ARGS_((Tcl_Event *evPtr, 
! 			    int flags));
! static int		FileGetHandleProc _ANSI_ARGS_((ClientData instanceData,
! 		            int direction, ClientData *handlePtr));
! static ThreadSpecificData *FileInit _ANSI_ARGS_((void));
! static int		FileInputProc _ANSI_ARGS_((ClientData instanceData,
! 	            	    char *buf, int toRead, int *errorCode));
! static int		FileOutputProc _ANSI_ARGS_((ClientData instanceData,
! 			    CONST char *buf, int toWrite, int *errorCode));
! static int		FileSeekProc _ANSI_ARGS_((ClientData instanceData,
! 			    long offset, int mode, int *errorCode));
! static Tcl_WideInt	FileWideSeekProc _ANSI_ARGS_((ClientData instanceData,
! 			    Tcl_WideInt offset, int mode, int *errorCode));
! static void		FileSetupProc _ANSI_ARGS_((ClientData clientData,
! 			    int flags));
! static void		FileWatchProc _ANSI_ARGS_((ClientData instanceData,
! 		            int mask));
  
  			    
  /*
--- 73,93 ----
   * Static routines for this file:
   */
  
! static Tcl_DriverBlockModeProc	FileBlockProc;
! static Tcl_ExitProc		FileChannelExitHandler;
! static Tcl_EventCheckProc	FileCheckProc;
! static Tcl_DriverCloseProc	FileCloseProc;
! static Tcl_DriverCutProc	FileCutProc;
! static Tcl_EventProc		FileEventProc;
! static Tcl_DriverGetHandleProc	FileGetHandleProc;
! static ThreadSpecificData *	FileInit _ANSI_ARGS_((void));
! static Tcl_DriverInputProc	FileInputProc;
! static Tcl_DriverOutputProc	FileOutputProc;
! static Tcl_DriverSeekProc	FileSeekProc;
! static Tcl_DriverWideSeekProc	FileWideSeekProc;
! static Tcl_EventSetupProc	FileSetupProc;
! static Tcl_DriverSpliceProc	FileSpliceProc;
! static Tcl_DriverWatchProc	FileWatchProc;
  
  			    
  /*
***************
*** 106,112 ****
  
  static Tcl_ChannelType fileChannelType = {
      "file",			/* Type name. */
!     TCL_CHANNEL_VERSION_3,	/* v3 channel */
      FileCloseProc,		/* Close proc. */
      FileInputProc,		/* Input proc. */
      FileOutputProc,		/* Output proc. */
--- 96,102 ----
  
  static Tcl_ChannelType fileChannelType = {
      "file",			/* Type name. */
!     TCL_CHANNEL_VERSION_4,	/* v4 channel */
      FileCloseProc,		/* Close proc. */
      FileInputProc,		/* Input proc. */
      FileOutputProc,		/* Output proc. */
***************
*** 120,125 ****
--- 110,117 ----
      NULL,			/* flush proc. */
      NULL,			/* handler proc. */
      FileWideSeekProc,		/* Wide seek proc. */
+     FileCutProc,		/* cut proc. */
+     FileSpliceProc,		/* splice proc. */
  };
  
  #if defined(HAVE_NO_SEH) && defined(TCL_MEM_DEBUG)
***************
*** 181,187 ****
  
  static void
  FileChannelExitHandler(clientData)
!     ClientData clientData;	/* Old window proc */
  {
      Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL);
  }
--- 173,179 ----
  
  static void
  FileChannelExitHandler(clientData)
!     ClientData clientData;	/* Not used. */
  {
      Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL);
  }
***************
*** 210,216 ****
  {
      FileInfo *infoPtr;
      Tcl_Time blockTime = { 0, 0 };
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
--- 202,210 ----
  {
      FileInfo *infoPtr;
      Tcl_Time blockTime = { 0, 0 };
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = FileInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
***************
*** 253,259 ****
  {
      FileEvent *evPtr;
      FileInfo *infoPtr;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
--- 247,255 ----
  {
      FileEvent *evPtr;
      FileInfo *infoPtr;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = FileInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
***************
*** 305,311 ****
  {
      FileEvent *fileEvPtr = (FileEvent *)evPtr;
      FileInfo *infoPtr;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return 0;
--- 301,309 ----
  {
      FileEvent *fileEvPtr = (FileEvent *)evPtr;
      FileInfo *infoPtr;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = FileInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return 0;
***************
*** 720,733 ****
  	return TCL_ERROR;
      }
  }
  
  
  /*
   *----------------------------------------------------------------------
   *
   * TclpOpenFileChannel --
   *
!  *	Open an File based channel on Unix systems.
   *
   * Results:
   *	The new channel or NULL. If NULL, the output argument
--- 718,808 ----
  	return TCL_ERROR;
      }
  }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * FileCutProc --
+  *
+  *	Driver procedure to remove any thread local refs to this
+  *	channel. See Tcl_CutChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ FileCutProc(instanceData)
+     ClientData instanceData;		/* The file state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     FileInfo *infoPtr = (FileInfo *) instanceData;
+     FileInfo **nextPtrPtr;
+     int removed = 0;
+ 
+     tsdPtr = FileInit();
+ 
+     for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL;
+ 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
+ 	if ((*nextPtrPtr) == infoPtr) {
+ 	    (*nextPtrPtr) = infoPtr->nextPtr;
+ 	    removed = 1;
+ 	    break;
+ 	}
+     }
+ 
+     /*
+      * This could happen if the channel was created in one thread
+      * and then moved to another without updating the thread
+      * local data in each thread.
+      */
+ 
+     if (!removed) {
+         Tcl_Panic("file info ptr not on thread channel list");
+     }
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * FileSpliceProc --
+  *
+  *	Insert thread local ref for this channel.
+  *	Tcl_SpliceChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ FileSpliceProc(instanceData)
+     ClientData instanceData;		/* The file state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     FileInfo *infoPtr = (FileInfo *) instanceData;
  
+     tsdPtr = FileInit();
+ 
+     infoPtr->nextPtr = tsdPtr->firstFilePtr;
+     tsdPtr->firstFilePtr = infoPtr;
+ }
  
  /*
   *----------------------------------------------------------------------
   *
   * TclpOpenFileChannel --
   *
!  *	Open a file based channel on Win32 systems.
   *
   * Results:
   *	The new channel or NULL. If NULL, the output argument
***************
*** 1338,1430 ****
  	}
      }
  }
- 
- /*
-  *----------------------------------------------------------------------
-  *
-  * TclpCutFileChannel --
-  *
-  *	Remove any thread local refs to this channel. See
-  *	Tcl_CutChannel for more info.
-  *
-  * Results:
-  *	None.
-  *
-  * Side effects:
-  *	Changes thread local list of valid channels.
-  *
-  *----------------------------------------------------------------------
-  */
- 
- void
- TclpCutFileChannel(chan)
-     Tcl_Channel chan;			/* The channel being removed. Must
-                                          * not be referenced in any
-                                          * interpreter. */
- {
-     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-     Channel *chanPtr = (Channel *) chan;
-     FileInfo *infoPtr;
-     FileInfo **nextPtrPtr;
-     int removed = 0;
- 
-     if (chanPtr->typePtr != &fileChannelType)
-         return;
- 
-     infoPtr = (FileInfo *) chanPtr->instanceData;
- 
-     for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL;
- 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
- 	if ((*nextPtrPtr) == infoPtr) {
- 	    (*nextPtrPtr) = infoPtr->nextPtr;
- 	    removed = 1;
- 	    break;
- 	}
-     }
- 
-     /*
-      * This could happen if the channel was created in one thread
-      * and then moved to another without updating the thread
-      * local data in each thread.
-      */
- 
-     if (!removed) {
-         Tcl_Panic("file info ptr not on thread channel list");
-     }
- }
- 
- /*
-  *----------------------------------------------------------------------
-  *
-  * TclpSpliceFileChannel --
-  *
-  *	Insert thread local ref for this channel.
-  *	Tcl_SpliceChannel for more info.
-  *
-  * Results:
-  *	None.
-  *
-  * Side effects:
-  *	Changes thread local list of valid channels.
-  *
-  *----------------------------------------------------------------------
-  */
- 
- void
- TclpSpliceFileChannel(chan)
-     Tcl_Channel chan;			/* The channel being removed. Must
-                                          * not be referenced in any
-                                          * interpreter. */
- {
-     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-     Channel *chanPtr = (Channel *) chan;
-     FileInfo *infoPtr;
- 
-     if (chanPtr->typePtr != &fileChannelType)
-         return;
- 
-     infoPtr = (FileInfo *) chanPtr->instanceData;
- 
-     infoPtr->nextPtr = tsdPtr->firstFilePtr;
-     tsdPtr->firstFilePtr = infoPtr;
- }
--- 1413,1415 ----

*** win/tclWinConsole.c	26 Nov 2002 22:41:58 -0000	1.11
--- win/tclWinConsole.c	14 Jan 2004 02:18:43 -0000
***************
*** 140,164 ****
   * Declarations for functions used only in this file.
   */
  
! static int		ConsoleBlockModeProc(ClientData instanceData, int mode);
! static void		ConsoleCheckProc(ClientData clientData, int flags);
! static int		ConsoleCloseProc(ClientData instanceData,
! 			    Tcl_Interp *interp);
! static int		ConsoleEventProc(Tcl_Event *evPtr, int flags);
! static void		ConsoleExitHandler(ClientData clientData);
! static int		ConsoleGetHandleProc(ClientData instanceData,
! 			    int direction, ClientData *handlePtr);
! static ThreadSpecificData *ConsoleInit(void);
! static int		ConsoleInputProc(ClientData instanceData, char *buf,
! 			    int toRead, int *errorCode);
! static int		ConsoleOutputProc(ClientData instanceData,
! 			    CONST char *buf, int toWrite, int *errorCode);
! static DWORD WINAPI	ConsoleReaderThread(LPVOID arg);
! static void		ConsoleSetupProc(ClientData clientData, int flags);
! static void		ConsoleWatchProc(ClientData instanceData, int mask);
! static DWORD WINAPI	ConsoleWriterThread(LPVOID arg);
! static void		ProcExitHandler(ClientData clientData);
! static int		WaitForRead(ConsoleInfo *infoPtr, int blocking);
  
  /*
   * This structure describes the channel type structure for command console
--- 140,163 ----
   * Declarations for functions used only in this file.
   */
  
! static Tcl_DriverBlockModeProc	ConsoleBlockModeProc;
! static Tcl_EventCheckProc	ConsoleCheckProc;
! static Tcl_DriverCloseProc	ConsoleCloseProc;
! static Tcl_DriverCutProc	ConsoleCutProc;
! static Tcl_EventProc		ConsoleEventProc;
! static Tcl_ExitProc		ConsoleExitHandler;
! static Tcl_DriverGetHandleProc	ConsoleGetHandleProc;
! static ThreadSpecificData *	ConsoleInit(void);
! static Tcl_DriverInputProc	ConsoleInputProc;
! static Tcl_DriverOutputProc	ConsoleOutputProc;
! static DWORD WINAPI		ConsoleReaderThread(LPVOID arg);
! static Tcl_EventSetupProc	ConsoleSetupProc;
! static Tcl_DriverSpliceProc	ConsoleSpliceProc;
! static Tcl_DriverWatchProc	ConsoleWatchProc;
! static DWORD WINAPI		ConsoleWriterThread(LPVOID arg);
! static Tcl_ExitProc		ProcExitHandler;
! static int			WaitForRead(ConsoleInfo *infoPtr,
! 				    int blocking);
  
  /*
   * This structure describes the channel type structure for command console
***************
*** 167,173 ****
  
  static Tcl_ChannelType consoleChannelType = {
      "console",			/* Type name. */
!     TCL_CHANNEL_VERSION_2,	/* v2 channel */
      ConsoleCloseProc,		/* Close proc. */
      ConsoleInputProc,		/* Input proc. */
      ConsoleOutputProc,		/* Output proc. */
--- 166,172 ----
  
  static Tcl_ChannelType consoleChannelType = {
      "console",			/* Type name. */
!     TCL_CHANNEL_VERSION_4,	/* v4 channel */
      ConsoleCloseProc,		/* Close proc. */
      ConsoleInputProc,		/* Input proc. */
      ConsoleOutputProc,		/* Output proc. */
***************
*** 180,185 ****
--- 179,187 ----
      ConsoleBlockModeProc,	/* Set blocking or non-blocking mode.*/
      NULL,			/* flush proc. */
      NULL,			/* handler proc. */
+     NULL,			/* wide seek proc. */
+     ConsoleCutProc,		/* cut proc. */
+     ConsoleSpliceProc,		/* splice proc. */
  };
  
  /*
***************
*** 246,252 ****
  
  static void
  ConsoleExitHandler(
!     ClientData clientData)	/* Old window proc */
  {
      Tcl_DeleteEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL);
  }
--- 248,254 ----
  
  static void
  ConsoleExitHandler(
!     ClientData clientData)	/* Not used. */
  {
      Tcl_DeleteEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL);
  }
***************
*** 270,276 ****
  
  static void
  ProcExitHandler(
!     ClientData clientData)	/* Old window proc */
  {
      Tcl_MutexLock(&consoleMutex);
      initialized = 0;
--- 272,278 ----
  
  static void
  ProcExitHandler(
!     ClientData clientData)	/* Not used. */
  {
      Tcl_MutexLock(&consoleMutex);
      initialized = 0;
***************
*** 302,308 ****
      ConsoleInfo *infoPtr;
      Tcl_Time blockTime = { 0, 0 };
      int block = 1;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
--- 304,312 ----
      ConsoleInfo *infoPtr;
      Tcl_Time blockTime = { 0, 0 };
      int block = 1;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = ConsoleInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
***************
*** 355,361 ****
      ConsoleInfo *infoPtr;
      ConsoleEvent *evPtr;
      int needEvent;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
--- 359,367 ----
      ConsoleInfo *infoPtr;
      ConsoleEvent *evPtr;
      int needEvent;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = ConsoleInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
***************
*** 463,479 ****
      ConsoleInfo *consolePtr = (ConsoleInfo *) instanceData;
      int errorCode;
      ConsoleInfo *infoPtr, **nextPtrPtr;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
      DWORD exitCode;
  
      errorCode = 0;
!     
      /*
       * Clean up the background thread if necessary.  Note that this
       * must be done before we can close the file, since the 
       * thread may be blocking trying to read from the console.
       */
!     
      if (consolePtr->readThread) {
  
  	/*
--- 469,486 ----
      ConsoleInfo *consolePtr = (ConsoleInfo *) instanceData;
      int errorCode;
      ConsoleInfo *infoPtr, **nextPtrPtr;
!     ThreadSpecificData *tsdPtr;
      DWORD exitCode;
  
      errorCode = 0;
!     tsdPtr = ConsoleInit();
! 
      /*
       * Clean up the background thread if necessary.  Note that this
       * must be done before we can close the file, since the 
       * thread may be blocking trying to read from the console.
       */
! 
      if (consolePtr->readThread) {
  
  	/*
***************
*** 832,838 ****
      ConsoleEvent *consoleEvPtr = (ConsoleEvent *)evPtr;
      ConsoleInfo *infoPtr;
      int mask;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return 0;
--- 839,847 ----
      ConsoleEvent *consoleEvPtr = (ConsoleEvent *)evPtr;
      ConsoleInfo *infoPtr;
      int mask;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = ConsoleInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return 0;
***************
*** 919,925 ****
      ConsoleInfo **nextPtrPtr, *ptr;
      ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData;
      int oldMask = infoPtr->watchMask;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      /*
       * Since most of the work is handled by the background threads,
--- 928,936 ----
      ConsoleInfo **nextPtrPtr, *ptr;
      ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData;
      int oldMask = infoPtr->watchMask;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = ConsoleInit();
  
      /*
       * Since most of the work is handled by the background threads,
***************
*** 986,991 ****
--- 997,1080 ----
  /*
   *----------------------------------------------------------------------
   *
+  * ConsoleCutProc --
+  *
+  *	Driver procedure to remove any thread local refs to this
+  *	channel. See Tcl_CutChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ ConsoleCutProc(instanceData)
+     ClientData instanceData;		/* Console state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData;
+     ConsoleInfo **nextPtrPtr;
+     int removed = 0;
+ 
+     tsdPtr = ConsoleInit();
+ 
+     for (nextPtrPtr = &(tsdPtr->firstConsolePtr); (*nextPtrPtr) != NULL;
+ 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
+ 	if ((*nextPtrPtr) == infoPtr) {
+ 	    (*nextPtrPtr) = infoPtr->nextPtr;
+ 	    removed = 1;
+ 	    break;
+ 	}
+     }
+ 
+     /*
+      * This could happen if the channel was created in one thread
+      * and then moved to another without updating the thread
+      * local data in each thread.
+      */
+ 
+     if (!removed) {
+         Tcl_Panic("ConsoleInfo ptr not on thread channel list");
+     }
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * ConsoleSpliceProc --
+  *
+  *	Driver procedure to insert thread local ref for this channel.
+  *	See Tcl_SpliceChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ ConsoleSpliceProc(instanceData)
+     ClientData instanceData;		/* Console state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData;
+ 
+     tsdPtr = ConsoleInit();
+ 
+     infoPtr->nextPtr = tsdPtr->firstConsolePtr;
+     tsdPtr->firstConsolePtr = infoPtr;
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
   * WaitForRead --
   *
   *	Wait until some data is available, the console is at

*** win/tclWinFile.c	16 Dec 2003 02:55:38 -0000	1.58
--- win/tclWinFile.c	14 Jan 2004 02:18:47 -0000
***************
*** 14,21 ****
   * RCS: @(#) $Id: tclWinFile.c,v 1.58 2003/12/16 02:55:38 davygrvy Exp $
   */
  
- //#define _WIN32_WINNT  0x0500
- 
  #include "tclWinInt.h"
  #include <winioctl.h>
  #include <sys/stat.h>
--- 14,19 ----

*** win/tclWinPipe.c	24 Dec 2003 04:18:23 -0000	1.39
--- win/tclWinPipe.c	14 Jan 2004 02:18:50 -0000
***************
*** 179,209 ****
   * Declarations for functions used only in this file.
   */
  
! static int		ApplicationType(Tcl_Interp *interp,
! 			    const char *fileName, char *fullName);
! static void		BuildCommandLine(const char *executable, int argc, 
! 			    CONST char **argv, Tcl_DString *linePtr);
! static BOOL		HasConsole(void);
! static int		PipeBlockModeProc(ClientData instanceData, int mode);
! static void		PipeCheckProc(ClientData clientData, int flags);
! static int		PipeClose2Proc(ClientData instanceData,
! 			    Tcl_Interp *interp, int flags);
! static int		PipeEventProc(Tcl_Event *evPtr, int flags);
! static void		PipeExitHandler(ClientData clientData);
! static int		PipeGetHandleProc(ClientData instanceData,
! 			    int direction, ClientData *handlePtr);
! static void		PipeInit(void);
! static int		PipeInputProc(ClientData instanceData, char *buf,
! 			    int toRead, int *errorCode);
! static int		PipeOutputProc(ClientData instanceData,
! 			    CONST char *buf, int toWrite, int *errorCode);
! static DWORD WINAPI	PipeReaderThread(LPVOID arg);
! static void		PipeSetupProc(ClientData clientData, int flags);
! static void		PipeWatchProc(ClientData instanceData, int mask);
! static DWORD WINAPI	PipeWriterThread(LPVOID arg);
! static void		ProcExitHandler(ClientData clientData);
! static int		TempFileName(WCHAR name[MAX_PATH]);
! static int		WaitForRead(PipeInfo *infoPtr, int blocking);
  
  /*
   * This structure describes the channel type structure for command pipe
--- 179,209 ----
   * Declarations for functions used only in this file.
   */
  
! static int			ApplicationType(Tcl_Interp *interp,
! 				    CONST char *fileName, char *fullName);
! static void			BuildCommandLine(const char *executable,
! 				    int argc, CONST char **argv,
! 				    Tcl_DString *linePtr);
! static BOOL			HasConsole(void);
! static Tcl_DriverBlockModeProc	PipeBlockModeProc;
! static Tcl_EventCheckProc	PipeCheckProc;
! static Tcl_DriverClose2Proc	PipeClose2Proc;
! static Tcl_DriverCutProc	PipeCutProc;
! static Tcl_EventProc		PipeEventProc;
! static Tcl_ExitProc		PipeExitHandler;
! static Tcl_DriverGetHandleProc	PipeGetHandleProc;
! static ThreadSpecificData *	PipeInit(void);
! static Tcl_DriverInputProc	PipeInputProc;
! static Tcl_DriverOutputProc	PipeOutputProc;
! static DWORD WINAPI		PipeReaderThread(LPVOID arg);
! static Tcl_EventSetupProc	PipeSetupProc;
! static Tcl_DriverSpliceProc	PipeSpliceProc;
! static Tcl_DriverWatchProc	PipeWatchProc;
! static DWORD WINAPI		PipeWriterThread(LPVOID arg);
! static Tcl_ExitProc		ProcExitHandler;
! static int			TempFileName(WCHAR name[MAX_PATH]);
! static int			WaitForRead(PipeInfo *infoPtr,
! 				    int blocking);
  
  /*
   * This structure describes the channel type structure for command pipe
***************
*** 212,218 ****
  
  static Tcl_ChannelType pipeChannelType = {
      "pipe",			/* Type name. */
!     TCL_CHANNEL_VERSION_2,	/* v2 channel */
      TCL_CLOSE2PROC,		/* Close proc. */
      PipeInputProc,		/* Input proc. */
      PipeOutputProc,		/* Output proc. */
--- 212,218 ----
  
  static Tcl_ChannelType pipeChannelType = {
      "pipe",			/* Type name. */
!     TCL_CHANNEL_VERSION_4,	/* v4 channel */
      TCL_CLOSE2PROC,		/* Close proc. */
      PipeInputProc,		/* Input proc. */
      PipeOutputProc,		/* Output proc. */
***************
*** 225,230 ****
--- 225,233 ----
      PipeBlockModeProc,		/* Set blocking or non-blocking mode.*/
      NULL,			/* flush proc. */
      NULL,			/* handler proc. */
+     NULL,			/* wide seek proc. */
+     PipeCutProc,		/* cut proc. */
+     PipeSpliceProc,		/* splice proc. */
  };
  
  /*
***************
*** 243,249 ****
   *----------------------------------------------------------------------
   */
  
! static void
  PipeInit()
  {
      ThreadSpecificData *tsdPtr;
--- 246,252 ----
   *----------------------------------------------------------------------
   */
  
! static ThreadSpecificData *
  PipeInit()
  {
      ThreadSpecificData *tsdPtr;
***************
*** 270,275 ****
--- 273,279 ----
  	Tcl_CreateEventSource(PipeSetupProc, PipeCheckProc, NULL);
  	Tcl_CreateThreadExitHandler(PipeExitHandler, NULL);
      }
+     return tsdPtr;
  }
  
  /*
***************
*** 315,321 ****
  
  static void
  ProcExitHandler(
!     ClientData clientData)	/* Old window proc */
  {
      Tcl_MutexLock(&pipeMutex);
      initialized = 0;
--- 319,325 ----
  
  static void
  ProcExitHandler(
!     ClientData clientData)	/* Not used. */
  {
      Tcl_MutexLock(&pipeMutex);
      initialized = 0;
***************
*** 404,410 ****
      PipeEvent *evPtr;
      WinFile *filePtr;
      int needEvent;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
--- 408,416 ----
      PipeEvent *evPtr;
      WinFile *filePtr;
      int needEvent;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = PipeInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return;
***************
*** 1882,1890 ****
      Tcl_Channel errChan;
      int errorCode, result;
      PipeInfo *infoPtr, **nextPtrPtr;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
      DWORD exitCode;
  
      errorCode = 0;
      if ((!flags || (flags == TCL_CLOSE_READ))
  	    && (pipePtr->readFile != NULL)) {
--- 1888,1898 ----
      Tcl_Channel errChan;
      int errorCode, result;
      PipeInfo *infoPtr, **nextPtrPtr;
!     ThreadSpecificData *tsdPtr;
      DWORD exitCode;
  
+     tsdPtr = PipeInit();
+ 
      errorCode = 0;
      if ((!flags || (flags == TCL_CLOSE_READ))
  	    && (pipePtr->readFile != NULL)) {
***************
*** 2299,2305 ****
      PipeInfo *infoPtr;
      WinFile *filePtr;
      int mask;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return 0;
--- 2307,2315 ----
      PipeInfo *infoPtr;
      WinFile *filePtr;
      int mask;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = PipeInit();
  
      if (!(flags & TCL_FILE_EVENTS)) {
  	return 0;
***************
*** 2386,2392 ****
      PipeInfo **nextPtrPtr, *ptr;
      PipeInfo *infoPtr = (PipeInfo *) instanceData;
      int oldMask = infoPtr->watchMask;
!     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
  
      /*
       * Since most of the work is handled by the background threads,
--- 2396,2404 ----
      PipeInfo **nextPtrPtr, *ptr;
      PipeInfo *infoPtr = (PipeInfo *) instanceData;
      int oldMask = infoPtr->watchMask;
!     ThreadSpecificData *tsdPtr;
! 
!     tsdPtr = PipeInit();
  
      /*
       * Since most of the work is handled by the background threads,
***************
*** 2463,2468 ****
--- 2475,2558 ----
  /*
   *----------------------------------------------------------------------
   *
+  * PipeCutProc --
+  *
+  *	Driver procedure to remove any thread local refs to this
+  *	channel. See Tcl_CutChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ PipeCutProc(instanceData)
+     ClientData instanceData;		/* Pipe state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     PipeInfo *infoPtr = (PipeInfo *) instanceData;
+     PipeInfo **nextPtrPtr;
+     int removed = 0;
+ 
+     tsdPtr = PipeInit();
+ 
+     for (nextPtrPtr = &(tsdPtr->firstPipePtr); (*nextPtrPtr) != NULL;
+ 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
+ 	if ((*nextPtrPtr) == infoPtr) {
+ 	    (*nextPtrPtr) = infoPtr->nextPtr;
+ 	    removed = 1;
+ 	    break;
+ 	}
+     }
+ 
+     /*
+      * This could happen if the channel was created in one thread
+      * and then moved to another without updating the thread
+      * local data in each thread.
+      */
+ 
+     if (!removed) {
+         Tcl_Panic("PipeInfo ptr not on thread channel list");
+     }
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * PipeSpliceProc --
+  *
+  *	Driver procedure to insert thread local ref for this channel.
+  *	See Tcl_SpliceChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ PipeSpliceProc(instanceData)
+     ClientData instanceData;		/* Pipe state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     PipeInfo *infoPtr = (PipeInfo *) instanceData;
+ 
+     tsdPtr = PipeInit();
+ 
+     infoPtr->nextPtr = tsdPtr->firstPipePtr;
+     tsdPtr->firstPipePtr = infoPtr;
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
   * Tcl_WaitPid --
   *
   *	Emulates the waitpid system call.

*** win/tclWinSerial.c	19 Aug 2003 19:39:56 -0000	1.28
--- win/tclWinSerial.c	14 Jan 2004 02:18:53 -0000
***************
*** 169,203 ****
   * Declarations for functions used only in this file.
   */
  
! static int			SerialBlockProc(ClientData instanceData,
! 				    int mode);
! static void			SerialCheckProc(ClientData clientData,
! 				    int flags);
! static int			SerialCloseProc(ClientData instanceData,
! 				    Tcl_Interp *interp);
! static int			SerialEventProc(Tcl_Event *evPtr, int flags);
! static void			SerialExitHandler(ClientData clientData);
! static int			SerialGetHandleProc(ClientData instanceData,
! 				    int direction, ClientData *handlePtr);
  static ThreadSpecificData *	SerialInit(void);
! static int			SerialInputProc(ClientData instanceData,
! 				    char *buf, int toRead, int *errorCode);
! static int			SerialOutputProc(ClientData instanceData,
! 				    CONST char *buf, int toWrite,
! 				    int *errorCode);
! static void			SerialSetupProc(ClientData clientData,
! 				    int flags);
! static void			SerialWatchProc(ClientData instanceData,
! 				    int mask);
! static void			ProcExitHandler(ClientData clientData);
! static int			SerialGetOptionProc _ANSI_ARGS_((
! 				    ClientData instanceData,
! 				    Tcl_Interp *interp, CONST char *optionName,
! 				    Tcl_DString *dsPtr));
! static int			SerialSetOptionProc _ANSI_ARGS_((
! 				    ClientData instanceData,
! 				    Tcl_Interp *interp, CONST char *optionName,
! 				    CONST char *value));
  static DWORD WINAPI		SerialWriterThread(LPVOID arg);
  
  /*
--- 169,190 ----
   * Declarations for functions used only in this file.
   */
  
! static Tcl_DriverBlockModeProc	SerialBlockProc;
! static Tcl_EventCheckProc	SerialCheckProc;
! static Tcl_DriverCloseProc	SerialCloseProc;
! static Tcl_DriverCutProc	SerialCutProc;
! static Tcl_EventProc		SerialEventProc;
! static Tcl_ExitProc		SerialExitHandler;
! static Tcl_DriverGetHandleProc	SerialGetHandleProc;
  static ThreadSpecificData *	SerialInit(void);
! static Tcl_DriverInputProc	SerialInputProc;
! static Tcl_DriverOutputProc	SerialOutputProc;
! static Tcl_EventSetupProc	SerialSetupProc;
! static Tcl_DriverSpliceProc	SerialSpliceProc;
! static Tcl_DriverWatchProc	SerialWatchProc;
! static Tcl_ExitProc		ProcExitHandler;
! static Tcl_DriverGetOptionProc	SerialGetOptionProc;
! static Tcl_DriverSetOptionProc	SerialSetOptionProc;
  static DWORD WINAPI		SerialWriterThread(LPVOID arg);
  
  /*
***************
*** 207,213 ****
  
  static Tcl_ChannelType serialChannelType = {
      "serial",			/* Type name. */
!     TCL_CHANNEL_VERSION_2,	/* v2 channel */
      SerialCloseProc,		/* Close proc. */
      SerialInputProc,		/* Input proc. */
      SerialOutputProc,		/* Output proc. */
--- 194,200 ----
  
  static Tcl_ChannelType serialChannelType = {
      "serial",			/* Type name. */
!     TCL_CHANNEL_VERSION_4,	/* v4 channel */
      SerialCloseProc,		/* Close proc. */
      SerialInputProc,		/* Input proc. */
      SerialOutputProc,		/* Output proc. */
***************
*** 220,225 ****
--- 207,215 ----
      SerialBlockProc,		/* Set blocking or non-blocking mode.*/
      NULL,			/* flush proc. */
      NULL,			/* handler proc. */
+     NULL,			/* wide seek proc. */
+     SerialCutProc,		/* cut proc. */
+     SerialSpliceProc,		/* splice proc. */
  };
  
  /*
***************
*** 1288,1293 ****
--- 1278,1361 ----
  /*
   *----------------------------------------------------------------------
   *
+  * SerialCutProc --
+  *
+  *	Driver procedure to remove any thread local refs to this
+  *	channel. See Tcl_CutChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ SerialCutProc(instanceData)
+     ClientData instanceData;		/* Serial state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     SerialInfo *infoPtr = (SerialInfo *) instanceData;
+     SerialInfo **nextPtrPtr;
+     int removed = 0;
+ 
+     tsdPtr = SerialInit();
+ 
+     for (nextPtrPtr = &(tsdPtr->firstSerialPtr); (*nextPtrPtr) != NULL;
+ 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
+ 	if ((*nextPtrPtr) == infoPtr) {
+ 	    (*nextPtrPtr) = infoPtr->nextPtr;
+ 	    removed = 1;
+ 	    break;
+ 	}
+     }
+ 
+     /*
+      * This could happen if the channel was created in one thread
+      * and then moved to another without updating the thread
+      * local data in each thread.
+      */
+ 
+     if (!removed) {
+         Tcl_Panic("SerialInfo ptr not on thread channel list");
+     }
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * SerialSpliceProc --
+  *
+  *	Driver procedure to insert thread local ref for this channel.
+  *	See Tcl_SpliceChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ SerialSpliceProc(instanceData)
+     ClientData instanceData;		/* Serial state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     SerialInfo *infoPtr = (SerialInfo *) instanceData;
+ 
+     tsdPtr = SerialInit();
+ 
+     infoPtr->nextPtr = tsdPtr->firstSerialPtr;
+     tsdPtr->firstSerialPtr = infoPtr;
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
   * SerialWriterThread --
   *
   *      This function runs in a separate thread and writes data

*** win/tclWinSock.c	24 Dec 2003 04:18:23 -0000	1.41
--- win/tclWinSock.c	14 Jan 2004 02:18:56 -0000
***************
*** 232,257 ****
   * Static functions defined in this file.
   */
  
! static SocketInfo *	    CreateSocket _ANSI_ARGS_((Tcl_Interp *interp,
  				    int port, CONST char *host,
  				    int server, CONST char *myaddr,
  				    int myport, int async));
! static int		    CreateSocketAddress _ANSI_ARGS_(
! 				    (LPSOCKADDR_IN sockaddrPtr,
  				    CONST char *host, int port));
! static void		    InitSockets _ANSI_ARGS_((void));
! static SocketInfo *	    NewSocketInfo _ANSI_ARGS_((SOCKET socket));
! static Tcl_EventCheckProc   SocketCheckProc;
! static Tcl_EventProc	    SocketEventProc;
! static void		    SocketExitHandler _ANSI_ARGS_((
! 				    ClientData clientData));
! static LRESULT CALLBACK	    SocketProc _ANSI_ARGS_((HWND hwnd,
  				    UINT message, WPARAM wParam,
  				    LPARAM lParam));
! static Tcl_EventSetupProc   SocketSetupProc;
! static Tcl_ExitProc	    SocketThreadExitHandler;
! static int		    SocketsEnabled _ANSI_ARGS_((void));
! static void		    TcpAccept _ANSI_ARGS_((SocketInfo *infoPtr));
  static Tcl_DriverBlockModeProc	TcpBlockProc;
  static Tcl_DriverCloseProc	TcpCloseProc;
  static Tcl_DriverSetOptionProc	TcpSetOptionProc;
--- 232,256 ----
   * Static functions defined in this file.
   */
  
! static SocketInfo *		CreateSocket _ANSI_ARGS_((Tcl_Interp *interp,
  				    int port, CONST char *host,
  				    int server, CONST char *myaddr,
  				    int myport, int async));
! static int			CreateSocketAddress _ANSI_ARGS_((
! 				    LPSOCKADDR_IN sockaddrPtr,
  				    CONST char *host, int port));
! static void			InitSockets _ANSI_ARGS_((void));
! static SocketInfo *		NewSocketInfo _ANSI_ARGS_((SOCKET socket));
! static Tcl_EventCheckProc	SocketCheckProc;
! static Tcl_EventProc		SocketEventProc;
! static Tcl_ExitProc		SocketExitHandler;
! static LRESULT CALLBACK		SocketProc _ANSI_ARGS_((HWND hwnd,
  				    UINT message, WPARAM wParam,
  				    LPARAM lParam));
! static Tcl_EventSetupProc	SocketSetupProc;
! static Tcl_ExitProc		SocketThreadExitHandler;
! static int			SocketsEnabled _ANSI_ARGS_((void));
! static void			TcpAccept _ANSI_ARGS_((SocketInfo *infoPtr));
  static Tcl_DriverBlockModeProc	TcpBlockProc;
  static Tcl_DriverCloseProc	TcpCloseProc;
  static Tcl_DriverSetOptionProc	TcpSetOptionProc;
***************
*** 260,269 ****
  static Tcl_DriverOutputProc	TcpOutputProc;
  static Tcl_DriverWatchProc	TcpWatchProc;
  static Tcl_DriverGetHandleProc	TcpGetHandleProc;
! static int		    WaitForSocketEvent _ANSI_ARGS_((
! 				SocketInfo *infoPtr, int events,
! 				int *errorCodePtr));
! static DWORD WINAPI	    SocketThread _ANSI_ARGS_((LPVOID arg));
  
  /*
   * This structure describes the channel type structure for TCP socket
--- 259,271 ----
  static Tcl_DriverOutputProc	TcpOutputProc;
  static Tcl_DriverWatchProc	TcpWatchProc;
  static Tcl_DriverGetHandleProc	TcpGetHandleProc;
! static Tcl_DriverCutProc	TcpCutProc;
! static Tcl_DriverSpliceProc	TcpSpliceProc;
! 
! static int			WaitForSocketEvent _ANSI_ARGS_((
! 				    SocketInfo *infoPtr, int events,
! 				    int *errorCodePtr));
! static DWORD WINAPI		SocketThread _ANSI_ARGS_((LPVOID arg));
  
  /*
   * This structure describes the channel type structure for TCP socket
***************
*** 272,278 ****
  
  static Tcl_ChannelType tcpChannelType = {
      "tcp",		    /* Type name. */
!     TCL_CHANNEL_VERSION_2,  /* v2 channel */
      TcpCloseProc,	    /* Close proc. */
      TcpInputProc,	    /* Input proc. */
      TcpOutputProc,	    /* Output proc. */
--- 274,280 ----
  
  static Tcl_ChannelType tcpChannelType = {
      "tcp",		    /* Type name. */
!     TCL_CHANNEL_VERSION_4,  /* v4 channel */
      TcpCloseProc,	    /* Close proc. */
      TcpInputProc,	    /* Input proc. */
      TcpOutputProc,	    /* Output proc. */
***************
*** 285,290 ****
--- 287,295 ----
      TcpBlockProc,	    /* Set socket into (non-)blocking mode. */
      NULL,		    /* flush proc. */
      NULL,		    /* handler proc. */
+     NULL,		    /* wideseek proc. */
+     TcpCutProc,		    /* cut proc. */
+     TcpSpliceProc,	    /* splice proc. */
  };
  
  
***************
*** 2284,2290 ****
  /*
   *----------------------------------------------------------------------
   *
!  * TcpGetProc --
   *
   *	Called from Tcl_GetChannelHandle to retrieve an OS handle from inside
   *	a TCP socket based channel.
--- 2289,2295 ----
  /*
   *----------------------------------------------------------------------
   *
!  * TcpGetHandleProc --
   *
   *	Called from Tcl_GetChannelHandle to retrieve an OS handle from inside
   *	a TCP socket based channel.
***************
*** 2313,2318 ****
--- 2318,2431 ----
  /*
   *----------------------------------------------------------------------
   *
+  * TcpCutProc --
+  *
+  *	Remove any thread local refs to this channel. See
+  *	Tcl_CutChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ TcpCutProc(instanceData)
+     ClientData instanceData;		/* The socket state. */
+ {
+     ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+     SocketInfo *infoPtr = (SocketInfo *) instanceData;
+     SocketInfo **nextPtrPtr;
+     int removed = 0;
+ 
+     for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL;
+ 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
+ 	if ((*nextPtrPtr) == infoPtr) {
+ 	    (*nextPtrPtr) = infoPtr->nextPtr;
+ 	    removed = 1;
+ 	    break;
+ 	}
+     }
+ 
+     /*
+      * This could happen if the channel was created in one thread
+      * and then moved to another without updating the thread
+      * local data in each thread.
+      */
+ 
+     if (!removed) {
+         Tcl_Panic("file info ptr not on thread channel list");
+     }
+ 
+     /*
+      * Stop notifications for the socket to occur in this thread.
+      */
+ 
+     SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
+ 		(WPARAM) UNSELECT, (LPARAM) infoPtr);
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
+  * TcpSpliceProc --
+  *
+  *	Insert thread local ref for this channel.
+  *	Tcl_SpliceChannel for more info.
+  *
+  * Results:
+  *	None.
+  *
+  * Side effects:
+  *	Changes thread local list of valid channels.
+  *
+  *----------------------------------------------------------------------
+  */
+ 
+ static void
+ TcpSpliceProc(instanceData)
+     ClientData instanceData;		/* The socket state. */
+ {
+     ThreadSpecificData *tsdPtr;
+     SocketInfo *infoPtr = (SocketInfo *) instanceData;
+ 
+     /*
+      * Ensure that socket subsystem is initialized in this thread, or
+      * else sockets will not work.
+      */
+ 
+     Tcl_MutexLock(&socketMutex);
+     InitSockets();
+     Tcl_MutexUnlock(&socketMutex);
+ 
+     /*
+      * The initializtion of tsdPtr _after_ we have determined that we
+      * are dealing with socket is necessary. Doing it before causes
+      * the module to access th tdsPtr when it is not initialized yet,
+      * causing a lockup.
+      */
+ 
+     tsdPtr  = TCL_TSD_INIT(&dataKey);
+ 
+     WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
+     infoPtr->nextPtr = tsdPtr->socketList;
+     tsdPtr->socketList = infoPtr;
+     SetEvent(tsdPtr->socketListLock);
+ 
+     /*
+      * Ensure that notifications for the socket occur in this thread.
+      */
+ 
+     SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
+ 		(WPARAM) SELECT, (LPARAM) infoPtr);
+ }
+ 
+ /*
+  *----------------------------------------------------------------------
+  *
   * SocketThread --
   *
   *	Helper thread used to manage the socket event handling window.
***************
*** 2666,2799 ****
  
      return winSock.getservbyname(name, proto);
  }
- 
- 
- 
- /*
-  *----------------------------------------------------------------------
-  *
-  * TclpCutSockChannel --
-  *
-  *	Remove any thread local refs to this channel. See
-  *	Tcl_CutChannel for more info.
-  *
-  * Results:
-  *	None.
-  *
-  * Side effects:
-  *	Changes thread local list of valid channels.
-  *
-  *----------------------------------------------------------------------
-  */
- 
- void
- TclpCutSockChannel(chan)
-     Tcl_Channel chan;			/* The channel being removed. Must
-                                          * not be referenced in any
-                                          * interpreter. */
- {
-     ThreadSpecificData *tsdPtr;
-     SocketInfo *infoPtr;
-     SocketInfo **nextPtrPtr;
-     int removed = 0;
- 
-     if (Tcl_GetChannelType(chan) != &tcpChannelType)
-         return;
- 
-     /*
-      * The initializtion of tsdPtr _after_ we have determined that we
-      * are dealing with socket is necessary. Doing it before causes
-      * the module to access th tdsPtr when it is not initialized yet,
-      * causing a lockup.
-      */
- 
-     tsdPtr  = TCL_TSD_INIT(&dataKey);
-     infoPtr = (SocketInfo *) Tcl_GetChannelInstanceData (chan);
- 
-     for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL;
- 	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
- 	if ((*nextPtrPtr) == infoPtr) {
- 	    (*nextPtrPtr) = infoPtr->nextPtr;
- 	    removed = 1;
- 	    break;
- 	}
-     }
- 
-     /*
-      * This could happen if the channel was created in one thread
-      * and then moved to another without updating the thread
-      * local data in each thread.
-      */
- 
-     if (!removed) {
-         Tcl_Panic("file info ptr not on thread channel list");
-     }
- 
-     /*
-      * Stop notifications for the socket to occur in this thread.
-      */
- 
-     SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
- 		(WPARAM) UNSELECT, (LPARAM) infoPtr);
- }
- 
- /*
-  *----------------------------------------------------------------------
-  *
-  * TclpSpliceSockChannel --
-  *
-  *	Insert thread local ref for this channel.
-  *	Tcl_SpliceChannel for more info.
-  *
-  * Results:
-  *	None.
-  *
-  * Side effects:
-  *	Changes thread local list of valid channels.
-  *
-  *----------------------------------------------------------------------
-  */
- 
- void
- TclpSpliceSockChannel(chan)
-     Tcl_Channel chan;			/* The channel being removed. Must
-                                          * not be referenced in any
-                                          * interpreter. */
- {
-     ThreadSpecificData *tsdPtr;
-     SocketInfo *infoPtr;
- 
-     if (Tcl_GetChannelType(chan) != &tcpChannelType)
-         return;
- 
-     /*
-      * Ensure that socket subsystem is initialized in this thread, or
-      * else sockets will not work.
-      */
- 
-     Tcl_MutexLock(&socketMutex);
-     InitSockets();
-     Tcl_MutexUnlock(&socketMutex);
- 
-     /*
-      * The initializtion of tsdPtr _after_ we have determined that we
-      * are dealing with socket is necessary. Doing it before causes
-      * the module to access th tdsPtr when it is not initialized yet,
-      * causing a lockup.
-      */
- 
-     tsdPtr  = TCL_TSD_INIT(&dataKey);
-     infoPtr = (SocketInfo *) Tcl_GetChannelInstanceData (chan);
- 
-     WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
-     infoPtr->nextPtr = tsdPtr->socketList;
-     tsdPtr->socketList = infoPtr;
-     SetEvent(tsdPtr->socketListLock);
- 
-     /*
-      * Ensure that notifications for the socket occur in this thread.
-      */
- 
-     SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
- 		(WPARAM) SELECT, (LPARAM) infoPtr);
- }
--- 2779,2781 ----

