tms: Tcl Message System experimental project - initial import.
authorPat Thoyts <patthoyts@users.sourceforge.net>
Sun, 7 Dec 2008 23:05:41 +0000 (23:05 +0000)
committerPat Thoyts <patthoyts@users.sourceforge.net>
Sun, 7 Dec 2008 23:05:41 +0000 (23:05 +0000)
  This is an experiment to try creating a general subsystem for
  handling message oriented protocols in Tcl. So far this includes
  Windows support for mailslots and the file notification API.

29 files changed:
Makefile.in [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
configure.in [new file with mode: 0644]
demos/demo.tcl [new file with mode: 0644]
generic/bgeval.c [new file with mode: 0644]
generic/config.c [new file with mode: 0644]
generic/subsystem.c [new file with mode: 0644]
generic/tms.c [new file with mode: 0644]
generic/tms.decls [new file with mode: 0644]
generic/tms.h [new file with mode: 0644]
generic/tmsDecls.h [new file with mode: 0644]
generic/tmsInt.h [new file with mode: 0644]
generic/tmsPlatDecls.h [new file with mode: 0644]
generic/tmsStubInit.c [new file with mode: 0644]
generic/tmsStubLib.c [new file with mode: 0644]
tclconfig/install-sh [new file with mode: 0644]
tclconfig/tcl.m4 [new file with mode: 0644]
tests/all.tcl [new file with mode: 0644]
tests/mailslot.test [new file with mode: 0644]
tools/genStubs.tcl [new file with mode: 0644]
win/makefile.vc [new file with mode: 0644]
win/nmakehlp.c [new file with mode: 0644]
win/rules.vc [new file with mode: 0644]
win/tms.rc [new file with mode: 0644]
win/tmsWinFNotify.c [new file with mode: 0644]
win/tmsWinHandle.c [new file with mode: 0644]
win/tmsWinInit.c [new file with mode: 0644]
win/tmsWinInt.h [new file with mode: 0644]
win/tmsWinMailslot.c [new file with mode: 0644]

diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..8a5f8d4
--- /dev/null
@@ -0,0 +1,443 @@
+# Makefile.in --
+#
+#      This file is a Makefile for Sample TEA Extension.  If it has the name
+#      "Makefile.in" then it is a template for a Makefile;  to generate the
+#      actual Makefile, run "./configure", which is a configuration script
+#      generated by the "autoconf" program (constructs like "@foo@" will get
+#      replaced in the actual Makefile.
+#
+# Copyright (c) 1999 Scriptics Corporation.
+# Copyright (c) 2002-2005 ActiveState Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: Makefile.in,v 1.1 2006/10/23 00:55:04 pat Exp $
+
+#========================================================================
+# Add additional lines to handle any additional AC_SUBST cases that
+# have been added in a customized configure script.
+#========================================================================
+
+#SAMPLE_NEW_VAR        = @SAMPLE_NEW_VAR@
+
+#========================================================================
+# Nothing of the variables below this line should need to be changed.
+# Please check the TARGETS section below to make sure the make targets
+# are correct.
+#========================================================================
+
+#========================================================================
+# The names of the source files is defined in the configure script.
+# The object files are used for linking into the final library.
+# This will be used when a dist target is added to the Makefile.
+# It is not important to specify the directory, as long as it is the
+# $(srcdir) or in the generic, win or unix subdirectory.
+#========================================================================
+
+PKG_SOURCES    = @PKG_SOURCES@
+PKG_OBJECTS    = @PKG_OBJECTS@
+
+PKG_STUB_SOURCES = @PKG_STUB_SOURCES@
+PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@
+
+#========================================================================
+# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with
+# this package that need to be installed, if any.
+#========================================================================
+
+PKG_TCL_SOURCES = @PKG_TCL_SOURCES@
+
+#========================================================================
+# This is a list of public header files to be installed, if any.
+#========================================================================
+
+PKG_HEADERS    = @PKG_HEADERS@
+
+#========================================================================
+# "PKG_LIB_FILE" refers to the library (dynamic or static as per
+# configuration options) composed of the named objects.
+#========================================================================
+
+PKG_LIB_FILE   = @PKG_LIB_FILE@
+PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@
+
+lib_BINARIES   = $(PKG_LIB_FILE)
+BINARIES       = $(lib_BINARIES)
+
+SHELL          = @SHELL@
+
+srcdir         = @srcdir@
+prefix         = @prefix@
+exec_prefix    = @exec_prefix@
+
+bindir         = @bindir@
+libdir         = @libdir@
+datadir                = @datadir@
+mandir         = @mandir@
+includedir     = @includedir@
+
+DESTDIR                =
+
+PKG_DIR                = $(PACKAGE_NAME)$(PACKAGE_VERSION)
+pkgdatadir     = $(datadir)/$(PKG_DIR)
+pkglibdir      = $(libdir)/$(PKG_DIR)
+pkgincludedir  = $(includedir)/$(PKG_DIR)
+
+top_builddir   = .
+
+INSTALL                = @INSTALL@
+INSTALL_PROGRAM        = @INSTALL_PROGRAM@
+INSTALL_DATA   = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+
+PACKAGE_NAME   = @PACKAGE_NAME@
+PACKAGE_VERSION        = @PACKAGE_VERSION@
+CC             = @CC@
+CFLAGS_DEFAULT = @CFLAGS_DEFAULT@
+CFLAGS_WARNING = @CFLAGS_WARNING@
+CLEANFILES     = @CLEANFILES@
+EXEEXT         = @EXEEXT@
+LDFLAGS_DEFAULT        = @LDFLAGS_DEFAULT@
+MAKE_LIB       = @MAKE_LIB@
+MAKE_SHARED_LIB        = @MAKE_SHARED_LIB@
+MAKE_STATIC_LIB        = @MAKE_STATIC_LIB@
+MAKE_STUB_LIB  = @MAKE_STUB_LIB@
+OBJEXT         = @OBJEXT@
+RANLIB         = @RANLIB@
+RANLIB_STUB    = @RANLIB_STUB@
+SHLIB_CFLAGS   = @SHLIB_CFLAGS@
+SHLIB_LD       = @SHLIB_LD@
+SHLIB_LD_LIBS  = @SHLIB_LD_LIBS@
+STLIB_LD       = @STLIB_LD@
+TCL_DEFS       = @TCL_DEFS@
+TCL_BIN_DIR    = @TCL_BIN_DIR@
+TCL_SRC_DIR    = @TCL_SRC_DIR@
+# This is necessary for packages that use private Tcl headers
+#TCL_TOP_DIR_NATIVE    = @TCL_TOP_DIR_NATIVE@
+# Not used, but retained for reference of what libs Tcl required
+TCL_LIBS       = @TCL_LIBS@
+
+#========================================================================
+# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our
+# package without installing.  The other environment variables allow us
+# to test against an uninstalled Tcl.  Add special env vars that you
+# require for testing here (like TCLX_LIBRARY).
+#========================================================================
+
+EXTRA_PATH     = $(top_builddir):$(TCL_BIN_DIR)
+TCLLIBPATH     = $(top_builddir)
+TCLSH_ENV      = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \
+                 @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
+                 PATH="$(EXTRA_PATH):$(PATH)" \
+                 TCLLIBPATH="$(TCLLIBPATH)"
+TCLSH_PROG     = @TCLSH_PROG@
+TCLSH          = $(TCLSH_ENV) $(TCLSH_PROG)
+SHARED_BUILD   = @SHARED_BUILD@
+
+INCLUDES       = @PKG_INCLUDES@ @TCL_INCLUDES@
+
+PKG_CFLAGS     = @PKG_CFLAGS@
+
+# TCL_DEFS is not strictly need here, but if you remove it, then you
+# must make sure that configure.in checks for the necessary components
+# that your library may use.  TCL_DEFS can actually be a problem if
+# you do not compile with a similar machine setup as the Tcl core was
+# compiled with.
+#DEFS          = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)
+DEFS           = @DEFS@ $(PKG_CFLAGS)
+
+CONFIG_CLEAN_FILES = Makefile
+
+CPPFLAGS       = @CPPFLAGS@
+LIBS           = @PKG_LIBS@ @LIBS@
+AR             = @AR@
+CFLAGS         = @CFLAGS@
+COMPILE                = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+
+#========================================================================
+# Start of user-definable TARGETS section
+#========================================================================
+
+#========================================================================
+# TEA TARGETS.  Please note that the "libraries:" target refers to platform
+# independent files, and the "binaries:" target inclues executable programs and
+# platform-dependent libraries.  Modify these targets so that they install
+# the various pieces of your package.  The make and install rules
+# for the BINARIES that you specified above have already been done.
+#========================================================================
+
+all: binaries libraries doc
+
+#========================================================================
+# The binaries target builds executable programs, Windows .dll's, unix
+# shared/static libraries, and any other platform-dependent files.
+# The list of targets to build for "binaries:" is specified at the top
+# of the Makefile, in the "BINARIES" variable.
+#========================================================================
+
+binaries: $(BINARIES) pkgIndex.tcl
+
+libraries:
+
+
+#========================================================================
+# Your doc target should differentiate from doc builds (by the developer)
+# and doc installs (see install-doc), which just install the docs on the
+# end user machine when building from source.
+#========================================================================
+
+doc:
+       @echo "If you have documentation to create, place the commands to"
+       @echo "build the docs in the 'doc:' target.  For example:"
+       @echo "        xml2nroff sample.xml > sample.n"
+       @echo "        xml2html sample.xml > sample.html"
+
+install: all install-binaries install-libraries install-doc
+
+install-binaries: binaries install-lib-binaries install-bin-binaries
+
+#========================================================================
+# This rule installs platform-independent files, such as header files.
+# The list=...; for p in $$list handles the empty list case x-platform.
+#========================================================================
+
+install-libraries: libraries
+       @mkdir -p $(DESTDIR)$(includedir)
+       @echo "Installing header files in $(DESTDIR)$(includedir)"
+       @list='$(PKG_HEADERS)'; for i in $$list; do \
+           echo "Installing $(srcdir)/$$i" ; \
+           $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \
+       done;
+
+#========================================================================
+# Install documentation.  Unix manpages should go in the $(mandir)
+# directory.
+#========================================================================
+
+install-doc: doc
+       @mkdir -p $(DESTDIR)$(mandir)/mann
+       @echo "Installing documentation in $(DESTDIR)$(mandir)"
+       @list='$(srcdir)/doc/*.n'; for i in $$list; do \
+           echo "Installing $$i"; \
+           rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \
+           $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
+       done
+
+test: binaries libraries
+       $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS)
+
+shell: binaries libraries
+       @$(TCLSH) $(SCRIPT)
+
+gdb:
+       $(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)
+
+depend:
+
+#========================================================================
+# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
+# mentioned above.  That will ensure that this target is built when you
+# run "make binaries".
+#
+# The $(PKG_OBJECTS) objects are created and linked into the final
+# library.  In most cases these object files will correspond to the
+# source files above.
+#========================================================================
+
+$(PKG_LIB_FILE): $(PKG_OBJECTS)
+       -rm -f $(PKG_LIB_FILE)
+       ${MAKE_LIB}
+       $(RANLIB) $(PKG_LIB_FILE)
+
+$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)
+       -rm -f $(PKG_STUB_LIB_FILE)
+       ${MAKE_STUB_LIB}
+       $(RANLIB_STUB) $(PKG_STUB_LIB_FILE)
+
+#========================================================================
+# We need to enumerate the list of .c to .o lines here.
+#
+# In the following lines, $(srcdir) refers to the toplevel directory
+# containing your extension.  If your sources are in a subdirectory,
+# you will have to modify the paths to reflect this:
+#
+# sample.$(OBJEXT): $(srcdir)/generic/sample.c
+#      $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@
+#
+# Setting the VPATH variable to a list of paths will cause the makefile
+# to look into these paths when resolving .c to .obj dependencies.
+# As necessary, add $(srcdir):$(srcdir)/compat:....
+#========================================================================
+
+VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win
+
+.c.@OBJEXT@:
+       $(COMPILE) -c `@CYGPATH@ $<` -o $@
+
+#========================================================================
+# Create the pkgIndex.tcl file.
+# It is usually easiest to let Tcl do this for you with pkg_mkIndex, but
+# you may find that you need to customize the package.  If so, either
+# modify the -hand version, or create a pkgIndex.tcl.in file and have
+# the configure script output the pkgIndex.tcl by editing configure.in.
+#========================================================================
+
+pkgIndex.tcl: $(PKG_LIB_FILE)
+       ( echo pkg_mkIndex . $(PKG_LIB_FILE) \; exit; ) | $(TCLSH)
+
+pkgIndex.tcl-hand:
+       (echo 'package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \
+           [list load [file join $$dir $(PKG_LIB_FILE)]]'\
+       ) > pkgIndex.tcl
+
+#========================================================================
+# Distribution creation
+# You may need to tweak this target to make it work correctly.
+#========================================================================
+
+#COMPRESS      = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar
+COMPRESS       = gtar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
+DIST_ROOT      = /tmp/dist
+DIST_DIR       = $(DIST_ROOT)/$(PKG_DIR)
+
+dist-clean:
+       rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*
+
+dist: dist-clean
+       mkdir -p $(DIST_DIR)
+       cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \
+               $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \
+               $(DIST_DIR)/
+       chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4
+       chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in
+
+       for i in $(srcdir)/*.[ch]; do \
+           if [ -f $$i ]; then \
+               cp -p $$i $(DIST_DIR)/ ; \
+           fi; \
+       done;
+
+       mkdir $(DIST_DIR)/tclconfig
+       cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \
+               $(DIST_DIR)/tclconfig/
+       chmod 664 $(DIST_DIR)/tclconfig/tcl.m4
+       chmod +x $(DIST_DIR)/tclconfig/install-sh
+
+       list='demos doc generic library mac tests unix win'; \
+       for p in $$list; do \
+           if test -d $(srcdir)/$$p ; then \
+               mkdir $(DIST_DIR)/$$p; \
+               cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \
+           fi; \
+       done
+
+       (cd $(DIST_ROOT); $(COMPRESS);)
+
+#========================================================================
+# End of user-definable section
+#========================================================================
+
+#========================================================================
+# Don't modify the file to clean here.  Instead, set the "CLEANFILES"
+# variable in configure.in
+#========================================================================
+
+clean:  
+       -test -z "$(BINARIES)" || rm -f $(BINARIES)
+       -rm -f *.$(OBJEXT) core *.core
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean: clean
+       -rm -f *.tab.c
+       -rm -f $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log config.status
+
+#========================================================================
+# Install binary object libraries.  On Windows this includes both .dll and
+# .lib files.  Because the .lib files are not explicitly listed anywhere,
+# we need to deduce their existence from the .dll file of the same name.
+# Library files go into the lib directory.
+# In addition, this will generate the pkgIndex.tcl
+# file in the install location (assuming it can find a usable tclsh shell)
+#
+# You should not have to modify this target.
+#========================================================================
+
+install-lib-binaries: binaries
+       @mkdir -p $(DESTDIR)$(pkglibdir)
+       @list='$(lib_BINARIES)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
+           $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \
+           stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \
+           if test "x$$stub" = "xstub"; then \
+               echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \
+               $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \
+           else \
+               echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \
+               $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \
+           fi; \
+           ext=`echo $$p|sed -e "s/.*\.//"`; \
+           if test "x$$ext" = "xdll"; then \
+               lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \
+               if test -f $$lib; then \
+                   echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \
+                   $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \
+               fi; \
+           fi; \
+         fi; \
+       done
+       @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
+         if test -f $(srcdir)/$$p; then \
+           destp=`basename $$p`; \
+           echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
+           $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
+         fi; \
+       done
+       @if test "x$(SHARED_BUILD)" = "x1"; then \
+           echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
+           $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \
+       fi
+
+#========================================================================
+# Install binary executables (e.g. .exe files and dependent .dll files)
+# This is for files that must go in the bin directory (located next to
+# wish and tclsh), like dependent .dll files on Windows.
+#
+# You should not have to modify this target, except to define bin_BINARIES
+# above if necessary.
+#========================================================================
+
+install-bin-binaries: binaries
+       @mkdir -p $(DESTDIR)$(bindir)
+       @list='$(bin_BINARIES)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
+           $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
+         fi; \
+       done
+
+.SUFFIXES: .c .$(OBJEXT)
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+uninstall-binaries:
+       list='$(lib_BINARIES)'; for p in $$list; do \
+         rm -f $(DESTDIR)$(pkglibdir)/$$p; \
+       done
+       list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
+         p=`basename $$p`; \
+         rm -f $(DESTDIR)$(pkglibdir)/$$p; \
+       done
+       list='$(bin_BINARIES)'; for p in $$list; do \
+         rm -f $(DESTDIR)$(bindir)/$$p; \
+       done
+
+.PHONY: all binaries clean depend distclean doc install libraries test
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..0b05739
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Include the TEA standard macro set
+#
+
+builtin(include,tclconfig/tcl.m4)
+
+#
+# Add here whatever m4 macros you want to define for your package
+#
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..27e1457
--- /dev/null
@@ -0,0 +1,195 @@
+#!/bin/bash -norc
+dnl    This file is an input file used by the GNU "autoconf" program to
+dnl    generate the file "configure", which is run during Tcl installation
+dnl    to configure the system for the local environment.
+#
+# RCS: @(#) $Id: configure.in,v 1.1 2006/10/23 00:55:04 pat Exp $
+
+#-----------------------------------------------------------------------
+# Sample configure.in for Tcl Extensions.  The only places you should
+# need to modify this file are marked by the string __CHANGE__
+#-----------------------------------------------------------------------
+
+#-----------------------------------------------------------------------
+# __CHANGE__
+# Set your package name and version numbers here.
+#
+# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
+# set as provided.  These will also be added as -D defs in your Makefile
+# so you can encode the package version directly into the source files.
+#-----------------------------------------------------------------------
+
+AC_INIT([tms], [0.1])
+
+#--------------------------------------------------------------------
+# Call TEA_INIT as the first TEA_ macro to set up initial vars.
+# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
+# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
+#--------------------------------------------------------------------
+
+TEA_INIT([3.5])
+
+AC_CONFIG_AUX_DIR(tclconfig)
+
+#--------------------------------------------------------------------
+# Load the tclConfig.sh file
+#--------------------------------------------------------------------
+
+TEA_PATH_TCLCONFIG
+TEA_LOAD_TCLCONFIG
+
+#--------------------------------------------------------------------
+# Load the tkConfig.sh file if necessary (Tk extension)
+#--------------------------------------------------------------------
+
+#TEA_PATH_TKCONFIG
+#TEA_LOAD_TKCONFIG
+
+#-----------------------------------------------------------------------
+# Handle the --prefix=... option by defaulting to what Tcl gave.
+# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.
+#-----------------------------------------------------------------------
+
+TEA_PREFIX
+
+#-----------------------------------------------------------------------
+# Standard compiler checks.
+# This sets up CC by using the CC env var, or looks for gcc otherwise.
+# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create
+# the basic setup necessary to compile executables.
+#-----------------------------------------------------------------------
+
+TEA_SETUP_COMPILER
+
+#-----------------------------------------------------------------------
+# __CHANGE__
+# Specify the C source files to compile in TEA_ADD_SOURCES,
+# public headers that need to be installed in TEA_ADD_HEADERS,
+# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
+# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
+# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS
+# and PKG_TCL_SOURCES.
+#-----------------------------------------------------------------------
+
+TEA_ADD_SOURCES([tms.c tmsStubInit.c])
+TEA_ADD_HEADERS([tms.h])
+TEA_ADD_INCLUDES([-I. -I\"`${CYGPATH} ${srcdir}/generic`\"])
+TEA_ADD_LIBS([])
+TEA_ADD_CFLAGS([])
+TEA_ADD_STUB_SOURCES([tmsStubLib.c])
+TEA_ADD_TCL_SOURCES([])
+
+#--------------------------------------------------------------------
+# __CHANGE__
+# A few miscellaneous platform-specific items:
+#
+# Define a special symbol for Windows (BUILD_sample in this case) so
+# that we create the export library with the dll.
+#
+# Windows creates a few extra files that need to be cleaned up.
+# You can add more files to clean if your extension creates any extra
+# files.
+#
+# TEA_ADD_* any platform specific compiler/build info here.
+#--------------------------------------------------------------------
+
+if test "${TEA_PLATFORM}" = "windows" ; then
+    CLEANFILES="pkgIndex.tcl *.lib *.dll *.exp *.ilk *.pdb vc*.pch"
+    #TEA_ADD_SOURCES([win/winFile.c])
+    #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"])
+else
+    CLEANFILES="pkgIndex.tcl"
+    #TEA_ADD_SOURCES([unix/unixFile.c])
+    #TEA_ADD_LIBS([-lsuperfly])
+fi
+AC_SUBST(CLEANFILES)
+
+#--------------------------------------------------------------------
+# __CHANGE__
+# Choose which headers you need.  Extension authors should try very
+# hard to only rely on the Tcl public header files.  Internal headers
+# contain private data structures and are subject to change without
+# notice.
+# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG
+#--------------------------------------------------------------------
+
+TEA_PUBLIC_TCL_HEADERS
+#TEA_PRIVATE_TCL_HEADERS
+
+#TEA_PUBLIC_TK_HEADERS
+#TEA_PRIVATE_TK_HEADERS
+#TEA_PATH_X
+
+#--------------------------------------------------------------------
+# Check whether --enable-threads or --disable-threads was given.
+# This auto-enables if Tcl was compiled threaded.
+#--------------------------------------------------------------------
+
+TEA_ENABLE_THREADS
+
+#--------------------------------------------------------------------
+# The statement below defines a collection of symbols related to
+# building as a shared library instead of a static library.
+#--------------------------------------------------------------------
+
+TEA_ENABLE_SHARED
+
+#--------------------------------------------------------------------
+# This macro figures out what flags to use with the compiler/linker
+# when building shared/static debug/optimized objects.  This information
+# can be taken from the tclConfig.sh file, but this figures it all out.
+#--------------------------------------------------------------------
+
+TEA_CONFIG_CFLAGS
+
+#--------------------------------------------------------------------
+# Set the default compiler switches based on the --enable-symbols option.
+#--------------------------------------------------------------------
+
+TEA_ENABLE_SYMBOLS
+
+#--------------------------------------------------------------------
+# Everyone should be linking against the Tcl stub library.  If you
+# can't for some reason, remove this definition.  If you aren't using
+# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
+# link against the non-stubbed Tcl library.  Add Tk too if necessary.
+#--------------------------------------------------------------------
+
+AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
+#AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])
+AC_DEFINE(BUILD_tms, [1], [Defined when building package])
+
+#--------------------------------------------------------------------
+# This macro generates a line to use when building a library.  It
+# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
+# and TEA_LOAD_TCLCONFIG macros above.
+#--------------------------------------------------------------------
+
+TEA_MAKE_LIB
+
+# Do not include the version in the stubs filename
+if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then
+    PKG_STUB_LIB_FILE=tmsstub.lib
+else
+    PKG_STUB_LIB_FILE=libtmsstub.a
+fi;
+
+#--------------------------------------------------------------------
+# Find tclsh so that we can run pkg_mkIndex to generate the pkgIndex.tcl
+# file during the install process.  Don't run the TCLSH_PROG through
+# ${CYGPATH} because it's being used directly by make.
+# Require that we use a tclsh shell version 8.2 or later since earlier
+# versions have bugs in the pkg_mkIndex routine.
+# Add WISH as well if this is a Tk extension.
+#--------------------------------------------------------------------
+
+TEA_PROG_TCLSH
+#TEA_PROG_WISH
+
+#--------------------------------------------------------------------
+# Finally, substitute all of the various values into the Makefile.
+# You may alternatively have a special pkgIndex.tcl.in or other files
+# which require substituting th AC variables in.  Include these here.
+#--------------------------------------------------------------------
+
+AC_OUTPUT([Makefile])
diff --git a/demos/demo.tcl b/demos/demo.tcl
new file mode 100644 (file)
index 0000000..70e64bb
--- /dev/null
@@ -0,0 +1,68 @@
+if {[info exists tcl_platform(debug)]} {
+    set dll [file join [file dirname [info script]] Debug tms02g.dll]
+} else {
+    set dll [file join [file dirname [info script]] Release tms02.dll]
+}
+load $dll
+
+#after 10
+
+package require tms
+package require tms::mailslot
+
+proc every {ms body} {uplevel \#0 $body; after $ms [info level 0]}
+
+proc SlotMessage {slot message} {
+    puts "$slot [string length $message]b '$message'"
+    return
+}
+
+set slotnames [list TclTesting TclTest\\Diagnostics TclTest\\Test]
+set slots {}
+foreach slotname $slotnames {
+    lappend slots [tms::mailslot create -name $slotname \
+                       -command [list SlotMessage $slotname] \
+                       -buffersize 32]
+}
+
+set slot [lindex $slots 0]
+
+puts "Mailslots: [tms::mailslot names]"
+puts "$slot configure [$slot configure]"
+
+puts [list conf -buffersize: [catch {$slot configure -buffersize} err] $err]
+puts [list cget -buffersize: [catch {$slot cget -buffersize} err] $err]
+puts [list cget -xyzzy     : [catch {$slot cget -xyzzy} err] $err]
+puts [list configure -xyzzy: [catch {$slot configure -xyzzy 1} err] $err]
+puts [list configure -xyzzy: [catch {$slot configure -xyzzy} err] $err]
+puts [list configure wrong : [catch {$slot configure -buffersize 1 -command } err] $err]
+puts [list conf -name      : [catch {$slot configure -name ads} err] $err]
+
+[lindex $slots end] close
+
+
+proc OnNotify {obj} {
+    puts "File notification: [$obj cget -path] [$obj cget -flags]"
+    flush stdout
+}
+
+lappend fn [tms::fnotify create -path /temp -command OnNotify -flags create]
+lappend fn [tms::fnotify create -path /temp -command OnNotify -flags delete]
+lappend fn [tms::fnotify create -path /temp -command OnNotify -flags modify]
+lappend fn [tms::fnotify create -path /temp -command OnNotify -flags access]
+lappend fn [tms::fnotify create -path /temp -command OnNotify -flags rename]
+after 1500 {
+    set fname c:/temp/xyzzy.tmp
+    set f [open $fname w]; puts $f okokok; close $f
+    puts "wrote file"; flush stdout
+    set f [open $fname r]; read $f; close $f
+    puts "read file"; flush stdout
+    file rename $fname [string map {.tmp .bak} $fname]
+    puts "renamed file"; flush stdout
+    after 250 [list file delete [string map {.tmp .bak} $fname]]
+}
+
+every 1000 [list tms::mailslot sendto [lindex $slotnames 0] tick]
+
+after 5000 {set forever 1}
+vwait forever
diff --git a/generic/bgeval.c b/generic/bgeval.c
new file mode 100644 (file)
index 0000000..bd57cca
--- /dev/null
@@ -0,0 +1,83 @@
+/* bgeval.c - Copyright (C) 2006 Pat Thoyts <patthoyts@users.sourceforge.net>
+ *
+ * $Id: bgeval.c,v 1.2 2006/10/25 08:26:21 pat Exp $
+ */
+
+#include "tms.h"
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Tms_BackgroundEvalObjEx --
+ *
+ *     Evaluate a command while ensuring that we do not affect the 
+ *     interpreters state. This is important when evaluating script
+ *     during background tasks.
+ *
+ * Results:
+ *     A standard Tcl result code.
+ *
+ * Side Effects:
+ *     The interpreters variables and code may be modified by the script
+ *     but the result will not be modified.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+TMSAPI int
+Tms_BackgroundEvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv,
+    int flags)
+{
+    Tcl_DString errorInfo, errorCode;
+    Tcl_SavedResult state;
+    int r = TCL_OK;
+    
+    Tcl_DStringInit(&errorInfo);
+    Tcl_DStringInit(&errorCode);
+
+    /*
+     * Record the state of the interpreter
+     */
+
+    Tcl_SaveResult(interp, &state);
+    Tcl_DStringAppend(&errorInfo, 
+       Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY), -1);
+    Tcl_DStringAppend(&errorCode, 
+       Tcl_GetVar(interp, "errorCode", TCL_GLOBAL_ONLY), -1);
+    
+    /*
+     * Evaluate the command and handle any error.
+     */
+    
+    r = Tcl_EvalObjv(interp, objc, objv, flags);
+    if (r == TCL_ERROR) {
+        Tcl_AddErrorInfo(interp, "\n    (background event handler)");
+        Tcl_BackgroundError(interp);
+    }
+    
+    /*
+     * Restore the state of the interpreter
+     */
+    
+    Tcl_SetVar(interp, "errorInfo",
+       Tcl_DStringValue(&errorInfo), TCL_GLOBAL_ONLY);
+    Tcl_SetVar(interp, "errorCode",
+       Tcl_DStringValue(&errorCode), TCL_GLOBAL_ONLY);
+    Tcl_RestoreResult(interp, &state);
+    
+    /*
+     * Clean up references.
+     */
+    
+    Tcl_DStringFree(&errorInfo);
+    Tcl_DStringFree(&errorCode);
+    
+    return r;
+}
+
+/*
+ * Local variables:
+ *   indent-tabs-mode: t
+ *   tab-width: 8
+ * End:
+ */
diff --git a/generic/config.c b/generic/config.c
new file mode 100644 (file)
index 0000000..aad329c
--- /dev/null
@@ -0,0 +1,147 @@
+/* config.c - Copyright (C) 2006 Pat Thoyts <patthoyts@users.sourceforge.net>
+ *
+ * General purpose configure/cget helper functions.
+ *
+ * $Id: config.c,v 1.2 2007/04/03 15:38:53 pat Exp $
+ */
+
+#include "tms.h"
+
+TMSAPI void
+Tms_ConfigureDefault(Tms_ConfigureSpec *tablePtr, ClientData clientData)
+{
+    Tms_ConfigureSpec *specPtr = tablePtr;
+    while (specPtr->optionName != NULL) {
+       Tcl_Obj **dest = (Tcl_Obj **)((char*)clientData + specPtr->offset);
+       *dest = NULL;
+       if (specPtr->defValue != NULL) {
+           *dest = Tcl_NewStringObj(specPtr->defValue, -1);
+       }
+       ++specPtr;
+    }
+}
+
+TMSAPI Tcl_Obj *
+Tms_ConfigureOptionError(Tms_ConfigureSpec *tablePtr, Tcl_Obj *optionObj)
+{
+    Tms_ConfigureSpec *specPtr = tablePtr;
+    Tcl_Obj *resultObj;
+    
+    resultObj = Tcl_NewStringObj("invalid option \"", -1);
+    Tcl_AppendObjToObj(resultObj, optionObj);
+    Tcl_AppendToObj(resultObj, "\": must be one of ", -1);
+    for (specPtr = tablePtr; specPtr->optionName != NULL; ++specPtr) {
+       Tcl_AppendToObj(resultObj, specPtr->optionName, -1);
+       if ((specPtr + 1)->optionName != NULL) {
+           Tcl_AppendToObj(resultObj, ", ", -1);
+       }
+    }
+    return resultObj;
+}
+
+TMSAPI int
+Tms_Configure(Tms_ConfigureSpec *tablePtr, ClientData clientData,
+    Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+    int option = 0, r = TCL_OK;
+    Tms_ConfigureSpec *specPtr = tablePtr;
+
+    /*
+     * Return all configuration items as a list with the option names
+     */
+
+    if (objc == 0) {
+       Tcl_Obj *resultObj = Tcl_NewListObj(0, NULL);
+       for (specPtr = tablePtr; specPtr->optionName != NULL; ++specPtr) {
+           Tcl_Obj **dest = (Tcl_Obj **)((char*)clientData 
+               + specPtr->offset);
+           Tcl_ListObjAppendElement(interp, resultObj, 
+               Tcl_NewStringObj(specPtr->optionName, -1));
+           if (*dest) {
+               Tcl_ListObjAppendElement(interp, resultObj, *dest);
+           } else {
+               Tcl_ListObjAppendElement(interp, resultObj,
+                   Tcl_NewStringObj("", -1));
+           }
+       }
+       Tcl_SetObjResult(interp, resultObj);
+       return TCL_OK;
+    }
+    
+    /*
+     * If we just got an option name, then return only the value for that
+     * option. (cget implementation)
+     */
+
+    if (objc == 1) {
+       Tcl_Obj *resultObj = NULL;
+       while (specPtr->optionName != NULL) {
+           if (strcmp(specPtr->optionName,
+                   Tcl_GetString(objv[option])) == 0) {
+               break;
+           }
+           ++specPtr;
+       }
+       if (specPtr->optionName != NULL) {
+           Tcl_Obj **dest = (Tcl_Obj **)((char*)clientData 
+               + specPtr->offset);
+           resultObj = *dest;
+       } else {
+           resultObj = Tms_ConfigureOptionError(tablePtr, objv[0]);
+           r = TCL_ERROR;
+       }
+       Tcl_SetObjResult(interp, resultObj);
+       return r;
+    }
+       
+    /*
+     * Input is option name, value pairs so lets apply the values.
+     */
+
+    while (option < objc) {
+       for (specPtr = tablePtr; specPtr->optionName != NULL; ++specPtr) {
+           if (strcmp(specPtr->optionName,
+                   Tcl_GetString(objv[option])) == 0) {
+               break;
+           }
+       }
+
+       if (specPtr->optionName != NULL) {
+           Tcl_Obj **dest = (Tcl_Obj **)((char*)clientData 
+               + specPtr->offset);
+           if (*dest && specPtr->flags & TMS_READONLY) {
+               Tcl_ResetResult(interp);
+               Tcl_AppendResult(interp, "cannot set read-only option \"",
+                   specPtr->optionName, "\"", NULL);
+               return TCL_ERROR;
+           }
+           ++option;
+           if (option < objc) {
+               if (*dest) {
+                   Tcl_DecrRefCount(*dest);
+               }
+               *dest = objv[option];
+               if (Tcl_IsShared(objv[option])) {
+                   *dest = Tcl_DuplicateObj(objv[option]);
+               }
+               Tcl_IncrRefCount(*dest);
+           } else {
+               Tcl_WrongNumArgs(interp, 0, objv, "?option value ...?");
+               return TCL_ERROR;
+           }
+       } else {
+           Tcl_SetObjResult(interp,
+               Tms_ConfigureOptionError(tablePtr, objv[option]));
+           return TCL_ERROR;
+       }
+       ++option;
+    }
+    return TCL_OK;
+}
+
+/*
+ * Local variables:
+ *   indent-tabs-mode: t
+ *   tab-width: 8
+ * End:
+ */
diff --git a/generic/subsystem.c b/generic/subsystem.c
new file mode 100644 (file)
index 0000000..27ac3a8
--- /dev/null
@@ -0,0 +1,129 @@
+/* subsystem.c- Copyright (C) 2006 Pat Thoyts <patthoyts@users.sourceforge.net>
+ *
+ * $Id: subsystem.c,v 1.4 2007/04/03 15:38:53 pat Exp $
+ */
+
+#include "tms.h"
+
+typedef struct Subsystem {
+    Tms_SubsystemSpec *specPtr;
+    void              *dataPtr;
+} Subsystem;
+
+static int
+SubsystemObjCmd(ClientData clientData, Tcl_Interp *interp,
+                int objc, Tcl_Obj *const objv[])
+{
+    Subsystem *ptr = (Subsystem *)clientData;
+
+    static const char *cmds[] = {
+        "create", "configure", "sendto", "names", NULL };
+    enum {CMD_CREATE, CMD_CONFIGURE, CMD_SENDTO, CMD_NAMES};
+    int index = 0, r = TCL_OK;
+
+    if (Tcl_GetIndexFromObj(interp, objv[1], cmds, "command", 0, &index)
+        != TCL_OK) {
+        return TCL_ERROR;
+    }
+    switch (index) {
+        case CMD_CREATE:
+           if (ptr->specPtr->create) {
+               if (objc < 3) {
+                Tcl_WrongNumArgs(interp, 2, objv, 
+                                 "?option value ...?");
+                r = TCL_ERROR;
+               } else {
+                   r = ptr->specPtr->create(ptr->dataPtr, ptr->specPtr,
+                                            interp, objc - 2, &objv[2]);
+               }
+           } else {
+               Tcl_SetResult(interp, "create command not implemented",
+                             TCL_STATIC);
+               r = TCL_ERROR;
+           }
+            break;
+        case CMD_CONFIGURE:
+           if (ptr->specPtr->config) {
+               if (objc < 3) {
+                   Tcl_WrongNumArgs(interp, 2, objv, "?option value ...?");
+                   r = TCL_ERROR;
+               } else {
+                   r = ptr->specPtr->config(ptr->dataPtr, ptr->specPtr,
+                       interp, objc - 2, &objv[2]);
+               }
+           } else {
+               Tcl_SetResult(interp, "configure command not implemented", TCL_STATIC);
+               r = TCL_ERROR;
+           }
+            break;
+        case CMD_SENDTO:
+           if (ptr->specPtr->sendto) {
+               if (objc < 3 || objc > 4 ) {
+                   Tcl_WrongNumArgs(interp, 2, objv, "path message");
+                   r = TCL_ERROR;
+               } else {
+                   r = ptr->specPtr->sendto(ptr->dataPtr, ptr->specPtr,
+                       interp, objv[2], objv[3]);
+               }
+           } else {
+               Tcl_SetResult(interp, "sendto command not implemented", TCL_STATIC);
+               r = TCL_ERROR;
+           }
+            break;
+        case CMD_NAMES:
+           if (ptr->specPtr->names) {
+               if (objc != 2) {
+                   Tcl_WrongNumArgs(interp, 2, objv, "");
+                   r = TCL_ERROR;
+               } else {
+                   r = ptr->specPtr->names(ptr->dataPtr, 
+                       ptr->specPtr, interp);
+               }
+           } else {
+               Tcl_SetResult(interp, "names command not implemented", TCL_STATIC);
+               r = TCL_ERROR;
+           }
+            break;
+    }
+    return r;
+}
+
+static void
+SubsystemCleanup(void *ptr)
+{
+    ckfree((char *)ptr);
+}
+
+TMSAPI int
+Tms_RegisterSubsystem(Tcl_Interp *interp, const char *name,
+                      Tms_SubsystemSpec *specPtr, void *dataPtr)
+{
+    Subsystem *ptr = NULL;
+    Tcl_Obj *cmdObj = NULL;
+
+    if (specPtr->magic != TMS_MAGIC_VERSION_1) {
+        Tcl_SetResult(interp, "invalid version", TCL_STATIC);
+        return TCL_ERROR;
+    }
+    if (specPtr->create == NULL) {
+       Tcl_SetResult(interp, "invalid specification: "
+           "the create method must be valid", TCL_STATIC);
+       return TCL_ERROR;
+    }
+
+    ptr = (Subsystem *)ckalloc(sizeof(Subsystem));    
+    ptr->specPtr = specPtr;
+    ptr->dataPtr = dataPtr;
+    cmdObj = Tcl_NewStringObj("tms::", -1);
+    Tcl_AppendToObj(cmdObj, name, -1);
+    Tcl_CreateObjCommand(interp, Tcl_GetString(cmdObj), SubsystemObjCmd,
+                                (ClientData)ptr, SubsystemCleanup);
+    return TCL_OK;
+}
+
+/*
+ * Local variables:
+ *   indent-tabs-mode: t
+ *   tab-width: 8
+ * End:
+ */
diff --git a/generic/tms.c b/generic/tms.c
new file mode 100644 (file)
index 0000000..849a002
--- /dev/null
@@ -0,0 +1,62 @@
+/* tms.c - Copyright (C) 2006 Pat Thoyts <patthoyts@users.sourceforge.net>
+ *
+ * $Id: tms.c,v 1.3 2007/04/03 15:38:53 pat Exp $
+ */
+
+#include "tmsInt.h"
+
+
+TMSAPI void
+Tms_RegisterCleanup(Tcl_Interp *interp, void *deleteData, Tms_CleanupProc *cleanupProc)
+{
+}
+\f
+/*
+ * RegisterSubsystems --
+ *     Register all generic subsystems. See also the various platform
+ *     specific init routines
+ */
+
+static void
+RegisterSubsystems(Tcl_Interp *interp)
+{
+#if 0
+    Windows_Init(interp);       /* Windows messages */
+    DBus_Init(interp);          /* DBUS messages */
+    Udp_Init(interp);           /* UDP datagrams */
+    Ipx_Init(interp);           /* IPX datagrams */
+    MQ_Init(interp);            /* Message Queue messaging */
+    KQueue_Init(interp);        /* kqueue events */
+    Usblib_Init(interp);        /* usb packets */
+#endif
+}
+\f
+/*
+ * Package initialization
+ */
+
+#define TCL_VERSION_WRONG "8.0" /* see tktable bug #1091431 */
+extern TmsStubs tmsStubs;
+
+int DLLEXPORT
+Tms_Init(Tcl_Interp *interp)
+{
+#ifdef USE_TCL_STUBS
+    if (Tcl_InitStubs(interp, TCL_VERSION_WRONG, 0) == NULL) {
+        return TCL_ERROR;
+    }
+#endif
+
+    RegisterSubsystems(interp);
+    TmspInitPlatform(interp);
+    
+    Tcl_PkgProvideEx(interp, PACKAGE_NAME, PACKAGE_VERSION, (void*)&tmsStubs);
+    return TCL_OK;
+}
+
+/*
+ * Local variables:
+ *   indent-tabs-mode: t
+ *   tab-width: 8
+ * End:
+ */
diff --git a/generic/tms.decls b/generic/tms.decls
new file mode 100644 (file)
index 0000000..e16a885
--- /dev/null
@@ -0,0 +1,47 @@
+# tms.decls  -*- c -*-
+library                tms
+interface      tms
+epoch          0
+scspec         TMSAPI
+
+declare 0 current {
+    int Tms_RegisterSubsystem(Tcl_Interp *interp, const char *name,
+        Tms_SubsystemSpec *specPtr, ClientData dataPtr);
+}
+
+declare 1 current {
+    void Tms_RegisterCleanup(
+        Tcl_Interp *interp, void *deleteData, Tms_CleanupProc *cleanupProc);
+}
+
+declare 2 current {
+    void Tms_ConfigureDefault(
+        Tms_ConfigureSpec *tablePtr, ClientData clientData);
+}
+
+declare 3 current {
+    Tcl_Obj *Tms_ConfigureOptionError(
+        Tms_ConfigureSpec *tablePtr, Tcl_Obj *optionObj);
+}
+
+declare 4 current {
+    int Tms_Configure(Tms_ConfigureSpec *tablePtr, ClientData clientData,
+        Tcl_Interp *interp, int objc, Tcl_Obj *const *objv);
+}
+
+declare 5 current {
+    int Tms_BackgroundEvalObjv(Tcl_Interp *interp, 
+        int objc, Tcl_Obj *const *objv, int flags);
+}
+
+# Platform-specific interface declarations
+
+interface tmsPlat
+
+declare 0 win {
+    void Tms_AddWin32Handle(Tms_Win32Handle handle);
+}
+
+declare 1 win {
+    void Tms_RemoveWin32Handle(Tms_Win32Handle handle);
+}
diff --git a/generic/tms.h b/generic/tms.h
new file mode 100644 (file)
index 0000000..a6d1b64
--- /dev/null
@@ -0,0 +1,81 @@
+/* tms.h - Copyright (C) 2006 Pat Thoyts <patthoyts@users.sourceforge.net>
+ *
+ * $Id: tms.h,v 1.3 2007/04/03 15:38:53 pat Exp $
+ */
+
+#ifndef TMS_H_INCLUDE
+#define TMS_H_INCLUDE 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <tcl.h>
+
+#if defined(BUILD_tms)
+#  define TMSAPI DLLEXPORT
+#  undef USE_TMS_STUBS
+#else
+#  define TMSAPI DLLIMPORT
+#endif
+
+#define PACKAGE_PATCHLEVEL PACKAGE_VERSION
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct Tms_SubsystemSpec Tms_SubsystemSpec;
+typedef void (Tms_CleanupProc)(void *clientData);
+
+typedef int (*Tms_SubsystemCreateProc)(void *, Tms_SubsystemSpec *,
+    Tcl_Interp *, int, Tcl_Obj *const *);
+typedef int (*Tms_SubsystemConfigureProc)(void *, Tms_SubsystemSpec *,
+    Tcl_Interp *, int, Tcl_Obj *const *);
+typedef int (*Tms_SubsystemSendtoProc)(void *, Tms_SubsystemSpec *,
+    Tcl_Interp *, Tcl_Obj *, Tcl_Obj *);
+typedef int (*Tms_SubsystemNamesProc)(void *, Tms_SubsystemSpec *,
+    Tcl_Interp *);
+
+typedef enum {TMS_MAGIC_VERSION_1 = 1} Tms_Magic;
+
+typedef struct Tms_SubsystemSpec {
+    Tms_Magic                  magic;
+    Tms_SubsystemCreateProc    create;
+    Tms_SubsystemConfigureProc config;
+    Tms_SubsystemSendtoProc    sendto;
+    Tms_SubsystemNamesProc     names;
+} Tms_SubsystemSpec;
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct Tms_ConfigureSpec {
+    const char *optionName;
+    int offset;
+    unsigned int flags;
+    const char *defValue;
+} Tms_ConfigureSpec;
+
+#ifdef offsetof
+#define Tms_Offset(type, field) ((int) offsetof(type, field))
+#else
+#define Tms_Offset(type, field) ((int) ((char *) &((type *) 0)->field))
+#endif
+#define TMS_READWRITE 0
+#define TMS_READONLY  1
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct TmsWin32Handle * Tms_Win32Handle;
+
+/* ----------------------------------------------------------------------
+ *
+ * Include the stubs table declarations - generic and platform specific.
+ */
+
+#include "tmsDecls.h"
+#include "tmsPlatDecls.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TMS_H_INCLUDE */
diff --git a/generic/tmsDecls.h b/generic/tmsDecls.h
new file mode 100644 (file)
index 0000000..282a010
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * $Id: tmsDecls.h,v 1.3 2007/04/03 15:38:53 pat Exp $
+ *
+ * This file is (mostly) automatically generated from tms.decls.
+ */
+
+
+#if defined(USE_TMS_STUBS)
+
+extern const char *TmsInitializeStubs(
+       Tcl_Interp *, const char *version, int epoch, int revision);
+#define Tms_InitStubs(interp) TmsInitializeStubs( \
+       interp, TMS_VERSION, TMS_STUBS_EPOCH, TMS_STUBS_REVISION)
+
+#else
+
+#define Tms_InitStubs(interp) Tcl_PkgRequire(interp,"tms",TMS_VERSION)
+
+#endif
+
+
+/* !BEGIN!: Do not edit below this line. */
+
+#define TMS_STUBS_EPOCH 0
+#define TMS_STUBS_REVISION 8
+
+#if !defined(USE_TMS_STUBS)
+
+/*
+ * Exported function declarations:
+ */
+
+/* 0 */
+TMSAPI int             Tms_RegisterSubsystem (Tcl_Interp * interp, 
+                               const char * name, 
+                               Tms_SubsystemSpec * specPtr, 
+                               ClientData dataPtr);
+/* 1 */
+TMSAPI void            Tms_RegisterCleanup (Tcl_Interp * interp, 
+                               void * deleteData, 
+                               Tms_CleanupProc * cleanupProc);
+/* 2 */
+TMSAPI void            Tms_ConfigureDefault (Tms_ConfigureSpec * tablePtr, 
+                               ClientData clientData);
+/* 3 */
+TMSAPI Tcl_Obj *       Tms_ConfigureOptionError (
+                               Tms_ConfigureSpec * tablePtr, 
+                               Tcl_Obj * optionObj);
+/* 4 */
+TMSAPI int             Tms_Configure (Tms_ConfigureSpec * tablePtr, 
+                               ClientData clientData, Tcl_Interp * interp, 
+                               int objc, Tcl_Obj *const * objv);
+/* 5 */
+TMSAPI int             Tms_BackgroundEvalObjv (Tcl_Interp * interp, 
+                               int objc, Tcl_Obj *const * objv, int flags);
+
+#endif /* !defined(USE_TMS_STUBS) */
+
+typedef struct TmsStubs {
+    int magic;
+    int epoch;
+    int revision;
+    struct TmsStubHooks *hooks;
+
+    int (*tms_RegisterSubsystem) (Tcl_Interp * interp, const char * name, Tms_SubsystemSpec * specPtr, ClientData dataPtr); /* 0 */
+    void (*tms_RegisterCleanup) (Tcl_Interp * interp, void * deleteData, Tms_CleanupProc * cleanupProc); /* 1 */
+    void (*tms_ConfigureDefault) (Tms_ConfigureSpec * tablePtr, ClientData clientData); /* 2 */
+    Tcl_Obj * (*tms_ConfigureOptionError) (Tms_ConfigureSpec * tablePtr, Tcl_Obj * optionObj); /* 3 */
+    int (*tms_Configure) (Tms_ConfigureSpec * tablePtr, ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *const * objv); /* 4 */
+    int (*tms_BackgroundEvalObjv) (Tcl_Interp * interp, int objc, Tcl_Obj *const * objv, int flags); /* 5 */
+} TmsStubs;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern const TmsStubs *tmsStubsPtr;
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TMS_STUBS)
+
+/*
+ * Inline function declarations:
+ */
+
+#ifndef Tms_RegisterSubsystem
+#define Tms_RegisterSubsystem \
+       (tmsStubsPtr->tms_RegisterSubsystem) /* 0 */
+#endif
+#ifndef Tms_RegisterCleanup
+#define Tms_RegisterCleanup \
+       (tmsStubsPtr->tms_RegisterCleanup) /* 1 */
+#endif
+#ifndef Tms_ConfigureDefault
+#define Tms_ConfigureDefault \
+       (tmsStubsPtr->tms_ConfigureDefault) /* 2 */
+#endif
+#ifndef Tms_ConfigureOptionError
+#define Tms_ConfigureOptionError \
+       (tmsStubsPtr->tms_ConfigureOptionError) /* 3 */
+#endif
+#ifndef Tms_Configure
+#define Tms_Configure \
+       (tmsStubsPtr->tms_Configure) /* 4 */
+#endif
+#ifndef Tms_BackgroundEvalObjv
+#define Tms_BackgroundEvalObjv \
+       (tmsStubsPtr->tms_BackgroundEvalObjv) /* 5 */
+#endif
+
+#endif /* defined(USE_TMS_STUBS) */
+
+/* !END!: Do not edit above this line. */
diff --git a/generic/tmsInt.h b/generic/tmsInt.h
new file mode 100644 (file)
index 0000000..6d9b4bc
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _tmsInt_h_INCLUDE
+#define _tmsInt_h_INCLUDE
+
+#include "tms.h"
+
+struct Ensemble {
+    const char *name;          /* subcommand name */
+    Tcl_ObjCmdProc *command;   /* subcommand implementation OR */
+    struct Ensemble *ensemble; /* subcommand ensemble */
+};
+
+/*MODULE_SCOPE*/ int TmspInitPlatform(Tcl_Interp *interp);
+
+#endif /* _tmsInt_h_INCLUDE */
diff --git a/generic/tmsPlatDecls.h b/generic/tmsPlatDecls.h
new file mode 100644 (file)
index 0000000..8506863
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * tmsPlatDecls.h --
+ *     Platform specific APIs
+ */
+
+#ifndef _tmsPlatDecls_h_INCLUDE
+#define _tmsPlatDecls_h_INCLUDE
+/* !BEGIN!: Do not edit below this line. */
+
+#define TMSPLAT_STUBS_EPOCH 0
+#define TMSPLAT_STUBS_REVISION 8
+
+#if !defined(USE_TMS_STUBS)
+
+/*
+ * Exported function declarations:
+ */
+
+/* 0 */
+TMSAPI void            Tms_AddWin32Handle (Tms_Win32Handle handle);
+/* 1 */
+TMSAPI void            Tms_RemoveWin32Handle (Tms_Win32Handle handle);
+
+#endif /* !defined(USE_TMS_STUBS) */
+
+typedef struct TmsPlatStubs {
+    int magic;
+    int epoch;
+    int revision;
+    struct TmsPlatStubHooks *hooks;
+
+    void (*tms_AddWin32Handle) (Tms_Win32Handle handle); /* 0 */
+    void (*tms_RemoveWin32Handle) (Tms_Win32Handle handle); /* 1 */
+} TmsPlatStubs;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern const TmsPlatStubs *tmsPlatStubsPtr;
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TMS_STUBS)
+
+/*
+ * Inline function declarations:
+ */
+
+#ifndef Tms_AddWin32Handle
+#define Tms_AddWin32Handle \
+       (tmsPlatStubsPtr->tms_AddWin32Handle) /* 0 */
+#endif
+#ifndef Tms_RemoveWin32Handle
+#define Tms_RemoveWin32Handle \
+       (tmsPlatStubsPtr->tms_RemoveWin32Handle) /* 1 */
+#endif
+
+#endif /* defined(USE_TMS_STUBS) */
+
+/* !END!: Do not edit above this line. */
+
+#endif /* _tmsPlatDecls_h_INCLUDE */
diff --git a/generic/tmsStubInit.c b/generic/tmsStubInit.c
new file mode 100644 (file)
index 0000000..2ebefe1
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * $Id: tmsStubInit.c,v 1.3 2007/04/03 15:38:53 pat Exp $
+ *
+ * This file is (mostly) automatically generated from tms.decls.
+ * It is compiled and linked in with the main package.
+ */
+
+#include <tcl.h>
+#include "tms.h"
+
+/* !BEGIN!: Do not edit below this line. */
+
+TmsStubs tmsStubs = {
+    TCL_STUB_MAGIC,
+    TMS_STUBS_EPOCH,
+    TMS_STUBS_REVISION,
+    0,
+    Tms_RegisterSubsystem, /* 0 */
+    Tms_RegisterCleanup, /* 1 */
+    Tms_ConfigureDefault, /* 2 */
+    Tms_ConfigureOptionError, /* 3 */
+    Tms_Configure, /* 4 */
+    Tms_BackgroundEvalObjv, /* 5 */
+};
+
+TmsPlatStubs tmsPlatStubs = {
+    TCL_STUB_MAGIC,
+    TMSPLAT_STUBS_EPOCH,
+    TMSPLAT_STUBS_REVISION,
+    0,
+    Tms_AddWin32Handle, /* 0 */
+    Tms_RemoveWin32Handle, /* 1 */
+};
+
+/* !END!: Do not edit above this line. */
diff --git a/generic/tmsStubLib.c b/generic/tmsStubLib.c
new file mode 100644 (file)
index 0000000..7ba3921
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Stubs link library code.
+ * This is based upon jenglish's modified stubs code with epoch.
+ *
+ * $Id: tmsStubLib.c,v 1.1 2006/10/23 00:55:06 pat Exp $
+ */
+
+#include <tcl.h>
+
+#define USE_TMS_STUBS 1
+#include "tms.h"
+
+const TmsStubs *tmsStubsPtr;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TmsInitializeStubs --
+ *     Load the TMS package, initialize stub table pointer.
+ *     Do not call this function directly, use Tms_InitStubs() macro instead.
+ *
+ * Results:
+ *     The actual version of the package that satisfies the request, or
+ *     NULL to indicate that an error occurred.
+ *
+ * Side effects:
+ *     Sets the stub table pointer.
+ *
+ */
+const char *TmsInitializeStubs(
+    Tcl_Interp *interp, const char *version, int epoch, int revision)
+{
+    int exact = 0;
+    const char *packageName = PACKAGE_NAME;
+    const char *errMsg = NULL;
+    ClientData pkgClientData = NULL;
+    const char *actualVersion= Tcl_PkgRequireEx(
+       interp, packageName, version, exact, &pkgClientData);
+    TmsStubs *stubsPtr = pkgClientData;
+
+    if (!actualVersion) {
+       return NULL;
+    }
+
+    if (!stubsPtr) {
+       errMsg = "missing stub table pointer";
+       goto error;
+    }
+    if (stubsPtr->epoch != epoch) {
+       errMsg = "epoch number mismatch";
+       goto error;
+    }
+    if (stubsPtr->revision < revision) {
+       errMsg = "require later revision";
+       goto error;
+    }
+
+    tmsStubsPtr = stubsPtr;
+    return actualVersion;
+
+error:
+    Tcl_ResetResult(interp);
+    Tcl_AppendResult(interp,
+       "Error loading ", packageName, " package",
+       " (requested version '", version,
+       "', loaded version '", actualVersion, "'): ",
+       errMsg, 
+       NULL);
+    return NULL;
+}
+
diff --git a/tclconfig/install-sh b/tclconfig/install-sh
new file mode 100644 (file)
index 0000000..0ff4b6a
--- /dev/null
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5; it is not part of GNU.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+fi
+
+if [ x"$dst" = x ]
+then
+       echo "install:  no destination specified"
+       exit 1
+fi
+
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+if [ -d $dst ]
+then
+       dst="$dst"/`basename $src`
+fi
+
+# Make a temp file name in the proper directory.
+
+dstdir=`dirname $dst`
+dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+$doit $instcmd $src $dsttmp
+
+# and set any options; do chmod last to preserve setuid bits
+
+if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+
+$doit $rmcmd $dst
+$doit $mvcmd $dsttmp $dst
+
+
+exit 0
diff --git a/tclconfig/tcl.m4 b/tclconfig/tcl.m4
new file mode 100644 (file)
index 0000000..8384455
--- /dev/null
@@ -0,0 +1,3858 @@
+# tcl.m4 --
+#
+#      This file provides a set of autoconf macros to help TEA-enable
+#      a Tcl extension.
+#
+# Copyright (c) 1999-2000 Ajuba Solutions.
+# Copyright (c) 2002-2005 ActiveState Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id: tcl.m4,v 1.66 2005/06/04 10:43:17 das Exp $
+
+AC_PREREQ(2.50)
+
+#------------------------------------------------------------------------
+# TEA_PATH_TCLCONFIG --
+#
+#      Locate the tclConfig.sh file and perform a sanity check on
+#      the Tcl compile flags
+#
+# Arguments:
+#      none
+#
+# Results:
+#
+#      Adds the following arguments to configure:
+#              --with-tcl=...
+#
+#      Defines the following vars:
+#              TCL_BIN_DIR     Full path to the directory containing
+#                              the tclConfig.sh file
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_PATH_TCLCONFIG, [
+    dnl Make sure we are initialized
+    AC_REQUIRE([TEA_INIT])
+    #
+    # Ok, lets find the tcl configuration
+    # First, look for one uninstalled.
+    # the alternative search directory is invoked by --with-tcl
+    #
+
+    if test x"${no_tcl}" = x ; then
+       # we reset no_tcl in case something fails here
+       no_tcl=true
+       AC_ARG_WITH(tcl, [  --with-tcl              directory containing tcl configuration (tclConfig.sh)], with_tclconfig=${withval})
+       AC_MSG_CHECKING([for Tcl configuration])
+       AC_CACHE_VAL(ac_cv_c_tclconfig,[
+
+           # First check to see if --with-tcl was specified.
+           if test x"${with_tclconfig}" != x ; then
+               case ${with_tclconfig} in
+                   */tclConfig.sh )
+                       if test -f ${with_tclconfig}; then
+                           AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself])
+                           with_tclconfig=`echo ${with_tclconfig} | sed 's!/tclConfig\.sh$!!'`
+                       fi ;;
+               esac
+               if test -f "${with_tclconfig}/tclConfig.sh" ; then
+                   ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
+               else
+                   AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
+               fi
+           fi
+
+           # then check for a private Tcl installation
+           if test x"${ac_cv_c_tclconfig}" = x ; then
+               for i in \
+                       ../tcl \
+                       `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+                       `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
+                       ../../tcl \
+                        `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+                        `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
+                       ../../../tcl \
+                        `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+                        `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
+                   if test -f "$i/unix/tclConfig.sh" ; then
+                       ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
+                       break
+                   fi
+               done
+           fi
+
+           # check in a few common install locations
+           if test x"${ac_cv_c_tclconfig}" = x ; then
+               for i in `ls -d ${exec_prefix}/lib 2>/dev/null` \
+                       `ls -d ${prefix}/lib 2>/dev/null` \
+                       `ls -d /usr/local/lib 2>/dev/null` \
+                       `ls -d /usr/contrib/lib 2>/dev/null` \
+                       `ls -d /usr/lib 2>/dev/null` \
+                       ; do
+                   if test -f "$i/tclConfig.sh" ; then
+                       ac_cv_c_tclconfig=`(cd $i; pwd)`
+                       break
+                   fi
+               done
+           fi
+
+           # check in a few other private locations
+           if test x"${ac_cv_c_tclconfig}" = x ; then
+               for i in \
+                       ${srcdir}/../tcl \
+                       `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+                       `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
+                   if test -f "$i/unix/tclConfig.sh" ; then
+                   ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
+                   break
+               fi
+               done
+           fi
+       ])
+
+       if test x"${ac_cv_c_tclconfig}" = x ; then
+           TCL_BIN_DIR="# no Tcl configs found"
+           AC_MSG_WARN("Cannot find Tcl configuration definitions")
+           exit 0
+       else
+           no_tcl=
+           TCL_BIN_DIR=${ac_cv_c_tclconfig}
+           AC_MSG_RESULT([found $TCL_BIN_DIR/tclConfig.sh])
+       fi
+    fi
+])
+
+#------------------------------------------------------------------------
+# TEA_PATH_TKCONFIG --
+#
+#      Locate the tkConfig.sh file
+#
+# Arguments:
+#      none
+#
+# Results:
+#
+#      Adds the following arguments to configure:
+#              --with-tk=...
+#
+#      Defines the following vars:
+#              TK_BIN_DIR      Full path to the directory containing
+#                              the tkConfig.sh file
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_PATH_TKCONFIG, [
+    #
+    # Ok, lets find the tk configuration
+    # First, look for one uninstalled.
+    # the alternative search directory is invoked by --with-tk
+    #
+
+    if test x"${no_tk}" = x ; then
+       # we reset no_tk in case something fails here
+       no_tk=true
+       AC_ARG_WITH(tk, [  --with-tk               directory containing tk configuration (tkConfig.sh)], with_tkconfig=${withval})
+       AC_MSG_CHECKING([for Tk configuration])
+       AC_CACHE_VAL(ac_cv_c_tkconfig,[
+
+           # First check to see if --with-tkconfig was specified.
+           if test x"${with_tkconfig}" != x ; then
+               case ${with_tkconfig} in
+                   */tkConfig.sh )
+                       if test -f ${with_tkconfig}; then
+                           AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself])
+                           with_tkconfig=`echo ${with_tkconfig} | sed 's!/tkConfig\.sh$!!'`
+                       fi ;;
+               esac
+               if test -f "${with_tkconfig}/tkConfig.sh" ; then
+                   ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`
+               else
+                   AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
+               fi
+           fi
+
+           # then check for a private Tk library
+           if test x"${ac_cv_c_tkconfig}" = x ; then
+               for i in \
+                       ../tk \
+                       `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+                       `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \
+                       ../../tk \
+                       `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+                       `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \
+                       ../../../tk \
+                       `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+                       `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
+                   if test -f "$i/unix/tkConfig.sh" ; then
+                       ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
+                       break
+                   fi
+               done
+           fi
+           # check in a few common install locations
+           if test x"${ac_cv_c_tkconfig}" = x ; then
+               for i in `ls -d ${exec_prefix}/lib 2>/dev/null` \
+                       `ls -d ${prefix}/lib 2>/dev/null` \
+                       `ls -d /usr/local/lib 2>/dev/null` \
+                       `ls -d /usr/contrib/lib 2>/dev/null` \
+                       `ls -d /usr/lib 2>/dev/null` \
+                       ; do
+                   if test -f "$i/tkConfig.sh" ; then
+                       ac_cv_c_tkconfig=`(cd $i; pwd)`
+                       break
+                   fi
+               done
+           fi
+           # check in a few other private locations
+           if test x"${ac_cv_c_tkconfig}" = x ; then
+               for i in \
+                       ${srcdir}/../tk \
+                       `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+                       `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
+                   if test -f "$i/unix/tkConfig.sh" ; then
+                       ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
+                       break
+                   fi
+               done
+           fi
+       ])
+       if test x"${ac_cv_c_tkconfig}" = x ; then
+           TK_BIN_DIR="# no Tk configs found"
+           AC_MSG_WARN("Cannot find Tk configuration definitions")
+           exit 0
+       else
+           no_tk=
+           TK_BIN_DIR=${ac_cv_c_tkconfig}
+           AC_MSG_RESULT([found $TK_BIN_DIR/tkConfig.sh])
+       fi
+    fi
+
+])
+
+#------------------------------------------------------------------------
+# TEA_LOAD_TCLCONFIG --
+#
+#      Load the tclConfig.sh file
+#
+# Arguments:
+#      
+#      Requires the following vars to be set:
+#              TCL_BIN_DIR
+#
+# Results:
+#
+#      Subst the following vars:
+#              TCL_BIN_DIR
+#              TCL_SRC_DIR
+#              TCL_LIB_FILE
+#
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_LOAD_TCLCONFIG, [
+    AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh])
+
+    if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
+        AC_MSG_RESULT([loading])
+       . $TCL_BIN_DIR/tclConfig.sh
+    else
+        AC_MSG_RESULT([file not found])
+    fi
+
+    #
+    # If the TCL_BIN_DIR is the build directory (not the install directory),
+    # then set the common variable name to the value of the build variables.
+    # For example, the variable TCL_LIB_SPEC will be set to the value
+    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
+    # instead of TCL_BUILD_LIB_SPEC since it will work with both an
+    # installed and uninstalled version of Tcl.
+    #
+
+    if test -f $TCL_BIN_DIR/Makefile ; then
+        TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
+        TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
+        TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
+    fi
+
+    #
+    # eval is required to do the TCL_DBGX substitution
+    #
+
+    eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
+    eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
+    eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
+
+    eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
+    eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
+    eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
+
+    AC_SUBST(TCL_VERSION)
+    AC_SUBST(TCL_BIN_DIR)
+    AC_SUBST(TCL_SRC_DIR)
+
+    AC_SUBST(TCL_LIB_FILE)
+    AC_SUBST(TCL_LIB_FLAG)
+    AC_SUBST(TCL_LIB_SPEC)
+
+    AC_SUBST(TCL_STUB_LIB_FILE)
+    AC_SUBST(TCL_STUB_LIB_FLAG)
+    AC_SUBST(TCL_STUB_LIB_SPEC)
+
+    AC_SUBST(TCL_LIBS)
+    AC_SUBST(TCL_DEFS)
+    AC_SUBST(TCL_EXTRA_CFLAGS)
+    AC_SUBST(TCL_LD_FLAGS)
+    AC_SUBST(TCL_SHLIB_LD_LIBS)
+    #AC_SUBST(TCL_BUILD_LIB_SPEC)
+    #AC_SUBST(TCL_BUILD_STUB_LIB_SPEC)
+])
+
+#------------------------------------------------------------------------
+# TEA_LOAD_TKCONFIG --
+#
+#      Load the tkConfig.sh file
+#
+# Arguments:
+#      
+#      Requires the following vars to be set:
+#              TK_BIN_DIR
+#
+# Results:
+#
+#      Sets the following vars that should be in tkConfig.sh:
+#              TK_BIN_DIR
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_LOAD_TKCONFIG, [
+    AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])
+
+    if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then
+        AC_MSG_RESULT([loading])
+       . $TK_BIN_DIR/tkConfig.sh
+    else
+        AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
+    fi
+
+    #
+    # If the TK_BIN_DIR is the build directory (not the install directory),
+    # then set the common variable name to the value of the build variables.
+    # For example, the variable TK_LIB_SPEC will be set to the value
+    # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC
+    # instead of TK_BUILD_LIB_SPEC since it will work with both an
+    # installed and uninstalled version of Tcl.
+    #
+
+    if test -f $TK_BIN_DIR/Makefile ; then
+        TK_LIB_SPEC=${TK_BUILD_LIB_SPEC}
+        TK_STUB_LIB_SPEC=${TK_BUILD_STUB_LIB_SPEC}
+        TK_STUB_LIB_PATH=${TK_BUILD_STUB_LIB_PATH}
+    fi
+
+    #
+    # eval is required to do the TK_DBGX substitution
+    #
+
+    eval "TK_LIB_FILE=\"${TK_LIB_FILE}\""
+    eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\""
+    eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\""
+
+    eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\""
+    eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\""
+    eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\""
+
+    AC_SUBST(TK_VERSION)
+    AC_SUBST(TK_BIN_DIR)
+    AC_SUBST(TK_SRC_DIR)
+
+    AC_SUBST(TK_LIB_FILE)
+    AC_SUBST(TK_LIB_FLAG)
+    AC_SUBST(TK_LIB_SPEC)
+
+    AC_SUBST(TK_STUB_LIB_FILE)
+    AC_SUBST(TK_STUB_LIB_FLAG)
+    AC_SUBST(TK_STUB_LIB_SPEC)
+
+    AC_SUBST(TK_LIBS)
+    AC_SUBST(TK_XINCLUDES)
+])
+
+#------------------------------------------------------------------------
+# TEA_ENABLE_SHARED --
+#
+#      Allows the building of shared libraries
+#
+# Arguments:
+#      none
+#      
+# Results:
+#
+#      Adds the following arguments to configure:
+#              --enable-shared=yes|no
+#
+#      Defines the following vars:
+#              STATIC_BUILD    Used for building import/export libraries
+#                              on Windows.
+#
+#      Sets the following vars:
+#              SHARED_BUILD    Value of 1 or 0
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_ENABLE_SHARED, [
+    AC_MSG_CHECKING([how to build libraries])
+    AC_ARG_ENABLE(shared,
+       [  --enable-shared         build and link with shared libraries [--enable-shared]],
+       [tcl_ok=$enableval], [tcl_ok=yes])
+
+    if test "${enable_shared+set}" = set; then
+       enableval="$enable_shared"
+       tcl_ok=$enableval
+    else
+       tcl_ok=yes
+    fi
+
+    if test "$tcl_ok" = "yes" ; then
+       AC_MSG_RESULT([shared])
+       SHARED_BUILD=1
+    else
+       AC_MSG_RESULT([static])
+       SHARED_BUILD=0
+       AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
+    fi
+    AC_SUBST(SHARED_BUILD)
+])
+
+#------------------------------------------------------------------------
+# TEA_ENABLE_THREADS --
+#
+#      Specify if thread support should be enabled.  If "yes" is
+#      specified as an arg (optional), threads are enabled by default.
+#      TCL_THREADS is checked so that if you are compiling an extension
+#      against a threaded core, your extension must be compiled threaded
+#      as well.
+#
+# Arguments:
+#      none
+#      
+# Results:
+#
+#      Adds the following arguments to configure:
+#              --enable-threads
+#
+#      Sets the following vars:
+#              THREADS_LIBS    Thread library(s)
+#
+#      Defines the following vars:
+#              TCL_THREADS
+#              _REENTRANT
+#
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_ENABLE_THREADS, [
+    AC_ARG_ENABLE(threads, [  --enable-threads        build with threads],
+       [tcl_ok=$enableval], [tcl_ok=$1])
+
+    if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
+       TCL_THREADS=1
+
+       if test "${TEA_PLATFORM}" != "windows" ; then
+           # We are always OK on Windows, so check what this platform wants.
+            AC_DEFINE(USE_THREAD_ALLOC, 1,
+                [Do we want to use the threaded memory allocator?])
+           AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
+           AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])
+           AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
+           if test "$tcl_ok" = "no"; then
+               # Check a little harder for __pthread_mutex_init in the
+               # same library, as some systems hide it there until
+               # pthread.h is defined.  We could alternatively do an
+               # AC_TRY_COMPILE with pthread.h, but that will work with
+               # libpthread really doesn't exist, like AIX 4.2.
+               # [Bug: 4359]
+               AC_CHECK_LIB(pthread, __pthread_mutex_init,
+                   tcl_ok=yes, tcl_ok=no)
+           fi
+           
+           if test "$tcl_ok" = "yes"; then
+               # The space is needed
+               THREADS_LIBS=" -lpthread"
+           else
+               AC_CHECK_LIB(pthreads, pthread_mutex_init,
+                   tcl_ok=yes, tcl_ok=no)
+               if test "$tcl_ok" = "yes"; then
+                   # The space is needed
+                   THREADS_LIBS=" -lpthreads"
+               else
+                   AC_CHECK_LIB(c, pthread_mutex_init,
+                       tcl_ok=yes, tcl_ok=no)
+                   if test "$tcl_ok" = "no"; then
+                       AC_CHECK_LIB(c_r, pthread_mutex_init,
+                           tcl_ok=yes, tcl_ok=no)
+                       if test "$tcl_ok" = "yes"; then
+                           # The space is needed
+                           THREADS_LIBS=" -pthread"
+                       else
+                           TCL_THREADS=0
+                           AC_MSG_WARN("Don t know how to find pthread lib on your system - thread support disabled")
+                       fi
+                   fi
+               fi
+           fi
+
+           # Does the pthread-implementation provide
+           # 'pthread_attr_setstacksize' ?
+
+           ac_saved_libs=$LIBS
+           LIBS="$LIBS $THREADS_LIBS"
+           AC_CHECK_FUNCS(pthread_attr_setstacksize)
+           LIBS=$ac_saved_libs
+           AC_CHECK_FUNCS(readdir_r)
+       fi
+    else
+       TCL_THREADS=0
+    fi
+    # Do checking message here to not mess up interleaved configure output
+    AC_MSG_CHECKING([for building with threads])
+    if test "${TCL_THREADS}" = "1"; then
+       AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?])
+       #LIBS="$LIBS $THREADS_LIBS"
+       AC_MSG_RESULT([yes])
+    else
+       AC_MSG_RESULT([no (default)])
+    fi
+    # TCL_THREADS sanity checking.  See if our request for building with
+    # threads is the same as the way Tcl was built.  If not, warn the user.
+    case ${TCL_DEFS} in
+       *THREADS=1*)
+           if test "${TCL_THREADS}" = "0"; then
+               AC_MSG_WARN([
+    Building ${PACKAGE_NAME} without threads enabled, but building against a Tcl
+    that IS thread-enabled.])
+           fi
+           ;;
+       *)
+           if test "${TCL_THREADS}" = "1"; then
+               AC_MSG_WARN([
+    --enable-threads requested, but attempting building against a Tcl
+    that is NOT thread-enabled.])
+           fi
+           ;;
+    esac
+    AC_SUBST(TCL_THREADS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ENABLE_SYMBOLS --
+#
+#      Specify if debugging symbols should be used
+#      Memory (TCL_MEM_DEBUG) debugging can also be enabled.
+#
+# Arguments:
+#      none
+#      
+#      Requires the following vars to be set:
+#              CFLAGS_DEBUG
+#              CFLAGS_OPTIMIZE
+#              LDFLAGS_DEBUG
+#              LDFLAGS_OPTIMIZE
+#      
+# Results:
+#
+#      Adds the following arguments to configure:
+#              --enable-symbols
+#
+#      Defines the following vars:
+#              CFLAGS_DEFAULT  Sets to CFLAGS_DEBUG if true
+#                              Sets to CFLAGS_OPTIMIZE if false
+#              LDFLAGS_DEFAULT Sets to LDFLAGS_DEBUG if true
+#                              Sets to LDFLAGS_OPTIMIZE if false
+#              DBGX            Formerly used as debug library extension;
+#                              always blank now.
+#
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_ENABLE_SYMBOLS, [
+    dnl Make sure we are initialized
+    AC_REQUIRE([TEA_CONFIG_CFLAGS])
+
+    DBGX=""
+
+    AC_MSG_CHECKING([for build with symbols])
+    AC_ARG_ENABLE(symbols, [  --enable-symbols        build with debugging symbols [--disable-symbols]],    [tcl_ok=$enableval], [tcl_ok=no])
+    if test "$tcl_ok" = "no"; then
+       CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE}"
+       LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}"
+       AC_MSG_RESULT([no])
+    else
+       CFLAGS_DEFAULT="${CFLAGS_DEBUG}"
+       LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}"
+       if test "$tcl_ok" = "yes"; then
+           AC_MSG_RESULT([yes (standard debugging)])
+       fi
+    fi
+    if test "${TEA_PLATFORM}" != "windows" ; then
+       LDFLAGS_DEFAULT="${LDFLAGS}"
+    fi
+
+    AC_SUBST(TCL_DBGX)
+    AC_SUBST(CFLAGS_DEFAULT)
+    AC_SUBST(LDFLAGS_DEFAULT)
+
+    if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
+       AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])
+    fi
+
+    if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
+       if test "$tcl_ok" = "all"; then
+           AC_MSG_RESULT([enabled symbols mem debugging])
+       else
+           AC_MSG_RESULT([enabled $tcl_ok debugging])
+       fi
+    fi
+])
+
+#------------------------------------------------------------------------
+# TEA_ENABLE_LANGINFO --
+#
+#      Allows use of modern nl_langinfo check for better l10n.
+#      This is only relevant for Unix.
+#
+# Arguments:
+#      none
+#      
+# Results:
+#
+#      Adds the following arguments to configure:
+#              --enable-langinfo=yes|no (default is yes)
+#
+#      Defines the following vars:
+#              HAVE_LANGINFO   Triggers use of nl_langinfo if defined.
+#
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_ENABLE_LANGINFO, [
+    AC_ARG_ENABLE(langinfo,
+       [  --enable-langinfo      use nl_langinfo if possible to determine
+                         encoding at startup, otherwise use old heuristic],
+       [langinfo_ok=$enableval], [langinfo_ok=yes])
+
+    HAVE_LANGINFO=0
+    if test "$langinfo_ok" = "yes"; then
+       if test "$langinfo_ok" = "yes"; then
+           AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
+       fi
+    fi
+    AC_MSG_CHECKING([whether to use nl_langinfo])
+    if test "$langinfo_ok" = "yes"; then
+       AC_TRY_COMPILE([#include <langinfo.h>],
+               [nl_langinfo(CODESET);],[langinfo_ok=yes],[langinfo_ok=no])
+       if test "$langinfo_ok" = "no"; then
+           langinfo_ok="no (could not compile with nl_langinfo)";
+       fi
+       if test "$langinfo_ok" = "yes"; then
+           AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
+       fi
+    fi
+    AC_MSG_RESULT([$langinfo_ok])
+])
+
+#--------------------------------------------------------------------
+# TEA_CONFIG_CFLAGS
+#
+#      Try to determine the proper flags to pass to the compiler
+#      for building shared libraries and other such nonsense.
+#
+# Arguments:
+#      none
+#
+# Results:
+#
+#      Defines the following vars:
+#
+#       DL_OBJS -       Name of the object file that implements dynamic
+#                       loading for Tcl on this system.
+#       DL_LIBS -       Library file(s) to include in tclsh and other base
+#                       applications in order for the "load" command to work.
+#       LDFLAGS -      Flags to pass to the compiler when linking object
+#                       files into an executable application binary such
+#                       as tclsh.
+#       LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib",
+#                       that tell the run-time dynamic linker where to look
+#                       for shared libraries such as libtcl.so.  Depends on
+#                       the variable LIB_RUNTIME_DIR in the Makefile.
+#       SHLIB_CFLAGS -  Flags to pass to cc when compiling the components
+#                       of a shared library (may request position-independent
+#                       code, among other things).
+#       SHLIB_LD -      Base command to use for combining object files
+#                       into a shared library.
+#       SHLIB_LD_LIBS - Dependent libraries for the linker to scan when
+#                       creating shared libraries.  This symbol typically
+#                       goes at the end of the "ld" commands that build
+#                       shared libraries. The value of the symbol is
+#                       "${LIBS}" if all of the dependent libraries should
+#                       be specified when creating a shared library.  If
+#                       dependent libraries should not be specified (as on
+#                       SunOS 4.x, where they cause the link to fail, or in
+#                       general if Tcl and Tk aren't themselves shared
+#                       libraries), then this symbol has an empty string
+#                       as its value.
+#       SHLIB_SUFFIX -  Suffix to use for the names of dynamically loadable
+#                       extensions.  An empty string means we don't know how
+#                       to use shared libraries on this platform.
+#       TCL_LIB_FILE -  Name of the file that contains the Tcl library, such
+#                       as libtcl7.8.so or libtcl7.8.a.
+#       TCL_LIB_SUFFIX -Specifies everything that comes after the "libtcl"
+#                       in the shared library name, using the
+#                       ${PACKAGE_VERSION} variable to put the version in
+#                       the right place.  This is used by platforms that
+#                       need non-standard library names.
+#                       Examples:  ${PACKAGE_VERSION}.so.1.1 on NetBSD,
+#                       since it needs to have a version after the .so, and
+#                       ${PACKAGE_VERSION}.a on AIX, since the Tcl shared
+#                       library needs to have a .a extension whereas shared
+#                       objects for loadable extensions have a .so
+#                       extension.  Defaults to
+#                       ${PACKAGE_VERSION}${SHLIB_SUFFIX}.
+#       TCL_NEEDS_EXP_FILE -
+#                       1 means that an export file is needed to link to a
+#                       shared library.
+#       TCL_EXP_FILE -  The name of the installed export / import file which
+#                       should be used to link to the Tcl shared library.
+#                       Empty if Tcl is unshared.
+#       TCL_BUILD_EXP_FILE -
+#                       The name of the built export / import file which
+#                       should be used to link to the Tcl shared library.
+#                       Empty if Tcl is unshared.
+#      CFLAGS_DEBUG -
+#                      Flags used when running the compiler in debug mode
+#      CFLAGS_OPTIMIZE -
+#                      Flags used when running the compiler in optimize mode
+#      CFLAGS -        We add CFLAGS to pass to the compiler
+#
+#      Subst's the following vars:
+#              DL_LIBS
+#              CFLAGS_DEBUG
+#              CFLAGS_OPTIMIZE
+#              CFLAGS_WARNING
+#
+#              STLIB_LD
+#              SHLIB_LD
+#              SHLIB_CFLAGS
+#              LDFLAGS_DEBUG
+#              LDFLAGS_OPTIMIZE
+#--------------------------------------------------------------------
+
+AC_DEFUN(TEA_CONFIG_CFLAGS, [
+    dnl Make sure we are initialized
+    AC_REQUIRE([TEA_INIT])
+
+    # Step 0: Enable 64 bit support?
+
+    AC_MSG_CHECKING([if 64bit support is enabled])
+    AC_ARG_ENABLE(64bit,[  --enable-64bit          enable 64bit support (where applicable)], [do64bit=$enableval], [do64bit=no])
+    AC_MSG_RESULT([$do64bit])
+    # Step 0.b: Enable Solaris 64 bit VIS support?
+
+    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
+    AC_ARG_ENABLE(64bit-vis,[  --enable-64bit-vis      enable 64bit Sparc VIS support], [do64bitVIS=$enableval], [do64bitVIS=no])
+    AC_MSG_RESULT([$do64bitVIS])
+
+    if test "$do64bitVIS" = "yes"; then
+       # Force 64bit on with VIS
+       do64bit=yes
+    fi
+
+    # Step 0.c: Cross-compiling options for Windows/CE builds?
+
+    if test "${TEA_PLATFORM}" = "windows" ; then
+       AC_MSG_CHECKING([if Windows/CE build is requested])
+       AC_ARG_ENABLE(wince,[  --enable-wince          enable Win/CE support (where applicable)], [doWince=$enableval], [doWince=no])
+       AC_MSG_RESULT($doWince)
+    fi
+
+    # Step 1: set the variable "system" to hold the name and version number
+    # for the system.  This can usually be done via the "uname" command, but
+    # there are a few systems, like Next, where this doesn't work.
+
+    AC_MSG_CHECKING([system version (for dynamic loading)])
+    if test -f /usr/lib/NextStep/software_version; then
+       system=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version`
+    else
+       system=`uname -s`-`uname -r`
+       if test "$?" -ne 0 ; then
+           AC_MSG_RESULT([unknown (can't find uname command)])
+           system=unknown
+       else
+           # Special check for weird MP-RAS system (uname returns weird
+           # results, and the version is kept in special file).
+       
+           if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then
+               system=MP-RAS-`awk '{print $3}' /etc/.relid'`
+           fi
+           if test "`uname -s`" = "AIX" ; then
+               system=AIX-`uname -v`.`uname -r`
+           fi
+           if test "${TEA_PLATFORM}" = "windows" ; then
+               system=windows
+           fi
+           AC_MSG_RESULT([$system])
+       fi
+    fi
+
+    # Step 2: check for existence of -ldl library.  This is needed because
+    # Linux can use either -ldl or -ldld for dynamic loading.
+
+    AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no)
+
+    # Step 3: set configuration options based on system name and version.
+    # This is similar to Tcl's unix/tcl.m4 except that we've added a
+    # "windows" case and CC_SEARCH_FLAGS becomes LD_SEARCH_FLAGS for us
+    # (and we have no CC_SEARCH_FLAGS).
+
+    do64bit_ok=no
+    LDFLAGS_ORIG="$LDFLAGS"
+    TCL_EXPORT_FILE_SUFFIX=""
+    UNSHARED_LIB_SUFFIX=""
+    TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`'
+    ECHO_VERSION='`echo ${PACKAGE_VERSION}`'
+    TCL_LIB_VERSIONS_OK=ok
+    CFLAGS_DEBUG=-g
+    if test "$GCC" = "yes" ; then
+       CFLAGS_OPTIMIZE=-O2
+       CFLAGS_WARNING="-Wall -Wno-implicit-int"
+    else
+       CFLAGS_OPTIMIZE=-O
+       CFLAGS_WARNING=""
+    fi
+    TCL_NEEDS_EXP_FILE=0
+    TCL_BUILD_EXP_FILE=""
+    TCL_EXP_FILE=""
+dnl FIXME: Replace AC_CHECK_PROG with AC_CHECK_TOOL once cross compiling is fixed.
+dnl AC_CHECK_TOOL(AR, ar, :)
+    AC_CHECK_PROG(AR, ar, ar)
+    STLIB_LD='${AR} cr'
+    LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
+    case $system in
+       windows)
+           # This is a 2-stage check to make sure we have the 64-bit SDK
+           # We have to know where the SDK is installed.
+           if test "$do64bit" = "yes" ; then
+               if test "x${MSSDK}x" = "xx" ; then
+                   MSSDK="C:/Progra~1/Microsoft SDK"
+               fi
+               # Ensure that this path has no spaces to work in autoconf
+               TEA_PATH_NOSPACE(MSSDK, ${MSSDK})
+               if test ! -d "${MSSDK}/bin/win64" ; then
+                   AC_MSG_WARN([could not find 64-bit SDK to enable 64bit mode])
+                   do64bit="no"
+               else
+                   do64bit_ok="yes"
+               fi
+           fi
+
+           if test "$doWince" != "no" ; then
+               if test "$do64bit" = "yes" ; then
+                   AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible])
+               fi
+               if test "$GCC" = "yes" ; then
+                   AC_MSG_ERROR([Windows/CE and GCC builds incompatible])
+               fi
+               TEA_PATH_CELIB
+               # Set defaults for common evc4/PPC2003 setup
+               # Currently Tcl requires 300+, possibly 420+ for sockets
+               CEVERSION=420;          # could be 211 300 301 400 420 ...
+               TARGETCPU=ARMV4;        # could be ARMV4 ARM MIPS SH3 X86 ...
+               ARCH=ARM;               # could be ARM MIPS X86EM ...
+               PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002"
+               if test "$doWince" != "yes"; then
+                   # If !yes then the user specified something
+                   # Reset ARCH to allow user to skip specifying it
+                   ARCH=
+                   eval `echo $doWince | awk -F, '{ \
+           if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \
+           if ([$]1 < 400)   { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \
+           if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \
+           if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \
+           if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \
+                   }'`
+                   if test "x${ARCH}" = "x" ; then
+                       ARCH=$TARGETCPU;
+                   fi
+               fi
+               OSVERSION=WCE$CEVERSION;
+               if test "x${WCEROOT}" = "x" ; then
+                       WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0"
+                   if test ! -d "${WCEROOT}" ; then
+                       WCEROOT="C:/Program Files/Microsoft eMbedded Tools"
+                   fi
+               fi
+               if test "x${SDKROOT}" = "x" ; then
+                   SDKROOT="C:/Program Files/Windows CE Tools"
+                   if test ! -d "${SDKROOT}" ; then
+                       SDKROOT="C:/Windows CE Tools"
+                   fi
+               fi
+               # Ensure that this path has no spaces to work in autoconf
+               TEA_PATH_NOSPACE(WCEROOT, ${WCEROOT})
+               TEA_PATH_NOSPACE(SDKROOT, ${SDKROOT})
+               if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \
+                   -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then
+                   AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]])
+                   doWince="no"
+               else
+                   # We could PATH_NOSPACE these, but that's not important,
+                   # as long as we quote them when used.
+                   CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include"
+                   if test -d "${CEINCLUDE}/${TARGETCPU}" ; then
+                       CEINCLUDE="${CEINCLUDE}/${TARGETCPU}"
+                   fi
+                   CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"
+               fi
+           fi
+
+           if test "$GCC" != "yes" ; then
+               if test "${SHARED_BUILD}" = "0" ; then
+                   runtime=-MT
+               else
+                   runtime=-MD
+               fi
+
+                if test "$do64bit" = "yes" ; then
+                   # All this magic is necessary for the Win64 SDK RC1 - hobbs
+                   CC="${MSSDK}/Bin/Win64/cl.exe"
+                   CFLAGS="${CFLAGS} -I${MSSDK}/Include/prerelease \
+                       -I${MSSDK}/Include/Win64/crt \
+                       -I${MSSDK}/Include"
+                   RC="${MSSDK}/bin/rc.exe"
+                   lflags="-MACHINE:IA64 -LIBPATH:${MSSDK}/Lib/IA64 \
+                       -LIBPATH:${MSSDK}/Lib/Prerelease/IA64 -nologo"
+                   LINKBIN="${MSSDK}/bin/win64/link.exe"
+                   CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d"
+                   CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
+               elif test "$doWince" != "no" ; then
+                   CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin"
+                   if test "${TARGETCPU}" = "X86"; then
+                       CC="${CEBINROOT}/cl.exe"
+                   else
+                       CC="${CEBINROOT}/cl${ARCH}.exe"
+                   fi
+                   CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\""
+                   RC="${WCEROOT}/Common/EVC/bin/rc.exe"
+                   arch=`echo ${ARCH} | awk '{print tolower([$]0)}'`
+                   defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS"
+                   if test "${SHARED_BUILD}" = "1" ; then
+                       # Static CE builds require static celib as well
+                       defs="${defs} _DLL"
+                   fi
+                   for i in $defs ; do
+                       AC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i)
+                   done
+                   AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version])
+                   AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version])
+                   CFLAGS_DEBUG="-nologo -Zi -Od"
+                   CFLAGS_OPTIMIZE="-nologo -Ox"
+                   lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
+                   lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
+                   LINKBIN="${CEBINROOT}/link.exe"
+                   AC_SUBST(CELIB_DIR)
+               else
+                   RC="rc"
+                   lflags="-nologo"
+                   LINKBIN="link"
+                   CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d"
+                   CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
+               fi
+           fi
+
+           if test "$GCC" = "yes"; then
+               # mingw gcc mode
+               RC="windres"
+               CFLAGS_DEBUG="-g"
+               CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
+               SHLIB_LD="$CC -shared"
+               UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+               LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}"
+               LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}"
+           else
+               SHLIB_LD="${LINKBIN} -dll ${lflags}"
+               # link -lib only works when -lib is the first arg
+               STLIB_LD="${LINKBIN} -lib ${lflags}"
+               UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib'
+               PATHTYPE=-w
+               # For information on what debugtype is most useful, see:
+               # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
+               # This essentially turns it all on.
+               LDFLAGS_DEBUG="-debug:full -debugtype:both -warn:2"
+               LDFLAGS_OPTIMIZE="-release"
+               if test "$doWince" != "no" ; then
+                   LDFLAGS_CONSOLE="-link ${lflags}"
+                   LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}
+               else
+                   LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
+                   LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
+               fi
+           fi
+
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".dll"
+           SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll'
+
+           TCL_LIB_VERSIONS_OK=nodots
+           # Bogus to avoid getting this turned off
+           DL_OBJS="tclLoadNone.obj"
+           ;;
+       AIX-*)
+           if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes" ; then
+               # AIX requires the _r compiler when gcc isn't being used
+               if test "${CC}" != "cc_r" ; then
+                   CC=${CC}_r
+               fi
+               AC_MSG_RESULT([Using $CC for compiling with threads])
+           fi
+           LIBS="$LIBS -lc"
+           SHLIB_CFLAGS=""
+           SHLIB_SUFFIX=".so"
+           SHLIB_LD_LIBS='${LIBS}'
+
+           DL_OBJS="tclLoadDl.o"
+           LD_LIBRARY_PATH_VAR="LIBPATH"
+
+           # AIX v<=4.1 has some different flags than 4.2+
+           if test "$system" = "AIX-4.1" -o "`uname -v`" -lt "4" ; then
+               #LIBOBJS="$LIBOBJS tclLoadAix.o"
+               AC_LIBOBJ([tclLoadAix])
+               DL_LIBS="-lld"
+           fi
+
+           # Check to enable 64-bit flags for compiler/linker on AIX 4+
+           if test "$do64bit" = "yes" -a "`uname -v`" -gt "3" ; then
+               if test "$GCC" = "yes" ; then
+                   AC_MSG_WARN("64bit mode not supported with GCC on $system")
+               else 
+                   do64bit_ok=yes
+                   CFLAGS="$CFLAGS -q64"
+                   LDFLAGS="$LDFLAGS -q64"
+                   RANLIB="${RANLIB} -X64"
+                   AR="${AR} -X64"
+                   SHLIB_LD_FLAGS="-b64"
+               fi
+           fi
+
+           if test "`uname -m`" = "ia64" ; then
+               # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
+               SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+               # AIX-5 has dl* in libc.so
+               DL_LIBS=""
+               if test "$GCC" = "yes" ; then
+                   LD_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+               else
+                   LD_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
+               fi
+           else
+               if test "$GCC" = "yes" ; then
+                   SHLIB_LD="gcc -shared"
+               else
+                   SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry"
+               fi
+               SHLIB_LD="${TCL_SRC_DIR}/unix/ldAix ${SHLIB_LD} ${SHLIB_LD_FLAGS}"
+               DL_LIBS="-ldl"
+               LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+               TCL_NEEDS_EXP_FILE=1
+               TCL_EXPORT_FILE_SUFFIX='${PACKAGE_VERSION}.exp'
+           fi
+
+           # On AIX <=v4 systems, libbsd.a has to be linked in to support
+           # non-blocking file IO.  This library has to be linked in after
+           # the MATH_LIBS or it breaks the pow() function.  The way to
+           # insure proper sequencing, is to add it to the tail of MATH_LIBS.
+           # This library also supplies gettimeofday.
+           #
+           # AIX does not have a timezone field in struct tm. When the AIX
+           # bsd library is used, the timezone global and the gettimeofday
+           # methods are to be avoided for timezone deduction instead, we
+           # deduce the timezone by comparing the localtime result on a
+           # known GMT value.
+
+           AC_CHECK_LIB(bsd, gettimeofday, libbsd=yes, libbsd=no)
+           if test $libbsd = yes; then
+               MATH_LIBS="$MATH_LIBS -lbsd"
+               AC_DEFINE(USE_DELTA_FOR_TZ, 1, [Do we need a special AIX hack for timezones?])
+           fi
+           ;;
+       BeOS*)
+           SHLIB_CFLAGS="-fPIC"
+           SHLIB_LD="${CC} -nostart"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           ;;
+       BSD/OS-2.1*|BSD/OS-3*)
+           SHLIB_CFLAGS=""
+           SHLIB_LD="shlicc -r"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           LD_SEARCH_FLAGS=""
+           ;;
+       BSD/OS-4.*)
+           SHLIB_CFLAGS="-export-dynamic -fPIC"
+           SHLIB_LD="cc -shared"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           LDFLAGS="$LDFLAGS -export-dynamic"
+           LD_SEARCH_FLAGS=""
+           ;;
+       dgux*)
+           SHLIB_CFLAGS="-K PIC"
+           SHLIB_LD="cc -G"
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           LD_SEARCH_FLAGS=""
+           ;;
+       HP-UX-*.11.*)
+           # Use updated header definitions where possible
+           AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])
+
+           SHLIB_SUFFIX=".sl"
+           AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
+           if test "$tcl_ok" = yes; then
+               SHLIB_CFLAGS="+z"
+               SHLIB_LD="ld -b"
+               SHLIB_LD_LIBS='${LIBS}'
+               DL_OBJS="tclLoadShl.o"
+               DL_LIBS="-ldld"
+               LDFLAGS="$LDFLAGS -Wl,-E"
+               LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
+               LD_LIBRARY_PATH_VAR="SHLIB_PATH"
+           fi
+           if test "$GCC" = "yes" ; then
+               SHLIB_LD="gcc -shared"
+               SHLIB_LD_LIBS='${LIBS}'
+               LD_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
+           fi
+
+           # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
+           #CFLAGS="$CFLAGS +DAportable"
+
+           # Check to enable 64-bit flags for compiler/linker
+           if test "$do64bit" = "yes" ; then
+               if test "$GCC" = "yes" ; then
+                   hpux_arch=`${CC} -dumpmachine`
+                   case $hpux_arch in
+                       hppa64*)
+                           # 64-bit gcc in use.  Fix flags for GNU ld.
+                           do64bit_ok=yes
+                           SHLIB_LD="${CC} -shared"
+                           SHLIB_LD_LIBS='${LIBS}'
+                           ;;
+                       *)
+                           AC_MSG_WARN("64bit mode not supported with GCC on $system")
+                           ;;
+                   esac
+               else
+                   do64bit_ok=yes
+                   CFLAGS="$CFLAGS +DD64"
+                   LDFLAGS="$LDFLAGS +DD64"
+               fi
+           fi
+           ;;
+       HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)
+           SHLIB_SUFFIX=".sl"
+           AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
+           if test "$tcl_ok" = yes; then
+               SHLIB_CFLAGS="+z"
+               SHLIB_LD="ld -b"
+               SHLIB_LD_LIBS=""
+               DL_OBJS="tclLoadShl.o"
+               DL_LIBS="-ldld"
+               LDFLAGS="$LDFLAGS -Wl,-E"
+               LD_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
+           fi
+           LD_LIBRARY_PATH_VAR="SHLIB_PATH"
+           ;;
+       IRIX-4.*)
+           SHLIB_CFLAGS="-G 0"
+           SHLIB_SUFFIX=".a"
+           SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0"
+           SHLIB_LD_LIBS='${LIBS}'
+           DL_OBJS="tclLoadAout.o"
+           DL_LIBS=""
+           LDFLAGS="$LDFLAGS -Wl,-D,08000000"
+           LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+           SHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'
+           ;;
+       IRIX-5.*)
+           SHLIB_CFLAGS=""
+           SHLIB_LD="ld -shared -rdata_shared"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS=""
+           LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+           ;;
+       IRIX-6.*|IRIX64-6.5*)
+           SHLIB_CFLAGS=""
+           SHLIB_LD="ld -n32 -shared -rdata_shared"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS=""
+           LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+           if test "$GCC" = "yes" ; then
+               CFLAGS="$CFLAGS -mabi=n32"
+               LDFLAGS="$LDFLAGS -mabi=n32"
+           else
+               case $system in
+                   IRIX-6.3)
+                       # Use to build 6.2 compatible binaries on 6.3.
+                       CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS"
+                       ;;
+                   *)
+                       CFLAGS="$CFLAGS -n32"
+                       ;;
+               esac
+               LDFLAGS="$LDFLAGS -n32"
+           fi
+           ;;
+       IRIX64-6.*)
+           SHLIB_CFLAGS=""
+           SHLIB_LD="ld -n32 -shared -rdata_shared"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS=""
+           LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+
+           # Check to enable 64-bit flags for compiler/linker
+
+           if test "$do64bit" = "yes" ; then
+               if test "$GCC" = "yes" ; then
+                   AC_MSG_WARN([64bit mode not supported by gcc])
+               else
+                   do64bit_ok=yes
+                   SHLIB_LD="ld -64 -shared -rdata_shared"
+                   CFLAGS="$CFLAGS -64"
+                   LDFLAGS="$LDFLAGS -64"
+               fi
+           fi
+           ;;
+       Linux*)
+           SHLIB_CFLAGS="-fPIC"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+
+           CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
+           # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings 
+           # when you inline the string and math operations.  Turn this off to
+           # get rid of the warnings.
+
+           #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"
+
+           if test "$have_dl" = yes; then
+               SHLIB_LD="${CC} -shared"
+               DL_OBJS="tclLoadDl.o"
+               DL_LIBS="-ldl"
+               LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+               LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+           else
+               AC_CHECK_HEADER(dld.h, [
+                   SHLIB_LD="ld -shared"
+                   DL_OBJS="tclLoadDld.o"
+                   DL_LIBS="-ldld"
+                   LD_SEARCH_FLAGS=""])
+           fi
+           if test "`uname -m`" = "alpha" ; then
+               CFLAGS="$CFLAGS -mieee"
+           fi
+
+           # The combo of gcc + glibc has a bug related
+           # to inlining of functions like strtod(). The
+           # -fno-builtin flag should address this problem
+           # but it does not work. The -fno-inline flag
+           # is kind of overkill but it works.
+           # Disable inlining only when one of the
+           # files in compat/*.c is being linked in.
+           if test x"${USE_COMPAT}" != x ; then
+               CFLAGS="$CFLAGS -fno-inline"
+           fi
+
+           ;;
+       GNU*)
+           SHLIB_CFLAGS="-fPIC"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+
+           if test "$have_dl" = yes; then
+               SHLIB_LD="${CC} -shared"
+               DL_OBJS=""
+               DL_LIBS="-ldl"
+               LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+               LD_SEARCH_FLAGS=""
+           else
+               AC_CHECK_HEADER(dld.h, [
+                   SHLIB_LD="ld -shared"
+                   DL_OBJS=""
+                   DL_LIBS="-ldld"
+                   LD_SEARCH_FLAGS=""])
+           fi
+           if test "`uname -m`" = "alpha" ; then
+               CFLAGS="$CFLAGS -mieee"
+           fi
+           ;;
+       MP-RAS-02*)
+           SHLIB_CFLAGS="-K PIC"
+           SHLIB_LD="cc -G"
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           LD_SEARCH_FLAGS=""
+           ;;
+       MP-RAS-*)
+           SHLIB_CFLAGS="-K PIC"
+           SHLIB_LD="cc -G"
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           LDFLAGS="$LDFLAGS -Wl,-Bexport"
+           LD_SEARCH_FLAGS=""
+           ;;
+       NetBSD-*|FreeBSD-[[1-2]].*)
+           # Not available on all versions:  check for include file.
+           AC_CHECK_HEADER(dlfcn.h, [
+               # NetBSD/SPARC needs -fPIC, -fpic will not do.
+               SHLIB_CFLAGS="-fPIC"
+               SHLIB_LD="ld -Bshareable -x"
+               SHLIB_LD_LIBS=""
+               SHLIB_SUFFIX=".so"
+               DL_OBJS="tclLoadDl.o"
+               DL_LIBS=""
+               LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+               AC_MSG_CHECKING([for ELF])
+               AC_EGREP_CPP(yes, [
+#ifdef __ELF__
+       yes
+#endif
+               ],
+                   AC_MSG_RESULT([yes])
+                   SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so',
+                   AC_MSG_RESULT([no])
+                   SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'
+               )
+           ], [
+               SHLIB_CFLAGS=""
+               SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r"
+               SHLIB_LD_LIBS='${LIBS}'
+               SHLIB_SUFFIX=".a"
+               DL_OBJS="tclLoadAout.o"
+               DL_LIBS=""
+               LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+               SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+           ])
+
+           # FreeBSD doesn't handle version numbers with dots.
+
+           UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+           TCL_LIB_VERSIONS_OK=nodots
+           ;;
+       OpenBSD-*)
+           SHLIB_LD="${CC} -shared"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS=""
+           LD_SEARCH_FLAGS=""
+           AC_MSG_CHECKING(for ELF)
+           AC_EGREP_CPP(yes, [
+#ifdef __ELF__
+       yes
+#endif
+           ],
+               [AC_MSG_RESULT(yes)
+               SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'],
+               [AC_MSG_RESULT(no)
+               SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0']
+           )
+
+           # OpenBSD doesn't do version numbers with dots.
+           UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+           TCL_LIB_VERSIONS_OK=nodots
+           ;;
+       FreeBSD-*)
+           # FreeBSD 3.* and greater have ELF.
+           SHLIB_CFLAGS="-fPIC"
+           SHLIB_LD="ld -Bshareable -x"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS=""
+           LDFLAGS="$LDFLAGS -export-dynamic"
+           LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+           if test "${TCL_THREADS}" = "1" ; then
+               # The -pthread needs to go in the CFLAGS, not LIBS
+               LIBS=`echo $LIBS | sed s/-pthread//`
+               CFLAGS="$CFLAGS -pthread"
+               LDFLAGS="$LDFLAGS -pthread"
+           fi
+           case $system in
+           FreeBSD-3.*)
+               # FreeBSD-3 doesn't handle version numbers with dots.
+               UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+               SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
+               TCL_LIB_VERSIONS_OK=nodots
+               ;;
+           esac
+           ;;
+       Darwin-*)
+           CFLAGS_OPTIMIZE="-Os"
+           SHLIB_CFLAGS="-fno-common"
+           SHLIB_LD="cc -dynamiclib \${LDFLAGS}"
+           AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
+               hold_ldflags=$LDFLAGS
+               LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
+               AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
+               LDFLAGS=$hold_ldflags])
+           if test $tcl_cv_ld_single_module = yes; then
+               SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
+           fi
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".dylib"
+           DL_OBJS="tclLoadDyld.o"
+           DL_LIBS=""
+           LDFLAGS="$LDFLAGS -prebind"
+           AC_CACHE_CHECK([if ld accepts -search_paths_first flag], tcl_cv_ld_search_paths_first, [
+               hold_ldflags=$LDFLAGS
+               LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+               AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes, tcl_cv_ld_search_paths_first=no)
+               LDFLAGS=$hold_ldflags])
+           if test $tcl_cv_ld_search_paths_first = yes; then
+               LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+           fi
+           LD_SEARCH_FLAGS=""
+           LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
+           ;;
+       NEXTSTEP-*)
+           SHLIB_CFLAGS=""
+           SHLIB_LD="cc -nostdlib -r"
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadNext.o"
+           DL_LIBS=""
+           LD_SEARCH_FLAGS=""
+           ;;
+       OS/390-*)
+           CFLAGS_OPTIMIZE=""          # Optimizer is buggy
+           AC_DEFINE(_OE_SOCKETS, 1,   # needed in sys/socket.h
+               [Should OS/390 do the right thing with sockets?])
+           ;;      
+       OSF1-1.0|OSF1-1.1|OSF1-1.2)
+           # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1
+           SHLIB_CFLAGS=""
+           # Hack: make package name same as library name
+           SHLIB_LD='ld -R -export $@:'
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadOSF.o"
+           DL_LIBS=""
+           LD_SEARCH_FLAGS=""
+           ;;
+       OSF1-1.*)
+           # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2
+           SHLIB_CFLAGS="-fPIC"
+           if test "$SHARED_BUILD" = "1" ; then
+               SHLIB_LD="ld -shared"
+           else
+               SHLIB_LD="ld -non_shared"
+           fi
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS=""
+           LD_SEARCH_FLAGS=""
+           ;;
+       OSF1-V*)
+           # Digital OSF/1
+           SHLIB_CFLAGS=""
+           if test "$SHARED_BUILD" = "1" ; then
+               SHLIB_LD='ld -shared -expect_unresolved "*"'
+           else
+               SHLIB_LD='ld -non_shared -expect_unresolved "*"'
+           fi
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS=""
+           LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+           if test "$GCC" = "yes" ; then
+               CFLAGS="$CFLAGS -mieee"
+            else
+               CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"
+           fi
+           # see pthread_intro(3) for pthread support on osf1, k.furukawa
+           if test "${TCL_THREADS}" = "1" ; then
+               CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
+               CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
+               LIBS=`echo $LIBS | sed s/-lpthreads//`
+               if test "$GCC" = "yes" ; then
+                   LIBS="$LIBS -lpthread -lmach -lexc"
+               else
+                   CFLAGS="$CFLAGS -pthread"
+                   LDFLAGS="$LDFLAGS -pthread"
+               fi
+           fi
+
+           ;;
+       QNX-6*)
+           # QNX RTP
+           # This may work for all QNX, but it was only reported for v6.
+           SHLIB_CFLAGS="-fPIC"
+           SHLIB_LD="ld -Bshareable -x"
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           # dlopen is in -lc on QNX
+           DL_LIBS=""
+           LD_SEARCH_FLAGS=""
+           ;;
+       RISCos-*)
+           SHLIB_CFLAGS="-G 0"
+           SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0"
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".a"
+           DL_OBJS="tclLoadAout.o"
+           DL_LIBS=""
+           LDFLAGS="$LDFLAGS -Wl,-D,08000000"
+           LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+           ;;
+       SCO_SV-3.2*)
+           # Note, dlopen is available only on SCO 3.2.5 and greater. However,
+           # this test works, since "uname -s" was non-standard in 3.2.4 and
+           # below.
+           if test "$GCC" = "yes" ; then
+               SHLIB_CFLAGS="-fPIC -melf"
+               LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
+           else
+               SHLIB_CFLAGS="-Kpic -belf"
+               LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
+           fi
+           SHLIB_LD="ld -G"
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS=""
+           LD_SEARCH_FLAGS=""
+           ;;
+       SINIX*5.4*)
+           SHLIB_CFLAGS="-K PIC"
+           SHLIB_LD="cc -G"
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           LD_SEARCH_FLAGS=""
+           ;;
+       SunOS-4*)
+           SHLIB_CFLAGS="-PIC"
+           SHLIB_LD="ld"
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+
+           # SunOS can't handle version numbers with dots in them in library
+           # specs, like -ltcl7.5, so use -ltcl75 instead.  Also, it
+           # requires an extra version number at the end of .so file names.
+           # So, the library has to have a name like libtcl75.so.1.0
+
+           SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.1.0'
+           UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+           TCL_LIB_VERSIONS_OK=nodots
+           ;;
+       SunOS-5.[[0-6]]*)
+
+           # Note: If _REENTRANT isn't defined, then Solaris
+           # won't define thread-safe library routines.
+
+           AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
+           AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
+               [Do we really want to follow the standard? Yes we do!])
+
+           SHLIB_CFLAGS="-KPIC"
+
+           # Note: need the LIBS below, otherwise Tk won't find Tcl's
+           # symbols when dynamically loaded into tclsh.
+
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           if test "$GCC" = "yes" ; then
+               SHLIB_LD="$CC -shared"
+               LD_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+           else
+               SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+               LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+           fi
+           ;;
+       SunOS-5*)
+
+           # Note: If _REENTRANT isn't defined, then Solaris
+           # won't define thread-safe library routines.
+
+           AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
+           AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
+               [Do we really want to follow the standard? Yes we do!])
+
+           SHLIB_CFLAGS="-KPIC"
+    
+           # Check to enable 64-bit flags for compiler/linker
+           if test "$do64bit" = "yes" ; then
+               arch=`isainfo`
+               if test "$arch" = "sparcv9 sparc" ; then
+                       if test "$GCC" = "yes" ; then
+                           if test "`gcc -dumpversion` | awk -F. '{print $1}'" -lt "3" ; then
+                               AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])
+                           else
+                               do64bit_ok=yes
+                               CFLAGS="$CFLAGS -m64 -mcpu=v9"
+                               LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
+                               SHLIB_CFLAGS="-fPIC"
+                           fi
+                       else
+                           do64bit_ok=yes
+                           if test "$do64bitVIS" = "yes" ; then
+                               CFLAGS="$CFLAGS -xarch=v9a"
+                               LDFLAGS="$LDFLAGS -xarch=v9a"
+                           else
+                               CFLAGS="$CFLAGS -xarch=v9"
+                               LDFLAGS="$LDFLAGS -xarch=v9"
+                           fi
+                       fi
+               else
+                   AC_MSG_WARN("64bit mode only supported sparcv9 system")
+               fi
+           fi
+           
+           # Note: need the LIBS below, otherwise Tk won't find Tcl's
+           # symbols when dynamically loaded into tclsh.
+
+           SHLIB_LD_LIBS='${LIBS}'
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           if test "$GCC" = "yes" ; then
+               SHLIB_LD="$CC -shared"
+               LD_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+               if test "$do64bit" = "yes" ; then
+                   # We need to specify -static-libgcc or we need to
+                   # add the path to the sparv9 libgcc.
+                   # JH: static-libgcc is necessary for core Tcl, but may
+                   # not be necessary for extensions.
+                   SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc"
+                   # for finding sparcv9 libgcc, get the regular libgcc
+                   # path, remove so name and append 'sparcv9'
+                   #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..."
+                   #LD_SEARCH_FLAGS="${LD_SEARCH_FLAGS},-R,$v9gcclibdir"
+               fi
+           else
+               SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+               LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+           fi
+           ;;
+       ULTRIX-4.*)
+           SHLIB_CFLAGS="-G 0"
+           SHLIB_SUFFIX=".a"
+           SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0"
+           SHLIB_LD_LIBS='${LIBS}'
+           DL_OBJS="tclLoadAout.o"
+           DL_LIBS=""
+           LDFLAGS="$LDFLAGS -Wl,-D,08000000"
+           LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+           if test "$GCC" != "yes" ; then
+               CFLAGS="$CFLAGS -DHAVE_TZSET -std1"
+           fi
+           ;;
+       UNIX_SV* | UnixWare-5*)
+           SHLIB_CFLAGS="-KPIC"
+           SHLIB_LD="cc -G"
+           SHLIB_LD_LIBS=""
+           SHLIB_SUFFIX=".so"
+           DL_OBJS="tclLoadDl.o"
+           DL_LIBS="-ldl"
+           # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
+           # that don't grok the -Bexport option.  Test that it does.
+           hold_ldflags=$LDFLAGS
+           AC_MSG_CHECKING(for ld accepts -Bexport flag)
+           LDFLAGS="$LDFLAGS -Wl,-Bexport"
+           AC_TRY_LINK(, [int i;], [found=yes],
+                       [LDFLAGS=$hold_ldflags found=no])
+           AC_MSG_RESULT([$found])
+           LD_SEARCH_FLAGS=""
+           ;;
+    esac
+
+    if test "$do64bit" = "yes" -a "$do64bit_ok" = "no" ; then
+    AC_MSG_WARN("64bit support being disabled -- don\'t know magic for this platform")
+    fi
+
+    # Step 4: If pseudo-static linking is in use (see K. B. Kenny, "Dynamic
+    # Loading for Tcl -- What Became of It?".  Proc. 2nd Tcl/Tk Workshop,
+    # New Orleans, LA, Computerized Processes Unlimited, 1994), then we need
+    # to determine which of several header files defines the a.out file
+    # format (a.out.h, sys/exec.h, or sys/exec_aout.h).  At present, we
+    # support only a file format that is more or less version-7-compatible. 
+    # In particular,
+    #  - a.out files must begin with `struct exec'.
+    #  - the N_TXTOFF on the `struct exec' must compute the seek address
+    #    of the text segment
+    #  - The `struct exec' must contain a_magic, a_text, a_data, a_bss
+    #    and a_entry fields.
+    # The following compilation should succeed if and only if either sys/exec.h
+    # or a.out.h is usable for the purpose.
+    #
+    # Note that the modified COFF format used on MIPS Ultrix 4.x is usable; the
+    # `struct exec' includes a second header that contains information that
+    # duplicates the v7 fields that are needed.
+
+    if test "x$DL_OBJS" = "xtclLoadAout.o" ; then
+       AC_MSG_CHECKING([sys/exec.h])
+       AC_TRY_COMPILE([#include <sys/exec.h>],[
+           struct exec foo;
+           unsigned long seek;
+           int flag;
+#if defined(__mips) || defined(mips)
+           seek = N_TXTOFF (foo.ex_f, foo.ex_o);
+#else
+           seek = N_TXTOFF (foo);
+#endif
+           flag = (foo.a_magic == OMAGIC);
+           return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry;
+    ], tcl_ok=usable, tcl_ok=unusable)
+       AC_MSG_RESULT([$tcl_ok])
+       if test $tcl_ok = usable; then
+           AC_DEFINE(USE_SYS_EXEC_H, 1,
+               [Should we use <sys/exec.h> when doing dynamic loading?])
+       else
+           AC_MSG_CHECKING([a.out.h])
+           AC_TRY_COMPILE([#include <a.out.h>],[
+               struct exec foo;
+               unsigned long seek;
+               int flag;
+#if defined(__mips) || defined(mips)
+               seek = N_TXTOFF (foo.ex_f, foo.ex_o);
+#else
+               seek = N_TXTOFF (foo);
+#endif
+               flag = (foo.a_magic == OMAGIC);
+               return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry;
+           ], tcl_ok=usable, tcl_ok=unusable)
+           AC_MSG_RESULT([$tcl_ok])
+           if test $tcl_ok = usable; then
+               AC_DEFINE(USE_A_OUT_H, 1,
+                   [Should we use <a.out.h> when doing dynamic loading?])
+           else
+               AC_MSG_CHECKING([sys/exec_aout.h])
+               AC_TRY_COMPILE([#include <sys/exec_aout.h>],[
+                   struct exec foo;
+                   unsigned long seek;
+                   int flag;
+#if defined(__mips) || defined(mips)
+                   seek = N_TXTOFF (foo.ex_f, foo.ex_o);
+#else
+                   seek = N_TXTOFF (foo);
+#endif
+                   flag = (foo.a_midmag == OMAGIC);
+                   return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry;
+               ], tcl_ok=usable, tcl_ok=unusable)
+               AC_MSG_RESULT([$tcl_ok])
+               if test $tcl_ok = usable; then
+                   AC_DEFINE(USE_SYS_EXEC_AOUT_H, 1,
+                       [Should we use <sys/exec_aout.h> when doing dynamic loading?])
+               else
+                   DL_OBJS=""
+               fi
+           fi
+       fi
+    fi
+
+    # Step 5: disable dynamic loading if requested via a command-line switch.
+
+    AC_ARG_ENABLE(load, [  --disable-load          disallow dynamic loading and "load" command],
+       [tcl_ok=$enableval], [tcl_ok=yes])
+    if test "$tcl_ok" = "no"; then
+       DL_OBJS=""
+    fi
+
+    if test "x$DL_OBJS" != "x" ; then
+       BUILD_DLTEST="\$(DLTEST_TARGETS)"
+    else
+       echo "Can't figure out how to do dynamic loading or shared libraries"
+       echo "on this system."
+       SHLIB_CFLAGS=""
+       SHLIB_LD=""
+       SHLIB_SUFFIX=""
+       DL_OBJS="tclLoadNone.o"
+       DL_LIBS=""
+       LDFLAGS="$LDFLAGS_ORIG"
+       LD_SEARCH_FLAGS=""
+       BUILD_DLTEST=""
+    fi
+
+    # If we're running gcc, then change the C flags for compiling shared
+    # libraries to the right flags for gcc, instead of those for the
+    # standard manufacturer compiler.
+
+    if test "$DL_OBJS" != "tclLoadNone.o" ; then
+       if test "$GCC" = "yes" ; then
+           case $system in
+               AIX-*)
+                   ;;
+               BSD/OS*)
+                   ;;
+               IRIX*)
+                   ;;
+               NetBSD-*|FreeBSD-*)
+                   ;;
+               Darwin-*)
+                   ;;
+               RISCos-*)
+                   ;;
+               SCO_SV-3.2*)
+                   ;;
+               ULTRIX-4.*)
+                   ;;
+               windows)
+                   ;;
+               *)
+                   SHLIB_CFLAGS="-fPIC"
+                   ;;
+           esac
+       fi
+    fi
+
+    if test "$SHARED_LIB_SUFFIX" = "" ; then
+       SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}'
+    fi
+    if test "$UNSHARED_LIB_SUFFIX" = "" ; then
+       UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'
+    fi
+
+    AC_SUBST(DL_LIBS)
+    AC_SUBST(CFLAGS_DEBUG)
+    AC_SUBST(CFLAGS_OPTIMIZE)
+    AC_SUBST(CFLAGS_WARNING)
+
+    AC_SUBST(STLIB_LD)
+    AC_SUBST(SHLIB_LD)
+    AC_SUBST(SHLIB_CFLAGS)
+    AC_SUBST(SHLIB_LD_LIBS)
+    AC_SUBST(LDFLAGS_DEBUG)
+    AC_SUBST(LDFLAGS_OPTIMIZE)
+    AC_SUBST(LD_LIBRARY_PATH_VAR)
+
+    # These must be called after we do the basic CFLAGS checks and
+    # verify any possible 64-bit or similar switches are necessary
+    TEA_TCL_EARLY_FLAGS
+    TEA_TCL_64BIT_FLAGS
+])
+
+#--------------------------------------------------------------------
+# TEA_SERIAL_PORT
+#
+#      Determine which interface to use to talk to the serial port.
+#      Note that #include lines must begin in leftmost column for
+#      some compilers to recognize them as preprocessor directives,
+#      and some build environments have stdin not pointing at a
+#      pseudo-terminal (usually /dev/null instead.)
+#
+# Arguments:
+#      none
+#      
+# Results:
+#
+#      Defines only one of the following vars:
+#              HAVE_SYS_MODEM_H
+#              USE_TERMIOS
+#              USE_TERMIO
+#              USE_SGTTY
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN(TEA_SERIAL_PORT, [
+    AC_CHECK_HEADERS(sys/modem.h)
+    AC_MSG_CHECKING([termios vs. termio vs. sgtty])
+    AC_CACHE_VAL(tcl_cv_api_serial, [
+    AC_TRY_RUN([
+#include <termios.h>
+
+int main() {
+    struct termios t;
+    if (tcgetattr(0, &t) == 0) {
+       cfsetospeed(&t, 0);
+       t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
+       return 0;
+    }
+    return 1;
+}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
+    if test $tcl_cv_api_serial = no ; then
+       AC_TRY_RUN([
+#include <termio.h>
+
+int main() {
+    struct termio t;
+    if (ioctl(0, TCGETA, &t) == 0) {
+       t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
+       return 0;
+    }
+    return 1;
+}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
+    fi
+    if test $tcl_cv_api_serial = no ; then
+       AC_TRY_RUN([
+#include <sgtty.h>
+
+int main() {
+    struct sgttyb t;
+    if (ioctl(0, TIOCGETP, &t) == 0) {
+       t.sg_ospeed = 0;
+       t.sg_flags |= ODDP | EVENP | RAW;
+       return 0;
+    }
+    return 1;
+}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none)
+    fi
+    if test $tcl_cv_api_serial = no ; then
+       AC_TRY_RUN([
+#include <termios.h>
+#include <errno.h>
+
+int main() {
+    struct termios t;
+    if (tcgetattr(0, &t) == 0
+       || errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
+       cfsetospeed(&t, 0);
+       t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
+       return 0;
+    }
+    return 1;
+}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
+    fi
+    if test $tcl_cv_api_serial = no; then
+       AC_TRY_RUN([
+#include <termio.h>
+#include <errno.h>
+
+int main() {
+    struct termio t;
+    if (ioctl(0, TCGETA, &t) == 0
+       || errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
+       t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
+       return 0;
+    }
+    return 1;
+    }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
+    fi
+    if test $tcl_cv_api_serial = no; then
+       AC_TRY_RUN([
+#include <sgtty.h>
+#include <errno.h>
+
+int main() {
+    struct sgttyb t;
+    if (ioctl(0, TIOCGETP, &t) == 0
+       || errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
+       t.sg_ospeed = 0;
+       t.sg_flags |= ODDP | EVENP | RAW;
+       return 0;
+    }
+    return 1;
+}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none)
+    fi])
+    case $tcl_cv_api_serial in
+       termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);;
+       termio)  AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);;
+       sgtty)   AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);;
+    esac
+    AC_MSG_RESULT([$tcl_cv_api_serial])
+])
+
+#--------------------------------------------------------------------
+# TEA_MISSING_POSIX_HEADERS
+#
+#      Supply substitutes for missing POSIX header files.  Special
+#      notes:
+#          - stdlib.h doesn't define strtol, strtoul, or
+#            strtod insome versions of SunOS
+#          - some versions of string.h don't declare procedures such
+#            as strstr
+#
+# Arguments:
+#      none
+#      
+# Results:
+#
+#      Defines some of the following vars:
+#              NO_DIRENT_H
+#              NO_ERRNO_H
+#              NO_VALUES_H
+#              HAVE_LIMITS_H or NO_LIMITS_H
+#              NO_STDLIB_H
+#              NO_STRING_H
+#              NO_SYS_WAIT_H
+#              NO_DLFCN_H
+#              HAVE_SYS_PARAM_H
+#
+#              HAVE_STRING_H ?
+#
+# tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and
+# CHECK on limits.h
+#--------------------------------------------------------------------
+
+AC_DEFUN(TEA_MISSING_POSIX_HEADERS, [
+    AC_MSG_CHECKING([dirent.h])
+    AC_CACHE_VAL(tcl_cv_dirent_h,
+    AC_TRY_LINK([#include <sys/types.h>
+#include <dirent.h>], [
+#ifndef _POSIX_SOURCE
+#   ifdef __Lynx__
+       /*
+        * Generate compilation error to make the test fail:  Lynx headers
+        * are only valid if really in the POSIX environment.
+        */
+
+       missing_procedure();
+#   endif
+#endif
+DIR *d;
+struct dirent *entryPtr;
+char *p;
+d = opendir("foobar");
+entryPtr = readdir(d);
+p = entryPtr->d_name;
+closedir(d);
+], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no))
+
+    if test $tcl_cv_dirent_h = no; then
+       AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
+    fi
+
+    AC_MSG_RESULT([$tcl_ok])
+    AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])])
+    AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
+    AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
+    AC_CHECK_HEADER(limits.h,
+       [AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have <limits.h>?])],
+       [AC_DEFINE(NO_LIMITS_H, 1, [Do we have <limits.h>?])])
+    AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0)
+    AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0)
+    AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0)
+    AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0)
+    if test $tcl_ok = 0; then
+       AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])
+    fi
+    AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)
+    AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)
+    AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)
+
+    # See also memmove check below for a place where NO_STRING_H can be
+    # set and why.
+
+    if test $tcl_ok = 0; then
+       AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])
+    fi
+
+    AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])
+    AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])
+
+    # OS/390 lacks sys/param.h (and doesn't need it, by chance).
+    AC_HAVE_HEADERS(sys/param.h)
+
+])
+
+#--------------------------------------------------------------------
+# TEA_PATH_X
+#
+#      Locate the X11 header files and the X11 library archive.  Try
+#      the ac_path_x macro first, but if it doesn't find the X stuff
+#      (e.g. because there's no xmkmf program) then check through
+#      a list of possible directories.  Under some conditions the
+#      autoconf macro will return an include directory that contains
+#      no include files, so double-check its result just to be safe.
+#
+#      This should be called after TEA_CONFIG_CFLAGS as setting the
+#      LIBS line can confuse some configure macro magic.
+#
+# Arguments:
+#      none
+#      
+# Results:
+#
+#      Sets the following vars:
+#              XINCLUDES
+#              XLIBSW
+#              LIBS (appends to)
+#              TEA_WINDOWINGSYSTEM
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN(TEA_PATH_X, [
+    if test "${TEA_PLATFORM}" = "unix" ; then
+       case ${TK_DEFS} in
+           *MAC_OSX_TK*)
+               AC_DEFINE(MAC_OSX_TK, 1 [Are we building against Mac OS X TkAqua?])
+               TEA_WINDOWINGSYSTEM="aqua"
+                if test -z "${ac_cv_c_tkh}" -o ! -r "${ac_cv_c_tkh}/X11/Xlib.h"; then
+                    TK_XINCLUDES='-I${TK_SRC_DIR}/xlib'
+                fi
+               ;;
+           *)
+               TEA_PATH_UNIX_X
+               TEA_WINDOWINGSYSTEM="x11"
+               ;;
+       esac
+    elif test "${TEA_PLATFORM}" = "windows" ; then
+       TEA_WINDOWINGSYSTEM="windows"
+    fi
+])
+
+AC_DEFUN(TEA_PATH_UNIX_X, [
+    AC_PATH_X
+    not_really_there=""
+    if test "$no_x" = ""; then
+       if test "$x_includes" = ""; then
+           AC_TRY_CPP([#include <X11/XIntrinsic.h>], , not_really_there="yes")
+       else
+           if test ! -r $x_includes/X11/Intrinsic.h; then
+               not_really_there="yes"
+           fi
+       fi
+    fi
+    if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
+       AC_MSG_CHECKING([for X11 header files])
+       XINCLUDES="# no special path needed"
+       AC_TRY_CPP([#include <X11/Intrinsic.h>], , XINCLUDES="nope")
+       if test "$XINCLUDES" = nope; then
+           dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
+           for i in $dirs ; do
+               if test -r $i/X11/Intrinsic.h; then
+                   AC_MSG_RESULT([$i])
+                   XINCLUDES=" -I$i"
+                   break
+               fi
+           done
+       fi
+    else
+       if test "$x_includes" != ""; then
+           XINCLUDES=-I$x_includes
+       else
+           XINCLUDES="# no special path needed"
+       fi
+    fi
+    if test "$XINCLUDES" = nope; then
+       AC_MSG_RESULT([could not find any!])
+       XINCLUDES="# no include files found"
+    fi
+
+    if test "$no_x" = yes; then
+       AC_MSG_CHECKING([for X11 libraries])
+       XLIBSW=nope
+       dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib"
+       for i in $dirs ; do
+           if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl; then
+               AC_MSG_RESULT([$i])
+               XLIBSW="-L$i -lX11"
+               x_libraries="$i"
+               break
+           fi
+       done
+    else
+       if test "$x_libraries" = ""; then
+           XLIBSW=-lX11
+       else
+           XLIBSW="-L$x_libraries -lX11"
+       fi
+    fi
+    if test "$XLIBSW" = nope ; then
+       AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow)
+    fi
+    if test "$XLIBSW" = nope ; then
+       AC_MSG_RESULT([could not find any!  Using -lX11.])
+       XLIBSW=-lX11
+    fi
+    if test x"${XLIBSW}" != x ; then
+       PKG_LIBS="${PKG_LIBS} ${XLIBSW}"
+    fi
+])
+
+#--------------------------------------------------------------------
+# TEA_BLOCKING_STYLE
+#
+#      The statements below check for systems where POSIX-style
+#      non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. 
+#      On these systems (mostly older ones), use the old BSD-style
+#      FIONBIO approach instead.
+#
+# Arguments:
+#      none
+#      
+# Results:
+#
+#      Defines some of the following vars:
+#              HAVE_SYS_IOCTL_H
+#              HAVE_SYS_FILIO_H
+#              USE_FIONBIO
+#              O_NONBLOCK
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN(TEA_BLOCKING_STYLE, [
+    AC_CHECK_HEADERS(sys/ioctl.h)
+    AC_CHECK_HEADERS(sys/filio.h)
+    AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O])
+    if test -f /usr/lib/NextStep/software_version; then
+       system=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version`
+    else
+       system=`uname -s`-`uname -r`
+       if test "$?" -ne 0 ; then
+           system=unknown
+       else
+           # Special check for weird MP-RAS system (uname returns weird
+           # results, and the version is kept in special file).
+       
+           if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then
+               system=MP-RAS-`awk '{print $3}' /etc/.relid'`
+           fi
+           if test "`uname -s`" = "AIX" ; then
+               system=AIX-`uname -v`.`uname -r`
+           fi
+       fi
+    fi
+    case $system in
+       # There used to be code here to use FIONBIO under AIX.  However, it
+       # was reported that FIONBIO doesn't work under AIX 3.2.5.  Since
+       # using O_NONBLOCK seems fine under AIX 4.*, I removed the FIONBIO
+       # code (JO, 5/31/97).
+
+       OSF*)
+           AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
+           AC_MSG_RESULT([FIONBIO])
+           ;;
+       SunOS-4*)
+           AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
+           AC_MSG_RESULT([FIONBIO])
+           ;;
+       ULTRIX-4.*)
+           AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
+           AC_MSG_RESULT([FIONBIO])
+           ;;
+       *)
+           AC_MSG_RESULT([O_NONBLOCK])
+           ;;
+    esac
+])
+
+#--------------------------------------------------------------------
+# TEA_TIME_HANLDER
+#
+#      Checks how the system deals with time.h, what time structures
+#      are used on the system, and what fields the structures have.
+#
+# Arguments:
+#      none
+#      
+# Results:
+#
+#      Defines some of the following vars:
+#              USE_DELTA_FOR_TZ
+#              HAVE_TM_GMTOFF
+#              HAVE_TM_TZADJ
+#              HAVE_TIMEZONE_VAR
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN(TEA_TIME_HANDLER, [
+    AC_CHECK_HEADERS(sys/time.h)
+    AC_HEADER_TIME
+    AC_STRUCT_TIMEZONE
+
+    AC_CHECK_FUNCS(gmtime_r localtime_r)
+
+    AC_MSG_CHECKING([tm_tzadj in struct tm])
+    AC_CACHE_VAL(tcl_cv_member_tm_tzadj,
+       AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
+           tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no))
+    AC_MSG_RESULT([$tcl_cv_member_tm_tzadj])
+    if test $tcl_cv_member_tm_tzadj = yes ; then
+       AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
+    fi
+
+    AC_MSG_CHECKING([tm_gmtoff in struct tm])
+    AC_CACHE_VAL(tcl_cv_member_tm_gmtoff,
+       AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],
+           tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no))
+    AC_MSG_RESULT([$tcl_cv_member_tm_gmtoff])
+    if test $tcl_cv_member_tm_gmtoff = yes ; then
+       AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
+    fi
+
+    #
+    # Its important to include time.h in this check, as some systems
+    # (like convex) have timezone functions, etc.
+    #
+    AC_MSG_CHECKING([long timezone variable])
+    AC_CACHE_VAL(tcl_cv_var_timezone,
+       AC_TRY_COMPILE([#include <time.h>],
+           [extern long timezone;
+           timezone += 1;
+           exit (0);],
+           tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no))
+    AC_MSG_RESULT([$tcl_cv_timezone_long])
+    if test $tcl_cv_timezone_long = yes ; then
+       AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
+    else
+       #
+       # On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
+       #
+       AC_MSG_CHECKING([time_t timezone variable])
+       AC_CACHE_VAL(tcl_cv_timezone_time,
+           AC_TRY_COMPILE([#include <time.h>],
+               [extern time_t timezone;
+               timezone += 1;
+               exit (0);],
+               tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no))
+       AC_MSG_RESULT([$tcl_cv_timezone_time])
+       if test $tcl_cv_timezone_time = yes ; then
+           AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
+       fi
+    fi
+])
+
+#--------------------------------------------------------------------
+# TEA_BUGGY_STRTOD
+#
+#      Under Solaris 2.4, strtod returns the wrong value for the
+#      terminating character under some conditions.  Check for this
+#      and if the problem exists use a substitute procedure
+#      "fixstrtod" (provided by Tcl) that corrects the error.
+#      Also, on Compaq's Tru64 Unix 5.0,
+#      strtod(" ") returns 0.0 instead of a failure to convert.
+#
+# Arguments:
+#      none
+#      
+# Results:
+#
+#      Might defines some of the following vars:
+#              strtod (=fixstrtod)
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN(TEA_BUGGY_STRTOD, [
+    AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0)
+    if test "$tcl_strtod" = 1; then
+       AC_MSG_CHECKING([for Solaris2.4/Tru64 strtod bugs])
+       AC_CACHE_VAL(tcl_cv_strtod_buggy,[
+       AC_TRY_RUN([
+           extern double strtod();
+           int main()
+           {
+               char *string = "NaN", *spaceString = " ";
+               char *term;
+               double value;
+               value = strtod(string, &term);
+               if ((term != string) && (term[-1] == 0)) {
+                   exit(1);
+               }
+               value = strtod(spaceString, &term);
+               if (term == (spaceString+1)) {
+                   exit(1);
+               }
+               exit(0);
+           }], tcl_cv_strtod_buggy=1, tcl_cv_strtod_buggy=0, tcl_cv_strtod_buggy=0)])
+       if test "$tcl_cv_strtod_buggy" = 1; then
+           AC_MSG_RESULT([ok])
+       else
+           AC_MSG_RESULT([buggy])
+           #LIBOBJS="$LIBOBJS fixstrtod.o"
+           AC_LIBOBJ([fixstrtod])
+           USE_COMPAT=1
+           AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])
+       fi
+    fi
+])
+
+#--------------------------------------------------------------------
+# TEA_TCL_LINK_LIBS
+#
+#      Search for the libraries needed to link the Tcl shell.
+#      Things like the math library (-lm) and socket stuff (-lsocket vs.
+#      -lnsl) are dealt with here.
+#
+# Arguments:
+#      Requires the following vars to be set in the Makefile:
+#              DL_LIBS
+#              LIBS
+#              MATH_LIBS
+#      
+# Results:
+#
+#      Subst's the following var:
+#              TCL_LIBS
+#              MATH_LIBS
+#
+#      Might append to the following vars:
+#              LIBS
+#
+#      Might define the following vars:
+#              HAVE_NET_ERRNO_H
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN(TEA_TCL_LINK_LIBS, [
+    #--------------------------------------------------------------------
+    # On a few very rare systems, all of the libm.a stuff is
+    # already in libc.a.  Set compiler flags accordingly.
+    # Also, Linux requires the "ieee" library for math to work
+    # right (and it must appear before "-lm").
+    #--------------------------------------------------------------------
+
+    AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm")
+    AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"])
+
+    #--------------------------------------------------------------------
+    # Interactive UNIX requires -linet instead of -lsocket, plus it
+    # needs net/errno.h to define the socket-related error codes.
+    #--------------------------------------------------------------------
+
+    AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"])
+    AC_CHECK_HEADER(net/errno.h, [
+       AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])])
+
+    #--------------------------------------------------------------------
+    #  Check for the existence of the -lsocket and -lnsl libraries.
+    #  The order here is important, so that they end up in the right
+    #  order in the command line generated by make.  Here are some
+    #  special considerations:
+    #  1. Use "connect" and "accept" to check for -lsocket, and
+    #     "gethostbyname" to check for -lnsl.
+    #  2. Use each function name only once:  can't redo a check because
+    #     autoconf caches the results of the last check and won't redo it.
+    #  3. Use -lnsl and -lsocket only if they supply procedures that
+    #     aren't already present in the normal libraries.  This is because
+    #     IRIX 5.2 has libraries, but they aren't needed and they're
+    #     bogus:  they goof up name resolution if used.
+    #  4. On some SVR4 systems, can't use -lsocket without -lnsl too.
+    #     To get around this problem, check for both libraries together
+    #     if -lsocket doesn't work by itself.
+    #--------------------------------------------------------------------
+
+    tcl_checkBoth=0
+    AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1)
+    if test "$tcl_checkSocket" = 1; then
+       AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt,
+           LIBS="$LIBS -lsocket", tcl_checkBoth=1)])
+    fi
+    if test "$tcl_checkBoth" = 1; then
+       tk_oldLibs=$LIBS
+       LIBS="$LIBS -lsocket -lnsl"
+       AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])
+    fi
+    AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
+           [LIBS="$LIBS -lnsl"])])
+    
+    # Don't perform the eval of the libraries here because DL_LIBS
+    # won't be set until we call TEA_CONFIG_CFLAGS
+
+    TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'
+    AC_SUBST(TCL_LIBS)
+    AC_SUBST(MATH_LIBS)
+])
+
+#--------------------------------------------------------------------
+# TEA_TCL_EARLY_FLAGS
+#
+#      Check for what flags are needed to be passed so the correct OS
+#      features are available.
+#
+# Arguments:
+#      None
+#      
+# Results:
+#
+#      Might define the following vars:
+#              _ISOC99_SOURCE
+#              _LARGEFILE64_SOURCE
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN(TEA_TCL_EARLY_FLAG,[
+    AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),
+       AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
+           AC_TRY_COMPILE([[#define ]$1[ 1
+]$2], $3,
+               [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
+               [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)))
+    if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
+       AC_DEFINE($1, 1, [Add the ]$1[ flag when building])
+       tcl_flags="$tcl_flags $1"
+    fi
+])
+
+AC_DEFUN(TEA_TCL_EARLY_FLAGS,[
+    AC_MSG_CHECKING([for required early compiler flags])
+    tcl_flags=""
+    TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>],
+       [char *p = (char *)strtoll; char *q = (char *)strtoull;])
+    TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],
+       [struct stat64 buf; int i = stat64("/", &buf);])
+    if test "x${tcl_flags}" = "x" ; then
+       AC_MSG_RESULT([none])
+    else
+       AC_MSG_RESULT([${tcl_flags}])
+    fi
+])
+
+#--------------------------------------------------------------------
+# TEA_TCL_64BIT_FLAGS
+#
+#      Check for what is defined in the way of 64-bit features.
+#
+# Arguments:
+#      None
+#      
+# Results:
+#
+#      Might define the following vars:
+#              TCL_WIDE_INT_IS_LONG
+#              TCL_WIDE_INT_TYPE
+#              HAVE_STRUCT_DIRENT64
+#              HAVE_STRUCT_STAT64
+#              HAVE_TYPE_OFF64_T
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN(TEA_TCL_64BIT_FLAGS, [
+    AC_MSG_CHECKING([for 64-bit integer type])
+    AC_CACHE_VAL(tcl_cv_type_64bit,[
+       tcl_cv_type_64bit=none
+       # See if the compiler knows natively about __int64
+       AC_TRY_COMPILE(,[__int64 value = (__int64) 0;],
+           tcl_type_64bit=__int64, tcl_type_64bit="long long")
+       # See if we should use long anyway  Note that we substitute in the
+       # type that is our current guess for a 64-bit type inside this check
+       # program, so it should be modified only carefully...
+        AC_TRY_COMPILE(,[switch (0) { 
+            case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ; 
+        }],tcl_cv_type_64bit=${tcl_type_64bit})])
+    if test "${tcl_cv_type_64bit}" = none ; then
+       AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])
+       AC_MSG_RESULT([using long])
+    elif test "${tcl_cv_type_64bit}" = "__int64" \
+               -a "${TEA_PLATFORM}" = "windows" ; then
+       # We actually want to use the default tcl.h checks in this
+       # case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER*
+       AC_MSG_RESULT([using Tcl header defaults])
+    else
+       AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
+           [What type should be used to define wide integers?])
+       AC_MSG_RESULT([${tcl_cv_type_64bit}])
+
+       # Now check for auxiliary declarations
+       AC_MSG_CHECKING([for struct dirent64])
+       AC_CACHE_VAL(tcl_cv_struct_dirent64,[
+           AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/dirent.h>],[struct dirent64 p;],
+               tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)])
+       if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
+           AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])
+       fi
+       AC_MSG_RESULT([${tcl_cv_struct_dirent64}])
+
+       AC_MSG_CHECKING([for struct stat64])
+       AC_CACHE_VAL(tcl_cv_struct_stat64,[
+           AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p;
+],
+               tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)])
+       if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
+           AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])
+       fi
+       AC_MSG_RESULT([${tcl_cv_struct_stat64}])
+
+       AC_MSG_CHECKING([for off64_t])
+       AC_CACHE_VAL(tcl_cv_type_off64_t,[
+           AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset;
+],
+               tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)])
+       if test "x${tcl_cv_type_off64_t}" = "xyes" ; then
+           AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
+       fi
+       AC_MSG_RESULT([${tcl_cv_type_off64_t}])
+    fi
+])
+
+##
+## Here ends the standard Tcl configuration bits and starts the
+## TEA specific functions
+##
+
+#------------------------------------------------------------------------
+# TEA_INIT --
+#
+#      Init various Tcl Extension Architecture (TEA) variables.
+#      This should be the first called TEA_* macro.
+#
+# Arguments:
+#      none
+#
+# Results:
+#
+#      Defines and substs the following vars:
+#              CYGPATH
+#              EXEEXT
+#      Defines only:
+#              TEA_INITED
+#              TEA_PLATFORM (windows or unix)
+#
+# "cygpath" is used on windows to generate native path names for include
+# files. These variables should only be used with the compiler and linker
+# since they generate native path names.
+#
+# EXEEXT
+#      Select the executable extension based on the host type.  This
+#      is a lightweight replacement for AC_EXEEXT that doesn't require
+#      a compiler.
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_INIT, [
+    # TEA extensions pass this us the version of TEA they think they
+    # are compatible with.
+    TEA_VERSION="3.2"
+
+    AC_MSG_CHECKING([for correct TEA configuration])
+    if test x"${PACKAGE_NAME}" = x ; then
+       AC_MSG_ERROR([
+The PACKAGE_NAME variable must be defined by your TEA configure.in])
+    fi
+    if test x"$1" = x ; then
+       AC_MSG_ERROR([
+TEA version not specified.])
+    elif test "$1" != "${TEA_VERSION}" ; then
+       AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"])
+    else
+       AC_MSG_RESULT([ok (TEA ${TEA_VERSION})])
+    fi
+    case "`uname -s`" in
+       *win32*|*WIN32*|*CYGWIN_NT*|*CYGWIN_9*|*CYGWIN_ME*|*MINGW32_*)
+           AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)
+           EXEEXT=".exe"
+           TEA_PLATFORM="windows"
+           ;;
+       *)
+           CYGPATH=echo
+           EXEEXT=""
+           TEA_PLATFORM="unix"
+           ;;
+    esac
+
+    # Check if exec_prefix is set. If not use fall back to prefix.
+    # Note when adjusted, so that TEA_PREFIX can correct for this.
+    # This is needed for recursive configures, since autoconf propagates
+    # $prefix, but not $exec_prefix (doh!).
+    if test x$exec_prefix = xNONE ; then
+       exec_prefix_default=yes
+       exec_prefix=$prefix
+    fi
+
+    AC_SUBST(EXEEXT)
+    AC_SUBST(CYGPATH)
+
+    # This package name must be replaced statically for AC_SUBST to work
+    AC_SUBST(PKG_LIB_FILE)
+    # Substitute STUB_LIB_FILE in case package creates a stub library too.
+    AC_SUBST(PKG_STUB_LIB_FILE)
+
+    # We AC_SUBST these here to ensure they are subst'ed,
+    # in case the user doesn't call TEA_ADD_...
+    AC_SUBST(PKG_STUB_SOURCES)
+    AC_SUBST(PKG_STUB_OBJECTS)
+    AC_SUBST(PKG_TCL_SOURCES)
+    AC_SUBST(PKG_HEADERS)
+    AC_SUBST(PKG_INCLUDES)
+    AC_SUBST(PKG_LIBS)
+    AC_SUBST(PKG_CFLAGS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_SOURCES --
+#
+#      Specify one or more source files.  Users should check for
+#      the right platform before adding to their list.
+#      It is not important to specify the directory, as long as it is
+#      in the generic, win or unix subdirectory of $(srcdir).
+#
+# Arguments:
+#      one or more file names
+#
+# Results:
+#
+#      Defines and substs the following vars:
+#              PKG_SOURCES
+#              PKG_OBJECTS
+#------------------------------------------------------------------------
+AC_DEFUN(TEA_ADD_SOURCES, [
+    vars="$@"
+    for i in $vars; do
+       case $i in
+           [\$]*)
+               # allow $-var names
+               PKG_SOURCES="$PKG_SOURCES $i"
+               PKG_OBJECTS="$PKG_OBJECTS $i"
+               ;;
+           *)
+               # check for existence - allows for generic/win/unix VPATH
+               if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
+                   -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
+                   ; then
+                   AC_MSG_ERROR([could not find source file '$i'])
+               fi
+               PKG_SOURCES="$PKG_SOURCES $i"
+               # this assumes it is in a VPATH dir
+               i=`basename $i`
+               # handle user calling this before or after TEA_SETUP_COMPILER
+               if test x"${OBJEXT}" != x ; then
+                   j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}"
+               else
+                   j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}"
+               fi
+               PKG_OBJECTS="$PKG_OBJECTS $j"
+               ;;
+       esac
+    done
+    AC_SUBST(PKG_SOURCES)
+    AC_SUBST(PKG_OBJECTS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_STUB_SOURCES --
+#
+#      Specify one or more source files.  Users should check for
+#      the right platform before adding to their list.
+#      It is not important to specify the directory, as long as it is
+#      in the generic, win or unix subdirectory of $(srcdir).
+#
+# Arguments:
+#      one or more file names
+#
+# Results:
+#
+#      Defines and substs the following vars:
+#              PKG_STUB_SOURCES
+#              PKG_STUB_OBJECTS
+#------------------------------------------------------------------------
+AC_DEFUN(TEA_ADD_STUB_SOURCES, [
+    vars="$@"
+    for i in $vars; do
+       # check for existence - allows for generic/win/unix VPATH
+       if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
+           -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
+           ; then
+           AC_MSG_ERROR([could not find stub source file '$i'])
+       fi
+       PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i"
+       # this assumes it is in a VPATH dir
+       i=`basename $i`
+       # handle user calling this before or after TEA_SETUP_COMPILER
+       if test x"${OBJEXT}" != x ; then
+           j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}"
+       else
+           j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}"
+       fi
+       PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j"
+    done
+    AC_SUBST(PKG_STUB_SOURCES)
+    AC_SUBST(PKG_STUB_OBJECTS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_TCL_SOURCES --
+#
+#      Specify one or more Tcl source files.  These should be platform
+#      independent runtime files.
+#
+# Arguments:
+#      one or more file names
+#
+# Results:
+#
+#      Defines and substs the following vars:
+#              PKG_TCL_SOURCES
+#------------------------------------------------------------------------
+AC_DEFUN(TEA_ADD_TCL_SOURCES, [
+    vars="$@"
+    for i in $vars; do
+       # check for existence, be strict because it is installed
+       if test ! -f "${srcdir}/$i" ; then
+           AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i'])
+       fi
+       PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i"
+    done
+    AC_SUBST(PKG_TCL_SOURCES)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_HEADERS --
+#
+#      Specify one or more source headers.  Users should check for
+#      the right platform before adding to their list.
+#
+# Arguments:
+#      one or more file names
+#
+# Results:
+#
+#      Defines and substs the following vars:
+#              PKG_HEADERS
+#------------------------------------------------------------------------
+AC_DEFUN(TEA_ADD_HEADERS, [
+    vars="$@"
+    for i in $vars; do
+       # check for existence, be strict because it is installed
+       if test ! -f "${srcdir}/$i" ; then
+           AC_MSG_ERROR([could not find header file '${srcdir}/$i'])
+       fi
+       PKG_HEADERS="$PKG_HEADERS $i"
+    done
+    AC_SUBST(PKG_HEADERS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_INCLUDES --
+#
+#      Specify one or more include dirs.  Users should check for
+#      the right platform before adding to their list.
+#
+# Arguments:
+#      one or more file names
+#
+# Results:
+#
+#      Defines and substs the following vars:
+#              PKG_INCLUDES
+#------------------------------------------------------------------------
+AC_DEFUN(TEA_ADD_INCLUDES, [
+    vars="$@"
+    for i in $vars; do
+       PKG_INCLUDES="$PKG_INCLUDES $i"
+    done
+    AC_SUBST(PKG_INCLUDES)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_LIBS --
+#
+#      Specify one or more libraries.  Users should check for
+#      the right platform before adding to their list.  For Windows,
+#      libraries provided in "foo.lib" format will be converted to
+#      "-lfoo" when using GCC (mingw).
+#
+# Arguments:
+#      one or more file names
+#
+# Results:
+#
+#      Defines and substs the following vars:
+#              PKG_LIBS
+#------------------------------------------------------------------------
+AC_DEFUN(TEA_ADD_LIBS, [
+    vars="$@"
+    for i in $vars; do
+       if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then
+           # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib
+           i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'`
+       fi
+       PKG_LIBS="$PKG_LIBS $i"
+    done
+    AC_SUBST(PKG_LIBS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_CFLAGS --
+#
+#      Specify one or more CFLAGS.  Users should check for
+#      the right platform before adding to their list.
+#
+# Arguments:
+#      one or more file names
+#
+# Results:
+#
+#      Defines and substs the following vars:
+#              PKG_CFLAGS
+#------------------------------------------------------------------------
+AC_DEFUN(TEA_ADD_CFLAGS, [
+    PKG_CFLAGS="$PKG_CFLAGS $@"
+    AC_SUBST(PKG_CFLAGS)
+])
+
+#------------------------------------------------------------------------
+# TEA_PREFIX --
+#
+#      Handle the --prefix=... option by defaulting to what Tcl gave
+#
+# Arguments:
+#      none
+#
+# Results:
+#
+#      If --prefix or --exec-prefix was not specified, $prefix and
+#      $exec_prefix will be set to the values given to Tcl when it was
+#      configured.
+#------------------------------------------------------------------------
+AC_DEFUN(TEA_PREFIX, [
+    if test "${prefix}" = "NONE"; then
+       prefix_default=yes
+       if test x"${TCL_PREFIX}" != x; then
+           AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}])
+           prefix=${TCL_PREFIX}
+       else
+           AC_MSG_NOTICE([--prefix defaulting to /usr/local])
+           prefix=/usr/local
+       fi
+    fi
+    if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \
+       -o x"${exec_prefix_default}" = x"yes" ; then
+       if test x"${TCL_EXEC_PREFIX}" != x; then
+           AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}])
+           exec_prefix=${TCL_EXEC_PREFIX}
+       else
+           AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}])
+           exec_prefix=$prefix
+       fi
+    fi
+])
+
+#------------------------------------------------------------------------
+# TEA_SETUP_COMPILER_CC --
+#
+#      Do compiler checks the way we want.  This is just a replacement
+#      for AC_PROG_CC in TEA configure.in files to make them cleaner.
+#
+# Arguments:
+#      none
+#
+# Results:
+#
+#      Sets up CC var and other standard bits we need to make executables.
+#------------------------------------------------------------------------
+AC_DEFUN(TEA_SETUP_COMPILER_CC, [
+    # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE)
+    # in this macro, they need to go into TEA_SETUP_COMPILER instead.
+
+    # If the user did not set CFLAGS, set it now to keep
+    # the AC_PROG_CC macro from adding "-g -O2".
+    if test "${CFLAGS+set}" != "set" ; then
+       CFLAGS=""
+    fi
+
+    AC_PROG_CC
+    AC_PROG_CPP
+
+    AC_PROG_INSTALL
+
+    #--------------------------------------------------------------------
+    # Checks to see if the make program sets the $MAKE variable.
+    #--------------------------------------------------------------------
+
+    AC_PROG_MAKE_SET
+
+    #--------------------------------------------------------------------
+    # Find ranlib
+    #--------------------------------------------------------------------
+
+    AC_PROG_RANLIB
+
+    #--------------------------------------------------------------------
+    # Determines the correct binary file extension (.o, .obj, .exe etc.)
+    #--------------------------------------------------------------------
+
+    AC_OBJEXT
+    AC_EXEEXT
+])
+
+#------------------------------------------------------------------------
+# TEA_SETUP_COMPILER --
+#
+#      Do compiler checks that use the compiler.  This must go after
+#      TEA_SETUP_COMPILER_CC, which does the actual compiler check.
+#
+# Arguments:
+#      none
+#
+# Results:
+#
+#      Sets up CC var and other standard bits we need to make executables.
+#------------------------------------------------------------------------
+AC_DEFUN(TEA_SETUP_COMPILER, [
+    # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here.
+    AC_REQUIRE([TEA_SETUP_COMPILER_CC])
+
+    #------------------------------------------------------------------------
+    # If we're using GCC, see if the compiler understands -pipe. If so, use it.
+    # It makes compiling go faster.  (This is only a performance feature.)
+    #------------------------------------------------------------------------
+
+    if test -z "$no_pipe" -a -n "$GCC"; then
+       AC_MSG_CHECKING([if the compiler understands -pipe])
+       OLDCC="$CC"
+       CC="$CC -pipe"
+       AC_TRY_COMPILE(,, AC_MSG_RESULT([yes]), CC="$OLDCC"
+           AC_MSG_RESULT([no]))
+    fi
+
+    #--------------------------------------------------------------------
+    # Common compiler flag setup
+    #--------------------------------------------------------------------
+
+    AC_C_BIGENDIAN
+    if test "${TEA_PLATFORM}" = "unix" ; then
+       TEA_TCL_LINK_LIBS
+       TEA_MISSING_POSIX_HEADERS
+       # Let the user call this, because if it triggers, they will
+       # need a compat/strtod.c that is correct.  Users can also
+       # use Tcl_GetDouble(FromObj) instead.
+       #TEA_BUGGY_STRTOD
+    fi
+])
+
+#------------------------------------------------------------------------
+# TEA_MAKE_LIB --
+#
+#      Generate a line that can be used to build a shared/unshared library
+#      in a platform independent manner.
+#
+# Arguments:
+#      none
+#
+#      Requires:
+#
+# Results:
+#
+#      Defines the following vars:
+#      CFLAGS -        Done late here to note disturb other AC macros
+#       MAKE_LIB -      Command to execute to build the Tcl library;
+#                       differs depending on whether or not Tcl is being
+#                       compiled as a shared library.
+#      MAKE_SHARED_LIB Makefile rule for building a shared library
+#      MAKE_STATIC_LIB Makefile rule for building a static library
+#      MAKE_STUB_LIB   Makefile rule for building a stub library
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_MAKE_LIB, [
+    if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then
+       MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)"
+       MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)"
+       MAKE_STUB_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_STUB_OBJECTS)"
+    else
+       MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)"
+       MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
+       MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)"
+    fi
+
+    if test "${SHARED_BUILD}" = "1" ; then
+       MAKE_LIB="${MAKE_SHARED_LIB} "
+    else
+       MAKE_LIB="${MAKE_STATIC_LIB} "
+    fi
+
+    #--------------------------------------------------------------------
+    # Shared libraries and static libraries have different names.
+    # Use the double eval to make sure any variables in the suffix is
+    # substituted. (@@@ Might not be necessary anymore)
+    #--------------------------------------------------------------------
+
+    if test "${TEA_PLATFORM}" = "windows" ; then
+       if test "${SHARED_BUILD}" = "1" ; then
+           # We force the unresolved linking of symbols that are really in
+           # the private libraries of Tcl and Tk.
+           SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\""
+           if test x"${TK_BIN_DIR}" != x ; then
+               SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\""
+           fi
+           eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
+       else
+           eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
+       fi
+       # Some packages build there own stubs libraries
+       eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
+       # These aren't needed on Windows (either MSVC or gcc)
+       RANLIB=:
+       RANLIB_STUB=:
+    else
+       RANLIB_STUB="${RANLIB}"
+       if test "${SHARED_BUILD}" = "1" ; then
+           SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}"
+           if test x"${TK_BIN_DIR}" != x ; then
+               SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}"
+           fi
+           eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
+           RANLIB=:
+       else
+           eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
+       fi
+       # Some packages build there own stubs libraries
+       eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
+    fi
+
+    # These are escaped so that only CFLAGS is picked up at configure time.
+    # The other values will be substituted at make time.
+    CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}"
+    if test "${SHARED_BUILD}" = "1" ; then
+       CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}"
+    fi
+
+    AC_SUBST(MAKE_LIB)
+    AC_SUBST(MAKE_SHARED_LIB)
+    AC_SUBST(MAKE_STATIC_LIB)
+    AC_SUBST(MAKE_STUB_LIB)
+    AC_SUBST(RANLIB_STUB)
+])
+
+#------------------------------------------------------------------------
+# TEA_LIB_SPEC --
+#
+#      Compute the name of an existing object library located in libdir
+#      from the given base name and produce the appropriate linker flags.
+#
+# Arguments:
+#      basename        The base name of the library without version
+#                      numbers, extensions, or "lib" prefixes.
+#      extra_dir       Extra directory in which to search for the
+#                      library.  This location is used first, then
+#                      $prefix/$exec-prefix, then some defaults.
+#
+# Requires:
+#      TEA_INIT and TEA_PREFIX must be called first.
+#
+# Results:
+#
+#      Defines the following vars:
+#              ${basename}_LIB_NAME    The computed library name.
+#              ${basename}_LIB_SPEC    The computed linker flags.
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_LIB_SPEC, [
+    AC_MSG_CHECKING([for $1 library])
+
+    # Look in exec-prefix for the library (defined by TEA_PREFIX).
+
+    tea_lib_name_dir="${exec_prefix}/lib"
+
+    # Or in a user-specified location.
+
+    if test x"$2" != x ; then
+       tea_extra_lib_dir=$2
+    else
+       tea_extra_lib_dir=NONE
+    fi
+
+    for i in \
+           `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \
+           `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \
+           `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \
+           `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \
+           `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \
+           `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \
+           `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \
+           `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do
+       if test -f "$i" ; then
+           tea_lib_name_dir=`dirname $i`
+           $1_LIB_NAME=`basename $i`
+           $1_LIB_PATH_NAME=$i
+           break
+       fi
+    done
+
+    if test "${TEA_PLATFORM}" = "windows"; then
+       $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\"
+    else
+       # Strip off the leading "lib" and trailing ".a" or ".so"
+
+       tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'`
+       $1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}"
+    fi
+
+    if test "x${$1_LIB_NAME}" = x ; then
+       AC_MSG_ERROR([not found])
+    else
+       AC_MSG_RESULT([${$1_LIB_SPEC}])
+    fi
+])
+
+#------------------------------------------------------------------------
+# TEA_PRIVATE_TCL_HEADERS --
+#
+#      Locate the private Tcl include files
+#
+# Arguments:
+#
+#      Requires:
+#              TCL_SRC_DIR     Assumes that TEA_LOAD_TCLCONFIG has
+#                               already been called.
+#
+# Results:
+#
+#      Substs the following vars:
+#              TCL_TOP_DIR_NATIVE
+#              TCL_GENERIC_DIR_NATIVE
+#              TCL_UNIX_DIR_NATIVE
+#              TCL_WIN_DIR_NATIVE
+#              TCL_BMAP_DIR_NATIVE
+#              TCL_TOOL_DIR_NATIVE
+#              TCL_PLATFORM_DIR_NATIVE
+#              TCL_BIN_DIR_NATIVE
+#              TCL_INCLUDES
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_PRIVATE_TCL_HEADERS, [
+    AC_MSG_CHECKING([for Tcl private include files])
+
+    if test "${TEA_PLATFORM}" = "windows"; then
+       TCL_TOP_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}`\"
+       TCL_GENERIC_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/generic`\"
+       TCL_UNIX_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/unix`\"
+       TCL_WIN_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/win`\"
+       TCL_BMAP_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/bitmaps`\"
+       TCL_TOOL_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/tools`\"
+       TCL_COMPAT_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/compat`\"
+       TCL_PLATFORM_DIR_NATIVE=${TCL_WIN_DIR_NATIVE}
+
+       TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}"
+    else
+       TCL_TOP_DIR_NATIVE='$(TCL_SRC_DIR)'
+       TCL_GENERIC_DIR_NATIVE='${TCL_TOP_DIR_NATIVE}/generic'
+       TCL_UNIX_DIR_NATIVE='${TCL_TOP_DIR_NATIVE}/unix'
+       TCL_WIN_DIR_NATIVE='${TCL_TOP_DIR_NATIVE}/win'
+       TCL_BMAP_DIR_NATIVE='${TCL_TOP_DIR_NATIVE}/bitmaps'
+       TCL_TOOL_DIR_NATIVE='${TCL_TOP_DIR_NATIVE}/tools'
+       TCL_COMPAT_DIR_NATIVE='${TCL_TOP_DIR_NATIVE}/compat'
+       TCL_PLATFORM_DIR_NATIVE=${TCL_UNIX_DIR_NATIVE}
+
+       # substitute these in "relaxed" so that TCL_INCLUDES still works
+       # without requiring the other vars to be defined in the Makefile
+       eval "TCL_INCLUDES=\"-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}\""
+    fi
+
+    AC_SUBST(TCL_TOP_DIR_NATIVE)
+    AC_SUBST(TCL_GENERIC_DIR_NATIVE)
+    AC_SUBST(TCL_UNIX_DIR_NATIVE)
+    AC_SUBST(TCL_WIN_DIR_NATIVE)
+    AC_SUBST(TCL_BMAP_DIR_NATIVE)
+    AC_SUBST(TCL_TOOL_DIR_NATIVE)
+    AC_SUBST(TCL_PLATFORM_DIR_NATIVE)
+
+    AC_SUBST(TCL_INCLUDES)
+    AC_MSG_RESULT([Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}])
+])
+
+#------------------------------------------------------------------------
+# TEA_PUBLIC_TCL_HEADERS --
+#
+#      Locate the installed public Tcl header files
+#
+# Arguments:
+#      None.
+#
+# Requires:
+#      CYGPATH must be set
+#
+# Results:
+#
+#      Adds a --with-tclinclude switch to configure.
+#      Result is cached.
+#
+#      Substs the following vars:
+#              TCL_INCLUDES
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_PUBLIC_TCL_HEADERS, [
+    AC_MSG_CHECKING([for Tcl public headers])
+
+    AC_ARG_WITH(tclinclude, [  --with-tclinclude       directory containing the public Tcl header files], with_tclinclude=${withval})
+
+    AC_CACHE_VAL(ac_cv_c_tclh, [
+       # Use the value from --with-tclinclude, if it was given
+
+       if test x"${with_tclinclude}" != x ; then
+           if test -f "${with_tclinclude}/tcl.h" ; then
+               ac_cv_c_tclh=${with_tclinclude}
+           else
+               AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h])
+           fi
+       else
+           # Check order: pkg --prefix location, Tcl's --prefix location,
+           # directory of tclConfig.sh, and Tcl source directory.
+           # Looking in the source dir is not ideal, but OK.
+
+           eval "temp_includedir=${includedir}"
+           list="`ls -d ${temp_includedir}      2>/dev/null` \
+               `ls -d ${TCL_PREFIX}/include     2>/dev/null` \
+               `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null` \
+               `ls -d ${TCL_SRC_DIR}/generic    2>/dev/null`"
+           if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
+               list="$list /usr/local/include /usr/include"
+           fi
+           for i in $list ; do
+               if test -f "$i/tcl.h" ; then
+                   ac_cv_c_tclh=$i
+                   break
+               fi
+           done
+       fi
+    ])
+
+    # Print a message based on how we determined the include path
+
+    if test x"${ac_cv_c_tclh}" = x ; then
+       AC_MSG_ERROR([tcl.h not found.  Please specify its location with --with-tclinclude])
+    else
+       AC_MSG_RESULT([${ac_cv_c_tclh}])
+    fi
+
+    # Convert to a native path and substitute into the output files.
+
+    INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}`
+
+    TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
+
+    AC_SUBST(TCL_INCLUDES)
+])
+
+#------------------------------------------------------------------------
+# TEA_PRIVATE_TK_HEADERS --
+#
+#      Locate the private Tk include files
+#
+# Arguments:
+#
+#      Requires:
+#              TK_SRC_DIR      Assumes that TEA_LOAD_TKCONFIG has
+#                               already been called.
+#
+# Results:
+#
+#      Substs the following vars:
+#              TK_INCLUDES
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_PRIVATE_TK_HEADERS, [
+    AC_MSG_CHECKING([for Tk private include files])
+
+    if test "${TEA_PLATFORM}" = "windows"; then
+       TK_TOP_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}`\"
+       TK_UNIX_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}/unix`\"
+       TK_WIN_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}/win`\"
+       TK_GENERIC_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}/generic`\"
+       TK_XLIB_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}/xlib`\"
+       TK_PLATFORM_DIR_NATIVE=${TK_WIN_DIR_NATIVE}
+
+       TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE} -I${TK_XLIB_DIR_NATIVE}"
+    else
+       TK_TOP_DIR_NATIVE='${TK_SRC_DIR}'
+       TK_GENERIC_DIR_NATIVE='${TK_TOP_DIR_NATIVE}/generic'
+       TK_UNIX_DIR_NATIVE='${TK_TOP_DIR_NATIVE}/unix'
+       TK_WIN_DIR_NATIVE='${TK_TOP_DIR_NATIVE}/win'
+       TK_PLATFORM_DIR_NATIVE=${TK_UNIX_DIR_NATIVE}
+
+       # substitute these in "relaxed" so that TK_INCLUDES still works
+       # without requiring the other vars to be defined in the Makefile
+       eval "TK_INCLUDES=\"-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}\""
+    fi
+
+    AC_SUBST(TK_TOP_DIR_NATIVE)
+    AC_SUBST(TK_UNIX_DIR_NATIVE)
+    AC_SUBST(TK_WIN_DIR_NATIVE)
+    AC_SUBST(TK_GENERIC_DIR_NATIVE)
+    AC_SUBST(TK_XLIB_DIR_NATIVE)
+    AC_SUBST(TK_PLATFORM_DIR_NATIVE)
+
+    AC_SUBST(TK_INCLUDES)
+    AC_MSG_RESULT([Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}])
+])
+
+#------------------------------------------------------------------------
+# TEA_PUBLIC_TK_HEADERS --
+#
+#      Locate the installed public Tk header files
+#
+# Arguments:
+#      None.
+#
+# Requires:
+#      CYGPATH must be set
+#
+# Results:
+#
+#      Adds a --with-tkinclude switch to configure.
+#      Result is cached.
+#
+#      Substs the following vars:
+#              TK_INCLUDES
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_PUBLIC_TK_HEADERS, [
+    AC_MSG_CHECKING([for Tk public headers])
+
+    AC_ARG_WITH(tkinclude, [  --with-tkinclude      directory containing the public Tk header files.], with_tkinclude=${withval})
+
+    AC_CACHE_VAL(ac_cv_c_tkh, [
+       # Use the value from --with-tkinclude, if it was given
+
+       if test x"${with_tkinclude}" != x ; then
+           if test -f "${with_tkinclude}/tk.h" ; then
+               ac_cv_c_tkh=${with_tkinclude}
+           else
+               AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h])
+           fi
+       else
+           # Check order: pkg --prefix location, Tcl's --prefix location,
+           # directory of tclConfig.sh, and Tcl source directory.
+           # Looking in the source dir is not ideal, but OK.
+
+           eval "temp_includedir=${includedir}"
+           list="`ls -d ${temp_includedir}      2>/dev/null` \
+               `ls -d ${TK_PREFIX}/include      2>/dev/null` \
+               `ls -d ${TCL_PREFIX}/include     2>/dev/null` \
+               `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null` \
+               `ls -d ${TK_SRC_DIR}/generic     2>/dev/null`"
+           if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
+               list="$list /usr/local/include /usr/include"
+           fi
+           for i in $list ; do
+               if test -f "$i/tk.h" ; then
+                   ac_cv_c_tkh=$i
+                   break
+               fi
+           done
+       fi
+    ])
+
+    # Print a message based on how we determined the include path
+
+    if test x"${ac_cv_c_tkh}" = x ; then
+       AC_MSG_ERROR([tk.h not found.  Please specify its location with --with-tkinclude])
+    else
+       AC_MSG_RESULT([${ac_cv_c_tkh}])
+    fi
+
+    # Convert to a native path and substitute into the output files.
+
+    INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}`
+
+    TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
+
+    AC_SUBST(TK_INCLUDES)
+
+    if test "${TEA_PLATFORM}" = "windows" ; then
+       # On Windows, we need the X compat headers
+       AC_MSG_CHECKING([for X11 header files])
+       if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then
+           INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`"
+           TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
+           AC_SUBST(TK_XINCLUDES)
+       fi
+       AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}])
+    fi
+])
+
+#------------------------------------------------------------------------
+# TEA_PROG_TCLSH
+#      Locate a tclsh shell in the following directories:
+#              ${TCL_BIN_DIR}          ${TCL_BIN_DIR}/../bin
+#              ${exec_prefix}/bin      ${prefix}/bin
+#              ${PATH}
+#
+# Arguments
+#      none
+#
+# Results
+#      Subst's the following values:
+#              TCLSH_PROG
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_PROG_TCLSH, [
+    # Allow the user to provide this setting in the env
+    if test "x${TCLSH_PROG}" = "x" ; then
+       AC_MSG_CHECKING([for tclsh])
+
+       AC_CACHE_VAL(ac_cv_path_tclsh, [
+       search_path=`echo ${PATH} | sed -e 's/:/ /g'`
+       if test "${TEA_PLATFORM}" != "windows" -o \
+               \( "$do64bit_ok" = "no" -a "$doWince" = "no" \) ; then
+           # Do not allow target tclsh in known cross-compile builds,
+           # as we need one we can run on this system
+           search_path="${TCL_BIN_DIR} ${TCL_BIN_DIR}/../bin ${exec_prefix}/bin ${prefix}/bin ${search_path}"
+       fi
+       for dir in $search_path ; do
+           for j in `ls -r $dir/tclsh[[8-9]]*${EXEEXT} 2> /dev/null` \
+                   `ls -r $dir/tclsh*${EXEEXT} 2> /dev/null` ; do
+               if test x"$ac_cv_path_tclsh" = x ; then
+                   if test -f "$j" ; then
+                       ac_cv_path_tclsh=$j
+                       break
+                   fi
+               fi
+           done
+       done
+       ])
+
+       if test -f "$ac_cv_path_tclsh" ; then
+           TCLSH_PROG=$ac_cv_path_tclsh
+           AC_MSG_RESULT([$TCLSH_PROG])
+       else
+           AC_MSG_ERROR([No tclsh found in PATH: $search_path])
+       fi
+    fi
+    AC_SUBST(TCLSH_PROG)
+])
+
+#------------------------------------------------------------------------
+# TEA_PROG_WISH
+#      Locate a wish shell in the following directories:
+#              ${TK_BIN_DIR}           ${TK_BIN_DIR}/../bin
+#              ${TCL_BIN_DIR}          ${TCL_BIN_DIR}/../bin
+#              ${exec_prefix}/bin      ${prefix}/bin
+#              ${PATH}
+#
+# Arguments
+#      none
+#
+# Results
+#      Subst's the following values:
+#              WISH_PROG
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_PROG_WISH, [
+    # Allow the user to provide this setting in the env
+    if test "x${WISH_PROG}" = "x" ; then
+       AC_MSG_CHECKING([for wish])
+
+       AC_CACHE_VAL(ac_cv_path_wish, [
+       search_path=`echo ${PATH} | sed -e 's/:/ /g'`
+       if test "${TEA_PLATFORM}" != "windows" -o \
+               \( "$do64bit_ok" = "no" -a "$doWince" = "no" \) ; then
+           # Do not allow target wish in known cross-compile builds,
+           # as we need one we can run on this system
+           search_path="${TK_BIN_DIR} ${TK_BIN_DIR}/../bin ${TCL_BIN_DIR} ${TCL_BIN_DIR}/../bin ${exec_prefix}/bin ${prefix}/bin ${search_path}"
+       fi
+       for dir in $search_path ; do
+           for j in `ls -r $dir/wish[[8-9]]*${EXEEXT} 2> /dev/null` \
+                   `ls -r $dir/wish*${EXEEXT} 2> /dev/null` ; do
+               if test x"$ac_cv_path_wish" = x ; then
+                   if test -f "$j" ; then
+                       ac_cv_path_wish=$j
+                       break
+                   fi
+               fi
+           done
+       done
+       ])
+
+       if test -f "$ac_cv_path_wish" ; then
+       WISH_PROG=$ac_cv_path_wish
+           AC_MSG_RESULT([$WISH_PROG])
+       else
+           AC_MSG_ERROR([No wish found in PATH: $search_path])
+       fi
+    fi
+    AC_SUBST(WISH_PROG)
+])
+
+#------------------------------------------------------------------------
+# TEA_PATH_CONFIG --
+#
+#      Locate the ${1}Config.sh file and perform a sanity check on
+#      the ${1} compile flags.  These are used by packages like
+#      [incr Tk] that load *Config.sh files from more than Tcl and Tk.
+#
+# Arguments:
+#      none
+#
+# Results:
+#
+#      Adds the following arguments to configure:
+#              --with-$1=...
+#
+#      Defines the following vars:
+#              $1_BIN_DIR      Full path to the directory containing
+#                              the $1Config.sh file
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_PATH_CONFIG, [
+    #
+    # Ok, lets find the $1 configuration
+    # First, look for one uninstalled.
+    # the alternative search directory is invoked by --with-$1
+    #
+
+    if test x"${no_$1}" = x ; then
+       # we reset no_$1 in case something fails here
+       no_$1=true
+       AC_ARG_WITH($1, [  --with-$1              directory containing $1 configuration ($1Config.sh)], with_$1config=${withval})
+       AC_MSG_CHECKING([for $1 configuration])
+       AC_CACHE_VAL(ac_cv_c_$1config,[
+
+           # First check to see if --with-$1 was specified.
+           if test x"${with_$1config}" != x ; then
+               case ${with_$1config} in
+                   */$1Config.sh )
+                       if test -f ${with_$1config}; then
+                           AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself])
+                           with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'`
+                       fi;;
+               esac
+               if test -f "${with_$1config}/$1Config.sh" ; then
+                   ac_cv_c_$1config=`(cd ${with_$1config}; pwd)`
+               else
+                   AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh])
+               fi
+           fi
+
+           # then check for a private $1 installation
+           if test x"${ac_cv_c_$1config}" = x ; then
+               for i in \
+                       ../$1 \
+                       `ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
+                       `ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
+                       `ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
+                       ../../$1 \
+                       `ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
+                       `ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
+                       `ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
+                       ../../../$1 \
+                       `ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
+                       `ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
+                       `ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
+                       ${srcdir}/../$1 \
+                       `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
+                       `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
+                       `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \
+                       `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
+                       ; do
+                   if test -f "$i/$1Config.sh" ; then
+                       ac_cv_c_$1config=`(cd $i; pwd)`
+                       break
+                   fi
+                   if test -f "$i/unix/$1Config.sh" ; then
+                       ac_cv_c_$1config=`(cd $i/unix; pwd)`
+                       break
+                   fi
+               done
+           fi
+
+           # check in a few common install locations
+           if test x"${ac_cv_c_$1config}" = x ; then
+               for i in `ls -d ${exec_prefix}/lib 2>/dev/null` \
+                       `ls -d ${prefix}/lib 2>/dev/null` \
+                       `ls -d /usr/local/lib 2>/dev/null` \
+                       `ls -d /usr/contrib/lib 2>/dev/null` \
+                       `ls -d /usr/lib 2>/dev/null` \
+                       ; do
+                   if test -f "$i/$1Config.sh" ; then
+                       ac_cv_c_$1config=`(cd $i; pwd)`
+                       break
+                   fi
+               done
+           fi
+       ])
+
+       if test x"${ac_cv_c_$1config}" = x ; then
+           $1_BIN_DIR="# no $1 configs found"
+           AC_MSG_WARN("Cannot find $1 configuration definitions")
+           exit 0
+       else
+           no_$1=
+           $1_BIN_DIR=${ac_cv_c_$1config}
+           AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh])
+       fi
+    fi
+])
+
+#------------------------------------------------------------------------
+# TEA_LOAD_CONFIG --
+#
+#      Load the $1Config.sh file
+#
+# Arguments:
+#      
+#      Requires the following vars to be set:
+#              $1_BIN_DIR
+#
+# Results:
+#
+#      Subst the following vars:
+#              $1_SRC_DIR
+#              $1_LIB_FILE
+#              $1_LIB_SPEC
+#
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_LOAD_CONFIG, [
+    AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh])
+
+    if test -f "${$1_BIN_DIR}/$1Config.sh" ; then
+        AC_MSG_RESULT([loading])
+       . ${$1_BIN_DIR}/$1Config.sh
+    else
+        AC_MSG_RESULT([file not found])
+    fi
+
+    #
+    # If the $1_BIN_DIR is the build directory (not the install directory),
+    # then set the common variable name to the value of the build variables.
+    # For example, the variable $1_LIB_SPEC will be set to the value
+    # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC
+    # instead of $1_BUILD_LIB_SPEC since it will work with both an
+    # installed and uninstalled version of Tcl.
+    #
+
+    if test -f ${$1_BIN_DIR}/Makefile ; then
+       AC_MSG_WARN([Found Makefile - using build library specs for $1])
+        $1_LIB_SPEC=${$1_BUILD_LIB_SPEC}
+        $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC}
+        $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH}
+    fi
+
+    AC_SUBST($1_VERSION)
+    AC_SUBST($1_BIN_DIR)
+    AC_SUBST($1_SRC_DIR)
+
+    AC_SUBST($1_LIB_FILE)
+    AC_SUBST($1_LIB_SPEC)
+
+    AC_SUBST($1_STUB_LIB_FILE)
+    AC_SUBST($1_STUB_LIB_SPEC)
+    AC_SUBST($1_STUB_LIB_PATH)
+])
+
+#------------------------------------------------------------------------
+# TEA_PATH_CELIB --
+#
+#      Locate Keuchel's celib emulation layer for targeting Win/CE
+#
+# Arguments:
+#      none
+#
+# Results:
+#
+#      Adds the following arguments to configure:
+#              --with-celib=...
+#
+#      Defines the following vars:
+#              CELIB_DIR       Full path to the directory containing
+#                              the include and platform lib files
+#------------------------------------------------------------------------
+
+AC_DEFUN(TEA_PATH_CELIB, [
+    # First, look for one uninstalled.
+    # the alternative search directory is invoked by --with-celib
+
+    if test x"${no_celib}" = x ; then
+       # we reset no_celib in case something fails here
+       no_celib=true
+       AC_ARG_WITH(celib,[  --with-celib=DIR        use Windows/CE support library from DIR], with_celibconfig=${withval})
+       AC_MSG_CHECKING([for Windows/CE celib directory])
+       AC_CACHE_VAL(ac_cv_c_celibconfig,[
+           # First check to see if --with-celibconfig was specified.
+           if test x"${with_celibconfig}" != x ; then
+               if test -d "${with_celibconfig}/inc" ; then
+                   ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)`
+               else
+                   AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory])
+               fi
+           fi
+
+           # then check for a celib library
+           if test x"${ac_cv_c_celibconfig}" = x ; then
+               for i in \
+                       ../celib-palm-3.0 \
+                       ../celib \
+                       ../../celib-palm-3.0 \
+                       ../../celib \
+                       `ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \
+                       ${srcdir}/../celib-palm-3.0 \
+                       ${srcdir}/../celib \
+                       `ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \
+                       ; do
+                   if test -d "$i/inc" ; then
+                       ac_cv_c_celibconfig=`(cd $i; pwd)`
+                       break
+                   fi
+               done
+           fi
+       ])
+       if test x"${ac_cv_c_celibconfig}" = x ; then
+           AC_MSG_ERROR([Cannot find celib support library directory])
+       else
+           no_celib=
+           CELIB_DIR=${ac_cv_c_celibconfig}
+           AC_MSG_RESULT([found $CELIB_DIR])
+           TEA_PATH_NOSPACE(CELIB_DIR, ${ac_cv_c_celibconfig})
+       fi
+    fi
+])
+
+#------------------------------------------------------------------------
+# TEA_PATH_NOSPACE
+#      Ensure that the given path has no spaces.  This is necessary for
+#      CC (and consitutuent vars that build it up) to work in the
+#      tortured autoconf environment.  Currently only for Windows use.
+#
+# Arguments
+#      VAR  - name of the variable to set
+#      PATH - path to ensure no spaces in
+#
+# Results
+#      Sets $VAR to short path of $PATH if it can be found.
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PATH_NOSPACE], [
+    if test "${TEA_PLATFORM}" = "windows" ; then
+       # we need TCLSH_PROG defined to get Windows short pathnames
+       AC_REQUIRE([TEA_PROG_TCLSH])
+
+       AC_MSG_CHECKING([short pathname for $1 ($2)])
+
+       shortpath=
+       case "$2" in
+           *\ *)
+               # Only do this if we need to.
+               shortpath=`echo "puts [[file attributes {$2} -shortname]] ; exit" | ${TCLSH_PROG} 2>/dev/null`
+               ;;
+       esac
+       if test "x${shortpath}" = "x" ; then
+           AC_MSG_RESULT([not changed])
+       else
+           $1=$shortpath
+           AC_MSG_RESULT([${$1}])
+       fi
+    fi
+])
diff --git a/tests/all.tcl b/tests/all.tcl
new file mode 100644 (file)
index 0000000..e300c57
--- /dev/null
@@ -0,0 +1,5 @@
+package require Tcl 8.4
+package require tcltest 2.2
+::tcltest::configure -testdir [file dirname [file normalize [info script]]]
+eval ::tcltest::configure $argv
+::tcltest::runAllTests
diff --git a/tests/mailslot.test b/tests/mailslot.test
new file mode 100644 (file)
index 0000000..fc180b8
--- /dev/null
@@ -0,0 +1,53 @@
+# mailslot.test                                                  -*- tcl -*-
+#
+#
+namespace eval ::tms::test {
+    package require tcltest 2
+    namespace import ::tcltest::test
+    ::tcltest::loadTestedCommands
+    
+    package require tms
+    package require tms::mailslot
+
+    variable received 0
+    proc recv {args} {
+        set [namespace current]::wait [list ok $args]
+    }
+    
+    proc waitforit {} {
+        variable wait waiting
+        set aid [after 1000 [list set [namespace current]::wait timeout]]
+        vwait [namespace current]::wait
+        after cancel $aid
+        return $wait
+    }
+
+    test mailslot-1.0 {} -constraints {win} -body {
+        list [catch {tms::mailslot z} err] $err
+    } -result {1 {bad command "z": must be create, configure, sendto, or names}}
+    test mailslot-1.1 {} -constraints {win} -body {
+        list [catch {tms::mailslot create} err] $err
+    } -result {1 {wrong # args: should be "tms::mailslot create ?option value ...?"}}
+
+    test mailslot-1.2 {} -constraints {win} -body {
+        set slot [tms::mailslot create -name TMSTest \
+                      -command [namespace origin recv]]
+    } -cleanup {
+        #rename $slot {}
+    } -match regexp -result {mailslot[0-9]+}
+    
+    test mailslot-1.3 {} -constraints {win} -body {
+        $slot cget -name
+    } -result {TMSTest}
+
+    test mailslot-1.4 {} -constraints {win} -body {
+        tms::mailslot sendto TMSTest testing
+        update
+        waitforit
+    } -result {ok testing}
+        
+
+    ::tcltest::cleanupTests
+}
+namespace delete ::tms::test
+return
\ No newline at end of file
diff --git a/tools/genStubs.tcl b/tools/genStubs.tcl
new file mode 100644 (file)
index 0000000..db05a5e
--- /dev/null
@@ -0,0 +1,861 @@
+# genStubs.tcl --
+#
+#      This script generates a set of stub files for a given
+#      interface.  
+#      
+#
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# 
+# $Id: genStubs.tcl,v 1.1 2006/10/23 00:55:08 pat Exp $
+#
+# SOURCE: tcl/tools/genStubs.tcl, revision 1.17
+#
+# CHANGES: 
+#      + Don't use _ANSI_ARGS_ macro
+#      + Remove xxx_TCL_DECLARED #ifdeffery
+#      + Use application-defined storage class specifier instead of "EXTERN"
+#      + Add "epoch" and "revision" fields to stubs table record
+#      + Remove dead code related to USE_*_STUB_PROCS (emitStubs, makeStub)
+#      + Second argument to "declare" is used as a status guard
+#        instead of a platform guard.
+#      + Use void (*reserved$i)(void) = 0 instead of void *reserved$i = NULL
+#        for unused stub entries, in case pointer-to-function and 
+#        pointer-to-object are different sizes.
+#      + Allow trailing semicolon in function declarations
+#      + stubs table is const-qualified
+#
+
+package require Tcl 8
+
+namespace eval genStubs {
+    # libraryName --
+    #
+    #  The name of the entire library.  This value is used to compute
+    #  the USE_*_STUBS macro, the name of the init file, and others.
+
+    variable libraryName "UNKNOWN"
+
+    # interfaces --
+    #
+    #  An array indexed by interface name that is used to maintain
+    #   the set of valid interfaces.  The value is empty.
+
+    array set interfaces {}
+
+    # curName --
+    #
+    #  The name of the interface currently being defined.
+
+    variable curName "UNKNOWN"
+
+    # scspec --
+    #
+    #  Storage class specifier for external function declarations.
+    #  Normally "extern", may be set to something like XYZAPI
+    #
+    variable scspec "extern"
+
+    # epoch, revision --
+    #
+    #  The epoch and revision numbers of the interface currently being defined.
+    #   (@@@TODO: should be an array mapping interface names -> numbers)
+    #
+
+    variable epoch 0
+    variable revision 0
+
+    # hooks --
+    #
+    #  An array indexed by interface name that contains the set of
+    #  subinterfaces that should be defined for a given interface.
+
+    array set hooks {}
+
+    # stubs --
+    #
+    #  This three dimensional array is indexed first by interface name,
+    #  second by field name, and third by a numeric offset or the
+    #  constant "lastNum".  The lastNum entry contains the largest
+    #  numeric offset used for a given interface.
+    #
+    #  Field "decl,$i" contains the C function specification that
+    #  should be used for the given entry in the stub table.  The spec
+    #  consists of a list in the form returned by parseDecl.
+    #   Other fields TBD later.
+
+    array set stubs {}
+
+    # outDir --
+    #
+    #  The directory where the generated files should be placed.
+
+    variable outDir .
+}
+
+# genStubs::library --
+#
+#      This function is used in the declarations file to set the name
+#      of the library that the interfaces are associated with (e.g. "tcl").
+#      This value will be used to define the inline conditional macro.
+#
+# Arguments:
+#      name    The library name.
+#
+# Results:
+#      None.
+
+proc genStubs::library {name} {
+    variable libraryName $name
+}
+
+# genStubs::interface --
+#
+#      This function is used in the declarations file to set the name
+#      of the interface currently being defined.
+#
+# Arguments:
+#      name    The name of the interface.
+#
+# Results:
+#      None.
+
+proc genStubs::interface {name} {
+    variable curName $name
+    variable interfaces
+    variable stubs
+
+    set interfaces($name) {}
+    set stubs($name,lastNum) 0
+    return
+}
+
+# genStubs::scspec --
+#
+#      Define the storage class macro used for external function declarations.
+#      Typically, this will be a macro like XYZAPI or EXTERN that
+#      expands to either DLLIMPORT or DLLEXPORT, depending on whether
+#      -DBUILD_XYZ has been set.
+#
+proc genStubs::scspec {value} {
+    variable scspec $value
+}
+
+# genStubs::epoch --
+#
+#      Define the epoch number for this library.  The epoch
+#      should be incrememented when a release is made that
+#      contains incompatible changes to the public API.
+#
+proc genStubs::epoch {value} {
+    variable epoch $value
+}
+
+# genStubs::hooks --
+#
+#      This function defines the subinterface hooks for the current
+#      interface.
+#
+# Arguments:
+#      names   The ordered list of interfaces that are reachable through the
+#              hook vector.
+#
+# Results:
+#      None.
+
+proc genStubs::hooks {names} {
+    variable curName
+    variable hooks
+
+    set hooks($curName) $names
+    return
+}
+
+# genStubs::declare --
+#
+#      This function is used in the declarations file to declare a new
+#      interface entry.
+#
+# Arguments:
+#      index           The index number of the interface.
+#      status          Status of the interface: one of "current",
+#                      "deprecated", or "obsolete".
+#      decl            The C function declaration, or {} for an undefined
+#                      entry.
+#
+proc genStubs::declare {index status decl} {
+    variable stubs
+    variable curName
+    variable revision
+
+    incr revision
+
+    # Check for duplicate declarations, then add the declaration and
+    # bump the lastNum counter if necessary.
+
+    if {[info exists stubs($curName,decl,$index)]} {
+       puts stderr "Duplicate entry: $index"
+    }
+    regsub -all "\[ \t\n\]+" [string trim $decl] " " decl
+    set decl [parseDecl $decl]
+
+    set stubs($curName,status,$index) $status
+    set stubs($curName,decl,$index) $decl
+
+    if {$index > $stubs($curName,lastNum)} {
+       set stubs($curName,lastNum) $index
+    }
+
+    return
+}
+
+# genStubs::rewriteFile --
+#
+#      This function replaces the machine generated portion of the
+#      specified file with new contents.  It looks for the !BEGIN! and
+#      !END! comments to determine where to place the new text.
+#
+# Arguments:
+#      file    The name of the file to modify.
+#      text    The new text to place in the file.
+#
+# Results:
+#      None.
+
+proc genStubs::rewriteFile {file text} {
+    if {![file exists $file]} {
+       puts stderr "Cannot find file: $file"
+       return
+    }
+    set in [open ${file} r]
+    set out [open ${file}.new w]
+
+    while {![eof $in]} {
+       set line [gets $in]
+       if {[string match "*!BEGIN!*" $line]} {
+           break
+       }
+       puts $out $line
+    }
+    puts $out "/* !BEGIN!: Do not edit below this line. */"
+    puts $out $text
+    while {![eof $in]} {
+       set line [gets $in]
+       if {[string match "*!END!*" $line]} {
+           break
+       }
+    }
+    puts $out "/* !END!: Do not edit above this line. */"
+    puts -nonewline $out [read $in]
+    close $in
+    close $out
+    file rename -force ${file}.new ${file}
+    return
+}
+
+# genStubs::addPlatformGuard --
+#
+#      Wrap a string inside a platform #ifdef.
+#
+# Arguments:
+#      plat    Platform to test.
+#
+# Results:
+#      Returns the original text inside an appropriate #ifdef.
+
+proc genStubs::addPlatformGuard {plat text} {
+    switch $plat {
+       win {
+           return "#ifdef __WIN32__\n${text}#endif /* __WIN32__ */\n"
+       }
+       unix {
+           return "#if !defined(__WIN32__) /* UNIX */\n${text}#endif /* UNIX */\n"
+       }                   
+       macosx {
+           return "#ifdef MAC_OSX_TCL\n${text}#endif /* MAC_OSX_TCL */\n"
+       }
+       aqua {
+           return "#ifdef MAC_OSX_TK\n${text}#endif /* MAC_OSX_TK */\n"
+       }
+       x11 {
+           return "#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */\n${text}#endif /* X11 */\n"
+       }
+    }
+    return "$text"
+}
+
+# genStubs::emitSlots --
+#
+#      Generate the stub table slots for the given interface.
+#
+# Arguments:
+#      name    The name of the interface being emitted.
+#      textVar The variable to use for output.
+#
+# Results:
+#      None.
+
+proc genStubs::emitSlots {name textVar} {
+    upvar $textVar text
+    forAllStubs $name makeSlot noGuard text {"    void (*reserved$i)(void);\n"}
+    return
+}
+
+# genStubs::parseDecl --
+#
+#      Parse a C function declaration into its component parts.
+#
+# Arguments:
+#      decl    The function declaration.
+#
+# Results:
+#      Returns a list of the form {returnType name args}.  The args
+#      element consists of a list of type/name pairs, or a single
+#      element "void".  If the function declaration is malformed
+#      then an error is displayed and the return value is {}.
+
+proc genStubs::parseDecl {decl} {
+    if {![regexp {^(.*)\((.*)\);?$} $decl all prefix args]} {
+       puts stderr "Malformed declaration: $decl"
+       return
+    }
+    set prefix [string trim $prefix]
+    if {![regexp {^(.+[ ][*]*)([^ *]+)$} $prefix all rtype fname]} {
+       puts stderr "Bad return type: $decl"
+       return
+    }
+    set rtype [string trim $rtype]
+    foreach arg [split $args ,] {
+       lappend argList [string trim $arg]
+    }
+    if {![string compare [lindex $argList end] "..."]} {
+       if {[llength $argList] != 2} {
+           puts stderr "Only one argument is allowed in varargs form: $decl"
+       }
+       set arg [parseArg [lindex $argList 0]]
+       if {$arg == "" || ([llength $arg] != 2)} {
+           puts stderr "Bad argument: '[lindex $argList 0]' in '$decl'"
+           return
+       }
+       set args [list TCL_VARARGS $arg]
+    } else {
+       set args {}
+       foreach arg $argList {
+           set argInfo [parseArg $arg]
+           if {![string compare $argInfo "void"]} {
+               lappend args "void"
+               break
+           } elseif {[llength $argInfo] == 2 || [llength $argInfo] == 3} {
+               lappend args $argInfo
+           } else {
+               puts stderr "Bad argument: '$arg' in '$decl'"
+               return
+           }
+       }
+    }
+    return [list $rtype $fname $args]
+}
+
+# genStubs::parseArg --
+#
+#      This function parses a function argument into a type and name.
+#
+# Arguments:
+#      arg     The argument to parse.
+#
+# Results:
+#      Returns a list of type and name with an optional third array
+#      indicator.  If the argument is malformed, returns "".
+
+proc genStubs::parseArg {arg} {
+    if {![regexp {^(.+[ ][*]*)([^][ *]+)(\[\])?$} $arg all type name array]} {
+       if {$arg == "void"} {
+           return $arg
+       } else {
+           return
+       }
+    }
+    set result [list [string trim $type] $name]
+    if {$array != ""} {
+       lappend result $array
+    }
+    return $result
+}
+
+# genStubs::makeDecl --
+#
+#      Generate the prototype for a function.
+#
+# Arguments:
+#      name    The interface name.
+#      decl    The function declaration.
+#      index   The slot index for this function.
+#
+# Results:
+#      Returns the formatted declaration string.
+
+proc genStubs::makeDecl {name decl index} {
+    variable scspec
+
+    lassign $decl rtype fname args
+
+    append text "/* $index */\n"
+    set line "$scspec $rtype"
+    set count [expr {2 - ([string length $line] / 8)}]
+    append line [string range "\t\t\t" 0 $count]
+    set pad [expr {24 - [string length $line]}]
+    if {$pad <= 0} {
+       append line " "
+       set pad 0
+    }
+    append line "$fname "
+
+    set arg1 [lindex $args 0]
+    switch -exact $arg1 {
+       void {
+           append line "(void)"
+       }
+       TCL_VARARGS {
+           set arg [lindex $args 1]
+           append line "TCL_VARARGS([lindex $arg 0],[lindex $arg 1])"
+       }
+       default {
+           set sep "("
+           foreach arg $args {
+               append line $sep
+               set next {}
+               append next [lindex $arg 0] " " [lindex $arg 1] \
+                       [lindex $arg 2]
+               if {[string length $line] + [string length $next] \
+                       + $pad > 76} {
+                   append text $line \n
+                   set line "\t\t\t\t"
+                   set pad 28
+               }
+               append line $next
+               set sep ", "
+           }
+           append line ")"
+       }
+    }
+    append text $line
+    
+    append text ";\n"
+    return $text
+}
+
+# genStubs::makeMacro --
+#
+#      Generate the inline macro for a function.
+#
+# Arguments:
+#      name    The interface name.
+#      decl    The function declaration.
+#      index   The slot index for this function.
+#
+# Results:
+#      Returns the formatted macro definition.
+
+proc genStubs::makeMacro {name decl index} {
+    lassign $decl rtype fname args
+
+    set lfname [string tolower [string index $fname 0]]
+    append lfname [string range $fname 1 end]
+
+    set text "#ifndef $fname\n#define $fname"
+    set arg1 [lindex $args 0]
+    set argList ""
+    switch -exact $arg1 {
+       void {
+           set argList "()"
+       }
+       TCL_VARARGS {
+       }
+       default {
+           set sep "("
+           foreach arg $args {
+               append argList $sep [lindex $arg 1]
+               set sep ", "
+           }
+           append argList ")"
+       }
+    }
+    append text " \\\n\t(${name}StubsPtr->$lfname)"
+    append text " /* $index */\n#endif\n"
+    return $text
+}
+
+# genStubs::makeSlot --
+#
+#      Generate the stub table entry for a function.
+#
+# Arguments:
+#      name    The interface name.
+#      decl    The function declaration.
+#      index   The slot index for this function.
+#
+# Results:
+#      Returns the formatted table entry.
+
+proc genStubs::makeSlot {name decl index} {
+    lassign $decl rtype fname args
+
+    set lfname [string tolower [string index $fname 0]]
+    append lfname [string range $fname 1 end]
+
+    set text "    "
+    append text $rtype " (*" $lfname ") "
+
+    set arg1 [lindex $args 0]
+    switch -exact $arg1 {
+       void {
+           append text "(void)"
+       }
+       TCL_VARARGS {
+           set arg [lindex $args 1]
+           append text "TCL_VARARGS([lindex $arg 0],[lindex $arg 1])"
+       }
+       default {
+           set sep "("
+           foreach arg $args {
+               append text $sep [lindex $arg 0] " " [lindex $arg 1] \
+                       [lindex $arg 2]
+               set sep ", "
+           }
+           append text ")"
+       }
+    }
+    
+    append text "; /* $index */\n"
+    return $text
+}
+
+# genStubs::makeInit --
+#
+#      Generate the prototype for a function.
+#
+# Arguments:
+#      name    The interface name.
+#      decl    The function declaration.
+#      index   The slot index for this function.
+#
+# Results:
+#      Returns the formatted declaration string.
+
+proc genStubs::makeInit {name decl index} {
+    append text "    " [lindex $decl 1] ", /* " $index " */\n"
+    return $text
+}
+
+# genStubs::forAllStubs --
+#
+#      This function iterates over all of the slots and invokes
+#      a callback for each slot.  The result of the callback is then
+#      placed inside appropriate guards.
+#
+# Arguments:
+#      name            The interface name.
+#      slotProc        The proc to invoke to handle the slot.  It will
+#                      have the interface name, the declaration,  and
+#                      the index appended.
+#      guardProc       The proc to invoke to add guards.  It will have
+#                      the slot status and text appended.
+#      textVar         The variable to use for output.
+#      skipString      The string to emit if a slot is skipped.  This
+#                      string will be subst'ed in the loop so "$i" can
+#                      be used to substitute the index value.
+#
+# Results:
+#      None.
+
+proc genStubs::forAllStubs {name slotProc guardProc textVar 
+       {skipString {"/* Slot $i is reserved */\n"}}} {
+    variable stubs
+    upvar $textVar text
+
+    set lastNum $stubs($name,lastNum)
+
+    for {set i 0} {$i <= $lastNum} {incr i} {
+       if {[info exists stubs($name,decl,$i)]} {
+           append text [$guardProc $stubs($name,status,$i) \
+                               [$slotProc $name $stubs($name,decl,$i) $i]]
+       } else {
+           eval {append text} $skipString
+       }
+    }
+}
+
+proc genStubs::noGuard  {status text} { return $text }
+
+proc genStubs::addGuard {status text} {
+    variable libraryName
+    set upName [string toupper $libraryName]
+
+    switch -- $status {
+       current { 
+           # No change
+       }
+       deprecated {
+           set text [ifdeffed "${upName}_DEPRECATED" $text]
+       }
+       obsolete {
+           set text ""
+       }
+       default {
+           puts stderr "Unrecognized status code $status"
+       }
+    }
+    return $text 
+}
+
+proc genStubs::ifdeffed {macro text} {
+    join [list "#ifdef $macro" $text "#endif" ""] \n
+}
+
+# genStubs::emitDeclarations --
+#
+#      This function emits the function declarations for this interface.
+#
+# Arguments:
+#      name    The interface name.
+#      textVar The variable to use for output.
+#
+# Results:
+#      None.
+
+proc genStubs::emitDeclarations {name textVar} {
+    variable libraryName
+    upvar $textVar text
+
+    set upName [string toupper $libraryName]
+    append text "\n#if !defined(USE_${upName}_STUBS)\n"
+    append text "\n/*\n * Exported function declarations:\n */\n\n"
+    forAllStubs $name makeDecl noGuard text
+    append text "\n#endif /* !defined(USE_${upName}_STUBS) */\n"
+
+    return
+}
+
+# genStubs::emitMacros --
+#
+#      This function emits the inline macros for an interface.
+#
+# Arguments:
+#      name    The name of the interface being emitted.
+#      textVar The variable to use for output.
+#
+# Results:
+#      None.
+
+proc genStubs::emitMacros {name textVar} {
+    variable libraryName
+    upvar $textVar text
+
+    set upName [string toupper $libraryName]
+    append text "\n#if defined(USE_${upName}_STUBS)\n"
+    append text "\n/*\n * Inline function declarations:\n */\n\n"
+    
+    forAllStubs $name makeMacro addGuard text
+
+    append text "\n#endif /* defined(USE_${upName}_STUBS) */\n"
+    return
+}
+
+# genStubs::emitHeader --
+#
+#      This function emits the body of the <name>Decls.h file for
+#      the specified interface.
+#
+# Arguments:
+#      name    The name of the interface being emitted.
+#
+# Results:
+#      None.
+
+proc genStubs::emitHeader {name} {
+    variable outDir
+    variable hooks
+    variable epoch
+    variable revision
+
+    set capName [string toupper [string index $name 0]]
+    append capName [string range $name 1 end]
+
+    set CAPName [string toupper $name]
+    append text "\n"
+    append text "#define ${CAPName}_STUBS_EPOCH $epoch\n"
+    append text "#define ${CAPName}_STUBS_REVISION $revision\n"
+
+    emitDeclarations $name text
+
+    if {[info exists hooks($name)]} {
+       append text "\ntypedef struct ${capName}StubHooks {\n"
+       foreach hook $hooks($name) {
+           set capHook [string toupper [string index $hook 0]]
+           append capHook [string range $hook 1 end]
+           append text "    struct ${capHook}Stubs *${hook}Stubs;\n"
+       }
+       append text "} ${capName}StubHooks;\n"
+    }
+    append text "\ntypedef struct ${capName}Stubs {\n"
+    append text "    int magic;\n"
+    append text "    int epoch;\n"
+    append text "    int revision;\n"
+    append text "    struct ${capName}StubHooks *hooks;\n\n"
+
+    emitSlots $name text
+
+    append text "} ${capName}Stubs;\n"
+
+    append text "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n"
+    append text "extern const ${capName}Stubs *${name}StubsPtr;\n"
+    append text "#ifdef __cplusplus\n}\n#endif\n"
+
+    emitMacros $name text
+
+    rewriteFile [file join $outDir ${name}Decls.h] $text
+    return
+}
+
+# genStubs::emitInit --
+#
+#      Generate the table initializers for an interface.
+#
+# Arguments:
+#      name            The name of the interface to initialize.
+#      textVar         The variable to use for output.
+#
+# Results:
+#      Returns the formatted output.
+
+proc genStubs::emitInit {name textVar} {
+    variable hooks
+    variable epoch
+    variable revision
+
+    upvar $textVar text
+
+    set capName [string toupper [string index $name 0]]
+    append capName [string range $name 1 end]
+    set CAPName [string toupper $name]
+
+    if {[info exists hooks($name)]} {
+       append text "\nstatic ${capName}StubHooks ${name}StubHooks = \{\n"
+       set sep "    "
+       foreach sub $hooks($name) {
+           append text $sep "&${sub}Stubs"
+           set sep ",\n    "
+       }
+       append text "\n\};\n"
+    }
+    append text "\n${capName}Stubs ${name}Stubs = \{\n"
+    append text "    TCL_STUB_MAGIC,\n"
+    append text "    ${CAPName}_STUBS_EPOCH,\n"
+    append text "    ${CAPName}_STUBS_REVISION,\n"
+    if {[info exists hooks($name)]} {
+       append text "    &${name}StubHooks,\n"
+    } else {
+       append text "    0,\n"
+    }
+    
+    forAllStubs $name makeInit noGuard text {"    0, /* $i */\n"}
+
+    append text "\};\n"
+    return
+}
+
+# genStubs::emitInits --
+#
+#      This function emits the body of the <name>StubInit.c file for
+#      the specified interface.
+#
+# Arguments:
+#      name    The name of the interface being emitted.
+#
+# Results:
+#      None.
+
+proc genStubs::emitInits {} {
+    variable hooks
+    variable outDir
+    variable libraryName
+    variable interfaces
+
+    # Assuming that dependencies only go one level deep, we need to emit
+    # all of the leaves first to avoid needing forward declarations.
+
+    set leaves {}
+    set roots {}
+    foreach name [lsort [array names interfaces]] {
+       if {[info exists hooks($name)]} {
+           lappend roots $name
+       } else {
+           lappend leaves $name
+       }
+    }
+    foreach name $leaves {
+       emitInit $name text
+    }
+    foreach name $roots {
+       emitInit $name text
+    }
+
+    rewriteFile [file join $outDir ${libraryName}StubInit.c] $text
+}
+
+# genStubs::init --
+#
+#      This is the main entry point.
+#
+# Arguments:
+#      None.
+#
+# Results:
+#      None.
+
+proc genStubs::init {} {
+    global argv argv0
+    variable outDir
+    variable interfaces
+
+    if {[llength $argv] < 2} {
+       puts stderr "usage: $argv0 outDir declFile ?declFile...?"
+       exit 1
+    }
+
+    set outDir [lindex $argv 0]
+
+    foreach file [lrange $argv 1 end] {
+       source $file
+    }
+
+    foreach name [lsort [array names interfaces]] {
+       puts "Emitting $name"
+       emitHeader $name
+    }
+
+    emitInits
+}
+
+# lassign --
+#
+#      This function emulates the TclX lassign command.
+#
+# Arguments:
+#      valueList       A list containing the values to be assigned.
+#      args            The list of variables to be assigned.
+#
+# Results:
+#      Returns any values that were not assigned to variables.
+
+proc lassign {valueList args} {
+  if {[llength $args] == 0} {
+      error "wrong # args: lassign list varname ?varname..?"
+  }
+
+  uplevel [list foreach $args $valueList {break}]
+  return [lrange $valueList [llength $args] end]
+}
+
+genStubs::init
diff --git a/win/makefile.vc b/win/makefile.vc
new file mode 100644 (file)
index 0000000..5cb6e50
--- /dev/null
@@ -0,0 +1,468 @@
+# makefile.vc --                                               -*- Makefile -*-
+#
+# Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+)
+#
+# This makefile is based upon the Tcl 8.4 Makefile.vc and modified to 
+# make it suitable as a general package makefile. Look for the word EDIT
+# which marks sections that may need modification. As a minumum you will
+# need to change the PROJECT, DOTVERSION and DLLOBJS variables to values
+# relevant to your package.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# 
+# Copyright (c) 1995-1996 Sun Microsystems, Inc.
+# Copyright (c) 1998-2000 Ajuba Solutions.
+# Copyright (c) 2001 ActiveState Corporation.
+# Copyright (c) 2001-2002 David Gravereaux.
+# Copyright (c) 2003-2006 Pat Thoyts
+#
+#-------------------------------------------------------------------------
+# RCS: @(#)$Id: makefile.vc,v 1.3 2007/04/03 15:38:53 pat Exp $
+#-------------------------------------------------------------------------
+
+# Check to see we are configured to build with MSVC (MSDEVDIR or MSVCDIR)
+# or with the MS Platform SDK (MSSDK). Visual Studio .NET 2003 and 2005 define
+# VCINSTALLDIR instead. The MSVC Toolkit release defines yet another.
+!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(MSSDK) && !defined(VCINSTALLDIR) && !defined(VCToolkitInstallDir)
+MSG = ^
+You need to run vcvars32.bat from Developer Studio or setenv.bat from the^
+Platform SDK first to setup the environment.  Jump to this line to read^
+the build instructions.
+!error $(MSG)
+!endif
+
+#------------------------------------------------------------------------------
+# HOW TO USE this makefile:
+#
+# 1)  It is now necessary to have %MSVCDir% set in the environment.  This is
+#     used  as a check to see if vcvars32.bat had been run prior to running
+#     nmake or during the installation of Microsoft Visual C++, MSVCDir had
+#     been set globally and the PATH adjusted.  Either way is valid.
+#
+#     You'll need to run vcvars32.bat contained in the MsDev's vc(98)/bin
+#     directory to setup the proper environment, if needed, for your current
+#     setup.  This is a needed bootstrap requirement and allows the swapping of
+#     different environments to be easier.
+#
+# 2)  To use the Platform SDK (not expressly needed), run setenv.bat after
+#     vcvars32.bat according to the instructions for it.  This can also turn on
+#     the 64-bit compiler, if your SDK has it.
+#
+# 3)  Targets are:
+#      all       -- Builds everything.
+#       <project> -- Builds the project (eg: nmake sample)
+#      test      -- Builds and runs the test suite.
+#      install   -- Installs the built binaries and libraries to $(INSTALLDIR)
+#                   in an appropriate subdirectory.
+#      clean/realclean/distclean -- varying levels of cleaning.
+#
+# 4)  Macros usable on the commandline:
+#      INSTALLDIR=<path>
+#              Sets where to install Tcl from the built binaries.
+#              C:\Progra~1\Tcl is assumed when not specified.
+#
+#      OPTS=static,msvcrt,staticpkg,threads,symbols,profile,loimpact,none
+#              Sets special options for the core.  The default is for none.
+#              Any combination of the above may be used (comma separated).
+#              'none' will over-ride everything to nothing.
+#
+#              static  =  Builds a static library of the core instead of a
+#                         dll.  The shell will be static (and large), as well.
+#              msvcrt  =  Effects the static option only to switch it from
+#                         using libcmt(d) as the C runtime [by default] to
+#                         msvcrt(d). This is useful for static embedding
+#                         support.
+#              staticpkg = Effects the static option only to switch
+#                         tclshXX.exe to have the dde and reg extension linked
+#                         inside it.
+#              nothreads = Turns off multithreading support (not recommended)
+#              thrdalloc = Use the thread allocator (shared global free pool).
+#              symbols =  Adds symbols for step debugging.
+#              profile =  Adds profiling hooks.  Map file is assumed.
+#              loimpact =  Adds a flag for how NT treats the heap to keep memory
+#                         in use, low.  This is said to impact alloc performance.
+#
+#      STATS=memdbg,compdbg,none
+#              Sets optional memory and bytecode compiler debugging code added
+#              to the core.  The default is for none.  Any combination of the
+#              above may be used (comma separated).  'none' will over-ride
+#              everything to nothing.
+#
+#              memdbg   = Enables the debugging memory allocator.
+#              compdbg  = Enables byte compilation logging.
+#
+#      MACHINE=(IX86|IA64|ALPHA|AMD64)
+#              Set the machine type used for the compiler, linker, and
+#              resource compiler.  This hook is needed to tell the tools
+#              when alternate platforms are requested.  IX86 is the default
+#              when not specified. If the CPU environment variable has been
+#              set (ie: recent Platform SDK) then MACHINE is set from CPU.
+#
+#      TMP_DIR=<path>
+#      OUT_DIR=<path>
+#              Hooks to allow the intermediate and output directories to be
+#              changed.  $(OUT_DIR) is assumed to be 
+#              $(BINROOT)\(Release|Debug) based on if symbols are requested.
+#              $(TMP_DIR) will de $(OUT_DIR)\<buildtype> by default.
+#
+#      TESTPAT=<file>
+#              Reads the tests requested to be run from this file.
+#
+#      CFG_ENCODING=encoding
+#              name of encoding for configuration information. Defaults
+#              to cp1252
+#
+# 5)  Examples:
+#
+#      Basic syntax of calling nmake looks like this:
+#      nmake [-nologo] -f makefile.vc [target|macrodef [target|macrodef] [...]]
+#
+#                        Standard (no frills)
+#       c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat
+#       Setting environment for using Microsoft Visual C++ tools.
+#       c:\tcl_src\win\>nmake -f makefile.vc all
+#       c:\tcl_src\win\>nmake -f makefile.vc install INSTALLDIR=c:\progra~1\tcl
+#
+#                         Building for Win64
+#       c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat
+#       Setting environment for using Microsoft Visual C++ tools.
+#       c:\tcl_src\win\>c:\progra~1\platfo~1\setenv.bat /pre64 /RETAIL
+#       Targeting Windows pre64 RETAIL
+#       c:\tcl_src\win\>nmake -f makefile.vc MACHINE=IA64
+#
+#------------------------------------------------------------------------------
+#==============================================================================
+###############################################################################
+#------------------------------------------------------------------------------
+
+!if !exist("makefile.vc")
+MSG = ^
+You must run this makefile only from the directory it is in.^
+Please `cd` to its location first.
+!error $(MSG)
+!endif
+
+#-------------------------------------------------------------------------
+# Project specific information (EDIT)
+#
+# You should edit this with the name and version of your project. This
+# information is used to generate the name of the package library and
+# it's install location.
+#
+# For example, the sample extension is  going to build sample04.dll and
+# would install it into $(INSTALLDIR)\lib\sample04
+#
+# You need to specify the object files that need to be linked into your
+# binary here.
+#
+#-------------------------------------------------------------------------
+
+PROJECT = tms
+
+# If your project uses Tk then you should uncomment the next line
+# USES_TK = 1
+
+!include "rules.vc"
+
+DOTVERSION      = 0.2
+VERSION         = $(DOTVERSION:.=)
+STUBPREFIX      = $(PROJECT)stub
+
+DLLOBJS = \
+       $(TMP_DIR)\tms.obj \
+       $(TMP_DIR)\subsystem.obj \
+       $(TMP_DIR)\bgeval.obj \
+       $(TMP_DIR)\config.obj \
+       $(TMP_DIR)\tmsWinInit.obj \
+       $(TMP_DIR)\tmsWinHandle.obj \
+       $(TMP_DIR)\tmsWinFNotify.obj \
+       $(TMP_DIR)\tmsWinMailslot.obj \
+       $(TMP_DIR)\tmsStubInit.obj \
+       $(TMP_DIR)\tmsStubLib.obj \
+       $(TMP_DIR)\tms.res
+
+PRJSTUBOBJS = \
+       $(TMP_DIR)\tmsStubLib.obj
+
+PRJHEADERS = \
+       $(GENERICDIR)\tms.h \
+       $(GENERICDIR)\tmsDecls.h \
+       $(GENERICDIR)\tmsPlatDecls.h
+
+#-------------------------------------------------------------------------
+# Target names and paths ( shouldn't need changing )
+#-------------------------------------------------------------------------
+
+BINROOT                = .
+ROOT            = ..
+
+PRJIMPLIB      = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
+PRJLIBNAME     = $(PROJECT)$(VERSION)$(SUFX).$(EXT)
+PRJLIB         = $(OUT_DIR)\$(PRJLIBNAME)
+
+PRJSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib
+PRJSTUBLIB     = $(OUT_DIR)\$(PRJSTUBLIBNAME)
+
+### Make sure we use backslash only.
+PRJ_INSTALL_DIR         = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION)
+LIB_INSTALL_DIR                = $(PRJ_INSTALL_DIR)
+BIN_INSTALL_DIR                = $(PRJ_INSTALL_DIR)
+DOC_INSTALL_DIR                = $(PRJ_INSTALL_DIR)
+SCRIPT_INSTALL_DIR     = $(PRJ_INSTALL_DIR)
+DEMO_INSTALL_DIR       = $(PRJ_INSTALL_DIR)
+INCLUDE_INSTALL_DIR    = $(_TCLDIR)\include
+
+### The following paths CANNOT have spaces in them.
+GENERICDIR     = $(ROOT)\generic
+WINDIR         = $(ROOT)\win
+LIBDIR          = $(ROOT)\library
+DOCDIR         = $(ROOT)\doc
+TOOLSDIR       = $(ROOT)\tools
+COMPATDIR      = $(ROOT)\compat
+
+#---------------------------------------------------------------------
+# Compile flags
+#---------------------------------------------------------------------
+
+!if !$(DEBUG)
+!if $(OPTIMIZING)
+### This cranks the optimization level to maximize speed
+cdebug = -Zi $(OPTIMIZATIONS)
+!else
+cdebug = -Zi
+!endif
+!else if "$(MACHINE)" == "IA64"
+### Warnings are too many, can't support warnings into errors.
+cdebug = -Zi -Od $(DEBUGFLAGS)
+!else
+cdebug = -Zi -WX $(DEBUGFLAGS)
+!endif
+
+### Declarations common to all compiler options
+cwarn = -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE
+cflags = -nologo -c $(COMPILERFLAGS) $(cwarn) -Fp$(TMP_DIR)^\
+
+# Warning level
+!if $(FULLWARNINGS)
+cflags = $(cflags) -W4
+!else
+cflags = $(cflags) -W3
+!endif
+
+!if $(MSVCRT)
+!if $(DEBUG) && !$(UNCHECKED)
+crt = -MDd
+!else
+crt = -MD
+!endif
+!else
+!if $(DEBUG) && !$(UNCHECKED)
+crt = -MTd
+!else
+crt = -MT
+!endif
+!endif
+
+!if !$(STATIC_BUILD)
+cflags = $(cflags) -DUSE_TCL_STUBS
+!if $(USES_TK)
+cflags = $(cflags) -DUSE_TK_STUBS
+!endif
+!endif
+
+INCLUDES       = $(TCL_INCLUDES) -I"$(WINDIR)" -I"$(GENERICDIR)"
+BASE_CFLAGS    = $(cflags) $(cdebug) $(crt) $(INCLUDES)
+CON_CFLAGS     = $(cflags) $(cdebug) $(crt) -DCONSOLE
+TCL_CFLAGS     = -DPACKAGE_NAME="\"$(PROJECT)\"" \
+                  -DPACKAGE_VERSION="\"$(DOTVERSION)\"" \
+                 -DBUILD_$(PROJECT) \
+                  $(BASE_CFLAGS) $(OPTDEFINES)
+
+#---------------------------------------------------------------------
+# Link flags
+#---------------------------------------------------------------------
+
+!if $(DEBUG)
+ldebug = -debug:full -debugtype:cv
+!if $(MSVCRT)
+ldebug = $(ldebug) -nodefaultlib:msvcrt
+!endif
+!else
+ldebug = -debug -opt:ref -opt:icf,3
+!endif
+
+### Declarations common to all linker options
+lflags = -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)
+
+!if $(FULLWARNINGS)
+lflags = $(lflags) -warn:3
+!endif
+
+!if $(PROFILE)
+lflags = $(lflags) -profile
+!endif
+
+!if $(ALIGN98_HACK) && !$(STATIC_BUILD)
+### Align sections for PE size savings.
+lflags = $(lflags) -opt:nowin98
+!else if !$(ALIGN98_HACK) && $(STATIC_BUILD)
+### Align sections for speed in loading by choosing the virtual page size.
+lflags = $(lflags) -align:4096
+!endif
+
+!if $(LOIMPACT)
+lflags = $(lflags) -ws:aggressive
+!endif
+
+dlllflags = $(lflags) -dll
+conlflags = $(lflags) -subsystem:console
+guilflags = $(lflags) -subsystem:windows
+!if !$(STATIC_BUILD)
+baselibs  = $(TCLSTUBLIB)
+!if $(USES_TK)
+baselibs  = $(baselibs) $(TKSTUBLIB)
+!endif
+!endif
+
+# Avoid 'unresolved external symbol __security_cookie' errors.
+# c.f. http://support.microsoft.com/?id=894573
+!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
+baselibs   = $(baselibs) bufferoverflowU.lib
+!endif
+
+#---------------------------------------------------------------------
+# TclTest flags
+#---------------------------------------------------------------------
+
+!IF "$(TESTPAT)" != ""
+TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT)
+!ENDIF
+
+#---------------------------------------------------------------------
+# Project specific targets (EDIT)
+#---------------------------------------------------------------------
+
+all:       setup $(PROJECT)
+$(PROJECT): setup $(PRJLIB)  $(PRJSTUBLIB)
+install:    install-binaries install-libraries install-docs install-demos
+
+!if "$(OS)" == "Windows_NT"  || "$(MSVCDIR)" == "IDE"
+test: setup $(PROJECT)
+       $(TCLSH) "$(ROOT)\tests\all.tcl" $(TESTFLAGS) -loadfile <<
+load [file normalize [file join [pwd] $(PRJLIB:\=/)]]
+<<
+!else
+test: setup $(PROJECT)
+        echo Please wait while the test results are collected
+       $(TCLSH) "$(ROOT)\tests\all.tcl" $(TESTFLAGS) -loadfile << >tests.log
+load [file normalize [file join [pwd] $(PRJLIB:\=/)]]
+<<
+        type tests.log | more
+!endif
+
+setup:
+       @if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR)
+       @if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR)
+
+$(PRJLIB): $(DLLOBJS)
+!if $(STATIC_BUILD)
+       $(lib32) -nologo -out:$@ @<<
+$**
+<<
+!else
+       $(link32) $(dlllflags) -base:0x14110000 -out:$@ $(baselibs) @<<
+$**
+<<
+       $(_VC_MANIFEST_EMBED_DLL)
+       -@del $*.exp
+!endif
+
+$(PRJSTUBLIB): $(PRJSTUBOBJS)
+       $(lib32) -nologo -out:$@ $(PRJSTUBOBJS)
+
+#---------------------------------------------------------------------
+# Implicit rules
+#---------------------------------------------------------------------
+
+{$(WINDIR)}.c{$(TMP_DIR)}.obj::
+    $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
+$<
+<<
+
+{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
+    $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
+$<
+<<
+
+{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
+    $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
+$<
+<<
+
+{$(WINDIR)}.rc{$(TMP_DIR)}.res:
+       $(rc32) -fo $@ -r -i "$(GENERICDIR)" -D__WIN32__ \
+                -DCOMMAVERSION=$(DOTVERSION:.=,),0 \
+                -DDOTVERSION=\"$(DOTVERSION)\" \
+                -DVERSION=\"$(VERSION)$(SUFX)\" \
+!if $(DEBUG)
+       -d DEBUG \
+!endif
+!if $(TCL_THREADS)
+       -d TCL_THREADS \
+!endif
+!if $(STATIC_BUILD)
+       -d STATIC_BUILD \
+!endif
+       $<
+
+.SUFFIXES:
+.SUFFIXES:.c .rc
+
+#---------------------------------------------------------------------
+# Installation. (EDIT)
+#
+# You may need to modify this section to reflect the final distribution
+# of your files and possibly to generate documentation.
+#
+#---------------------------------------------------------------------
+
+install-binaries:
+       @echo Installing binaries to '$(SCRIPT_INSTALL_DIR)'
+       @if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)"
+       @$(CPY) $(PRJLIB) "$(SCRIPT_INSTALL_DIR)" >NUL
+       @$(CPY) $(PRJSTUBLIB) "$(SCRIPT_INSTALL_DIR)" > NUL
+       @$(CPY) $(PRJHEADERS) "$(SCRIPT_INSTALL_DIR)" > NUL
+
+
+install-libraries:
+        @echo Installing libraries to '$(SCRIPT_INSTALL_DIR)'
+        @if exist $(LIBDIR) $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)"
+        @echo Installing package index in '$(SCRIPT_INSTALL_DIR)'
+        @type << >"$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl"
+package ifneeded tms $(DOTVERSION) "load \[file join [list $$dir] $(PROJECT)$(VERSION).$(EXT)\]"
+<<
+
+install-docs:
+       @echo Installing documentation files to '$(DOC_INSTALL_DIR)'
+       @if exist $(DOCDIR) $(CPY) $(DOCDIR)\*.n "$(DOC_INSTALL_DIR)"
+
+install-demos:
+       #@echo Installing sample applications in '$(DEMO_INSTALL_DIR)\demos'
+       #@if not exist "$(DEMO_INSTALL_DIR)\demos" mkdir "$(DEMO_INSTALL_DIR)\demos"
+       #@$(CPY) "$(ROOT)\demos" "$(DEMO_INSTALL_DIR)\demos" >NUL
+
+#---------------------------------------------------------------------
+# Clean up
+#---------------------------------------------------------------------
+
+clean:
+       @if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR)
+       @if exist $(WINDIR)\version.vc del $(WINDIR)\version.vc
+
+realclean: clean
+       @if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR)
+
+distclean: realclean
+       @if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe
+       @if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj
diff --git a/win/nmakehlp.c b/win/nmakehlp.c
new file mode 100644 (file)
index 0000000..d02d136
--- /dev/null
@@ -0,0 +1,570 @@
+/*
+ * ----------------------------------------------------------------------------
+ * nmakehlp.c --
+ *
+ *     This is used to fix limitations within nmake and the environment.
+ *
+ * Copyright (c) 2002 by David Gravereaux.
+ * Copyright (c) 2006 by Pat Thoyts
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * ----------------------------------------------------------------------------
+ * RCS: @(#) $Id: nmakehlp.c,v 1.2 2007/04/03 15:38:53 pat Exp $
+ * ----------------------------------------------------------------------------
+ */
+
+#define _CRT_SECURE_NO_DEPRECATE
+#include <windows.h>
+#pragma comment (lib, "user32.lib")
+#pragma comment (lib, "kernel32.lib")
+#include <stdio.h>
+#include <math.h>
+#if defined(_M_IA64) || defined(_M_AMD64)
+#pragma comment(lib, "bufferoverflowU")
+#endif
+
+/* ISO hack for dumb VC++ */
+#ifdef _MSC_VER
+#define   snprintf     _snprintf
+#endif
+
+
+
+/* protos */
+
+int            CheckForCompilerFeature(const char *option);
+int            CheckForLinkerFeature(const char *option);
+int            IsIn(const char *string, const char *substring);
+int            GrepForDefine(const char *file, const char *string);
+const char *    GetVersionFromFile(const char *filename, const char *match);
+DWORD WINAPI   ReadFromPipe(LPVOID args);
+
+/* globals */
+
+#define CHUNK  25
+#define STATICBUFFERSIZE    1000
+typedef struct {
+    HANDLE pipe;
+    char buffer[STATICBUFFERSIZE];
+} pipeinfo;
+
+pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'};
+pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'};
+\f
+/*
+ * exitcodes: 0 == no, 1 == yes, 2 == error
+ */
+
+int
+main(
+    int argc,
+    char *argv[])
+{
+    char msg[300];
+    DWORD dwWritten;
+    int chars;
+
+    /*
+     * Make sure children (cl.exe and link.exe) are kept quiet.
+     */
+
+    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+
+    /*
+     * Make sure the compiler and linker aren't effected by the outside world.
+     */
+
+    SetEnvironmentVariable("CL", "");
+    SetEnvironmentVariable("LINK", "");
+
+    if (argc > 1 && *argv[1] == '-') {
+       switch (*(argv[1]+1)) {
+       case 'c':
+           if (argc != 3) {
+               chars = snprintf(msg, sizeof(msg) - 1,
+                       "usage: %s -c <compiler option>\n"
+                       "Tests for whether cl.exe supports an option\n"
+                       "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
+               WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
+                       &dwWritten, NULL);
+               return 2;
+           }
+           return CheckForCompilerFeature(argv[2]);
+       case 'l':
+           if (argc != 3) {
+               chars = snprintf(msg, sizeof(msg) - 1,
+                       "usage: %s -l <linker option>\n"
+                       "Tests for whether link.exe supports an option\n"
+                       "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
+               WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
+                       &dwWritten, NULL);
+               return 2;
+           }
+           return CheckForLinkerFeature(argv[2]);
+       case 'f':
+           if (argc == 2) {
+               chars = snprintf(msg, sizeof(msg) - 1,
+                       "usage: %s -f <string> <substring>\n"
+                       "Find a substring within another\n"
+                       "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
+               WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
+                       &dwWritten, NULL);
+               return 2;
+           } else if (argc == 3) {
+               /*
+                * If the string is blank, there is no match.
+                */
+
+               return 0;
+           } else {
+               return IsIn(argv[2], argv[3]);
+           }
+       case 'g':
+           if (argc == 2) {
+               chars = snprintf(msg, sizeof(msg) - 1,
+                       "usage: %s -g <file> <string>\n"
+                       "grep for a #define\n"
+                       "exitcodes: integer of the found string (no decimals)\n",
+                       argv[0]);
+               WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
+                       &dwWritten, NULL);
+               return 2;
+           }
+           return GrepForDefine(argv[2], argv[3]);
+       case 'V':
+           if (argc != 4) {
+               chars = snprintf(msg, sizeof(msg) - 1,
+                   "usage: %s -V filename matchstring\n"
+                   "Extract a version from a file:\n"
+                   "eg: pkgIndex.tcl \"package ifneeded http\"",
+                   argv[0]);
+               WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
+                   &dwWritten, NULL);
+               return 0;
+           }
+           printf("%s\n", GetVersionFromFile(argv[2], argv[3]));
+           return 0;
+       }
+    }
+    chars = snprintf(msg, sizeof(msg) - 1,
+           "usage: %s -c|-l|-f|-g|-V ...\n"
+           "This is a little helper app to equalize shell differences between WinNT and\n"
+           "Win9x and get nmake.exe to accomplish its job.\n",
+           argv[0]);
+    WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
+    return 2;
+}
+\f
+int
+CheckForCompilerFeature(
+    const char *option)
+{
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    SECURITY_ATTRIBUTES sa;
+    DWORD threadID;
+    char msg[300];
+    BOOL ok;
+    HANDLE hProcess, h, pipeThreads[2];
+    char cmdline[100];
+
+    hProcess = GetCurrentProcess();
+
+    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+    ZeroMemory(&si, sizeof(STARTUPINFO));
+    si.cb = sizeof(STARTUPINFO);
+    si.dwFlags   = STARTF_USESTDHANDLES;
+    si.hStdInput = INVALID_HANDLE_VALUE;
+
+    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+    sa.lpSecurityDescriptor = NULL;
+    sa.bInheritHandle = FALSE;
+
+    /*
+     * Create a non-inheritible pipe.
+     */
+
+    CreatePipe(&Out.pipe, &h, &sa, 0);
+
+    /*
+     * Dupe the write side, make it inheritible, and close the original.
+     */
+
+    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
+           DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+    /*
+     * Same as above, but for the error side.
+     */
+
+    CreatePipe(&Err.pipe, &h, &sa, 0);
+    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
+           DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+    /*
+     * Base command line.
+     */
+
+    lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch ");
+
+    /*
+     * Append our option for testing
+     */
+
+    lstrcat(cmdline, option);
+
+    /*
+     * Filename to compile, which exists, but is nothing and empty.
+     */
+
+    lstrcat(cmdline, " .\\nul");
+
+    ok = CreateProcess(
+           NULL,           /* Module name. */
+           cmdline,        /* Command line. */
+           NULL,           /* Process handle not inheritable. */
+           NULL,           /* Thread handle not inheritable. */
+           TRUE,           /* yes, inherit handles. */
+           DETACHED_PROCESS, /* No console for you. */
+           NULL,           /* Use parent's environment block. */
+           NULL,           /* Use parent's starting directory. */
+           &si,            /* Pointer to STARTUPINFO structure. */
+           &pi);           /* Pointer to PROCESS_INFORMATION structure. */
+
+    if (!ok) {
+       DWORD err = GetLastError();
+       int chars = snprintf(msg, sizeof(msg) - 1,
+               "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
+
+       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
+               FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
+               (300-chars), 0);
+       WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg,lstrlen(msg), &err,NULL);
+       return 2;
+    }
+
+    /*
+     * Close our references to the write handles that have now been inherited.
+     */
+
+    CloseHandle(si.hStdOutput);
+    CloseHandle(si.hStdError);
+
+    WaitForInputIdle(pi.hProcess, 5000);
+    CloseHandle(pi.hThread);
+
+    /*
+     * Start the pipe reader threads.
+     */
+
+    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
+    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
+
+    /*
+     * Block waiting for the process to end.
+     */
+
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    CloseHandle(pi.hProcess);
+
+    /*
+     * Wait for our pipe to get done reading, should it be a little slow.
+     */
+
+    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
+    CloseHandle(pipeThreads[0]);
+    CloseHandle(pipeThreads[1]);
+
+    /*
+     * Look for the commandline warning code in both streams.
+     *  - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
+     */
+
+    return !(strstr(Out.buffer, "D4002") != NULL
+             || strstr(Err.buffer, "D4002") != NULL
+             || strstr(Out.buffer, "D9002") != NULL
+             || strstr(Err.buffer, "D9002") != NULL);
+}
+\f
+int
+CheckForLinkerFeature(
+    const char *option)
+{
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    SECURITY_ATTRIBUTES sa;
+    DWORD threadID;
+    char msg[300];
+    BOOL ok;
+    HANDLE hProcess, h, pipeThreads[2];
+    char cmdline[100];
+
+    hProcess = GetCurrentProcess();
+
+    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+    ZeroMemory(&si, sizeof(STARTUPINFO));
+    si.cb = sizeof(STARTUPINFO);
+    si.dwFlags   = STARTF_USESTDHANDLES;
+    si.hStdInput = INVALID_HANDLE_VALUE;
+
+    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+    sa.lpSecurityDescriptor = NULL;
+    sa.bInheritHandle = TRUE;
+
+    /*
+     * Create a non-inheritible pipe.
+     */
+
+    CreatePipe(&Out.pipe, &h, &sa, 0);
+
+    /*
+     * Dupe the write side, make it inheritible, and close the original.
+     */
+
+    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
+           DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+    /*
+     * Same as above, but for the error side.
+     */
+
+    CreatePipe(&Err.pipe, &h, &sa, 0);
+    DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
+           DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+
+    /*
+     * Base command line.
+     */
+
+    lstrcpy(cmdline, "link.exe -nologo ");
+
+    /*
+     * Append our option for testing.
+     */
+
+    lstrcat(cmdline, option);
+
+    ok = CreateProcess(
+           NULL,           /* Module name. */
+           cmdline,        /* Command line. */
+           NULL,           /* Process handle not inheritable. */
+           NULL,           /* Thread handle not inheritable. */
+           TRUE,           /* yes, inherit handles. */
+           DETACHED_PROCESS, /* No console for you. */
+           NULL,           /* Use parent's environment block. */
+           NULL,           /* Use parent's starting directory. */
+           &si,            /* Pointer to STARTUPINFO structure. */
+           &pi);           /* Pointer to PROCESS_INFORMATION structure. */
+
+    if (!ok) {
+       DWORD err = GetLastError();
+       int chars = snprintf(msg, sizeof(msg) - 1,
+               "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
+
+       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
+               FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars],
+               (300-chars), 0);
+       WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg,lstrlen(msg), &err,NULL);
+       return 2;
+    }
+
+    /*
+     * Close our references to the write handles that have now been inherited.
+     */
+
+    CloseHandle(si.hStdOutput);
+    CloseHandle(si.hStdError);
+
+    WaitForInputIdle(pi.hProcess, 5000);
+    CloseHandle(pi.hThread);
+
+    /*
+     * Start the pipe reader threads.
+     */
+
+    pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
+    pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
+
+    /*
+     * Block waiting for the process to end.
+     */
+
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    CloseHandle(pi.hProcess);
+
+    /*
+     * Wait for our pipe to get done reading, should it be a little slow.
+     */
+
+    WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
+    CloseHandle(pipeThreads[0]);
+    CloseHandle(pipeThreads[1]);
+
+    /*
+     * Look for the commandline warning code in the stderr stream.
+     */
+
+    return !(strstr(Out.buffer, "LNK1117") != NULL ||
+           strstr(Err.buffer, "LNK1117") != NULL ||
+           strstr(Out.buffer, "LNK4044") != NULL ||
+           strstr(Err.buffer, "LNK4044") != NULL);
+}
+\f
+DWORD WINAPI
+ReadFromPipe(
+    LPVOID args)
+{
+    pipeinfo *pi = (pipeinfo *) args;
+    char *lastBuf = pi->buffer;
+    DWORD dwRead;
+    BOOL ok;
+
+  again:
+    if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
+       CloseHandle(pi->pipe);
+       return (DWORD)-1;
+    }
+    ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
+    if (!ok || dwRead == 0) {
+       CloseHandle(pi->pipe);
+       return 0;
+    }
+    lastBuf += dwRead;
+    goto again;
+
+    return 0;  /* makes the compiler happy */
+}
+\f
+int
+IsIn(
+    const char *string,
+    const char *substring)
+{
+    return (strstr(string, substring) != NULL);
+}
+\f
+/*
+ * Find a specified #define by name.
+ *
+ * If the line is '#define TCL_VERSION "8.5"', it returns 85 as the result.
+ */
+
+int
+GrepForDefine(
+    const char *file,
+    const char *string)
+{
+    char s1[51], s2[51], s3[51];
+    FILE *f = fopen(file, "rt");
+
+    if (f == NULL) {
+       return 0;
+    }
+
+    do {
+       int r = fscanf(f, "%50s", s1);
+
+       if (r == 1 && !strcmp(s1, "#define")) {
+           /*
+            * Get next two words.
+            */
+
+           r = fscanf(f, "%50s %50s", s2, s3);
+           if (r != 2) {
+               continue;
+           }
+
+           /*
+            * Is the first word what we're looking for?
+            */
+
+           if (!strcmp(s2, string)) {
+               double d1;
+
+               fclose(f);
+
+               /*
+                * Add 1 past first double quote char. "8.5"
+                */
+
+               d1 = atof(s3 + 1);                /*    8.5  */
+               while (floor(d1) != d1) {
+                   d1 *= 10.0;
+               }
+               return ((int) d1);                /*    85   */
+           }
+       }
+    } while (!feof(f));
+
+    fclose(f);
+    return 0;
+}
+\f
+/*
+ * GetVersionFromFile --
+ *     Looks for a match string in a file and then returns the version
+ *     following the match where a version is anything acceptable to
+ *     package provide or package ifneeded.
+ */
+
+const char *
+GetVersionFromFile(
+    const char *filename,
+    const char *match)
+{
+    size_t cbBuffer = 100;
+    static char szBuffer[100];
+    char *szResult = NULL;
+    FILE *fp = fopen(filename, "rt");
+
+    if (fp != NULL) {
+       /*
+        * Read data until we see our match string.
+        */
+
+       while (fgets(szBuffer, cbBuffer, fp) != NULL) {
+           LPSTR p, q;
+
+           p = strstr(szBuffer, match);
+           if (p != NULL) {
+               /*
+                * Skip to first digit.
+                */
+
+               while (*p && !isdigit(*p)) {
+                   ++p;
+               }
+
+               /*
+                * Find ending whitespace.
+                */
+
+               q = p;
+               while (*q && (isalnum(*q) || *q == '.')) {
+                   ++q;
+               }
+
+               memcpy(szBuffer, p, q - p);
+               szBuffer[q-p] = 0;
+               szResult = szBuffer;
+               break;
+           }
+       }
+       fclose(fp);
+    }
+    return szResult;
+}
+
+/*
+ * Local variables:
+ *   mode: c
+ *   c-basic-offset: 4
+ *   fill-column: 78
+ *   indent-tabs-mode: t
+ *   tab-width: 8
+ * End:
+ */
diff --git a/win/rules.vc b/win/rules.vc
new file mode 100644 (file)
index 0000000..7fe0637
--- /dev/null
@@ -0,0 +1,586 @@
+#------------------------------------------------------------------------------
+# rules.vc --
+#
+#      Microsoft Visual C++ makefile include for decoding the commandline
+#      macros.  This file does not need editing to build Tcl.
+#
+#      This version is modified from the Tcl source version to support
+#      building extensions using nmake.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# 
+# Copyright (c) 2001-2002 David Gravereaux.
+# Copyright (c) 2003-2005 Patrick Thoyts
+#
+#------------------------------------------------------------------------------
+# RCS: @(#) $Id: rules.vc,v 1.2 2007/04/03 15:38:53 pat Exp $
+#------------------------------------------------------------------------------
+
+!ifndef _RULES_VC
+_RULES_VC = 1
+
+cc32           = $(CC)   # built-in default.
+link32         = link
+lib32          = lib
+rc32           = $(RC)   # built-in default.
+
+!ifndef INSTALLDIR
+### Assume the normal default.
+_INSTALLDIR    = C:\Program Files\Tcl
+!else
+### Fix the path separators.
+_INSTALLDIR    = $(INSTALLDIR:/=\)
+!endif
+
+!ifndef MACHINE
+MACHINE                = IX86
+!endif
+
+!ifndef CFG_ENCODING
+CFG_ENCODING   = \"cp1252\"
+!endif
+
+!ifndef USES_TK
+USES_TK         = 0
+!endif
+
+#----------------------------------------------------------
+# Set the proper copy method to avoid overwrite questions
+# to the user when copying files and selecting the right
+# "delete all" method.
+#----------------------------------------------------------
+
+!if "$(OS)" == "Windows_NT"
+RMDIR  = rmdir /S /Q
+ERRNULL  = 2>NUL
+!if ![ver | find "4.0" > nul]
+CPY    = echo y | xcopy /i >NUL
+COPY   = copy >NUL
+!else
+CPY    = xcopy /i /y >NUL
+COPY   = copy /y >NUL
+!endif
+!else # "$(OS)" != "Windows_NT"
+CPY    = xcopy /i >_JUNK.OUT # On Win98 NUL does not work here.
+COPY   = copy >_JUNK.OUT # On Win98 NUL does not work here.
+RMDIR  = deltree /Y
+NULL    = \NUL # Used in testing directory existence
+ERRNULL = >NUL # Win9x shell cannot redirect stderr
+!endif
+MKDIR   = mkdir
+
+!message ===============================================================================
+
+#----------------------------------------------------------
+# build the helper app we need to overcome nmake's limiting
+# environment.
+#----------------------------------------------------------
+
+!if !exist(nmakehlp.exe)
+!if [$(cc32) -nologo nmakehlp.c -link -subsystem:console > nul]
+!endif
+!endif
+
+#----------------------------------------------------------
+# Test for compiler features
+#----------------------------------------------------------
+
+### test for optimizations
+!if [nmakehlp -c -Ot]
+!message *** Compiler has 'Optimizations'
+OPTIMIZING     = 1
+!else
+!message *** Compiler doesn't have 'Optimizations'
+OPTIMIZING     = 0
+!endif
+
+OPTIMIZATIONS  =
+
+!if [nmakehlp -c -Ot]
+OPTIMIZATIONS  = $(OPTIMIZATIONS) -Ot
+!endif
+
+!if [nmakehlp -c -Oi]
+OPTIMIZATIONS  = $(OPTIMIZATIONS) -Oi
+!endif
+
+!if [nmakehlp -c -Op]
+OPTIMIZATIONS  = $(OPTIMIZATIONS) -Op
+!endif
+
+!if [nmakehlp -c -fp:strict]
+OPTIMIZATIONS  = $(OPTIMIZATIONS) -fp:strict
+!endif
+
+!if [nmakehlp -c -Gs]
+OPTIMIZATIONS  = $(OPTIMIZATIONS) -Gs
+!endif
+
+!if [nmakehlp -c -GS]
+OPTIMIZATIONS  = $(OPTIMIZATIONS) -GS
+!endif
+
+!if [nmakehlp -c -GL]
+OPTIMIZATIONS  = $(OPTIMIZATIONS) -GL
+!endif
+
+DEBUGFLAGS     =
+
+!if [nmakehlp -c -RTC1]
+DEBUGFLAGS     = $(DEBUGFLAGS) -RTC1
+!elseif [nmakehlp -c -GZ]
+DEBUGFLAGS     = $(DEBUGFLAGS) -GZ
+!endif
+
+COMPILERFLAGS  =-W3
+
+# In v13 -GL and -YX are incompatible.
+!if [nmakehlp -c -YX]
+!if ![nmakehlp -c -GL]
+OPTIMIZATIONS  = $(OPTIMIZATIONS) -YX
+!endif
+!endif
+
+!if "$(MACHINE)" == "IX86"
+### test for pentium errata
+!if [nmakehlp -c -QI0f]
+!message *** Compiler has 'Pentium 0x0f fix'
+COMPILERFLAGS  = $(COMPILERFLAGSS) -QI0f
+!else
+!message *** Compiler doesn't have 'Pentium 0x0f fix'
+!endif
+!endif
+
+!if "$(MACHINE)" == "IA64"
+### test for Itanium errata
+!if [nmakehlp -c -QIA64_Bx]
+!message *** Compiler has 'B-stepping errata workarounds'
+COMPILERFLAGS   = $(COMPILERFLAGS) -QIA64_Bx
+!else
+!message *** Compiler does not have 'B-stepping errata workarounds'
+!endif
+!endif
+
+!if "$(MACHINE)" == "IX86"
+### test for -align:4096, when align:512 will do.
+!if [nmakehlp -l -opt:nowin98]
+!message *** Linker has 'Win98 alignment problem'
+ALIGN98_HACK   = 1
+!else
+!message *** Linker doesn't have 'Win98 alignment problem'
+ALIGN98_HACK   = 0
+!endif
+!else
+ALIGN98_HACK   = 0
+!endif
+
+LINKERFLAGS     =
+
+!if [nmakehlp -l -ltcg]
+LINKERFLAGS     =-ltcg
+!endif
+
+#----------------------------------------------------------
+# MSVC8 (ships with Visual Studio 2005) generates a manifest
+# file that we should link into the binaries. This is how.
+#----------------------------------------------------------
+
+_VC_MANIFEST_EMBED_EXE=
+_VC_MANIFEST_EMBED_DLL=
+VCVER=0
+!if ![echo VCVERSION=_MSC_VER > vercl.x] \
+    && ![cl -nologo -TC -P vercl.x $(ERRNULL)]
+!include vercl.i
+!if $(VCVERSION) >= 1400
+VCVER=8
+_VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1
+_VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
+!elseif $(VCVERSION) >= 1300
+VCVER=7
+!elseif $(VCVERSION) >= 1200
+VCVER=6
+!endif
+!endif
+
+#----------------------------------------------------------
+# Decode the options requested.
+#----------------------------------------------------------
+
+!if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"]
+STATIC_BUILD   = 0
+TCL_THREADS    = 1
+DEBUG          = 0
+PROFILE                = 0
+MSVCRT         = 0
+LOIMPACT       = 0
+TCL_USE_STATIC_PACKAGES        = 0
+USE_THREAD_ALLOC = 1
+USE_THREAD_STORAGE = 1
+UNCHECKED       = 0
+!else
+!if [nmakehlp -f $(OPTS) "static"]
+!message *** Doing static
+STATIC_BUILD   = 1
+!else
+STATIC_BUILD   = 0
+!endif
+!if [nmakehlp -f $(OPTS) "msvcrt"]
+!message *** Doing msvcrt
+MSVCRT         = 1
+!else
+MSVCRT         = 0
+!endif
+!if [nmakehlp -f $(OPTS) "staticpkg"]
+!message *** Doing staticpkg
+TCL_USE_STATIC_PACKAGES        = 1
+!else
+TCL_USE_STATIC_PACKAGES        = 0
+!endif
+!if [nmakehlp -f $(OPTS) "nothreads"]
+!message *** Compile explicitly for non-threaded tcl
+TCL_THREADS    = 0
+!else
+TCL_THREADS     = 1
+!endif
+!if [nmakehlp -f $(OPTS) "symbols"]
+!message *** Doing symbols
+DEBUG          = 1
+!else
+DEBUG          = 0
+!endif
+!if [nmakehlp -f $(OPTS) "profile"]
+!message *** Doing profile
+PROFILE                = 1
+!else
+PROFILE                = 0
+!endif
+!if [nmakehlp -f $(OPTS) "loimpact"]
+!message *** Doing loimpact
+LOIMPACT       = 1
+!else
+LOIMPACT       = 0
+!endif
+!if [nmakehlp -f $(OPTS) "thrdalloc"]
+!message *** Doing thrdalloc
+USE_THREAD_ALLOC = 1
+!else
+USE_THREAD_ALLOC = 0
+!endif
+!if [nmakehlp -f $(OPTS) "thrdstorage"]
+!message *** Doing thrdstorage
+USE_THREAD_STORAGE = 1
+!else
+USE_THREAD_STORAGE = 0
+!endif
+!if [nmakehlp -f $(OPTS) "unchecked"]
+!message *** Doing unchecked
+UNCHECKED = 1
+!else
+UNCHECKED = 0
+!endif
+!endif
+
+
+!if !$(STATIC_BUILD)
+# Make sure we don't build overly fat DLLs.
+MSVCRT         = 1
+# We shouldn't statically put the extensions inside the shell when dynamic.
+TCL_USE_STATIC_PACKAGES = 0
+!endif
+
+
+#----------------------------------------------------------
+# Figure-out how to name our intermediate and output directories.
+# We wouldn't want different builds to use the same .obj files
+# by accident.
+#----------------------------------------------------------
+
+#----------------------------------------
+# Naming convention:
+#   t = full thread support.
+#   s = static library (as opposed to an
+#      import library)
+#   g = linked to the debug enabled C
+#      run-time.
+#   x = special static build when it
+#      links to the dynamic C run-time.
+#----------------------------------------
+SUFX       = sgx
+
+!if $(DEBUG)
+BUILDDIRTOP = Debug
+!else
+BUILDDIRTOP = Release
+!endif
+
+!if "$(MACHINE)" != "IX86"
+BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE)
+!endif
+!if $(VCVER) > 6
+BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER)
+!endif
+
+!if !$(DEBUG) || $(DEBUG) && $(UNCHECKED)
+SUFX       = $(SUFX:g=)
+!endif
+
+TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX
+
+!if !$(STATIC_BUILD)
+TMP_DIRFULL = $(TMP_DIRFULL:Static=)
+SUFX       = $(SUFX:s=)
+EXT        = dll
+!if $(MSVCRT)
+TMP_DIRFULL = $(TMP_DIRFULL:X=)
+SUFX       = $(SUFX:x=)
+!endif
+!else
+TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=)
+EXT        = lib
+!if !$(MSVCRT)
+TMP_DIRFULL = $(TMP_DIRFULL:X=)
+SUFX       = $(SUFX:x=)
+!endif
+!endif
+
+!if !$(TCL_THREADS)
+TMP_DIRFULL = $(TMP_DIRFULL:Threaded=)
+SUFX       = $(SUFX:t=)
+!endif
+
+!ifndef TMP_DIR
+TMP_DIR            = $(TMP_DIRFULL)
+!ifndef OUT_DIR
+OUT_DIR            = .\$(BUILDDIRTOP)
+!endif
+!else
+!ifndef OUT_DIR
+OUT_DIR            = $(TMP_DIR)
+!endif
+!endif
+
+
+#----------------------------------------------------------
+# Decode the statistics requested.
+#----------------------------------------------------------
+
+!if "$(STATS)" == "" || [nmakehlp -f "$(STATS)" "none"]
+TCL_MEM_DEBUG      = 0
+TCL_COMPILE_DEBUG   = 0
+!else
+!if [nmakehlp -f $(STATS) "memdbg"]
+!message *** Doing memdbg
+TCL_MEM_DEBUG      = 1
+!else
+TCL_MEM_DEBUG      = 0
+!endif
+!if [nmakehlp -f $(STATS) "compdbg"]
+!message *** Doing compdbg
+TCL_COMPILE_DEBUG   = 1
+!else
+TCL_COMPILE_DEBUG   = 0
+!endif
+!endif
+
+
+#----------------------------------------------------------
+# Decode the checks requested.
+#----------------------------------------------------------
+
+!if "$(CHECKS)" == "" || [nmakehlp -f "$(CHECKS)" "none"]
+TCL_NO_DEPRECATED          = 0
+FULLWARNINGS               = 0
+!else
+!if [nmakehlp -f $(CHECKS) "nodep"]
+!message *** Doing nodep check
+TCL_NO_DEPRECATED          = 1
+!else
+TCL_NO_DEPRECATED          = 0
+!endif
+!if [nmakehlp -f $(CHECKS) "fullwarn"]
+!message *** Doing full warnings check
+FULLWARNINGS               = 1
+!else
+FULLWARNINGS               = 0
+!endif
+!endif
+
+
+#----------------------------------------------------------
+# Set our defines now armed with our options.
+#----------------------------------------------------------
+
+OPTDEFINES     = -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING)
+
+!if $(TCL_MEM_DEBUG)
+OPTDEFINES     = $(OPTDEFINES) -DTCL_MEM_DEBUG
+!endif
+!if $(TCL_COMPILE_DEBUG)
+OPTDEFINES     = $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS
+!endif
+!if $(TCL_THREADS)
+OPTDEFINES     = $(OPTDEFINES) -DTCL_THREADS=1
+!if $(USE_THREAD_ALLOC)
+OPTDEFINES     = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1
+!endif
+!if $(USE_THREAD_STORAGE)
+OPTDEFINES     = $(OPTDEFINES) -DUSE_THREAD_STORAGE=1
+!endif
+!endif
+!if $(STATIC_BUILD)
+OPTDEFINES     = $(OPTDEFINES) -DSTATIC_BUILD
+!endif
+!if $(TCL_NO_DEPRECATED)
+OPTDEFINES     = $(OPTDEFINES) -DTCL_NO_DEPRECATED
+!endif
+
+!if $(DEBUG)
+OPTDEFINES     = $(OPTDEFINES) -DTCL_CFG_DEBUG
+!elseif $(OPTIMIZING)
+OPTDEFINES     = $(OPTDEFINES) -DTCL_CFG_OPTIMIZED
+!endif
+!if $(PROFILE)
+OPTDEFINES     = $(OPTDEFINES) -DTCL_CFG_PROFILED
+!endif
+!if "$(MACHINE)" == "IA64"
+OPTDEFINES     = $(OPTDEFINES) -DTCL_CFG_DO64BIT
+!endif
+
+
+#----------------------------------------------------------
+# Get common info used when building extensions.
+#----------------------------------------------------------
+
+!if "$(PROJECT)" != "tcl"
+
+# If INSTALLDIR set to tcl root dir then reset to the lib dir.
+!if exist("$(_INSTALLDIR)\include\tcl.h")
+_INSTALLDIR=$(_INSTALLDIR)\lib
+!endif
+
+!if !defined(TCLDIR)
+!if exist("$(_INSTALLDIR)\..\include\tcl.h")
+TCLINSTALL     = 1
+_TCLDIR                = $(_INSTALLDIR)\..
+_TCL_H          = $(_INSTALLDIR)\..\include\tcl.h
+TCLDIR          = $(_INSTALLDIR)\..
+!else
+MSG=^
+Failed to find tcl.h.  Set the TCLDIR macro.
+!error $(MSG)
+!endif
+!else
+_TCLDIR        = $(TCLDIR:/=\)
+!if exist("$(_TCLDIR)\include\tcl.h")
+TCLINSTALL     = 1
+_TCL_H          = $(_TCLDIR)\include\tcl.h
+!elseif exist("$(_TCLDIR)\generic\tcl.h")
+TCLINSTALL     = 0
+_TCL_H          = $(_TCLDIR)\generic\tcl.h
+!else
+MSG =^
+Failed to find tcl.h.  The TCLDIR macro does not appear correct.
+!error $(MSG)
+!endif
+!endif
+
+!if [echo REM = This file is generated from rules.vc > version.vc]
+!endif
+!if exist("$(_TCL_H)")
+!if [echo TCL_DOTVERSION = \>> version.vc] \
+   && [nmakehlp -V "$(_TCL_H)" TCL_VERSION >> version.vc]
+!endif
+!endif
+!include version.vc
+TCL_VERSION    = $(TCL_DOTVERSION:.=)
+
+!if $(TCLINSTALL)
+TCLSH          = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe"
+TCLSTUBLIB     = "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib"
+TCLIMPLIB      = "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib"
+TCL_LIBRARY    = $(_TCLDIR)\lib
+TCL_INCLUDES    = -I"$(_TCLDIR)\include"
+!else
+TCLSH          = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe"
+TCLSTUBLIB     = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib"
+TCLIMPLIB      = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib"
+TCL_LIBRARY    = $(_TCLDIR)\library
+TCL_INCLUDES   = -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"
+!endif
+
+!endif
+
+#----------------------------------------------------------
+# Optionally check for Tk info for building extensions.
+#----------------------------------------------------------
+
+!if $(USES_TK)
+
+!if !defined(TKDIR)
+!if exist("$(_INSTALLDIR)\..\include\tk.h")
+TKINSTALL      = 1
+_TKDIR         = $(_INSTALLDIR)\..
+_TK_H          = $(_TKDIR)\include\tk.h
+TKDIR          = $(_TKDIR)
+!elseif exist("$(_TCLDIR)\include\tk.h")
+TKINSTALL      = 1
+_TKDIR         = $(_TCLDIR)
+_TK_H          = $(_TKDIR)\include\tk.h
+TKDIR          = $(_TKDIR)
+!else
+MSG =^
+Failed to find tk.h. Set the TKDIR macro.
+!error $(MSG)
+!endif
+!else
+_TKDIR = $(TKDIR:/=\)
+!if exist("$(_TKDIR)\include\tk.h")
+TKINSTALL      = 1
+_TK_H          = $(_TKDIR)\include\tk.h
+!elseif exist("$(_TKDIR)\generic\tk.h")
+TKINSTALL      = 0
+_TK_H          = $(_TKDIR)\generic\tk.h
+!else
+MSG =^
+Failed to find tk.h. The TKDIR macro does not appear correct.
+!error $(MSG)
+!endif
+!endif
+
+TK_DOTVERSION = 8.4
+!if exist("$(_TK_H)")
+!if [echo TK_DOTVERSION = \>> version.vc] \
+   && [nmakehlp -V "$(_TK_H)" TK_VERSION >> version.vc]
+!endif
+!endif
+!include version.vc
+TK_VERSION = $(TK_DOTVERSION:.=)
+
+!if $(TKINSTALL)
+WISH           = "$(_TKDIR)\bin\wish$(TK_VERSION)$(SUFX).exe"
+TKSTUBLIB      = "$(_TKDIR)\lib\tkstub$(TK_VERSION).lib"
+TKIMPLIB       = "$(_TKDIR)\lib\tk$(TK_VERSION)$(SUFX).lib"
+TK_INCLUDES     = -I"$(_TKDIR)\include"
+!else
+WISH           = "$(_TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)$(SUFX).exe"
+TKSTUBLIB      = "$(_TKDIR)\win\$(BUILDDIRTOP)\tkstub$(TCL_VERSION).lib"
+TKIMPLIB       = "$(_TKDIR)\win\$(BUILDDIRTOP)\tk$(TCL_VERSION)$(SUFX).lib"
+TK_INCLUDES     = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
+!endif
+
+!endif
+
+#----------------------------------------------------------
+# Display stats being used.
+#----------------------------------------------------------
+
+!message *** Intermediate directory will be '$(TMP_DIR)'
+!message *** Output directory will be '$(OUT_DIR)'
+!message *** Suffix for binaries will be '$(SUFX)'
+!message *** Optional defines are '$(OPTDEFINES)'
+!message *** Compiler version $(VCVER)
+!message *** Compiler options '$(OPTIMIZATIONS) $(DEBUGFLAGS)'
+!message *** Link options '$(LINKERFLAGS)'
+
+!endif
diff --git a/win/tms.rc b/win/tms.rc
new file mode 100644 (file)
index 0000000..82394ef
--- /dev/null
@@ -0,0 +1,38 @@
+// tms.rc - Copyright (C) 2006 Pat Thoyts <patthoyts@users.sourceforge.net>
+//
+// There is no need to modify this file.
+//
+
+#include <winver.h>
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION   COMMAVERSION
+ PRODUCTVERSION        COMMAVERSION
+ FILEFLAGSMASK 0x3fL
+#ifdef DEBUG
+ FILEFLAGS     VS_FF_DEBUG
+#else
+ FILEFLAGS     0x0L
+#endif
+ FILEOS                VOS__WINDOWS32
+ FILETYPE      VFT_DLL
+ FILESUBTYPE   0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "FileDescription",  "Tcl Message System " DOTVERSION "\0"
+            VALUE "OriginalFilename", "tms" VERSION ".dll\0"
+            VALUE "CompanyName",      "Pat Thoyts\0"
+            VALUE "FileVersion",      DOTVERSION "\0"
+            VALUE "LegalCopyright",   "Copyright \251 2006 Pat Thoyts\0"
+            VALUE "ProductName",      "Tcl Message System " DOTVERSION "\0"
+            VALUE "ProductVersion",   DOTVERSION "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
diff --git a/win/tmsWinFNotify.c b/win/tmsWinFNotify.c
new file mode 100644 (file)
index 0000000..5531e13
--- /dev/null
@@ -0,0 +1,385 @@
+/* tclWinFNotify.c - Copyright (C) 2007 Pat Thoyts <patthoyts@users.sf.net>
+ *
+ * Implement the Win32 FindFirstChangeNotification stuff within the TMS
+ * system. This should really be the platform specific side of a generic
+ * file change notification tms subsystem.
+ *
+ * $Id: tmsWinFNotify.c,v 1.1 2007/04/03 15:38:53 pat Exp $
+ */
+
+#include "tmsWinInt.h"
+
+typedef struct FNotifyItem {
+    TmsWin32Handle wait;
+    Tcl_Interp    *interp;
+    Tcl_Command    token;
+    Tcl_Obj       *pathObj;
+    Tcl_Obj       *cmdObj;
+    Tcl_Obj       *flagsObj;
+    Tcl_Obj       *recurseObj;
+    struct FNotifyItem *nextPtr;
+} FNotifyItem;
+
+typedef struct FNotifyPackage {
+    Tcl_Interp  *interp;
+    int          uid;
+    int          count;
+    FNotifyItem *items;
+} FNotifyPackage;
+
+typedef struct FNotifyEvent {
+    Tcl_Event   header;
+    Tcl_Interp *interp;
+    Tcl_Command token;
+    Tcl_Obj    *cmdObj;
+} FNotifyEvent;
+
+
+struct Tms_ConfigureSpec FNotifyConfig[] = {
+    /* name    type    dataelement                 default */
+    { "-path", Tms_Offset(FNotifyItem,pathObj), TMS_READONLY, NULL },
+    { "-command", Tms_Offset(FNotifyItem,cmdObj), TMS_READWRITE, NULL },
+    { "-recurse", Tms_Offset(FNotifyItem,recurseObj), TMS_READWRITE, "1" },
+    { "-flags", Tms_Offset(FNotifyItem,flagsObj), TMS_READONLY, NULL },
+    { NULL },
+};
+
+static int EventProc(Tcl_Event *eventPtr, int flags);
+static void NotificationProc(void *clientData);
+
+
+enum {
+    MOD_ACCESS, MOD_MODIFY, MOD_CREATE, MOD_DELETE, MOD_RENAME, MOD_ATTRIB,
+    MOD_SIZE, MOD_SECURITY
+};
+
+const char *flagStrings[] = {
+    "access", "modify", "create", "delete", "rename", "attrib",
+    "size", "security", NULL
+};
+
+static int
+GetFlagsFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *flagsPtr)
+{
+    Tcl_Obj **eltv;
+    int eltc = 0, elt = 0, flag = 0, flags = 0;
+    int r = Tcl_ListObjGetElements(interp, objPtr, &eltc, &eltv);
+    for (elt = 0; TCL_OK == r && elt < eltc; ++elt) {
+       r = Tcl_GetIndexFromObj(interp, eltv[elt], flagStrings, 
+           "flags", 0, &flag);
+       if (r == TCL_OK) {
+           switch (flag) {
+               case MOD_ACCESS: 
+                   flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
+                   break;
+               case MOD_MODIFY:
+                   flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
+                   break;
+               case MOD_CREATE:
+                   flags |= FILE_NOTIFY_CHANGE_CREATION;
+                   break;
+               case MOD_DELETE:
+               case MOD_RENAME:
+                   flags |= FILE_NOTIFY_CHANGE_FILE_NAME 
+                       | FILE_NOTIFY_CHANGE_DIR_NAME;
+                   break;
+               case MOD_ATTRIB:
+                   flags |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
+                   break;
+               case MOD_SIZE:
+                   flags |= FILE_NOTIFY_CHANGE_SIZE;
+                   break;
+               case MOD_SECURITY:
+                   flags |= FILE_NOTIFY_CHANGE_FILE_NAME;
+                   break;
+               default:
+                   return TCL_ERROR;
+           }
+       }
+    }
+    *flagsPtr = flags;
+    return r;
+}
+\f
+static int
+InstanceConfigureCmd(ClientData clientData, Tcl_Interp *interp,
+    int objc, Tcl_Obj *const objv[])
+{
+    if (objc > 4 && objc % 2 != 0) {
+       Tcl_WrongNumArgs(interp, 2, objv, "?name value ...?");
+       return TCL_ERROR;
+    }
+    return Tms_Configure(FNotifyConfig, clientData,
+       interp, objc - 2, objv + 2);
+}
+\f
+static int
+InstanceCgetCmd(ClientData clientData, Tcl_Interp *interp,
+    int objc, Tcl_Obj *const objv[])
+{
+    if (objc != 3) {
+       Tcl_WrongNumArgs(interp, 2, objv, "-option");
+       return TCL_ERROR;
+    }
+    return Tms_Configure(FNotifyConfig, clientData,
+       interp, objc - 2, objv + 2);
+}
+\f
+/*
+ * InstanceCloseCmd --
+ *     Close the fnotify instance
+ */
+
+static int
+InstanceCloseCmd(ClientData clientData, Tcl_Interp *interp,
+    int objc, Tcl_Obj *const objv[])
+{
+    FNotifyItem *itemPtr = clientData;
+    return Tcl_DeleteCommandFromToken(interp, itemPtr->token);
+}
+\f
+/*
+ * InstanceCmd --
+ *     Instance command ensemble
+ */
+
+struct Ensemble InstanceEnsemble[] = {
+    { "configure", InstanceConfigureCmd, NULL },
+    { "cget",      InstanceCgetCmd, NULL },
+    { "close",     InstanceCloseCmd, NULL },
+    { NULL, NULL, NULL },
+};
+
+static int
+InstanceCmd(ClientData clientData, Tcl_Interp *interp,
+    int objc, Tcl_Obj *const objv[])
+{
+    struct Ensemble *ensemble = InstanceEnsemble;
+    int option = 1, index;
+
+    while (option < objc) {
+        if (Tcl_GetIndexFromObjStruct(interp, objv[option], 
+               ensemble, sizeof(ensemble[0]), "command", 0, &index) != TCL_OK)
+        {
+            return TCL_ERROR;
+        }
+
+        if (ensemble[index].command) {
+            return ensemble[index].command(clientData, interp, objc, objv);
+        }
+        ensemble = ensemble[index].ensemble;
+        ++option;
+    }
+    Tcl_WrongNumArgs(interp, option, objv, "option ?arg arg...?");
+    return TCL_ERROR;
+}
+\f
+/*
+ * InstanceCleanup --
+ *     Cleanup all resources associated with the instance.
+ */
+
+static void
+InstanceCleanup(ClientData clientData)
+{
+    FNotifyItem *itemPtr = clientData;
+    if (itemPtr) {
+       Tms_RemoveWin32Handle((TmsWin32Handle *)itemPtr);
+       Tcl_DecrRefCount(itemPtr->pathObj);
+       Tcl_DecrRefCount(itemPtr->cmdObj);
+       Tcl_DecrRefCount(itemPtr->recurseObj);
+       Tcl_DecrRefCount(itemPtr->flagsObj);
+       FindCloseChangeNotification(itemPtr->wait.handle);
+       ckfree((char *)clientData);
+    }    
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ *
+ *     tms::fnotify create path -mask {. . .} -command cmd
+ */
+
+static int
+FNotifyCreate(void *clientData, Tms_SubsystemSpec *specPtr,
+    Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+    FNotifyPackage *pkgPtr = clientData;
+    FNotifyItem *itemPtr = NULL;
+    HANDLE hNotify = INVALID_HANDLE_VALUE;
+    char name[TCL_INTEGER_SPACE + 8];
+    DWORD flags = 0;
+    int r = TCL_OK, recurse = 0;
+
+    itemPtr = (FNotifyItem *)ckalloc(sizeof(FNotifyItem));
+    Tms_ConfigureDefault(FNotifyConfig, itemPtr);
+    r = Tms_Configure(FNotifyConfig, itemPtr, interp, objc, objv);
+    if (r != TCL_OK) {
+       ckfree((char *)itemPtr);
+       return r;
+    }
+
+    r = GetFlagsFromObj(interp, itemPtr->flagsObj, &flags);
+    if (TCL_OK == r) 
+       r = Tcl_GetBooleanFromObj(interp, itemPtr->recurseObj, &recurse);
+    if (TCL_OK == r) {
+       //const TCHAR *native = Tcl_FSGetNativePath(itemPtr->pathObj);
+       //OutputDebugString("Notification path: ");
+       //OutputDebugString(native);
+       //OutputDebugString("\n");
+       //hNotify = FindFirstChangeNotification(native, recurse, flags);
+       const WCHAR *native = Tcl_GetUnicode(itemPtr->pathObj);
+       hNotify = FindFirstChangeNotificationW(native, recurse, flags);
+       if (hNotify == INVALID_HANDLE_VALUE) {
+           // FIX ME: Win32Error stuff.
+           Tcl_SetResult(interp, "error setting notification", TCL_STATIC);
+           r = TCL_ERROR;
+       }
+    }
+    if (r != TCL_OK) {
+       ckfree((char *)itemPtr);
+       return r;
+    }
+
+    itemPtr->interp = interp;
+    itemPtr->wait.handle = hNotify;
+    itemPtr->wait.proc = NotificationProc;
+    itemPtr->wait.tid = Tcl_GetCurrentThread();
+    Tms_AddWin32Handle((TmsWin32Handle *)itemPtr);
+
+    sprintf(name, "fnotify%d", InterlockedIncrement(&pkgPtr->uid));
+    itemPtr->token = Tcl_CreateObjCommand(interp, name, InstanceCmd,
+       itemPtr, InstanceCleanup);
+    Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
+    
+    return TCL_OK;
+}
+
+static void
+NotificationProc(void *clientData)
+{
+    FNotifyItem *itemPtr = clientData;
+    FNotifyEvent *evPtr = NULL;
+
+    OutputDebugString("NotificationProc\n");
+    evPtr = (FNotifyEvent *)ckalloc(sizeof(FNotifyEvent));
+    evPtr->header.proc = EventProc;
+    evPtr->header.nextPtr = NULL;
+    evPtr->interp = itemPtr->interp;
+    evPtr->token = itemPtr->token;
+    evPtr->cmdObj = Tcl_DuplicateObj(itemPtr->cmdObj);
+    Tcl_Preserve(evPtr->interp);
+    Tcl_IncrRefCount(evPtr->cmdObj);
+    Tcl_ThreadQueueEvent(itemPtr->wait.tid, 
+       (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
+    Tcl_ThreadAlert(itemPtr->wait.tid);
+
+    /* Wait for the next such event */
+    FindNextChangeNotification(itemPtr->wait.handle);
+
+    return;
+}
+\f
+/*
+ * EventProc --
+ *     Returns 1 if the event was handled. 0 if the flags indicate we 
+ *     should not process file events.
+ */
+
+static int
+EventProc(Tcl_Event *eventPtr, int flags)
+{
+    FNotifyEvent *evPtr = (FNotifyEvent *)eventPtr;
+    Tcl_Obj **objv;
+    int objc = 0;
+
+    OutputDebugString("EventProc\n");
+
+    if (!(flags & TCL_FILE_EVENTS)) {
+       return 0;
+    }
+    
+    /*
+     * Append our instance name to the end of the command list and
+     * evaluate in the background
+     */
+    
+    Tcl_ListObjGetElements(NULL, evPtr->cmdObj, &objc, &objv);
+    if (objc > 0) {
+       Tcl_Obj **cmdv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 1));
+       memcpy(cmdv, objv, sizeof(Tcl_Obj *) * objc);
+       cmdv[objc] = Tcl_NewStringObj(
+           Tcl_GetCommandName(evPtr->interp, evPtr->token), -1);
+       OutputDebugString("EventProc eval\n");
+       Tms_BackgroundEvalObjv(evPtr->interp, objc+1, cmdv, TCL_EVAL_GLOBAL);
+       ckfree((char *)cmdv);
+    }
+
+    /*
+     * Clean up reference counts that were set when the event was queued
+     */
+
+    Tcl_DecrRefCount(evPtr->cmdObj);
+    Tcl_Release(evPtr->interp);
+    
+    return 1;                  /* we handled the event */
+}
+\f
+/*
+ * FNotifyNames --
+ *     Return a list of all the current notification instances.
+ */
+
+static int
+FNotifyNames(void *clientData, Tms_SubsystemSpec *specPtr, Tcl_Interp *interp)
+{
+    Tcl_SetResult(interp, "not implemented", TCL_STATIC);
+    return TCL_ERROR;
+}
+\f
+/*
+ * FNotify_Init --
+ *     Setup the File notification Tcl Event Subsystem.
+ */
+
+static Tms_SubsystemSpec FNotifySpec =
+{
+    /* version   */  TMS_MAGIC_VERSION_1,
+    /* create    */  FNotifyCreate,
+    /* configure */  NULL,
+    /* sendto    */  NULL,
+    /* names     */  FNotifyNames,
+};
+
+int
+FNotify_Init(Tcl_Interp *interp)
+{
+    FNotifyPackage *pkgPtr = NULL;
+
+    /*
+     * Create and initialize the package data
+     */
+
+    pkgPtr = (FNotifyPackage *)ckalloc(sizeof(FNotifyPackage));
+    memset(pkgPtr, 0, sizeof(FNotifyPackage));
+    pkgPtr->interp = interp;
+
+    /*
+     * Register the mailslot subsystem 
+     */
+
+    Tms_RegisterSubsystem(interp, "fnotify", &FNotifySpec, pkgPtr);
+    
+    Tcl_PkgProvide(interp, "tms::fnotify", "1.0");
+    return TCL_OK;
+}
+
+/*
+ * Local variables:
+ *   mode: c
+ *   c-basic-offset: 4
+ *   fill-column: 78
+ *   indent-tabs-mode: t
+ *   tab-width: 8
+ * End:
+ */
diff --git a/win/tmsWinHandle.c b/win/tmsWinHandle.c
new file mode 100644 (file)
index 0000000..e6de389
--- /dev/null
@@ -0,0 +1,222 @@
+#include "tmsWinInt.h"
+#include <process.h>
+
+#define MAGIC 0x39383736
+
+typedef struct HandleList {
+    HANDLE     *handles;       /* array of handles current waited on */
+    HANDLE      update;         /* handle to signal list update */
+    HANDLE      mutex;         /* lock access to the list of items */
+    HANDLE      thread;        /* listener thread handle */
+    HANDLE      ready;         /* thread creation synchronisation */
+    SIZE_T      count;         /* size of the wait handles array */
+    DWORD       magic;         /* structure validation value */
+    TmsWin32Handle *items;     /* registered handle information */
+} HandleList;
+
+/*
+ * Process global list of all handles being waited upon by this subsystem
+ */
+
+static HandleList *g_Handles;
+
+/*
+ * UpdateHandles --
+ *     Walk the set of slots registered with the package and create
+ *     an array of event handles to wait upon.
+ */
+
+static void
+UpdateHandles(HandleList *listPtr)
+{
+    TmsWin32Handle *itemPtr = NULL;
+    DWORD dwLock;
+    int item = 1;
+
+    if (listPtr->magic != MAGIC) {
+       Tcl_Panic("invalid magic");
+    }
+
+    dwLock = WaitForSingleObject(listPtr->mutex, INFINITE);
+    if (dwLock == WAIT_OBJECT_0) {
+       if (listPtr->handles) {
+           ckfree((char *)listPtr->handles);
+           listPtr->handles = NULL;
+       }
+       listPtr->handles = (HANDLE *)ckalloc(sizeof(HANDLE) * (1+listPtr->count));
+       listPtr->handles[0] = listPtr->update;
+       for (itemPtr = listPtr->items; itemPtr; itemPtr = itemPtr->next) {
+           listPtr->handles[item] = itemPtr->handle;
+           ++item;
+       }
+       ReleaseMutex(listPtr->mutex);
+    }
+    else {
+       Tcl_Panic("UpdateHandles error");
+    }
+}
+\f
+/*
+ * Tms_AddWin32Handle --
+ *     Add a new handle to the wait list and update the set of wait
+ *     handles examined by the event system.
+ */
+
+void
+Tms_AddWin32Handle(TmsWin32Handle *itemPtr)
+{
+    HandleList *listPtr = g_Handles;
+    DWORD dwLock;
+
+    if (listPtr->magic != MAGIC) {
+       Tcl_Panic("invalid magic");
+    }
+
+    dwLock = WaitForSingleObject(listPtr->mutex, INFINITE);
+    if (dwLock == WAIT_OBJECT_0) {
+       if (listPtr->items == NULL) {
+           listPtr->items = itemPtr;
+       } else {
+           TmsWin32Handle *p = listPtr->items;
+           while (p->next != NULL) {
+               p = p->next;
+           }
+           p->next = itemPtr;
+       }
+       itemPtr->next = NULL;
+       listPtr->count += 1;
+       ReleaseMutex(listPtr->mutex);
+       SetEvent(listPtr->update);
+    } else {
+       Tcl_Panic("Failed to obtain lock");
+    }
+}
+\f
+/*
+ * Tms_RemoveWin32Handle --
+ *     Remove a handle from the set of wait handles.
+ */
+
+void
+Tms_RemoveWin32Handle(TmsWin32Handle *itemPtr)
+{
+    HandleList *listPtr = g_Handles;
+    TmsWin32Handle *p, *q;
+    DWORD dwLock;
+
+    if (listPtr->magic != MAGIC) {
+       Tcl_Panic("invalid magic");
+    }
+
+    dwLock = WaitForSingleObject(listPtr->mutex, INFINITE);
+    if (dwLock == WAIT_OBJECT_0) {
+       p = q = listPtr->items;
+       while (p && p != itemPtr) {
+           q = p;
+           p = p->next;
+       }
+       if (p) {
+           if (p == listPtr->items) {
+               listPtr->items = p->next;
+           } else {
+               q->next = p->next;
+           }
+           listPtr->count -= 1;
+           ReleaseMutex(listPtr->mutex);
+           SetEvent(listPtr->update);
+       }
+    } else {
+       Tcl_Panic("Failed to obtain lock");
+    }
+}
+\f
+/*
+ * Listen --
+ *     Test the set of wait handles registered with the package and
+ *     returns the item pointer for the signalled instance.
+ */
+
+static DWORD WINAPI
+Listen(void *clientData)
+{
+    TmsWin32Handle *itemPtr = NULL;
+    HandleList *listPtr = clientData;
+    DWORD dwWait = 0, dwFail = 0;
+
+    if (listPtr->magic != MAGIC) {
+       Tcl_Panic("invalid magic");
+    }
+
+    SetEvent(listPtr->ready);
+
+    while (1) {
+       dwWait = WaitForMultipleObjects(listPtr->count + 1,
+           listPtr->handles, FALSE, INFINITE);
+       if (dwWait == WAIT_FAILED) {
+           UpdateHandles(listPtr);
+           if (dwFail++ > 5) {
+               Tcl_Panic("Invalid wait handle");
+           }
+       } else if (dwWait == WAIT_ABANDONED) {
+           Tcl_Panic("Wait abandoned!?!");
+       } else if (dwWait == WAIT_OBJECT_0) {
+           dwFail = 0;
+           UpdateHandles(listPtr);
+           ResetEvent(listPtr->update);
+       } else {
+           int n = 0;
+           int item = dwWait - WAIT_OBJECT_0 - 1;
+           DWORD dwLock = WaitForSingleObject(listPtr->mutex, INFINITE);
+           if (dwLock == WAIT_OBJECT_0) {
+               itemPtr = listPtr->items;
+               for (n = 0; n < item; ++n) {
+                   itemPtr = itemPtr->next;
+               }
+               ReleaseMutex(listPtr->mutex);
+               if (itemPtr->proc) {
+                   itemPtr->proc((void *)itemPtr);
+               }
+           }
+           dwFail = 0;
+       }
+    }
+    return 0;
+}
+\f
+int
+Win32Handle_Init()
+{
+    DWORD dwReady = 0xffffffff;
+
+    g_Handles = (HandleList *)ckalloc(sizeof(HandleList));
+    g_Handles->handles = NULL;
+    g_Handles->count = 0;
+    g_Handles->items = NULL;
+    g_Handles->magic = MAGIC;
+    g_Handles->update = CreateEvent(NULL, TRUE, FALSE, NULL);
+    g_Handles->ready = CreateEvent(NULL, TRUE, FALSE, NULL);
+    g_Handles->mutex = CreateMutex(NULL, FALSE, NULL);
+
+    UpdateHandles(g_Handles);
+    ResetEvent(g_Handles->update);
+
+    g_Handles->thread = CreateThread(NULL, 8192, Listen, g_Handles, 0, NULL);
+
+    dwReady = WaitForSingleObject(g_Handles->ready, INFINITE);
+    CloseHandle(g_Handles->ready);
+    g_Handles->ready = INVALID_HANDLE_VALUE;
+
+    /* FIX ME: add stuff to clean up memory and thread */
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ *   mode: c
+ *   c-basic-offset: 4
+ *   fill-column: 78
+ *   indent-tabs-mode: t
+ *   tab-width: 8
+ * End:
+ */
diff --git a/win/tmsWinInit.c b/win/tmsWinInit.c
new file mode 100644 (file)
index 0000000..420d38d
--- /dev/null
@@ -0,0 +1,35 @@
+#include "tmsWinInt.h"
+
+/*
+ * Declare any built-in Win32 specific subsystems here
+ */
+
+extern int Win32Handle_Init(Tcl_Interp *interp);
+extern int Mailslot_Init(Tcl_Interp *interp);
+extern int FNotify_Init(Tcl_Interp *interp);
+
+/*
+ * TmspInitPlatform --
+ *     Windows specific initialization
+ */
+
+int
+TmspInitPlatform(Tcl_Interp *interp)
+{
+    int r = Win32Handle_Init(interp);
+    if (r == TCL_OK)
+        r = Mailslot_Init(interp);
+    if (r == TCL_OK)
+       r = FNotify_Init(interp);
+    return r;
+}
+
+/*
+ * Local variables:
+ *   mode: c
+ *   c-basic-offset: 4
+ *   fill-column: 78
+ *   indent-tabs-mode: t
+ *   tab-width: 8
+ * End:
+ */
diff --git a/win/tmsWinInt.h b/win/tmsWinInt.h
new file mode 100644 (file)
index 0000000..8790dd1
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _tmsWinInt_h_INCLUDE
+#define _tmsWinInt_h_INCLUDE
+
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "tmsInt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*TmsWin32HandleProc)(void *);
+
+typedef struct TmsWin32Handle {
+    HANDLE handle;
+    Tcl_ThreadId tid;
+    TmsWin32HandleProc proc;
+    struct TmsWin32Handle *next;
+} TmsWin32Handle;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _tmsWinInt_h_INCLUDE */
diff --git a/win/tmsWinMailslot.c b/win/tmsWinMailslot.c
new file mode 100644 (file)
index 0000000..86144a9
--- /dev/null
@@ -0,0 +1,494 @@
+/* mailslot.c - Copyright (C) 2006 Pat Thoyts <patthoyts@users.sourceforge.net>
+ *
+ * $Id: tmsWinMailslot.c,v 1.5 2007/04/03 15:38:53 pat Exp $
+ */
+
+#include "tmsWinInt.h"
+
+typedef struct MailslotPackage MailslotPackage;
+
+typedef struct MailslotData {
+    TmsWin32Handle  wait;
+    HANDLE          handle;    /* mailslot handle */
+    Tcl_Obj         *nameObj;  /* mailslot name */
+    Tcl_Obj         *cmdObj;    /* command to run when message received */
+    Tcl_Obj         *encObj;
+    Tcl_Obj         *sizeObj;  /* size of message buffer in bytes */
+    Tcl_Command     token;     /* tcl command token */
+    unsigned char   *message;  /* message buffer */
+    OVERLAPPED       ov;       /* overlapped io */
+    MailslotPackage *pkgPtr;   /* pointer to the package data */
+    struct MailslotData *next;
+} MailslotData;
+
+typedef struct MailslotPackage {
+    Tcl_Interp *interp;
+    HANDLE *handles;
+    SIZE_T  count;
+    LONG    uid;
+    MailslotData *slots;
+} MailslotPackage;
+
+typedef struct MailslotEvent {
+    Tcl_Event header;
+    Tcl_Interp *interp;
+    MailslotData *slotPtr;
+    Tcl_Obj *messageObj;
+} MailslotEvent;
+
+static void MailslotSignalledProc(void *);
+static Tcl_EventProc EventProc;
+
+static long mailslot_counter = 0;
+
+/*
+ * SlotSendMessage --
+ *     Open a client mailslot connection and send the message.
+ */
+
+static int
+SlotSendMessage(Tcl_Interp *interp, LPCWSTR wszSlotName, DWORD cbMsg, LPBYTE aMsg)
+{
+    HANDLE hMailslot = INVALID_HANDLE_VALUE;
+    int r = TCL_ERROR;
+    hMailslot = CreateFileW(wszSlotName, GENERIC_WRITE,
+        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (hMailslot != INVALID_HANDLE_VALUE) {
+       DWORD cbWrote = 0;
+        if (WriteFile(hMailslot, aMsg, cbMsg, &cbWrote, NULL)) {
+           r = TCL_OK;
+       } else {
+           Tcl_SetObjResult(interp,
+               Tcl_NewStringObj("failed to write data", -1));
+       }
+        CloseHandle(hMailslot);
+    } else {
+       Tcl_Obj *errObj = 
+           Tcl_NewStringObj("failed to create client mailslot \"", -1);
+       Tcl_AppendObjToObj(errObj, Tcl_NewUnicodeObj(wszSlotName + 13 , -1));
+       Tcl_AppendToObj(errObj, "\"", -1);
+       Tcl_SetObjResult(interp, errObj);
+    }
+    return r;
+
+}
+\f
+struct Tms_ConfigureSpec MailslotConfig[] = {
+    /* name    type    dataelement                  default */
+    { "-name", Tms_Offset(MailslotData,nameObj), TMS_READONLY, NULL},
+    { "-command", Tms_Offset(MailslotData,cmdObj), TMS_READWRITE, NULL },
+    { "-encoding", Tms_Offset(MailslotData,encObj), TMS_READWRITE, NULL },
+    { "-buffersize", Tms_Offset(MailslotData,sizeObj), TMS_READWRITE, "1024"},
+    { NULL },
+};
+
+static int
+SlotConfigureCmd(ClientData clientData, Tcl_Interp *interp,
+    int objc, Tcl_Obj *const objv[])
+{
+    if (objc > 4 && objc % 2 != 0) {
+       Tcl_WrongNumArgs(interp, 2, objv, "?name value ...?");
+       return TCL_ERROR;
+    }
+    return Tms_Configure(MailslotConfig, clientData,
+       interp, objc - 2, objv + 2);
+}
+\f
+static int
+SlotCgetCmd(ClientData clientData, Tcl_Interp *interp,
+    int objc, Tcl_Obj *const objv[])
+{
+    if (objc != 3) {
+       Tcl_WrongNumArgs(interp, 2, objv, "-option");
+       return TCL_ERROR;
+    }
+    return Tms_Configure(MailslotConfig, clientData,
+       interp, objc - 2, objv + 2);
+}
+\f
+/*
+ * SlotCloseCmd --
+ *     Close the mailslot instance
+ */
+
+static int
+SlotCloseCmd(ClientData clientData, Tcl_Interp *interp,
+    int objc, Tcl_Obj *const objv[])
+{
+    MailslotData *dataPtr = clientData;
+    return Tcl_DeleteCommandFromToken(interp, dataPtr->token);
+}
+\f
+/*
+ * SlotSendCmd --
+ *     Mailslot instance send message subcommand.
+ */
+
+static int
+SlotSendCmd(ClientData clientData, Tcl_Interp *interp,
+    int objc, Tcl_Obj *const objv[])
+{
+    MailslotData *dataPtr = clientData;
+    Tcl_Obj *pathObj;
+    unsigned char *message = NULL;
+    unsigned int messagelen = 0;
+
+    if (objc != 3) {
+       Tcl_WrongNumArgs(interp, 2, objv, "message");
+       return TCL_ERROR;
+    }
+    
+    pathObj = Tcl_NewUnicodeObj(L"\\\\.\\mailslot\\", -1);
+    Tcl_AppendObjToObj(pathObj, dataPtr->nameObj);
+
+    message = Tcl_GetByteArrayFromObj(objv[2], (int *)&messagelen);
+    return SlotSendMessage(interp, Tcl_GetUnicode(pathObj), messagelen, message);
+}
+\f
+/*
+ * SlotCmd --
+ *     Mailslot instance ensemble
+ */
+
+struct Ensemble SlotEnsemble[] = {
+    { "configure", SlotConfigureCmd, NULL },
+    { "cget",      SlotCgetCmd, NULL },
+    { "close",     SlotCloseCmd, NULL },
+    { "send",      SlotSendCmd, NULL },
+    { NULL, NULL, NULL },
+};
+
+static int
+SlotCmd(ClientData clientData, Tcl_Interp *interp,
+    int objc, Tcl_Obj *const objv[])
+{
+    struct Ensemble *ensemble = SlotEnsemble;
+    int option = 1, index;
+
+    while (option < objc) {
+        if (Tcl_GetIndexFromObjStruct(interp, objv[option], 
+               ensemble, sizeof(ensemble[0]), "command", 0, &index) != TCL_OK)
+        {
+            return TCL_ERROR;
+        }
+
+        if (ensemble[index].command) {
+            return ensemble[index].command(clientData, interp, objc, objv);
+        }
+        ensemble = ensemble[index].ensemble;
+        ++option;
+    }
+    Tcl_WrongNumArgs(interp, option, objv, "option ?arg arg...?");
+    return TCL_ERROR;
+}
+\f
+/*
+ * SlotCleanup --
+ *     Cleanup all resources associated with a mailslot instance.
+ */
+
+static void
+SlotCleanup(ClientData clientData)
+{
+    MailslotData *dataPtr = clientData;
+    Tms_RemoveWin32Handle((TmsWin32Handle *)dataPtr);
+    if (dataPtr) {
+       Tcl_DecrRefCount(dataPtr->nameObj);
+       Tcl_DecrRefCount(dataPtr->cmdObj);
+       CloseHandle(dataPtr->ov.hEvent);
+       CloseHandle(dataPtr->handle);
+       ckfree((char *)dataPtr->message);
+       ckfree((char *)clientData);
+    }    
+}
+\f
+/*
+ * MailslotCreate --
+ *     We create a mailslot and setup a Mailslot instance structure
+ *     with the handle and command to run when a message is received. 
+ *     The read notification handle is then registered with the Win32
+ *     handle processing system which will arrange for our callback
+ *     to be run when a message arrives.
+ */
+
+static int
+MailslotCreate(void *clientData, Tms_SubsystemSpec *specPtr,
+    Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+    MailslotPackage *packagePtr = clientData;
+    MailslotData *dataPtr;
+    HANDLE hSlot = INVALID_HANDLE_VALUE;
+    char name[TCL_INTEGER_SPACE + 9];
+    int r = TCL_OK;
+    long size = 0;
+    Tcl_Obj *pathObj = NULL;
+
+    dataPtr = (MailslotData *)ckalloc(sizeof(MailslotData));
+    memset(dataPtr, 0, sizeof(MailslotData));
+
+    Tms_ConfigureDefault(MailslotConfig, dataPtr);
+    r = Tms_Configure(MailslotConfig, dataPtr, interp, objc, objv );
+    if (r != TCL_OK) {
+       ckfree((char *)dataPtr);
+       return r;
+    }
+
+    pathObj = Tcl_NewUnicodeObj(L"\\\\.\\mailslot\\", -1);
+    Tcl_AppendObjToObj(pathObj, dataPtr->nameObj);
+
+    hSlot = CreateMailslotW(Tcl_GetUnicode(pathObj), 0,
+       MAILSLOT_WAIT_FOREVER, NULL);
+    if (hSlot != INVALID_HANDLE_VALUE) {
+
+       dataPtr->handle = hSlot;
+       dataPtr->pkgPtr = packagePtr;
+
+       /*
+        * Setup the overlapped i/o structure and place a read on the
+        * mailslot. This event will get signalled when a message is ready.
+        * We reset the signalled event when we handle the message.
+        */
+
+       dataPtr->ov.Offset = 0;
+       dataPtr->ov.OffsetHigh = 0;
+       dataPtr->ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+       /* add the wait handle to the handle subsystem */
+       dataPtr->wait.handle = dataPtr->ov.hEvent;
+       dataPtr->wait.proc = MailslotSignalledProc;
+       dataPtr->wait.tid = Tcl_GetCurrentThread();
+       Tms_AddWin32Handle((TmsWin32Handle *)dataPtr);
+
+       sprintf(name, "mailslot%d", InterlockedIncrement(&packagePtr->uid));
+       dataPtr->token = Tcl_CreateObjCommand(interp, name, SlotCmd,
+           dataPtr, SlotCleanup);
+       Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
+
+       Tcl_GetLongFromObj(interp, dataPtr->sizeObj, &size);
+       dataPtr->message = (unsigned char *)ckalloc(size);
+       ReadFile(hSlot, dataPtr->message, size, NULL, &dataPtr->ov);
+
+    } else {
+       Tcl_Obj *errObj = 
+           Tcl_NewStringObj("failed to create mailslot \"", -1);
+       Tcl_AppendObjToObj(errObj, dataPtr->nameObj);
+       Tcl_AppendToObj(errObj, "\"", -1);
+       Tcl_SetObjResult(interp, errObj);
+
+       Tcl_DecrRefCount(dataPtr->nameObj);
+       Tcl_DecrRefCount(dataPtr->cmdObj);
+       ckfree((char *)dataPtr);
+       
+       return TCL_ERROR;
+    }
+    return TCL_OK;
+}
+\f
+static int
+MailslotConfigure(void *clientData, Tms_SubsystemSpec *specPtr,
+    Tcl_Interp *interp, int objc, Tcl_Obj *const *instObj)
+{
+    Tcl_SetResult(interp, "not implemented", TCL_STATIC);
+    return TCL_ERROR;
+}
+\f
+/*
+ * MailslotSendto --
+ *     Send a message to a mailslot. The message data is currently
+ *     treated as binary data. In future we may add an encoding to
+ *     to the instance object.
+ */
+
+static int
+MailslotSendto(void *clientData, Tms_SubsystemSpec *specPtr,
+    Tcl_Interp *interp, Tcl_Obj *slotObj, Tcl_Obj *msgObj)
+{
+    int r = TCL_OK;
+    unsigned long messagelen = 0;
+    unsigned char *message = NULL;
+    Tcl_Obj *pathObj = Tcl_NewUnicodeObj(L"\\\\.\\mailslot\\", -1);
+    Tcl_AppendObjToObj(pathObj, slotObj);
+
+    message = Tcl_GetByteArrayFromObj(msgObj, (int *)&messagelen);
+    return SlotSendMessage(interp, Tcl_GetUnicode(pathObj), messagelen, message);
+}
+\f
+/*
+ * MailslotNames --
+ *     Returns a Tcl list containing the paths for all mailslots available
+ *     on the local system.
+ */
+
+static int
+MailslotNames(void *clientData, Tms_SubsystemSpec *specPtr, Tcl_Interp *interp)
+{
+    int r = TCL_OK;
+    WIN32_FIND_DATAW fd;
+    Tcl_Obj *resultObj = Tcl_NewListObj(-1, NULL);
+    
+    HANDLE hFind = FindFirstFileW(L"\\\\.\\mailslot\\*.*", &fd);
+    if (hFind != INVALID_HANDLE_VALUE) {
+       BOOL br = FALSE;
+       do {
+           Tcl_ListObjAppendElement(interp, resultObj,
+               Tcl_NewUnicodeObj(fd.cFileName, -1));
+           br = FindNextFileW(hFind, &fd);
+       } while (br);
+       FindClose(hFind);
+    } else {
+       Tcl_SetStringObj(resultObj, "error enumerating mailslots", -1);
+       r = TCL_ERROR;
+    }
+    Tcl_SetObjResult(interp, resultObj);
+    return r;
+}
+\f
+/*
+ * MailslotSignalledProc --
+ *     This function is called from the thread that is waiting upon all 
+ *     the Win32 handles. When a mailslot read handle is signalled the
+ *     handle subsystem calls here and we queue a Tcl event and alert
+ *     the notifier for the thread owning the correct interp.
+ */
+
+static void
+MailslotSignalledProc(void *clientData)
+{
+    MailslotData *slotPtr = (MailslotData *)clientData;
+    MailslotEvent *evPtr = NULL;
+    DWORD cbRead, cbSize = 0, cQueued = 0;
+    BOOL br = FALSE;
+
+    Tcl_GetLongFromObj(NULL, slotPtr->sizeObj, &cbSize);
+    GetOverlappedResult(slotPtr->handle, &slotPtr->ov, &cbRead, FALSE);
+    do
+    {
+       evPtr = (MailslotEvent *)ckalloc(sizeof(MailslotEvent));
+       evPtr->header.proc = EventProc;
+       evPtr->header.nextPtr = NULL;
+       evPtr->interp = slotPtr->pkgPtr->interp;
+       Tcl_Preserve(evPtr->interp);
+       evPtr->slotPtr = slotPtr;
+       evPtr->messageObj = Tcl_NewByteArrayObj(slotPtr->message, cbRead);
+       Tcl_IncrRefCount(evPtr->messageObj);
+       Tcl_ThreadQueueEvent(slotPtr->wait.tid, 
+           (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
+       
+       /*
+        * Schedule another read on the mailslot. This may return
+        * immediately if data is already available. We also rate-limit
+        * by enforcing a wait after 64 immediate messages.
+        */
+       br = ReadFile(slotPtr->handle, slotPtr->message,
+           cbSize, &cbRead, &slotPtr->ov);
+       ++cQueued;
+    } while (br && cQueued < 64);
+
+    // check GetLastError == ERROR_IO_PENDING
+
+    Tcl_ThreadAlert(slotPtr->wait.tid);
+    return;
+}
+\f
+/*
+ * EventProc --
+ *     This is the Tcl event handler. We append the message received
+ *     which has been added to the event and evaluate the resulting
+ *     command.
+ *     Returns 1 if the event was handled. 0 if the flags indicate we 
+ *     should not process file events.
+ */
+
+static int
+EventProc(Tcl_Event *eventPtr, int flags)
+{
+    MailslotEvent *evPtr = (MailslotEvent *)eventPtr;
+    int objc;
+    Tcl_Obj **objv;
+
+    if (!(flags & TCL_FILE_EVENTS)) {
+       return 0;
+    }
+    
+    /*
+     * Append the mailslot message to the end of the supplied command
+     * and evaluate.
+     */
+
+    Tcl_ListObjGetElements(NULL, evPtr->slotPtr->cmdObj, &objc, &objv);
+    if (objc > 0) {
+       Tcl_Obj **cmdv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 1));
+       memcpy(cmdv, objv, sizeof(Tcl_Obj *) * objc);
+       cmdv[objc] = evPtr->messageObj;
+       Tms_BackgroundEvalObjv(evPtr->interp, objc+1, cmdv, TCL_EVAL_GLOBAL);
+       ckfree((char *)cmdv);
+    }
+
+    /*
+     * Clean up reference counts that were set when the event was queued
+     */
+
+    Tcl_DecrRefCount(evPtr->messageObj);
+    Tcl_Release(evPtr->interp);
+    
+    return 1;
+}
+\f
+/*
+ * MailslotPkgCleanup --
+ *     Cleanup the package data structure.
+ */
+
+static void
+MailslotPkgCleanup(void *deleteData)
+{
+    ckfree((char *)deleteData);
+}
+\f
+/*
+ * Mailslot_Init --
+ *     Setup the Mailslot Tcl Event Subsystem.
+ */
+
+static Tms_SubsystemSpec MailslotSpec =
+{
+    TMS_MAGIC_VERSION_1,
+    MailslotCreate,
+    MailslotConfigure,
+    MailslotSendto,
+    MailslotNames,
+};
+
+int
+Mailslot_Init(Tcl_Interp *interp)
+{
+    MailslotPackage *pkgPtr = NULL;
+
+    /*
+     * Create and initialize the package data
+     */
+
+    pkgPtr = (MailslotPackage *)ckalloc(sizeof(MailslotPackage));
+    memset(pkgPtr, 0, sizeof(MailslotPackage));
+    pkgPtr->interp = interp;
+
+    /*
+     * Register the mailslot subsystem 
+     */
+
+    Tms_RegisterSubsystem(interp, "mailslot", &MailslotSpec, pkgPtr);
+    
+    //Tms_RegisterCleanup(interp, (void *)pkgPtr, MailslotPkgCleanup);
+    Tcl_PkgProvide(interp, "tms::mailslot", "1.0");
+    return TCL_OK;
+}
+
+/*
+ * Local variables:
+ *   mode: c
+ *   c-basic-offset: 4
+ *   fill-column: 78
+ *   indent-tabs-mode: t
+ *   tab-width: 8
+ * End:
+ */