Tcl Source Code

Artifact [6c3d81b2ce]
Login

Artifact 6c3d81b2ce89782ff662d43bb5dc2a6b80c00aa6:

Attachment "tcl-CFNotifier-HEAD.diff" to ticket [1202052fff] added by das 2005-05-15 03:41:00.
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.2630
diff -u -p -u -p -r1.2630 ChangeLog
--- ChangeLog	13 May 2005 21:20:35 -0000	1.2630
+++ ChangeLog	14 May 2005 19:11:43 -0000
@@ -1,3 +1,55 @@
+2005-05-14  Daniel Steffen  <[email protected]>
+
+	* generic/tclInt.decls:
+	* generic/tclTest.c:
+	* generic/tclUtil.c:
+	* win/tclWin32Dll.c: fixed link error due to direct access by
+	tclTest.c to the MODULE_SCOPE tclPlatform global: renamed existing
+	TclWinGetPlatform() accessor to TclGetPlatform() and moved it to
+	generic code so that it can be used by on all platforms where
+	MODULE_SCOPE is enforced.
+	
+	* macosx/tclMacOSXBundle.c:
+	* unix/tclUnixInit.c: 
+	* unix/tcl.m4 (Darwin): made use of CoreFoundation API configurable
+	and added test of CoreFoundation availablility to allow building on
+	ppc64, replaced HAVE_CFBUNDLE by HAVE_COREFOUNDATION; test for
+	availability of Tiger or later OSSpinLockLock API.
+
+	* unix/tclUnixNotfy.c:
+	* unix/Makefile.in:
+	* macosx/tclMacOSXNotify.c (new file): when CoreFoundation is
+	available, use new CFRunLoop based notifier: allows easy integration
+	with other event loops on Mac OS X, in particular the TkAqua Carbon
+	event loop is now integrated via a standard tcl event source (instead
+	of TkAqua upon loading having to finalize the exsting notifier and 
+	replace it with its custom version). [Patch 1202052]
+
+	* tests/unixNotfy.test: don't run unthreaded tests on Darwin
+	since notifier may be using threads even in unthreaded core.
+
+	* unix/tclUnixPort.h:
+	* unix/tcl.m4 (Darwin): test for thread-unsafe realpath durning
+	configure, as Darwin 7 and later realpath is threadsafe.
+	
+	* macosx/Makefile: enable configure caching.
+
+	* unix/configure.in: wrap tclConfig.h header in #ifndef _TCLCONFIG so
+	that it can be included more than once without warnings from gcc4.0
+	(as happens e.g. when including both tclInt.h and tclPort.h)
+
+	* macosx/tclMacOSXBundle.c:
+	* unix/tclUnixChan.c:
+	* unix/tclLoadDyld.c:
+	* unix/tclUnixInit.c: fixed gcc 4.0 warnings.
+
+	* unix/configure: autoconf-2.59
+	* unix/tclConfig.h.in: autoheader-2.59
+
+	* generic/tclIntDecls.h:
+	* generic/tclIntPlatDecls.h:
+	* generic/tclStubInit.c: make genstubs
+
 2005-05-13  Kevin Kenny  <[email protected]>
 
 	* win/tclWin32Dll.c: Further rework of the SEH logic.  All
Index: generic/tclInt.decls
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.decls,v
retrieving revision 1.88
diff -u -p -u -p -r1.88 tclInt.decls
--- generic/tclInt.decls	10 May 2005 18:34:41 -0000	1.88
+++ generic/tclInt.decls	14 May 2005 19:11:44 -0000
@@ -891,6 +891,10 @@ declare 222 generic {
 declare 223 generic {
     int TclBN_mp_read_radix(mp_int *a, const char *str, int radix)
 }
+# for use in tclTest.c
+declare 224 generic {
+    TclPlatformType *TclGetPlatform(void)
+}
 
 ##############################################################################
 
@@ -993,9 +997,10 @@ declare 23 win {
 declare 24 win {
     char *TclWinNoBackslash(char *path)
 }
-declare 25 win {
-    TclPlatformType *TclWinGetPlatform(void)
-}
+# replaced by generic TclGetPlatform
+#declare 25 win {
+#    TclPlatformType *TclWinGetPlatform(void)
+#}
 declare 26 win {
     void TclWinSetInterfaces(int wide)
 }
Index: generic/tclIntDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIntDecls.h,v
retrieving revision 1.79
diff -u -p -u -p -r1.79 tclIntDecls.h
--- generic/tclIntDecls.h	10 May 2005 18:34:42 -0000	1.79
+++ generic/tclIntDecls.h	14 May 2005 19:11:44 -0000
@@ -1156,6 +1156,11 @@ EXTERN int		TclBN_mp_init _ANSI_ARGS_((m
 EXTERN int		TclBN_mp_read_radix _ANSI_ARGS_((mp_int * a, 
 				const char * str, int radix));
 #endif
+#ifndef TclGetPlatform_TCL_DECLARED
+#define TclGetPlatform_TCL_DECLARED
+/* 224 */
+EXTERN TclPlatformType * TclGetPlatform _ANSI_ARGS_((void));
+#endif
 
 typedef struct TclIntStubs {
     int magic;
@@ -1400,6 +1405,7 @@ typedef struct TclIntStubs {
     void (*tclBN_mp_clear) _ANSI_ARGS_((mp_int * a)); /* 221 */
     int (*tclBN_mp_init) _ANSI_ARGS_((mp_int * a)); /* 222 */
     int (*tclBN_mp_read_radix) _ANSI_ARGS_((mp_int * a, const char * str, int radix)); /* 223 */
+    TclPlatformType * (*tclGetPlatform) _ANSI_ARGS_((void)); /* 224 */
 } TclIntStubs;
 
 #ifdef __cplusplus
@@ -2174,6 +2180,10 @@ extern TclIntStubs *tclIntStubsPtr;
 #define TclBN_mp_read_radix \
 	(tclIntStubsPtr->tclBN_mp_read_radix) /* 223 */
 #endif
+#ifndef TclGetPlatform
+#define TclGetPlatform \
+	(tclIntStubsPtr->tclGetPlatform) /* 224 */
+#endif
 
 #endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
 
Index: generic/tclIntPlatDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIntPlatDecls.h,v
retrieving revision 1.26
diff -u -p -u -p -r1.26 tclIntPlatDecls.h
--- generic/tclIntPlatDecls.h	3 Nov 2004 19:13:40 -0000	1.26
+++ generic/tclIntPlatDecls.h	14 May 2005 19:11:44 -0000
@@ -249,11 +249,7 @@ EXTERN char *		TclpGetTZName _ANSI_ARGS_
 /* 24 */
 EXTERN char *		TclWinNoBackslash _ANSI_ARGS_((char * path));
 #endif
-#ifndef TclWinGetPlatform_TCL_DECLARED
-#define TclWinGetPlatform_TCL_DECLARED
-/* 25 */
-EXTERN TclPlatformType * TclWinGetPlatform _ANSI_ARGS_((void));
-#endif
+/* Slot 25 is reserved */
 #ifndef TclWinSetInterfaces_TCL_DECLARED
 #define TclWinSetInterfaces_TCL_DECLARED
 /* 26 */
@@ -348,7 +344,7 @@ typedef struct TclIntPlatStubs {
     TclFile (*tclpCreateTempFile) _ANSI_ARGS_((CONST char * contents)); /* 22 */
     char * (*tclpGetTZName) _ANSI_ARGS_((int isdst)); /* 23 */
     char * (*tclWinNoBackslash) _ANSI_ARGS_((char * path)); /* 24 */
-    TclPlatformType * (*tclWinGetPlatform) _ANSI_ARGS_((void)); /* 25 */
+    void *reserved25;
     void (*tclWinSetInterfaces) _ANSI_ARGS_((int wide)); /* 26 */
     void (*tclWinFlushDirtyChannels) _ANSI_ARGS_((void)); /* 27 */
     void (*tclWinResetInterfaces) _ANSI_ARGS_((void)); /* 28 */
@@ -520,10 +516,7 @@ extern TclIntPlatStubs *tclIntPlatStubsP
 #define TclWinNoBackslash \
 	(tclIntPlatStubsPtr->tclWinNoBackslash) /* 24 */
 #endif
-#ifndef TclWinGetPlatform
-#define TclWinGetPlatform \
-	(tclIntPlatStubsPtr->tclWinGetPlatform) /* 25 */
-#endif
+/* Slot 25 is reserved */
 #ifndef TclWinSetInterfaces
 #define TclWinSetInterfaces \
 	(tclIntPlatStubsPtr->tclWinSetInterfaces) /* 26 */
Index: generic/tclStubInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclStubInit.c,v
retrieving revision 1.116
diff -u -p -u -p -r1.116 tclStubInit.c
--- generic/tclStubInit.c	10 May 2005 18:34:49 -0000	1.116
+++ generic/tclStubInit.c	14 May 2005 19:11:44 -0000
@@ -308,6 +308,7 @@ TclIntStubs tclIntStubs = {
     TclBN_mp_clear, /* 221 */
     TclBN_mp_init, /* 222 */
     TclBN_mp_read_radix, /* 223 */
+    TclGetPlatform, /* 224 */
 };
 
 TclIntPlatStubs tclIntPlatStubs = {
@@ -356,7 +357,7 @@ TclIntPlatStubs tclIntPlatStubs = {
     TclpCreateTempFile, /* 22 */
     TclpGetTZName, /* 23 */
     TclWinNoBackslash, /* 24 */
-    TclWinGetPlatform, /* 25 */
+    NULL, /* 25 */
     TclWinSetInterfaces, /* 26 */
     TclWinFlushDirtyChannels, /* 27 */
     TclWinResetInterfaces, /* 28 */
Index: generic/tclTest.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclTest.c,v
retrieving revision 1.89
diff -u -p -u -p -r1.89 tclTest.c
--- generic/tclTest.c	10 May 2005 18:34:50 -0000	1.89
+++ generic/tclTest.c	14 May 2005 19:11:46 -0000
@@ -2457,11 +2457,7 @@ TestgetplatformCmd(clientData, interp, a
     static CONST char *platformStrings[] = { "unix", "mac", "windows" };
     TclPlatformType *platform;
 
-#ifdef __WIN32__
-    platform = TclWinGetPlatform();
-#else
-    platform = &tclPlatform;
-#endif
+    platform = TclGetPlatform();
     
     if (argc != 1) {
         Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
@@ -3697,11 +3693,7 @@ TestsetplatformCmd(clientData, interp, a
     size_t length;
     TclPlatformType *platform;
 
-#ifdef __WIN32__
-    platform = TclWinGetPlatform();
-#else
-    platform = &tclPlatform;
-#endif
+    platform = TclGetPlatform();
     
     if (argc != 2) {
         Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
Index: generic/tclUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclUtil.c,v
retrieving revision 1.59
diff -u -p -u -p -r1.59 tclUtil.c
--- generic/tclUtil.c	10 May 2005 18:34:52 -0000	1.59
+++ generic/tclUtil.c	14 May 2005 19:11:46 -0000
@@ -2993,3 +2993,26 @@ TclpGetTime(timePtr)
 {
     Tcl_GetTime(timePtr);
 }
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetPlatform --
+ *
+ *      This is a kludge that allows the test library to get access
+ *      the internal tclPlatform variable.
+ *
+ * Results:
+ *      Returns a pointer to the tclPlatform variable.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TclPlatformType *
+TclGetPlatform()
+{
+    return &tclPlatform;
+}
Index: macosx/Makefile
===================================================================
RCS file: /cvsroot/tcl/tcl/macosx/Makefile,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 Makefile
--- macosx/Makefile	19 Nov 2004 06:28:29 -0000	1.18
+++ macosx/Makefile	14 May 2005 19:11:46 -0000
@@ -124,7 +124,7 @@ export CPPROG		:= cp -p
 ${PROJECT}: install-${PROJECT}
 
 ${OBJ_DIR}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure
-	mkdir -p ${OBJ_DIR} && cd ${OBJ_DIR} && ${UNIX_DIR}/configure \
+	mkdir -p ${OBJ_DIR} && cd ${OBJ_DIR} && ${UNIX_DIR}/configure -C \
 	--prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} \
 	--includedir=${INCLUDEDIR} --mandir=${MANDIR} --enable-threads \
 	--enable-framework ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}
Index: macosx/tclMacOSXBundle.c
===================================================================
RCS file: /cvsroot/tcl/tcl/macosx/tclMacOSXBundle.c,v
retrieving revision 1.6
diff -u -p -u -p -r1.6 tclMacOSXBundle.c
--- macosx/tclMacOSXBundle.c	20 Jul 2004 05:40:57 -0000	1.6
+++ macosx/tclMacOSXBundle.c	14 May 2005 19:11:46 -0000
@@ -51,8 +51,11 @@
  *      license.
  */
 
+#ifdef HAVE_COREFOUNDATION
 #include <CoreFoundation/CoreFoundation.h>
 #include <mach-o/dyld.h>
+#endif /* HAVE_COREFOUNDATION */
+
 #include "tcl.h"
 
 /*
@@ -119,6 +122,7 @@ Tcl_MacOSXOpenVersionedBundleResources(
     int         maxPathLen,
     char       *libraryPath)
 {
+#ifdef HAVE_COREFOUNDATION
     CFBundleRef bundleRef;
     CFStringRef bundleNameRef;
     CFURLRef libURL;
@@ -199,7 +203,7 @@ Tcl_MacOSXOpenVersionedBundleResources(
 	     */
 
 	    CFURLGetFileSystemRepresentation(libURL, TRUE,
-		    libraryPath, maxPathLen);
+		    (unsigned char*) libraryPath, maxPathLen);
 	    CFRelease(libURL);
 	}
     }
@@ -209,4 +213,7 @@ Tcl_MacOSXOpenVersionedBundleResources(
     } else {
 	return TCL_ERROR;
     }
+#else  /* HAVE_COREFOUNDATION */
+    return TCL_ERROR;
+#endif /* HAVE_COREFOUNDATION */
 }
Index: macosx/tclMacOSXNotify.c
===================================================================
RCS file: macosx/tclMacOSXNotify.c
diff -N macosx/tclMacOSXNotify.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ macosx/tclMacOSXNotify.c	14 May 2005 19:11:46 -0000
@@ -0,0 +1,1048 @@
+/*
+ * tclMacOSXNotify.c --
+ *
+ *	This file contains the implementation of a merged 
+ *	CFRunLoop/select-based notifier, which is the lowest-level part 
+ *	of the Tcl event loop.  This file works together with
+ *	generic/tclNotify.c.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001, Apple Computer, Inc.
+ * Copyright 2005, Tcl Core Team.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#ifdef HAVE_COREFOUNDATION /* Traditional unix select-based notifier
+                            * is in tclUnixNotfy.c */ 
+#include "tclInt.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <pthread.h>
+
+extern TclStubs tclStubs;
+extern Tcl_NotifierProcs tclOriginalNotifier;
+
+/*
+ * This structure is used to keep track of the notifier info for a 
+ * a registered file.
+ */
+
+typedef struct FileHandler {
+    int fd;
+    int mask;			/* Mask of desired events: TCL_READABLE,
+				 * etc. */
+    int readyMask;		/* Mask of events that have been seen since the
+				 * last time file handlers were invoked for
+				 * this file. */
+    Tcl_FileProc *proc;		/* Procedure to call, in the style of
+				 * Tcl_CreateFileHandler. */
+    ClientData clientData;	/* Argument to pass to proc. */
+    struct FileHandler *nextPtr;/* Next in list of all files we care about. */
+} FileHandler;
+
+/*
+ * The following structure is what is added to the Tcl event queue when
+ * file handlers are ready to fire.
+ */
+
+typedef struct FileHandlerEvent {
+    Tcl_Event header;		/* Information that is standard for
+				 * all events. */
+    int fd;			/* File descriptor that is ready.  Used
+				 * to find the FileHandler structure for
+				 * the file (can't point directly to the
+				 * FileHandler structure because it could
+				 * go away while the event is queued). */
+} FileHandlerEvent;
+
+/*
+ *
+ * The following structure contains a set of select() masks to track
+ * readable, writable, and exceptional conditions.
+ */
+
+typedef struct SelectMasks {
+    fd_set readable;
+    fd_set writable;
+    fd_set exceptional;
+} SelectMasks;
+
+/*
+ * The following static structure contains the state information for the
+ * select based implementation of the Tcl notifier.  One of these structures
+ * is created for each thread that is using the notifier.  
+ */
+
+typedef struct ThreadSpecificData {
+    FileHandler *firstFileHandlerPtr;
+				/* Pointer to head of file handler list. */
+
+    SelectMasks checkMasks;	/* This structure is used to build up the masks
+				 * to be used in the next call to select.
+				 * Bits are set in response to calls to
+				 * Tcl_CreateFileHandler. */
+    SelectMasks readyMasks;	/* This array reflects the readable/writable
+				 * conditions that were found to exist by the
+				 * last call to select. */
+    int numFdBits;		/* Number of valid bits in checkMasks
+				 * (one more than highest fd for which
+				 * Tcl_WatchFile has been called). */
+    int onList;			/* True if it is in this list */
+    unsigned int pollState;	/* pollState is used to implement a polling 
+				 * handshake between each thread and the
+				 * notifier thread. Bits defined below. */
+    struct ThreadSpecificData *nextPtr, *prevPtr;
+				/* All threads that are currently waiting on 
+				 * an event have their ThreadSpecificData
+				 * structure on a doubly-linked listed formed
+				 * from these pointers.  You must hold the
+				 * notifierLock before accessing these
+				 * fields. */
+    CFRunLoopSourceRef runLoopSource;
+                                /* Any other thread alerts a notifier
+				 * that an event is ready to be processed
+				 * by signaling this CFRunLoopSource. */
+    CFRunLoopRef runLoop;       /* This thread's CFRunLoop, needs to be woken
+                                 * up whenever the runLoopSource is signaled. */
+    int eventReady;		/* True if an event is ready to be processed. */
+} ThreadSpecificData;
+
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * The following static indicates the number of threads that have
+ * initialized notifiers.
+ *
+ * You must hold the notifierInitLock before accessing this variable.
+ */
+
+static int notifierCount = 0;
+
+/*
+ * The following variable points to the head of a doubly-linked list of 
+ * of ThreadSpecificData structures for all threads that are currently
+ * waiting on an event.
+ *
+ * You must hold the notifierLock before accessing this list.
+ */
+
+static ThreadSpecificData *waitingListPtr = NULL;
+
+/*
+ * The notifier thread spends all its time in select() waiting for a
+ * file descriptor associated with one of the threads on the waitingListPtr
+ * list to do something interesting.  But if the contents of the
+ * waitingListPtr list ever changes, we need to wake up and restart
+ * the select() system call.  You can wake up the notifier thread by
+ * writing a single byte to the file descriptor defined below.  This
+ * file descriptor is the input-end of a pipe and the notifier thread is
+ * listening for data on the output-end of the same pipe.  Hence writing
+ * to this file descriptor will cause the select() system call to return
+ * and wake up the notifier thread.
+ *
+ * You must hold the notifierLock lock before writing to the pipe.
+ */
+
+static int triggerPipe = -1;
+static int receivePipe = -1; /* Output end of triggerPipe */
+
+/*
+ * We use Darwin-native spinlocks instead of pthread mutexes for notifier
+ * locking: this radically simplifies the implementation and lowers
+ * overhead. Note that these are not pure spinlocks, they employ various
+ * strategies to back off, making them immune to most priority-inversion
+ * livelocks (c.f. man 3 OSSpinLockLock).
+ */
+
+#if defined(HAVE_LIBKERN_OSATOMIC_H) && defined(HAVE_OSSPINLOCKLOCK)
+/* Use OSSpinLock API where available (Tiger or later) */
+#include <libkern/OSAtomic.h>
+#else
+/* Otherwise, use commpage spinlock SPI directly */
+typedef uint32_t OSSpinLock;
+extern void _spin_lock(OSSpinLock *lock);
+extern void _spin_unlock(OSSpinLock *lock);
+#define OSSpinLockLock(p) _spin_lock(p)
+#define OSSpinLockUnlock(p) _spin_unlock(p)
+#endif
+
+/*
+ * These spinlocks lock access to the global notifier state. 
+ */
+
+static OSSpinLock notifierInitLock = 0;
+static OSSpinLock notifierLock = 0;
+
+/* 
+ * Macros abstracting notifier locking/unlocking
+ */
+
+#define LOCK_NOTIFIER_INIT   OSSpinLockLock(&notifierInitLock)
+#define UNLOCK_NOTIFIER_INIT OSSpinLockUnlock(&notifierInitLock)
+#define LOCK_NOTIFIER        OSSpinLockLock(&notifierLock)
+#define UNLOCK_NOTIFIER      OSSpinLockUnlock(&notifierLock)
+
+/*
+ * The pollState bits
+ *	POLL_WANT is set by each thread before it waits on its condition
+ *		variable.  It is checked by the notifier before it does
+ *		select.
+ *	POLL_DONE is set by the notifier if it goes into select after
+ *		seeing POLL_WANT.  The idea is to ensure it tries a select
+ *		with the same bits the initial thread had set.
+ */
+#define POLL_WANT	0x1
+#define POLL_DONE	0x2
+
+/*
+ * This is the thread ID of the notifier thread that does select.
+ */
+static pthread_t notifierThread;
+
+/*
+ * Static routines defined in this file.
+ */
+
+static void	NotifierThreadProc(ClientData clientData);
+static int	FileHandlerEventProc(Tcl_Event *evPtr, int flags);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InitNotifier --
+ *
+ *	Initializes the platform specific notifier state.
+ *
+ * Results:
+ *	Returns a handle to the notifier state for this thread..
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_InitNotifier()
+{
+    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+    tsdPtr->eventReady = 0;
+    
+     /*
+     * Initialize CFRunLoopSource and add it to CFRunLoop of this thread
+     */
+    
+    if (!tsdPtr->runLoop) {
+        CFRunLoopRef runLoop = CFRunLoopGetCurrent();
+        CFRunLoopSourceRef runLoopSource;
+        CFRunLoopSourceContext runLoopSourceContext;
+        
+        bzero(&runLoopSourceContext, sizeof(CFRunLoopSourceContext));
+        runLoopSourceContext.info = tsdPtr;
+        runLoopSource = CFRunLoopSourceCreate(NULL, 0, &runLoopSourceContext);
+        if (!runLoopSource) {
+            Tcl_Panic("Tcl_InitNotifier: could not create CFRunLoopSource.");
+        }
+        CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopCommonModes);
+        CFRelease(runLoopSource);
+        tsdPtr->runLoopSource = runLoopSource;
+        tsdPtr->runLoop = runLoop;
+    }
+
+    /*
+     * Initialize trigger pipe and start the Notifier thread if necessary.
+     */
+
+    LOCK_NOTIFIER_INIT;
+    if (notifierCount == 0) {
+        int fds[2], status, result;
+        pthread_attr_t attr;
+    
+        if (pipe(fds) != 0) {
+            Tcl_Panic("Tcl_InitNotifier: could not create trigger pipe.");
+        }
+        
+        status = fcntl(fds[0], F_GETFL);
+        status |= O_NONBLOCK;
+        if (fcntl(fds[0], F_SETFL, status) < 0) {
+            Tcl_Panic("Tcl_InitNotifier: could not make receive pipe non blocking.");
+        }
+        status = fcntl(fds[1], F_GETFL);
+        status |= O_NONBLOCK;
+        if (fcntl(fds[1], F_SETFL, status) < 0) {
+            Tcl_Panic("Tcl_InitNotifier: could not make trigger pipe non blocking.");
+        }
+
+        receivePipe = fds[0];
+        triggerPipe = fds[1];
+
+        pthread_attr_init(&attr);
+        pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+        pthread_attr_setstacksize(&attr, 60 * 1024);
+        result = pthread_create(&notifierThread, &attr, (void * (*)(void *))NotifierThreadProc, NULL);
+        pthread_attr_destroy(&attr);
+	if (result) {
+	    Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread.");
+	}
+    }
+    notifierCount++;
+    UNLOCK_NOTIFIER_INIT;
+    
+    return (ClientData) tsdPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FinalizeNotifier --
+ *
+ *	This function is called to cleanup the notifier state before
+ *	a thread is terminated.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	May terminate the background notifier thread if this is the
+ *	last notifier instance.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_FinalizeNotifier(clientData)
+    ClientData clientData;		/* Not used. */
+{
+    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+    LOCK_NOTIFIER_INIT;
+    notifierCount--;
+
+    /*
+     * If this is the last thread to use the notifier, close the notifier
+     * pipe and wait for the background thread to terminate.
+     */
+
+    if (notifierCount == 0) {
+        int result;
+        
+	if (triggerPipe < 0) {
+	    Tcl_Panic("Tcl_FinalizeNotifier: notifier pipe not initialized.");
+	}
+
+	/*
+	 * Send "q" message to the notifier thread so that it will
+	 * terminate.  The notifier will return from its call to select()
+	 * and notice that a "q" message has arrived, it will then close
+	 * its side of the pipe and terminate its thread.  Note the we can
+	 * not just close the pipe and check for EOF in the notifier
+	 * thread because if a background child process was created with
+	 * exec, select() would not register the EOF on the pipe until the
+	 * child processes had terminated. [Bug: 4139]
+	 */
+	write(triggerPipe, "q", 1);
+	close(triggerPipe);
+
+	result = pthread_join(notifierThread, NULL); 
+	if (result) {
+	    Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier thread.");
+	}
+	
+	close(receivePipe);
+        triggerPipe = -1;
+    }
+    UNLOCK_NOTIFIER_INIT;
+    
+    LOCK_NOTIFIER; /* for concurrency with Tcl_AlertNotifier */
+    if (tsdPtr->runLoop) {
+        tsdPtr->runLoop = NULL;
+        /* Remove runLoopSource from all CFRunLoops and release it */
+        CFRunLoopSourceInvalidate(tsdPtr->runLoopSource);
+        tsdPtr->runLoopSource = NULL;
+    }
+    UNLOCK_NOTIFIER;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AlertNotifier --
+ *
+ *	Wake up the specified notifier from any thread. This routine
+ *	is called by the platform independent notifier code whenever
+ *	the Tcl_ThreadAlert routine is called.  This routine is
+ *	guaranteed not to be called on a given notifier after
+ *	Tcl_FinalizeNotifier is called for that notifier.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Signals the notifier condition variable for the specified
+ *	notifier.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AlertNotifier(clientData)
+    ClientData clientData;
+{
+    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
+    LOCK_NOTIFIER;
+    if (tsdPtr->runLoop) {
+        tsdPtr->eventReady = 1;
+        CFRunLoopSourceSignal(tsdPtr->runLoopSource);
+        CFRunLoopWakeUp(tsdPtr->runLoop);
+    }
+    UNLOCK_NOTIFIER;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetTimer --
+ *
+ *	This procedure sets the current notifier timer value.  This
+ *	interface is not implemented in this notifier because we are
+ *	always running inside of Tcl_DoOneEvent.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetTimer(timePtr)
+    Tcl_Time *timePtr;		/* Timeout value, may be NULL. */
+{
+    /*
+     * The interval timer doesn't do anything in this implementation,
+     * because the only event loop is via Tcl_DoOneEvent, which passes
+     * timeout values to Tcl_WaitForEvent.
+     */
+
+    if (tclStubs.tcl_SetTimer != tclOriginalNotifier.setTimerProc) {
+	tclStubs.tcl_SetTimer(timePtr);
+    }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ServiceModeHook --
+ *
+ *	This function is invoked whenever the service mode changes.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_ServiceModeHook(mode)
+    int mode;			/* Either TCL_SERVICE_ALL, or
+				 * TCL_SERVICE_NONE. */
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateFileHandler --
+ *
+ *	This procedure registers a file handler with the select notifier.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Creates a new file handler structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_CreateFileHandler(fd, mask, proc, clientData)
+    int fd;			/* Handle of stream to watch. */
+    int mask;			/* OR'ed combination of TCL_READABLE,
+				 * TCL_WRITABLE, and TCL_EXCEPTION:
+				 * indicates conditions under which
+				 * proc should be called. */
+    Tcl_FileProc *proc;		/* Procedure to call for each
+				 * selected event. */
+    ClientData clientData;	/* Arbitrary data to pass to proc. */
+{
+    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+    FileHandler *filePtr;
+
+    if (tclStubs.tcl_CreateFileHandler != tclOriginalNotifier.createFileHandlerProc) {
+	tclStubs.tcl_CreateFileHandler(fd, mask, proc, clientData);
+	return;
+    }
+
+    for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
+	    filePtr = filePtr->nextPtr) {
+	if (filePtr->fd == fd) {
+	    break;
+	}
+    }
+    if (filePtr == NULL) {
+	filePtr = (FileHandler*) ckalloc(sizeof(FileHandler));
+	filePtr->fd = fd;
+	filePtr->readyMask = 0;
+	filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
+	tsdPtr->firstFileHandlerPtr = filePtr;
+    }
+    filePtr->proc = proc;
+    filePtr->clientData = clientData;
+    filePtr->mask = mask;
+
+    /*
+     * Update the check masks for this file.
+     */
+
+    if (mask & TCL_READABLE) {
+	FD_SET(fd, &(tsdPtr->checkMasks.readable));
+    } else {
+	FD_CLR(fd, &(tsdPtr->checkMasks.readable));
+    }
+    if (mask & TCL_WRITABLE) {
+	FD_SET(fd, &(tsdPtr->checkMasks.writable));
+    } else {
+	FD_CLR(fd, &(tsdPtr->checkMasks.writable));
+    }
+    if (mask & TCL_EXCEPTION) {
+	FD_SET(fd, &(tsdPtr->checkMasks.exceptional));
+    } else {
+	FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
+    }
+    if (tsdPtr->numFdBits <= fd) {
+	tsdPtr->numFdBits = fd+1;
+    }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteFileHandler --
+ *
+ *	Cancel a previously-arranged callback arrangement for
+ *	a file.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	If a callback was previously registered on file, remove it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteFileHandler(fd)
+    int fd;		/* Stream id for which to remove callback procedure. */
+{
+    FileHandler *filePtr, *prevPtr;
+    int i;
+    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+    if (tclStubs.tcl_DeleteFileHandler != tclOriginalNotifier.deleteFileHandlerProc) {
+	tclStubs.tcl_DeleteFileHandler(fd);
+	return;
+    }
+
+    /*
+     * Find the entry for the given file (and return if there isn't one).
+     */
+
+    for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
+	 prevPtr = filePtr, filePtr = filePtr->nextPtr) {
+	if (filePtr == NULL) {
+	    return;
+	}
+	if (filePtr->fd == fd) {
+	    break;
+	}
+    }
+
+    /*
+     * Update the check masks for this file.
+     */
+
+    if (filePtr->mask & TCL_READABLE) {
+	FD_CLR(fd, &(tsdPtr->checkMasks.readable));
+    }
+    if (filePtr->mask & TCL_WRITABLE) {
+	FD_CLR(fd, &(tsdPtr->checkMasks.writable));
+    }
+    if (filePtr->mask & TCL_EXCEPTION) {
+	FD_CLR(fd, &(tsdPtr->checkMasks.exceptional));
+    }
+
+    /*
+     * Find current max fd.
+     */
+
+    if (fd+1 == tsdPtr->numFdBits) {
+	tsdPtr->numFdBits = 0;
+	for (i = fd-1; i >= 0; i--) {
+	    if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
+		    || FD_ISSET(i, &(tsdPtr->checkMasks.writable))
+		    || FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
+		tsdPtr->numFdBits = i+1;
+		break;
+	    }
+	}
+    }
+
+    /*
+     * Clean up information in the callback record.
+     */
+
+    if (prevPtr == NULL) {
+	tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
+    } else {
+	prevPtr->nextPtr = filePtr->nextPtr;
+    }
+    ckfree((char *) filePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileHandlerEventProc --
+ *
+ *	This procedure is called by Tcl_ServiceEvent when a file event
+ *	reaches the front of the event queue.  This procedure is
+ *	responsible for actually handling the event by invoking the
+ *	callback for the file handler.
+ *
+ * Results:
+ *	Returns 1 if the event was handled, meaning it should be removed
+ *	from the queue.  Returns 0 if the event was not handled, meaning
+ *	it should stay on the queue.  The only time the event isn't
+ *	handled is if the TCL_FILE_EVENTS flag bit isn't set.
+ *
+ * Side effects:
+ *	Whatever the file handler's callback procedure does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileHandlerEventProc(evPtr, flags)
+    Tcl_Event *evPtr;		/* Event to service. */
+    int flags;			/* Flags that indicate what events to
+				 * handle, such as TCL_FILE_EVENTS. */
+{
+    int mask;
+    FileHandler *filePtr;
+    FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr;
+    ThreadSpecificData *tsdPtr;
+
+    if (!(flags & TCL_FILE_EVENTS)) {
+	return 0;
+    }
+
+    /*
+     * Search through the file handlers to find the one whose handle matches
+     * the event.  We do this rather than keeping a pointer to the file
+     * handler directly in the event, so that the handler can be deleted
+     * while the event is queued without leaving a dangling pointer.
+     */
+
+    tsdPtr = TCL_TSD_INIT(&dataKey);
+    for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
+	    filePtr = filePtr->nextPtr) {
+	if (filePtr->fd != fileEvPtr->fd) {
+	    continue;
+	}
+
+	/*
+	 * The code is tricky for two reasons:
+	 * 1. The file handler's desired events could have changed
+	 *    since the time when the event was queued, so AND the
+	 *    ready mask with the desired mask.
+	 * 2. The file could have been closed and re-opened since
+	 *    the time when the event was queued.  This is why the
+	 *    ready mask is stored in the file handler rather than
+	 *    the queued event:  it will be zeroed when a new
+	 *    file handler is created for the newly opened file.
+	 */
+
+	mask = filePtr->readyMask & filePtr->mask;
+	filePtr->readyMask = 0;
+	if (mask != 0) {
+	    (*filePtr->proc)(filePtr->clientData, mask);
+	}
+	break;
+    }
+    return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_WaitForEvent --
+ *
+ *	This function is called by Tcl_DoOneEvent to wait for new
+ *	events on the message queue.  If the block time is 0, then
+ *	Tcl_WaitForEvent just polls without blocking.
+ *
+ * Results:
+ *	Returns -1 if the select would block forever, otherwise
+ *	returns 0.
+ *
+ * Side effects:
+ *	Queues file events that are detected by the select.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_WaitForEvent(timePtr)
+    Tcl_Time *timePtr;		/* Maximum block time, or NULL. */
+{
+    FileHandler *filePtr;
+    FileHandlerEvent *fileEvPtr;
+    int mask;
+    Tcl_Time myTime;
+    int waitForFiles;
+    Tcl_Time *myTimePtr;
+    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+    if (tclStubs.tcl_WaitForEvent != tclOriginalNotifier.waitForEventProc) {
+	return tclStubs.tcl_WaitForEvent(timePtr);
+    }
+
+    if (timePtr != NULL) {
+	/* TIP #233 (Virtualized Time). Is virtual time in effect ?
+	 * And do we actually have something to scale ? If yes to both
+	 * then we call the handler to do this scaling */
+
+	myTime.sec  = timePtr->sec;
+	myTime.usec = timePtr->usec;
+
+	if (myTime.sec != 0 || myTime.usec != 0) {
+	    (*tclScaleTimeProcPtr) (&myTime, tclTimeClientData);
+	}
+
+	myTimePtr = &myTime;
+    } else {
+	myTimePtr = NULL;
+    }
+
+    /*
+     * Place this thread on the list of interested threads, signal the
+     * notifier thread, and wait for a response or a timeout.
+     */
+
+    LOCK_NOTIFIER;
+
+    waitForFiles = (tsdPtr->numFdBits > 0);
+    if (myTimePtr != NULL && myTimePtr->sec == 0 && myTimePtr->usec == 0) {
+	/*
+	 * Cannot emulate a polling select with a polling condition variable.
+	 * Instead, pretend to wait for files and tell the notifier
+	 * thread what we are doing.  The notifier thread makes sure
+	 * it goes through select with its select mask in the same state
+	 * as ours currently is.  We block until that happens.
+	 */
+
+	waitForFiles = 1;
+	tsdPtr->pollState = POLL_WANT;
+	myTimePtr = NULL;
+    } else {
+	tsdPtr->pollState = 0;
+    }
+
+    if (waitForFiles) {
+	/*
+	 * Add the ThreadSpecificData structure of this thread to the list
+	 * of ThreadSpecificData structures of all threads that are waiting
+	 * on file events.
+	 */
+
+	tsdPtr->nextPtr = waitingListPtr;
+	if (waitingListPtr) {
+	    waitingListPtr->prevPtr = tsdPtr;
+	}
+	tsdPtr->prevPtr = 0;
+	waitingListPtr = tsdPtr;
+	tsdPtr->onList = 1;
+
+	write(triggerPipe, "", 1);
+    }
+
+    FD_ZERO(&(tsdPtr->readyMasks.readable));
+    FD_ZERO(&(tsdPtr->readyMasks.writable));
+    FD_ZERO(&(tsdPtr->readyMasks.exceptional));
+
+    if (!tsdPtr->eventReady) {
+        CFTimeInterval waitTime;
+
+        if (myTimePtr == NULL) {
+            waitTime = 1.0e10; /* Wait forever, as per CFRunLoop.c */
+        } else {
+            waitTime = myTimePtr->sec + 1.0e-6 * myTimePtr->usec;
+        }
+        UNLOCK_NOTIFIER;
+        CFRunLoopRunInMode(kCFRunLoopDefaultMode, waitTime, TRUE);
+        LOCK_NOTIFIER;
+    }
+    tsdPtr->eventReady = 0;
+
+    if (waitForFiles && tsdPtr->onList) {
+	/*
+	 * Remove the ThreadSpecificData structure of this thread from the
+	 * waiting list.  Alert the notifier thread to recompute its select
+	 * masks - skipping this caused a hang when trying to close a pipe
+	 * which the notifier thread was still doing a select on.
+	 */
+
+	if (tsdPtr->prevPtr) {
+	    tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
+	} else {
+	    waitingListPtr = tsdPtr->nextPtr;
+	}
+	if (tsdPtr->nextPtr) {
+	    tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
+	}
+	tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
+	tsdPtr->onList = 0;
+	write(triggerPipe, "", 1);
+    }
+
+    
+    /*
+     * Queue all detected file events before returning.
+     */
+
+    for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
+	    filePtr = filePtr->nextPtr) {
+
+	mask = 0;
+	if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.readable))) {
+	    mask |= TCL_READABLE;
+	}
+	if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.writable))) {
+	    mask |= TCL_WRITABLE;
+	}
+	if (FD_ISSET(filePtr->fd, &(tsdPtr->readyMasks.exceptional))) {
+	    mask |= TCL_EXCEPTION;
+	}
+
+	if (!mask) {
+	    continue;
+	}
+
+	/*
+	 * Don't bother to queue an event if the mask was previously
+	 * non-zero since an event must still be on the queue.
+	 */
+
+	if (filePtr->readyMask == 0) {
+	    fileEvPtr = (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent));
+	    fileEvPtr->header.proc = FileHandlerEventProc;
+	    fileEvPtr->fd = filePtr->fd;
+	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
+	}
+	filePtr->readyMask = mask;
+    }
+    UNLOCK_NOTIFIER;
+    return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NotifierThreadProc --
+ *
+ *	This routine is the initial (and only) function executed by the
+ *	special notifier thread.  Its job is to wait for file descriptors
+ *	to become readable or writable or to have an exception condition
+ *	and then to notify other threads who are interested in this
+ *	information by signalling a condition variable.  Other threads
+ *	can signal this notifier thread of a change in their interests
+ *	by writing a single byte to a special pipe that the notifier
+ *	thread is monitoring.
+ *
+ * Result:
+ *	None.  Once started, this routine never exits.  It dies with
+ *	the overall process.
+ *
+ * Side effects:
+ *	The trigger pipe used to signal the notifier thread is created
+ *	when the notifier thread first starts.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+NotifierThreadProc(clientData)
+    ClientData clientData;	/* Not used. */
+{
+    ThreadSpecificData *tsdPtr;
+    fd_set readableMask;
+    fd_set writableMask;
+    fd_set exceptionalMask;
+    int i, numFdBits = 0;
+    long found;
+    struct timeval poll = {0., 0.}, *timePtr;
+    char buf[2];
+
+    /*
+     * Look for file events and report them to interested threads.
+     */
+
+    while (1) {
+	FD_ZERO(&readableMask);
+	FD_ZERO(&writableMask);
+	FD_ZERO(&exceptionalMask);
+
+	/*
+	 * Compute the logical OR of the select masks from all the
+	 * waiting notifiers.
+	 */
+
+	LOCK_NOTIFIER;
+	timePtr = NULL;
+	for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
+	    for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
+		if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))) {
+		    FD_SET(i, &readableMask);
+		}
+		if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))) {
+		    FD_SET(i, &writableMask);
+		}
+		if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))) {
+		    FD_SET(i, &exceptionalMask);
+		}
+	    }
+	    if (tsdPtr->numFdBits > numFdBits) {
+		numFdBits = tsdPtr->numFdBits;
+	    }
+	    if (tsdPtr->pollState & POLL_WANT) {
+		/*
+		 * Here we make sure we go through select() with the same
+		 * mask bits that were present when the thread tried to poll.
+		 */
+
+		tsdPtr->pollState |= POLL_DONE;
+		timePtr = &poll;
+	    }
+	}
+	UNLOCK_NOTIFIER;
+
+	/*
+	 * Set up the select mask to include the receive pipe.
+	 */
+
+	if (receivePipe >= numFdBits) {
+	    numFdBits = receivePipe + 1;
+	}
+	FD_SET(receivePipe, &readableMask);
+
+	if (select(numFdBits, &readableMask, &writableMask, &exceptionalMask,
+		timePtr) == -1) {
+	    /*
+	     * Try again immediately on an error.
+	     */
+
+	    continue;
+	}
+
+	/*
+	 * Alert any threads that are waiting on a ready file descriptor.
+	 */
+
+	LOCK_NOTIFIER;
+	for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
+	    found = 0;
+
+	    for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
+		if (FD_ISSET(i, &(tsdPtr->checkMasks.readable))
+			&& FD_ISSET(i, &readableMask)) {
+		    FD_SET(i, &(tsdPtr->readyMasks.readable));
+		    found = 1;
+		}
+		if (FD_ISSET(i, &(tsdPtr->checkMasks.writable))
+			&& FD_ISSET(i, &writableMask)) {
+		    FD_SET(i, &(tsdPtr->readyMasks.writable));
+		    found = 1;
+		}
+		if (FD_ISSET(i, &(tsdPtr->checkMasks.exceptional))
+			&& FD_ISSET(i, &exceptionalMask)) {
+		    FD_SET(i, &(tsdPtr->readyMasks.exceptional));
+		    found = 1;
+		}
+	    }
+
+	    if (found || (tsdPtr->pollState & POLL_DONE)) {
+		tsdPtr->eventReady = 1;
+		if (tsdPtr->onList) {
+		    /*
+		     * Remove the ThreadSpecificData structure of this
+		     * thread from the waiting list. This prevents us from
+		     * continuously spining on select until the other
+		     * threads runs and services the file event.
+		     */
+
+		    if (tsdPtr->prevPtr) {
+			tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
+		    } else {
+			waitingListPtr = tsdPtr->nextPtr;
+		    }
+		    if (tsdPtr->nextPtr) {
+			tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
+		    }
+		    tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
+		    tsdPtr->onList = 0;
+		    tsdPtr->pollState = 0;
+		}
+		if (tsdPtr->runLoop) {
+		    CFRunLoopSourceSignal(tsdPtr->runLoopSource);
+		    CFRunLoopWakeUp(tsdPtr->runLoop);
+		}
+	    }
+	}
+	UNLOCK_NOTIFIER;
+
+	/*
+	 * Consume the next byte from the notifier pipe if the pipe was
+	 * readable.  Note that there may be multiple bytes pending, but
+	 * to avoid a race condition we only read one at a time.
+	 */
+
+	if (FD_ISSET(receivePipe, &readableMask)) {
+	    i = read(receivePipe, buf, 1);
+
+	    if ((i == 0) || ((i == 1) && (buf[0] == 'q'))) {
+		/*
+		 * Someone closed the write end of the pipe or sent us a
+		 * Quit message [Bug: 4139] and then closed the write end
+		 * of the pipe so we need to shut down the notifier thread.
+		 */
+
+		break;
+	    }
+	}
+    }
+    pthread_exit (0);
+}
+
+#endif /* HAVE_COREFOUNDATION */
Index: tests/unixNotfy.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/unixNotfy.test,v
retrieving revision 1.17
diff -u -p -u -p -r1.17 unixNotfy.test
--- tests/unixNotfy.test	24 Jun 2004 10:34:12 -0000	1.17
+++ tests/unixNotfy.test	14 May 2005 19:11:46 -0000
@@ -24,8 +24,10 @@ if {[lsearch [namespace children] ::tclt
 # When run in a Tk shell, these tests hang.
 testConstraint noTk       [expr {![info exists tk_version]}]
 testConstraint testthread [expr {[info commands testthread] != {}}]
+# Darwin always uses a threaded notifier
 testConstraint unthreaded [expr {
-    ![info exist tcl_platform(threaded)] || !$tcl_platform(threaded)
+    (![info exist tcl_platform(threaded)] || !$tcl_platform(threaded))
+    && $tcl_platform(os) ne "Darwin"
 }]
 
 # The next two tests will hang if threads are enabled because the notifier
Index: unix/Makefile.in
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/Makefile.in,v
retrieving revision 1.166
diff -u -p -u -p -r1.166 Makefile.in
--- unix/Makefile.in	13 May 2005 17:12:19 -0000	1.166
+++ unix/Makefile.in	14 May 2005 19:11:46 -0000
@@ -323,7 +323,7 @@ TOMMATH_OBJS = bncore.o bn_reverse.o bn_
 
 STUB_LIB_OBJS = tclStubLib.o ${COMPAT_OBJS}
 
-MAC_OSX_OBJS = tclMacOSXBundle.o tclMacOSXFCmd.o
+MAC_OSX_OBJS = tclMacOSXBundle.o tclMacOSXFCmd.o tclMacOSXNotify.o
 
 OBJS = ${GENERIC_OBJS} ${TOMMATH_OBJS} ${UNIX_OBJS} ${NOTIFY_OBJS} \
 	${COMPAT_OBJS} @DL_OBJS@ @PLAT_OBJS@
@@ -504,7 +504,8 @@ DL_SRCS = \
 
 MAC_OSX_SRCS = \
 	$(MAC_OSX_DIR)/tclMacOSXBundle.c \
-	$(MAC_OSX_DIR)/tclMacOSXFCmd.c
+	$(MAC_OSX_DIR)/tclMacOSXFCmd.c \
+	$(MAC_OSX_DIR)/tclMacOSXNotify.c
 
 # Note: don't include DL_SRCS or MAC_OSX_SRCS in SRCS: most of those
 # files won't compile on the current machine, and they will cause
@@ -825,6 +826,9 @@ install-private-headers: libraries
 	    do \
 	    $(INSTALL_DATA) $$i $(PRIVATE_INCLUDE_INSTALL_DIR); \
 	    done;
+	@if test -f tclConfig.h; then\
+	    $(INSTALL_DATA) tclConfig.h $(PRIVATE_INCLUDE_INSTALL_DIR); \
+	    fi;
 
 Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
 	$(SHELL) config.status
@@ -1352,6 +1356,9 @@ tclMacOSXBundle.o: $(MAC_OSX_DIR)/tclMac
 tclMacOSXFCmd.o: $(MAC_OSX_DIR)/tclMacOSXFCmd.c
 	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXFCmd.c
 
+tclMacOSXNotify.o: $(MAC_OSX_DIR)/tclMacOSXNotify.c
+	$(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXNotify.c
+
 # The following targets are not completely general.  They are provide
 # purely for documentation purposes so people who are interested in
 # the Xt based notifier can modify them to suit their own installation.
Index: unix/configure
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/configure,v
retrieving revision 1.144
diff -u -p -u -p -r1.144 configure
--- unix/configure	7 May 2005 00:05:56 -0000	1.144
+++ unix/configure	14 May 2005 19:11:47 -0000
@@ -851,6 +851,7 @@ Optional Features:
   --enable-shared         build and link with shared libraries --enable-shared
   --enable-64bit          enable 64bit support (where applicable)
   --enable-64bit-vis      enable 64bit Sparc VIS support
+  --enable-corefoundation use CoreFoundation API --enable-corefoundation
   --disable-load          disallow dynamic loading and "load" command
   --enable-symbols        build with debugging symbols --disable-symbols
   --enable-langinfo	  use nl_langinfo if possible to determine
@@ -1322,6 +1323,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
 TCL_VERSION=8.5
 TCL_MAJOR_VERSION=8
 TCL_MINOR_VERSION=5
@@ -7913,19 +7915,344 @@ echo "${ECHO_T}$tcl_cv_ld_search_paths_f
 	    CC_SEARCH_FLAGS=""
 	    LD_SEARCH_FLAGS=""
 	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
-	    PLAT_OBJS="\${MAC_OSX_OBJS}"
-	    PLAT_SRCS="\${MAC_OSX_SRCS}"
+	    PLAT_OBJS='${MAC_OSX_OBJS}'
+	    PLAT_SRCS='${MAC_OSX_SRCS}'
 	    TCL_SHLIB_LD_EXTRAS='-compatibility_version ${VERSION} -current_version ${VERSION} -install_name ${DYLIB_INSTALL_DIR}/${TCL_LIB_FILE} -seg1addr 0xa000000'
 	    TK_SHLIB_LD_EXTRAS=' -compatibility_version ${VERSION} -current_version ${VERSION} -install_name ${DYLIB_INSTALL_DIR}/${TK_LIB_FILE}  -seg1addr 0xb000000 -unexported_symbols_list $$(f=$(TCL_STUB_LIB_FILE).E && nm -gjp $(TCL_BIN_DIR)/$(TCL_STUB_LIB_FILE) | tail +3 > $$f && echo $$f)'
-	    LIBS="$LIBS -framework CoreFoundation"
+            echo "$as_me:$LINENO: checking whether to use CoreFoundation" >&5
+echo $ECHO_N "checking whether to use CoreFoundation... $ECHO_C" >&6
+            # Check whether --enable-corefoundation or --disable-corefoundation was given.
+if test "${enable_corefoundation+set}" = set; then
+  enableval="$enable_corefoundation"
+  tcl_corefoundation=$enableval
+else
+  tcl_corefoundation=yes
+fi;
+            echo "$as_me:$LINENO: result: $tcl_corefoundation" >&5
+echo "${ECHO_T}$tcl_corefoundation" >&6
+            if test $tcl_corefoundation = yes; then
+                echo "$as_me:$LINENO: checking for CoreFoundation.framework" >&5
+echo $ECHO_N "checking for CoreFoundation.framework... $ECHO_C" >&6
+if test "${tcl_cv_lib_corefoundation+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+                    hold_libs=$LIBS
+                    LIBS="$LIBS -framework CoreFoundation"
+                    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <CoreFoundation/CoreFoundation.h>
+int
+main ()
+{
+CFBundleRef b = CFBundleGetMainBundle();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  tcl_cv_lib_corefoundation=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+tcl_cv_lib_corefoundation=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+                    LIBS=$hold_libs
+fi
+echo "$as_me:$LINENO: result: $tcl_cv_lib_corefoundation" >&5
+echo "${ECHO_T}$tcl_cv_lib_corefoundation" >&6
+                if test $tcl_cv_lib_corefoundation = yes; then
+                    LIBS="$LIBS -framework CoreFoundation"
 
 cat >>confdefs.h <<\_ACEOF
-#define MAC_OSX_TCL 1
+#define HAVE_COREFOUNDATION 1
+_ACEOF
+
+                fi
+	    fi
+
+for ac_header in libkern/OSAtomic.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------ ##
+## Report this to the tcl lists.  ##
+## ------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in OSSpinLockLock
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
 _ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
 
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_CFBUNDLE 1
+#define MAC_OSX_TCL 1
 _ACEOF
 
 
@@ -7943,6 +8270,103 @@ cat >>confdefs.h <<\_ACEOF
 #define MODULE_SCOPE __private_extern__
 _ACEOF
 
+	    # prior to Darwin 7, realpath is not threadsafe, so don't
+	    # use it when threads are enabled, c.f. bug # 711232:
+	    echo "$as_me:$LINENO: checking for realpath" >&5
+echo $ECHO_N "checking for realpath... $ECHO_C" >&6
+if test "${ac_cv_func_realpath+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define realpath to an innocuous variant, in case <limits.h> declares realpath.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define realpath innocuous_realpath
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char realpath (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef realpath
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char realpath ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_realpath) || defined (__stub___realpath)
+choke me
+#else
+char (*f) () = realpath;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != realpath;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_realpath=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_realpath=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_realpath" >&5
+echo "${ECHO_T}$ac_cv_func_realpath" >&6
+
+	    if test "$ac_cv_func_realpath" = yes -a "${TCL_THREADS}" = 1 \
+	            -a `uname -r | awk -F. '{print $1}'` -lt 7 ; then
+	        ac_cv_func_realpath=no
+	    fi
 	    ;;
 	NEXTSTEP-*)
 	    SHLIB_CFLAGS=""
@@ -14904,6 +15328,11 @@ echo "${ECHO_T}framework" >&6
 echo "$as_me: WARNING: \"Frameworks can only be built if --enable-shared is yes\"" >&2;}
 	    FRAMEWORK_BUILD=0
 	fi
+	if test $tcl_corefoundation = no; then
+	    { echo "$as_me:$LINENO: WARNING: \"Frameworks can only be used when CoreFoundation is available\"" >&5
+echo "$as_me: WARNING: \"Frameworks can only be used when CoreFoundation is available\"" >&2;}
+	    FRAMEWORK_BUILD=0
+	fi
     else
 	echo "$as_me:$LINENO: result: standard shared library" >&5
 echo "${ECHO_T}standard shared library" >&6
Index: unix/configure.in
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/configure.in,v
retrieving revision 1.128
diff -u -p -u -p -r1.128 configure.in
--- unix/configure.in	10 May 2005 18:35:26 -0000	1.128
+++ unix/configure.in	14 May 2005 19:11:47 -0000
@@ -7,8 +7,12 @@ dnl	to configure the system for the loca
 
 AC_INIT([tcl],[8.5])
 AC_PREREQ(2.57)
+
 dnl AC_CONFIG_HEADERS([tclConfig.h])
-dnl AC_CONFIG_COMMANDS_PRE([DEFS=-DHAVE_TCL_CONFIG_H])
+dnl AC_CONFIG_COMMANDS_PRE([DEFS="-DHAVE_TCL_CONFIG_H  -imacros tclConfig.h"])
+dnl AH_TOP([#ifndef _TCLCONFIG
+dnl #define _TCLCONFIG])
+dnl AH_BOTTOM([#endif /* _TCLCONFIG */])
 
 TCL_VERSION=8.5
 TCL_MAJOR_VERSION=8
Index: unix/tcl.m4
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tcl.m4,v
retrieving revision 1.143
diff -u -p -u -p -r1.143 tcl.m4
--- unix/tcl.m4	7 May 2005 00:06:03 -0000	1.143
+++ unix/tcl.m4	14 May 2005 19:11:47 -0000
@@ -402,6 +402,10 @@ AC_DEFUN(SC_ENABLE_FRAMEWORK, [
 	    AC_MSG_WARN("Frameworks can only be built if --enable-shared is yes")
 	    FRAMEWORK_BUILD=0
 	fi
+	if test $tcl_corefoundation = no; then
+	    AC_MSG_WARN("Frameworks can only be used when CoreFoundation is available")
+	    FRAMEWORK_BUILD=0
+	fi
     else
 	AC_MSG_RESULT([standard shared library])
 	FRAMEWORK_BUILD=0
@@ -1406,17 +1410,42 @@ dnl AC_CHECK_TOOL(AR, ar)
 	    CC_SEARCH_FLAGS=""
 	    LD_SEARCH_FLAGS=""
 	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
-	    PLAT_OBJS="\${MAC_OSX_OBJS}"
-	    PLAT_SRCS="\${MAC_OSX_SRCS}"
+	    PLAT_OBJS='${MAC_OSX_OBJS}'
+	    PLAT_SRCS='${MAC_OSX_SRCS}'
 	    TCL_SHLIB_LD_EXTRAS='-compatibility_version ${VERSION} -current_version ${VERSION} -install_name ${DYLIB_INSTALL_DIR}/${TCL_LIB_FILE} -seg1addr 0xa000000'
 	    TK_SHLIB_LD_EXTRAS=' -compatibility_version ${VERSION} -current_version ${VERSION} -install_name ${DYLIB_INSTALL_DIR}/${TK_LIB_FILE}  -seg1addr 0xb000000 -unexported_symbols_list $$(f=$(TCL_STUB_LIB_FILE).E && nm -gjp $(TCL_BIN_DIR)/$(TCL_STUB_LIB_FILE) | tail +3 > $$f && echo $$f)'
-	    LIBS="$LIBS -framework CoreFoundation"
-	    AC_DEFINE(MAC_OSX_TCL, 1, ["Is this a Mac I see before me?"])
-	    AC_DEFINE(HAVE_CFBUNDLE, 1, [Do we have access to Mac bundles?])
+            AC_MSG_CHECKING([whether to use CoreFoundation])
+            AC_ARG_ENABLE(corefoundation, [  --enable-corefoundation use CoreFoundation API [--enable-corefoundation]],
+                [tcl_corefoundation=$enableval], [tcl_corefoundation=yes])
+            AC_MSG_RESULT([$tcl_corefoundation])
+            if test $tcl_corefoundation = yes; then
+                AC_CACHE_CHECK([for CoreFoundation.framework], tcl_cv_lib_corefoundation, [
+                    hold_libs=$LIBS
+                    LIBS="$LIBS -framework CoreFoundation"
+                    AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>], 
+                        [CFBundleRef b = CFBundleGetMainBundle();], 
+                        tcl_cv_lib_corefoundation=yes, tcl_cv_lib_corefoundation=no)
+                    LIBS=$hold_libs])
+                if test $tcl_cv_lib_corefoundation = yes; then
+                    LIBS="$LIBS -framework CoreFoundation"
+                    AC_DEFINE(HAVE_COREFOUNDATION, 1, 
+                        [Do we have access to Darwin CoreFoundation.framework ?])
+                fi
+	    fi
+	    AC_CHECK_HEADERS(libkern/OSAtomic.h)
+	    AC_CHECK_FUNCS(OSSpinLockLock)
+	    AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?])
 	    AC_DEFINE(USE_VFORK, 1, [Should we use vfork() instead of fork()?])
 	    AC_DEFINE(TCL_DEFAULT_ENCODING,"utf-8",
 		[Are we to override what our default encoding is?])
 	    AC_DEFINE(MODULE_SCOPE, __private_extern__, [Linker support for module scope symbols])
+	    # prior to Darwin 7, realpath is not threadsafe, so don't
+	    # use it when threads are enabled, c.f. bug # 711232:
+	    AC_CHECK_FUNC(realpath)
+	    if test "$ac_cv_func_realpath" = yes -a "${TCL_THREADS}" = 1 \
+	            -a `uname -r | awk -F. '{print [$]1}'` -lt 7 ; then
+	        ac_cv_func_realpath=no
+	    fi
 	    ;;
 	NEXTSTEP-*)
 	    SHLIB_CFLAGS=""
Index: unix/tclConfig.h.in
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclConfig.h.in,v
retrieving revision 1.3
diff -u -p -u -p -r1.3 tclConfig.h.in
--- unix/tclConfig.h.in	9 Jan 2005 19:31:38 -0000	1.3
+++ unix/tclConfig.h.in	14 May 2005 19:11:47 -0000
@@ -1,5 +1,8 @@
 /* tclConfig.h.in.  Generated from configure.in by autoheader.  */
 
+#ifndef _TCLCONFIG
+#define _TCLCONFIG
+
 /* Is pthread_attr_get_np() declared in <pthread.h>? */
 #undef ATTRGETNP_NOT_DECLARED
 
@@ -12,12 +15,12 @@
 /* Do we have BSDgettimeofday()? */
 #undef HAVE_BSDGETTIMEOFDAY
 
-/* Do we have access to Mac bundles? */
-#undef HAVE_CFBUNDLE
-
 /* Define to 1 if you have the `chflags' function. */
 #undef HAVE_CHFLAGS
 
+/* Do we have access to Darwin CoreFoundation.framework ? */
+#undef HAVE_COREFOUNDATION
+
 /* Define to 1 if you have the `getattrlist' function. */
 #undef HAVE_GETATTRLIST
 
@@ -33,12 +36,18 @@
 /* Do we have nl_langinfo()? */
 #undef HAVE_LANGINFO
 
+/* Define to 1 if you have the <libkern/OSAtomic.h> header file. */
+#undef HAVE_LIBKERN_OSATOMIC_H
+
 /* Do we have <limits.h>? */
 #undef HAVE_LIMITS_H
 
 /* Define to 1 if you have the `localtime_r' function. */
 #undef HAVE_LOCALTIME_R
 
+/* Define to 1 if you have the `lseek64' function. */
+#undef HAVE_LSEEK64
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
@@ -48,9 +57,15 @@
 /* Do we have <net/errno.h>? */
 #undef HAVE_NET_ERRNO_H
 
+/* Define to 1 if you have the `open64' function. */
+#undef HAVE_OPEN64
+
 /* Define to 1 if you have the `opendir' function. */
 #undef HAVE_OPENDIR
 
+/* Define to 1 if you have the `OSSpinLockLock' function. */
+#undef HAVE_OSSPINLOCKLOCK
+
 /* Do we want a BSD-like thread-attribute interface? */
 #undef HAVE_PTHREAD_ATTR_GET_NP
 
@@ -78,9 +93,6 @@
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
-/* Define to 1 if you have the `strstr' function. */
-#undef HAVE_STRSTR
-
 /* Define to 1 if you have the `strtol' function. */
 #undef HAVE_STRTOL
 
@@ -159,9 +171,12 @@
 /* Define to 1 if you have the `waitpid' function. */
 #undef HAVE_WAITPID
 
-/* "Is this a Mac I see before me?" */
+/* Is this a Mac I see before me? */
 #undef MAC_OSX_TCL
 
+/* Linker support for module scope symbols */
+#undef MODULE_SCOPE
+
 /* Do we have <dirent.h>? */
 #undef NO_DIRENT_H
 
@@ -261,9 +276,6 @@
 /* Are bytecode statistics enabled? */
 #undef TCL_COMPILE_STATS
 
-/* What extra letters do we insert for debugging binary code? */
-#undef TCL_DBGX
-
 /* Are we to override what our default encoding is? */
 #undef TCL_DEFAULT_ENCODING
 
@@ -386,3 +398,5 @@
 
 /* Define to `int' if <sys/types.h> doesn't define. */
 #undef uid_t
+
+#endif /* _TCLCONFIG */
Index: unix/tclLoadDyld.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclLoadDyld.c,v
retrieving revision 1.15
diff -u -p -u -p -r1.15 tclLoadDyld.c
--- unix/tclLoadDyld.c	6 Apr 2004 22:25:56 -0000	1.15
+++ unix/tclLoadDyld.c	14 May 2005 19:11:47 -0000
@@ -23,7 +23,7 @@ typedef struct Tcl_DyldModuleHandle {
 } Tcl_DyldModuleHandle;
 
 typedef struct Tcl_DyldLoadHandle {
-    const struct mach_header *dyld_lib;
+    CONST struct mach_header *dyld_lib;
     Tcl_DyldModuleHandle *firstModuleHandle;
 } Tcl_DyldLoadHandle;
 
@@ -59,7 +59,7 @@ TclpDlopen(interp, pathPtr, loadHandle, 
 				 * this file. */
 {
     Tcl_DyldLoadHandle *dyldLoadHandle;
-    const struct mach_header *dyld_lib;
+    CONST struct mach_header *dyld_lib;
     CONST char *native;
 
     /* 
@@ -89,7 +89,7 @@ TclpDlopen(interp, pathPtr, loadHandle, 
     
     if (!dyld_lib) {
         NSLinkEditErrors editError;
-        char *name, *msg;
+        CONST char *name, *msg;
         NSLinkEditError(&editError, &errno, &name, &msg);
         Tcl_AppendResult(interp, msg, (char *) NULL);
         return TCL_ERROR;
@@ -152,7 +152,7 @@ TclpFindSymbol(interp, loadHandle, symbo
 	}
     } else {
         NSLinkEditErrors editError;
-        char *name, *msg;
+        CONST char *name, *msg;
         NSLinkEditError(&editError, &errno, &name, &msg);
         Tcl_AppendResult(interp, msg, (char *) NULL);
     }
@@ -198,7 +198,7 @@ TclpUnloadFile(loadHandle)
 	dyldModuleHandle = dyldModuleHandle->nextModuleHandle;
 	ckfree(ptr);
     }
-    ckfree(dyldLoadHandle);
+    ckfree((char*) dyldLoadHandle);
 }
 
 /*
Index: unix/tclUnixChan.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclUnixChan.c,v
retrieving revision 1.56
diff -u -p -u -p -r1.56 tclUnixChan.c
--- unix/tclUnixChan.c	10 May 2005 18:35:27 -0000	1.56
+++ unix/tclUnixChan.c	14 May 2005 19:11:47 -0000
@@ -43,6 +43,13 @@
 
 #define SUPPORTS_TTY
 
+#undef DIRECT_BAUD
+#ifdef B4800
+#   if (B4800 == 4800)
+#	define DIRECT_BAUD
+#   endif /* B4800 == 4800 */
+#endif /* B4800 */
+
 #ifdef USE_TERMIOS
 #   include <termios.h>
 #   ifdef HAVE_SYS_IOCTL_H
@@ -261,11 +268,15 @@ static int		TtyCloseProc _ANSI_ARGS_((Cl
 			    Tcl_Interp *interp));
 static void		TtyGetAttributes _ANSI_ARGS_((int fd,
 			    TtyAttrs *ttyPtr));
+#ifndef DIRECT_BAUD
 static int		TtyGetBaud _ANSI_ARGS_((unsigned long speed));
+#endif
 static int		TtyGetOptionProc _ANSI_ARGS_((ClientData instanceData,
 			    Tcl_Interp *interp, CONST char *optionName,
 			    Tcl_DString *dsPtr));
+#ifndef DIRECT_BAUD
 static unsigned long	TtyGetSpeed _ANSI_ARGS_((int baud));
+#endif
 static FileState *	TtyInit _ANSI_ARGS_((int fd, int initialize));
 static void		TtyModemStatusStr _ANSI_ARGS_((int status,
 			    Tcl_DString *dsPtr));
@@ -1190,13 +1201,6 @@ TtyGetOptionProc(instanceData, interp, o
     }
 }
 
-#undef DIRECT_BAUD
-#ifdef B4800
-#   if (B4800 == 4800)
-#	define DIRECT_BAUD
-#   endif /* B4800 == 4800 */
-#endif /* B4800 */
-
 #ifdef DIRECT_BAUD
 #   define TtyGetSpeed(baud)   ((unsigned) (baud))
 #   define TtyGetBaud(speed)   ((int) (speed))
Index: unix/tclUnixInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclUnixInit.c,v
retrieving revision 1.56
diff -u -p -u -p -r1.56 tclUnixInit.c
--- unix/tclUnixInit.c	10 May 2005 18:35:27 -0000	1.56
+++ unix/tclUnixInit.c	14 May 2005 19:11:47 -0000
@@ -26,7 +26,7 @@
 #	include <dlfcn.h>
 #   endif
 #endif
-#ifdef HAVE_CFBUNDLE
+#ifdef HAVE_COREFOUNDATION
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
@@ -328,11 +328,11 @@ static CONST LocaleTable localeTable[] =
 #ifndef TCL_NO_STACK_CHECK
 static int		GetStackSize _ANSI_ARGS_((size_t *stackSizePtr));
 #endif /* TCL_NO_STACK_CHECK */
-#ifdef HAVE_CFBUNDLE
+#ifdef HAVE_COREFOUNDATION
 static int		MacOSXGetLibraryPath _ANSI_ARGS_((
 			    Tcl_Interp *interp, int maxPathLen,
 			    char *tclLibPath));
-#endif /* HAVE_CFBUNDLE */
+#endif /* HAVE_COREFOUNDATION */
 
 
 /*
@@ -511,13 +511,13 @@ TclpInitLibraryPath(valuePtr, lengthPtr,
      */
 
     {
-#ifdef HAVE_CFBUNDLE
+#ifdef HAVE_COREFOUNDATION
     char tclLibPath[MAXPATHLEN + 1];
 
     if (MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
         str = tclLibPath;
     } else
-#endif /* HAVE_CFBUNDLE */
+#endif /* HAVE_COREFOUNDATION */
     {
 	/* TODO: Pull this value from the TIP 59 table */
         str = defaultLibraryDir;
@@ -724,7 +724,7 @@ TclpSetVariables(interp)
     CONST char *user;
     Tcl_DString ds;
 
-#ifdef HAVE_CFBUNDLE
+#ifdef HAVE_COREFOUNDATION
     char tclLibPath[MAXPATHLEN + 1];
 
     if (MacOSXGetLibraryPath(interp, MAXPATHLEN, tclLibPath) == TCL_OK) {
@@ -756,7 +756,7 @@ TclpSetVariables(interp)
             Tcl_StatBuf statBuf;
             if((frameworksURL = CFBundleCopyPrivateFrameworksURL(bundleRef))) {
                 if(CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
-                            tclLibPath, MAXPATHLEN) &&
+                            (unsigned char*) tclLibPath, MAXPATHLEN) &&
                         ! TclOSstat(tclLibPath, &statBuf) &&
                         S_ISDIR(statBuf.st_mode)) {
                     Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
@@ -768,7 +768,7 @@ TclpSetVariables(interp)
             }
             if((frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef))) {
                 if(CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
-                            tclLibPath, MAXPATHLEN) &&
+                            (unsigned char*) tclLibPath, MAXPATHLEN) &&
                         ! TclOSstat(tclLibPath, &statBuf) &&
                         S_ISDIR(statBuf.st_mode)) {
                     Tcl_SetVar(interp, "tcl_pkgPath", tclLibPath,
@@ -782,7 +782,7 @@ TclpSetVariables(interp)
         Tcl_SetVar(interp, "tcl_pkgPath", pkgPath,
                 TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
     } else
-#endif /* HAVE_CFBUNDLE */
+#endif /* HAVE_COREFOUNDATION */
     {
         Tcl_SetVar(interp, "tcl_pkgPath", pkgPath, TCL_GLOBAL_ONLY);
     }
@@ -1131,7 +1131,7 @@ GetStackSize(stackSizePtr)
  *----------------------------------------------------------------------
  */
 
-#ifdef HAVE_CFBUNDLE
+#ifdef HAVE_COREFOUNDATION
 static int
 MacOSXGetLibraryPath(Tcl_Interp *interp, int maxPathLen, char *tclLibPath)
 {
@@ -1142,4 +1142,4 @@ MacOSXGetLibraryPath(Tcl_Interp *interp,
 #endif
     return foundInFramework;
 }
-#endif /* HAVE_CFBUNDLE */
+#endif /* HAVE_COREFOUNDATION */
Index: unix/tclUnixNotfy.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclUnixNotfy.c,v
retrieving revision 1.23
diff -u -p -u -p -r1.23 tclUnixNotfy.c
--- unix/tclUnixNotfy.c	10 May 2005 18:35:28 -0000	1.23
+++ unix/tclUnixNotfy.c	14 May 2005 19:11:48 -0000
@@ -14,6 +14,8 @@
  * RCS: @(#) $Id: tclUnixNotfy.c,v 1.23 2005/05/10 18:35:28 kennykb Exp $
  */
 
+#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier
+                             * is in tclMacOSXNotify.c */
 #include "tclInt.h"
 #include <signal.h> 
 
@@ -1080,3 +1082,5 @@ NotifierThreadProc(clientData)
     TclpThreadExit (0);
 }
 #endif
+
+#endif /* HAVE_COREFOUNDATION */
Index: unix/tclUnixPort.h
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclUnixPort.h,v
retrieving revision 1.41
diff -u -p -u -p -r1.41 tclUnixPort.h
--- unix/tclUnixPort.h	10 May 2005 18:35:28 -0000	1.41
+++ unix/tclUnixPort.h	14 May 2005 19:11:48 -0000
@@ -563,13 +563,6 @@ EXTERN char *          	TclpInetNtoa(str
  * #define gmtime(x)	TclpGmtime(x)    */
 #   undef inet_ntoa
 #   define inet_ntoa(x)	TclpInetNtoa(x)
-#   ifdef MAC_OSX_TCL
-/* 
- * On Mac OS X, realpath is currently not
- * thread safe, c.f. SF bug # 711232.
- */
-#	define NO_REALPATH
-#   endif
 #   ifdef HAVE_PTHREAD_ATTR_GET_NP
 #	define TclpPthreadGetAttrs	pthread_attr_get_np
 #	ifdef ATTRGETNP_NOT_DECLARED
Index: win/tclWin32Dll.c
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWin32Dll.c,v
retrieving revision 1.42
diff -u -p -u -p -r1.42 tclWin32Dll.c
--- win/tclWin32Dll.c	13 May 2005 21:20:36 -0000	1.42
+++ win/tclWin32Dll.c	14 May 2005 19:11:48 -0000
@@ -627,29 +627,6 @@ TclpCheckStackSpace()
 }
 
 /*
- *----------------------------------------------------------------------
- *
- * TclWinGetPlatform --
- *
- *      This is a kludge that allows the test library to get access
- *      the internal tclPlatform variable.
- *
- * Results:
- *      Returns a pointer to the tclPlatform variable.
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
- */
-
-TclPlatformType *
-TclWinGetPlatform()
-{
-    return &tclPlatform;
-}
-
-/*
  *---------------------------------------------------------------------------
  *
  * TclWinSetInterfaces --