summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
Diffstat (limited to 'unix')
-rw-r--r--unix/Makefile.in2149
-rw-r--r--unix/README169
-rw-r--r--unix/aclocal.m41
-rwxr-xr-xunix/configure11611
-rw-r--r--unix/configure.ac1028
-rw-r--r--unix/dltest/Makefile.in110
-rw-r--r--unix/dltest/README4
-rw-r--r--unix/dltest/pkga.c137
-rw-r--r--unix/dltest/pkgb.c190
-rw-r--r--unix/dltest/pkgc.c162
-rw-r--r--unix/dltest/pkgd.c162
-rw-r--r--unix/dltest/pkge.c45
-rw-r--r--unix/dltest/pkgooa.c141
-rw-r--r--unix/dltest/pkgua.c332
-rwxr-xr-xunix/install-sh528
-rwxr-xr-xunix/installManPage117
-rwxr-xr-xunix/ldAix58
-rw-r--r--unix/tcl.m43019
-rw-r--r--unix/tcl.pc.in15
-rw-r--r--unix/tcl.spec52
-rw-r--r--unix/tclAppInit.c169
-rw-r--r--unix/tclConfig.h.in508
-rw-r--r--unix/tclConfig.sh.in169
-rw-r--r--unix/tclEpollNotfy.c806
-rw-r--r--unix/tclKqueueNotfy.c842
-rw-r--r--unix/tclLoadAix.c630
-rw-r--r--unix/tclLoadDl.c274
-rw-r--r--unix/tclLoadDyld.c719
-rw-r--r--unix/tclLoadNext.c217
-rw-r--r--unix/tclLoadOSF.c235
-rw-r--r--unix/tclLoadShl.c224
-rw-r--r--unix/tclSelectNotfy.c1117
-rw-r--r--unix/tclUnixChan.c1776
-rw-r--r--unix/tclUnixCompat.c1022
-rw-r--r--unix/tclUnixEvent.c95
-rw-r--r--unix/tclUnixFCmd.c2515
-rw-r--r--unix/tclUnixFile.c1244
-rw-r--r--unix/tclUnixInit.c1087
-rw-r--r--unix/tclUnixNotfy.c575
-rw-r--r--unix/tclUnixPipe.c1327
-rw-r--r--unix/tclUnixPort.h725
-rw-r--r--unix/tclUnixSock.c1821
-rw-r--r--unix/tclUnixTest.c781
-rw-r--r--unix/tclUnixThrd.c815
-rw-r--r--unix/tclUnixThrd.h19
-rw-r--r--unix/tclUnixTime.c548
-rw-r--r--unix/tclXtNotify.c667
-rw-r--r--unix/tclXtTest.c134
-rw-r--r--unix/tclooConfig.sh19
49 files changed, 41110 insertions, 0 deletions
diff --git a/unix/Makefile.in b/unix/Makefile.in
new file mode 100644
index 0000000..c31d128
--- /dev/null
+++ b/unix/Makefile.in
@@ -0,0 +1,2149 @@
+#
+# This file is a Makefile for Tcl. 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.
+
+VERSION = @TCL_VERSION@
+MAJOR_VERSION = @TCL_MAJOR_VERSION@
+MINOR_VERSION = @TCL_MINOR_VERSION@
+PATCH_LEVEL = @TCL_PATCH_LEVEL@
+
+#--------------------------------------------------------------------------
+# Things you can change to personalize the Makefile for your own site (you can
+# make these changes in either Makefile.in or Makefile, but changes to
+# Makefile will get lost if you re-run the configuration script).
+#--------------------------------------------------------------------------
+
+# Default top-level directories in which to install architecture-specific
+# files (exec_prefix) and machine-independent files such as scripts (prefix).
+# The values specified here may be overridden at configure-time with the
+# --exec-prefix and --prefix options to the "configure" script. The *dir vars
+# are standard configure substitutions that are based off prefix and
+# exec_prefix.
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+includedir = @includedir@
+datarootdir = @datarootdir@
+mandir = @mandir@
+
+# The following definition can be set to non-null for special systems like AFS
+# with replication. It allows the pathnames used for installation to be
+# different than those used for actually reference files at run-time.
+# INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files.
+INSTALL_ROOT = $(DESTDIR)
+
+# Path for the platform independent Tcl scripting libraries:
+TCL_LIBRARY = @TCL_LIBRARY@
+
+# Path to use at runtime to refer to LIB_INSTALL_DIR:
+LIB_RUNTIME_DIR = $(libdir)
+
+# Directory in which to install the program tclsh:
+BIN_INSTALL_DIR = $(INSTALL_ROOT)$(bindir)
+
+# Directory in which to install libtcl.so or libtcl.a:
+LIB_INSTALL_DIR = $(INSTALL_ROOT)$(libdir)
+DLL_INSTALL_DIR = @DLL_INSTALL_DIR@
+
+# Path name to use when installing library scripts.
+SCRIPT_INSTALL_DIR = $(INSTALL_ROOT)$(TCL_LIBRARY)
+
+# Directory in which to install the include file tcl.h:
+INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir)
+
+# Path to the private tcl header dir:
+PRIVATE_INCLUDE_DIR = @PRIVATE_INCLUDE_DIR@
+
+# Directory in which to (optionally) install the private tcl headers:
+PRIVATE_INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(PRIVATE_INCLUDE_DIR)
+
+# Top-level directory in which to install manual entries:
+MAN_INSTALL_DIR = $(INSTALL_ROOT)$(mandir)
+
+# Directory in which to install manual entry for tclsh:
+MAN1_INSTALL_DIR = $(MAN_INSTALL_DIR)/man1
+
+# Directory in which to install manual entries for Tcl's C library procedures:
+MAN3_INSTALL_DIR = $(MAN_INSTALL_DIR)/man3
+
+# Directory in which to install manual entries for the built-in Tcl commands:
+MANN_INSTALL_DIR = $(MAN_INSTALL_DIR)/mann
+
+# Path to the html documentation dir:
+HTML_DIR = @HTML_DIR@
+
+# Directory in which to install html documentation:
+HTML_INSTALL_DIR = $(INSTALL_ROOT)$(HTML_DIR)
+
+# Directory in which to install the configuration file tclConfig.sh
+CONFIG_INSTALL_DIR = $(INSTALL_ROOT)$(libdir)
+
+# Directory in which to install bundled packages:
+PACKAGE_DIR = @PACKAGE_DIR@
+
+# Package search path.
+TCL_PACKAGE_PATH = @TCL_PACKAGE_PATH@
+
+# Tcl Module default path roots (TIP189).
+TCL_MODULE_PATH = @TCL_MODULE_PATH@
+
+# warning flags
+CFLAGS_WARNING = @CFLAGS_WARNING@
+
+# The default switches for optimization or debugging
+CFLAGS_DEBUG = @CFLAGS_DEBUG@
+CFLAGS_OPTIMIZE = @CFLAGS_OPTIMIZE@
+
+# To change the compiler switches, for example to change from optimization to
+# debugging symbols, change the following line:
+#CFLAGS = $(CFLAGS_DEBUG)
+#CFLAGS = $(CFLAGS_OPTIMIZE)
+#CFLAGS = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE)
+CFLAGS = @CFLAGS_DEFAULT@ @CFLAGS@
+
+# Flags to pass to the linker
+LDFLAGS_DEBUG = @LDFLAGS_DEBUG@
+LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@
+LDFLAGS = @LDFLAGS_DEFAULT@ @LDFLAGS@
+
+# To disable ANSI-C procedure prototypes reverse the comment characters on the
+# following lines:
+PROTO_FLAGS =
+#PROTO_FLAGS = -DNO_PROTOTYPE
+
+# If you use the setenv, putenv, or unsetenv procedures to modify environment
+# variables in your application and you'd like those modifications to appear
+# in the "env" Tcl variable, switch the comments on the two lines below so
+# that Tcl provides these procedures instead of your standard C library.
+
+ENV_FLAGS =
+#ENV_FLAGS = -DTclSetEnv=setenv -DTcl_PutEnv=putenv -DTclUnsetEnv=unsetenv
+
+# To enable memory debugging, call configure with --enable-symbols=mem
+# Warning: if you enable memory debugging, you must do it *everywhere*,
+# including all the code that calls Tcl, and you must use ckalloc and ckfree
+# everywhere instead of malloc and free.
+
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+#TCL_STUB_LIB_FILE = libtclstub.a
+
+# Generic stub lib name used in rules that apply to tcl and tk
+STUB_LIB_FILE = ${TCL_STUB_LIB_FILE}
+
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+#TCL_STUB_LIB_FLAG = -ltclstub
+
+# To compile without backward compatibility and deprecated code uncomment the
+# following
+NO_DEPRECATED_FLAGS =
+#NO_DEPRECATED_FLAGS = -DTCL_NO_DEPRECATED
+
+# Some versions of make, like SGI's, use the following variable to determine
+# which shell to use for executing commands:
+SHELL = @MAKEFILE_SHELL@
+
+# Tcl used to let the configure script choose which program to use for
+# installing, but there are just too many different versions of "install"
+# around; better to use the install-sh script that comes with the
+# distribution, which is slower but guaranteed to work.
+
+INSTALL_STRIP_PROGRAM = -s
+INSTALL_STRIP_LIBRARY = -S -x
+
+INSTALL = $(SHELL) $(UNIX_DIR)/install-sh -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_LIBRARY = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_DATA_DIR = ${INSTALL} -d -m 755
+
+# NATIVE_TCLSH is the name of a tclsh executable that is available *BEFORE*
+# running make for the first time. Certain build targets (make genstubs) need
+# it to be available on the PATH. This executable should *NOT* be required
+# just to do a normal build although it can be required to run make dist.
+# Do not use SHELL_ENV for NATIVE_TCLSH unless it is the tclsh being built.
+EXE_SUFFIX = @EXEEXT@
+TCL_EXE = tclsh${EXE_SUFFIX}
+TCLTEST_EXE = tcltest${EXE_SUFFIX}
+NATIVE_TCLSH = @TCLSH_PROG@
+
+# The symbols below provide support for dynamic loading and shared libraries.
+# See configure.ac for a description of what the symbols mean. The values of
+# the symbols are normally set by the configure script. You shouldn't normally
+# need to modify any of these definitions by hand.
+
+STLIB_LD = @STLIB_LD@
+SHLIB_LD = @SHLIB_LD@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@ -DBUILD_tcl
+SHLIB_LD_LIBS = @SHLIB_LD_LIBS@
+TCL_SHLIB_LD_EXTRAS = @TCL_SHLIB_LD_EXTRAS@
+
+SHLIB_SUFFIX = @SHLIB_SUFFIX@
+
+DLTEST_TARGETS = dltest.marker
+
+# Additional search flags needed to find the various shared libraries at
+# run-time. The first symbol is for use when creating a binary with cc, and
+# the second is for use when running ld directly.
+CC_SEARCH_FLAGS = @CC_SEARCH_FLAGS@
+LD_SEARCH_FLAGS = @LD_SEARCH_FLAGS@
+
+# The following symbol is defined to "$(DLTEST_TARGETS)" if dynamic loading is
+# available; this causes everything in the "dltest" subdirectory to be built
+# when making "tcltest. If dynamic loading isn't available, configure defines
+# this symbol to an empty string, in which case the shared libraries aren't
+# built.
+BUILD_DLTEST = @BUILD_DLTEST@
+#BUILD_DLTEST =
+
+TCL_LIB_FILE = @TCL_LIB_FILE@
+#TCL_LIB_FILE = libtcl.a
+
+# Generic lib name used in rules that apply to tcl and tk
+LIB_FILE = ${TCL_LIB_FILE}
+
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+#TCL_LIB_FLAG = -ltcl
+
+# support for embedded libraries on Darwin / Mac OS X
+DYLIB_INSTALL_DIR = ${LIB_RUNTIME_DIR}
+
+#--------------------------------------------------------------------------
+# The information below is modified by the configure script when Makefile is
+# generated from Makefile.in. You shouldn't normally modify any of this stuff
+# by hand.
+#--------------------------------------------------------------------------
+
+COMPAT_OBJS = @LIBOBJS@
+
+AC_FLAGS = @DEFS@
+AR = @AR@
+RANLIB = @RANLIB@
+DTRACE = @DTRACE@
+SRC_DIR = @srcdir@
+TOP_DIR = @TCL_SRC_DIR@
+BUILD_DIR = @builddir@
+GENERIC_DIR = $(TOP_DIR)/generic
+TOMMATH_DIR = $(TOP_DIR)/libtommath
+COMPAT_DIR = $(TOP_DIR)/compat
+TOOL_DIR = $(TOP_DIR)/tools
+UNIX_DIR = $(TOP_DIR)/unix
+MAC_OSX_DIR = $(TOP_DIR)/macosx
+PKGS_DIR = $(TOP_DIR)/pkgs
+# Must be absolute because of the cd dltest $(DLTEST_DIR)/configure below.
+DLTEST_DIR = @TCL_SRC_DIR@/unix/dltest
+# Must be absolute to so the corresponding tcltest's tcl_library is absolute.
+TCL_BUILDTIME_LIBRARY = @TCL_SRC_DIR@/library
+
+ZLIB_DIR = ${COMPAT_DIR}/zlib
+ZLIB_INCLUDE = @ZLIB_INCLUDE@
+
+CC = @CC@
+#CC = purify -best-effort @CC@ -DPURIFY
+
+# Flags to be passed to installManPage to control how the manpages should be
+# installed (symlinks, compression, package name suffix).
+MAN_FLAGS = @MAN_FLAGS@
+
+# If non-empty, install the timezone files that are included with Tcl,
+# otherwise use the ones that ship with the OS.
+INSTALL_TZDATA = @INSTALL_TZDATA@
+
+#--------------------------------------------------------------------------
+# The information below is usually usable as is. The configure script won't
+# modify it and it only exists to make working around selected rare system
+# configurations easier.
+#--------------------------------------------------------------------------
+
+GDB = gdb
+TRACE = strace
+TRACE_OPTS =
+VALGRIND = valgrind
+VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high --leak-check=yes --show-reachable=yes -v
+
+#--------------------------------------------------------------------------
+# The information below should be usable as is. The configure script won't
+# modify it and you shouldn't need to modify it either.
+#--------------------------------------------------------------------------
+
+STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \
+-I"${BUILD_DIR}" -I${UNIX_DIR} -I${GENERIC_DIR} -I${TOMMATH_DIR} \
+${AC_FLAGS} ${PROTO_FLAGS} ${ENV_FLAGS} ${EXTRA_CFLAGS} @EXTRA_CC_SWITCHES@
+
+CC_SWITCHES = $(STUB_CC_SWITCHES) ${NO_DEPRECATED_FLAGS}
+
+APP_CC_SWITCHES = $(CC_SWITCHES) @EXTRA_APP_CC_SWITCHES@
+
+LIBS = @TCL_LIBS@
+
+DEPEND_SWITCHES = ${CFLAGS} -I${UNIX_DIR} -I${GENERIC_DIR} \
+${AC_FLAGS} ${PROTO_FLAGS} ${EXTRA_CFLAGS} @EXTRA_CC_SWITCHES@
+
+TCLSH_OBJS = tclAppInit.o
+
+TCLTEST_OBJS = tclTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
+ tclThreadTest.o tclUnixTest.o
+
+XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
+ tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o
+
+GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.o \
+ tclAssembly.o tclAsync.o tclBasic.o tclBinary.o tclCkalloc.o \
+ tclClock.o tclCmdAH.o tclCmdIL.o tclCmdMZ.o \
+ tclCompCmds.o tclCompCmdsGR.o tclCompCmdsSZ.o tclCompExpr.o \
+ tclCompile.o tclConfig.o tclDate.o tclDictObj.o tclDisassemble.o \
+ tclEncoding.o tclEnsemble.o \
+ tclEnv.o tclEvent.o tclExecute.o tclFCmd.o tclFileName.o tclGet.o \
+ tclHash.o tclHistory.o tclIndexObj.o tclInterp.o tclIO.o tclIOCmd.o \
+ tclIORChan.o tclIORTrans.o tclIOGT.o tclIOSock.o tclIOUtil.o \
+ tclLink.o tclListObj.o \
+ tclLiteral.o tclLoad.o tclMain.o tclNamesp.o tclNotify.o \
+ tclObj.o tclOptimize.o tclPanic.o tclParse.o tclPathObj.o tclPipe.o \
+ tclPkg.o tclPkgConfig.o tclPosixStr.o \
+ tclPreserve.o tclProc.o tclRegexp.o \
+ tclResolve.o tclResult.o tclScan.o tclStringObj.o \
+ tclStrToD.o tclThread.o \
+ tclThreadAlloc.o tclThreadJoin.o tclThreadStorage.o tclStubInit.o \
+ tclTimer.o tclTrace.o tclUtf.o tclUtil.o tclVar.o tclZlib.o \
+ tclTomMathInterface.o
+
+OO_OBJS = tclOO.o tclOOBasic.o tclOOCall.o tclOODefineCmds.o tclOOInfo.o \
+ tclOOMethod.o tclOOStubInit.o
+
+TOMMATH_OBJS = bncore.o bn_reverse.o bn_fast_s_mp_mul_digs.o \
+ bn_fast_s_mp_sqr.o bn_mp_add.o bn_mp_and.o \
+ bn_mp_add_d.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o \
+ bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \
+ bn_mp_cnt_lsb.o bn_mp_copy.o \
+ bn_mp_count_bits.o bn_mp_div.o bn_mp_div_d.o bn_mp_div_2.o \
+ bn_mp_div_2d.o bn_mp_div_3.o \
+ bn_mp_exch.o bn_mp_expt_d.o bn_mp_expt_d_ex.o bn_mp_get_int.o bn_mp_get_long.o bn_mp_get_long_long.o bn_mp_grow.o bn_mp_init.o \
+ bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \
+ bn_mp_init_set_int.o bn_mp_init_size.o bn_mp_karatsuba_mul.o \
+ bn_mp_karatsuba_sqr.o \
+ bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mul.o bn_mp_mul_2.o \
+ bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_neg.o bn_mp_or.o \
+ bn_mp_radix_size.o bn_mp_radix_smap.o \
+ bn_mp_read_radix.o bn_mp_rshd.o bn_mp_set.o bn_mp_set_int.o \
+ bn_mp_set_long.o bn_mp_set_long_long.o bn_mp_shrink.o \
+ bn_mp_sqr.o bn_mp_sqrt.o bn_mp_sub.o bn_mp_sub_d.o \
+ bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o \
+ bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_toradix_n.o \
+ bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o bn_s_mp_add.o \
+ bn_s_mp_mul_digs.o bn_s_mp_sqr.o bn_s_mp_sub.o
+
+STUB_LIB_OBJS = tclStubLib.o \
+ tclTomMathStubLib.o \
+ tclOOStubLib.o \
+ ${COMPAT_OBJS}
+
+UNIX_OBJS = tclUnixChan.o tclUnixEvent.o tclUnixFCmd.o \
+ tclUnixFile.o tclUnixPipe.o tclUnixSock.o \
+ tclUnixTime.o tclUnixInit.o tclUnixThrd.o \
+ tclUnixCompat.o
+
+NOTIFY_OBJS = tclEpollNotfy.o tclKqueueNotfy.o tclSelectNotfy.o
+
+MAC_OSX_OBJS = tclMacOSXBundle.o tclMacOSXFCmd.o tclMacOSXNotify.o
+
+CYGWIN_OBJS = tclWinError.o
+
+DTRACE_OBJ = tclDTrace.o
+
+ZLIB_OBJS = Zadler32.o Zcompress.o Zcrc32.o Zdeflate.o Zinfback.o \
+ Zinffast.o Zinflate.o Zinftrees.o Ztrees.o Zuncompr.o Zzutil.o
+
+TCL_OBJS = ${GENERIC_OBJS} ${UNIX_OBJS} ${NOTIFY_OBJS} ${COMPAT_OBJS} \
+ ${OO_OBJS} @DL_OBJS@ @PLAT_OBJS@
+
+OBJS = ${TCL_OBJS} ${TOMMATH_OBJS} @DTRACE_OBJ@ @ZLIB_OBJS@
+
+TCL_DECLS = \
+ $(GENERIC_DIR)/tcl.decls \
+ $(GENERIC_DIR)/tclInt.decls \
+ $(GENERIC_DIR)/tclOO.decls \
+ $(GENERIC_DIR)/tclTomMath.decls
+
+GENERIC_HDRS = \
+ $(GENERIC_DIR)/tcl.h \
+ $(GENERIC_DIR)/tclDecls.h \
+ $(GENERIC_DIR)/tclInt.h \
+ $(GENERIC_DIR)/tclIntDecls.h \
+ $(GENERIC_DIR)/tclIntPlatDecls.h \
+ $(GENERIC_DIR)/tclTomMath.h \
+ $(GENERIC_DIR)/tclTomMathDecls.h \
+ $(GENERIC_DIR)/tclOO.h \
+ $(GENERIC_DIR)/tclOODecls.h \
+ $(GENERIC_DIR)/tclOOInt.h \
+ $(GENERIC_DIR)/tclOOIntDecls.h \
+ $(GENERIC_DIR)/tclPatch.h \
+ $(GENERIC_DIR)/tclPlatDecls.h \
+ $(GENERIC_DIR)/tclPort.h \
+ $(GENERIC_DIR)/tclRegexp.h
+
+GENERIC_SRCS = \
+ $(GENERIC_DIR)/regcomp.c \
+ $(GENERIC_DIR)/regexec.c \
+ $(GENERIC_DIR)/regfree.c \
+ $(GENERIC_DIR)/regerror.c \
+ $(GENERIC_DIR)/tclAlloc.c \
+ $(GENERIC_DIR)/tclAssembly.c \
+ $(GENERIC_DIR)/tclAsync.c \
+ $(GENERIC_DIR)/tclBasic.c \
+ $(GENERIC_DIR)/tclBinary.c \
+ $(GENERIC_DIR)/tclCkalloc.c \
+ $(GENERIC_DIR)/tclClock.c \
+ $(GENERIC_DIR)/tclCmdAH.c \
+ $(GENERIC_DIR)/tclCmdIL.c \
+ $(GENERIC_DIR)/tclCmdMZ.c \
+ $(GENERIC_DIR)/tclCompCmds.c \
+ $(GENERIC_DIR)/tclCompCmdsGR.c \
+ $(GENERIC_DIR)/tclCompCmdsSZ.c \
+ $(GENERIC_DIR)/tclCompExpr.c \
+ $(GENERIC_DIR)/tclCompile.c \
+ $(GENERIC_DIR)/tclConfig.c \
+ $(GENERIC_DIR)/tclDate.c \
+ $(GENERIC_DIR)/tclDictObj.c \
+ $(GENERIC_DIR)/tclDisassemble.c \
+ $(GENERIC_DIR)/tclEncoding.c \
+ $(GENERIC_DIR)/tclEnsemble.c \
+ $(GENERIC_DIR)/tclEnv.c \
+ $(GENERIC_DIR)/tclEvent.c \
+ $(GENERIC_DIR)/tclExecute.c \
+ $(GENERIC_DIR)/tclFCmd.c \
+ $(GENERIC_DIR)/tclFileName.c \
+ $(GENERIC_DIR)/tclGet.c \
+ $(GENERIC_DIR)/tclHash.c \
+ $(GENERIC_DIR)/tclHistory.c \
+ $(GENERIC_DIR)/tclIndexObj.c \
+ $(GENERIC_DIR)/tclInterp.c \
+ $(GENERIC_DIR)/tclIO.c \
+ $(GENERIC_DIR)/tclIOCmd.c \
+ $(GENERIC_DIR)/tclIOGT.c \
+ $(GENERIC_DIR)/tclIOSock.c \
+ $(GENERIC_DIR)/tclIOUtil.c \
+ $(GENERIC_DIR)/tclIORChan.c \
+ $(GENERIC_DIR)/tclIORTrans.c \
+ $(GENERIC_DIR)/tclLink.c \
+ $(GENERIC_DIR)/tclListObj.c \
+ $(GENERIC_DIR)/tclLiteral.c \
+ $(GENERIC_DIR)/tclLoad.c \
+ $(GENERIC_DIR)/tclMain.c \
+ $(GENERIC_DIR)/tclNamesp.c \
+ $(GENERIC_DIR)/tclNotify.c \
+ $(GENERIC_DIR)/tclObj.c \
+ $(GENERIC_DIR)/tclOptimize.c \
+ $(GENERIC_DIR)/tclParse.c \
+ $(GENERIC_DIR)/tclPathObj.c \
+ $(GENERIC_DIR)/tclPipe.c \
+ $(GENERIC_DIR)/tclPkg.c \
+ $(GENERIC_DIR)/tclPkgConfig.c \
+ $(GENERIC_DIR)/tclPosixStr.c \
+ $(GENERIC_DIR)/tclPreserve.c \
+ $(GENERIC_DIR)/tclProc.c \
+ $(GENERIC_DIR)/tclRegexp.c \
+ $(GENERIC_DIR)/tclResolve.c \
+ $(GENERIC_DIR)/tclResult.c \
+ $(GENERIC_DIR)/tclScan.c \
+ $(GENERIC_DIR)/tclStubInit.c \
+ $(GENERIC_DIR)/tclStringObj.c \
+ $(GENERIC_DIR)/tclStrToD.c \
+ $(GENERIC_DIR)/tclTest.c \
+ $(GENERIC_DIR)/tclTestObj.c \
+ $(GENERIC_DIR)/tclTestProcBodyObj.c \
+ $(GENERIC_DIR)/tclThread.c \
+ $(GENERIC_DIR)/tclThreadAlloc.c \
+ $(GENERIC_DIR)/tclThreadJoin.c \
+ $(GENERIC_DIR)/tclThreadStorage.c \
+ $(GENERIC_DIR)/tclTimer.c \
+ $(GENERIC_DIR)/tclTrace.c \
+ $(GENERIC_DIR)/tclUtil.c \
+ $(GENERIC_DIR)/tclVar.c \
+ $(GENERIC_DIR)/tclAssembly.c \
+ $(GENERIC_DIR)/tclZlib.c
+
+OO_SRCS = \
+ $(GENERIC_DIR)/tclOO.c \
+ $(GENERIC_DIR)/tclOOBasic.c \
+ $(GENERIC_DIR)/tclOOCall.c \
+ $(GENERIC_DIR)/tclOODefineCmds.c \
+ $(GENERIC_DIR)/tclOOInfo.c \
+ $(GENERIC_DIR)/tclOOMethod.c \
+ $(GENERIC_DIR)/tclOOStubInit.c
+
+STUB_SRCS = \
+ $(GENERIC_DIR)/tclStubLib.c \
+ $(GENERIC_DIR)/tclTomMathStubLib.c \
+ $(GENERIC_DIR)/tclOOStubLib.c
+
+TOMMATH_SRCS = \
+ $(TOMMATH_DIR)/bncore.c \
+ $(TOMMATH_DIR)/bn_reverse.c \
+ $(TOMMATH_DIR)/bn_fast_s_mp_mul_digs.c \
+ $(TOMMATH_DIR)/bn_fast_s_mp_sqr.c \
+ $(TOMMATH_DIR)/bn_mp_add.c \
+ $(TOMMATH_DIR)/bn_mp_add_d.c \
+ $(TOMMATH_DIR)/bn_mp_and.c \
+ $(TOMMATH_DIR)/bn_mp_clamp.c \
+ $(TOMMATH_DIR)/bn_mp_clear.c \
+ $(TOMMATH_DIR)/bn_mp_clear_multi.c \
+ $(TOMMATH_DIR)/bn_mp_cmp.c \
+ $(TOMMATH_DIR)/bn_mp_cmp_d.c \
+ $(TOMMATH_DIR)/bn_mp_cmp_mag.c \
+ $(TOMMATH_DIR)/bn_mp_copy.c \
+ $(TOMMATH_DIR)/bn_mp_cnt_lsb.c \
+ $(TOMMATH_DIR)/bn_mp_count_bits.c \
+ $(TOMMATH_DIR)/bn_mp_div.c \
+ $(TOMMATH_DIR)/bn_mp_div_d.c \
+ $(TOMMATH_DIR)/bn_mp_div_2.c \
+ $(TOMMATH_DIR)/bn_mp_div_2d.c \
+ $(TOMMATH_DIR)/bn_mp_div_3.c \
+ $(TOMMATH_DIR)/bn_mp_exch.c \
+ $(TOMMATH_DIR)/bn_mp_expt_d.c \
+ $(TOMMATH_DIR)/bn_mp_expt_d_ex.c \
+ $(TOMMATH_DIR)/bn_mp_get_int.c \
+ $(TOMMATH_DIR)/bn_mp_get_long.c \
+ $(TOMMATH_DIR)/bn_mp_get_long_long.c \
+ $(TOMMATH_DIR)/bn_mp_grow.c \
+ $(TOMMATH_DIR)/bn_mp_init.c \
+ $(TOMMATH_DIR)/bn_mp_init_copy.c \
+ $(TOMMATH_DIR)/bn_mp_init_multi.c \
+ $(TOMMATH_DIR)/bn_mp_init_set.c \
+ $(TOMMATH_DIR)/bn_mp_init_set_int.c \
+ $(TOMMATH_DIR)/bn_mp_init_size.c \
+ $(TOMMATH_DIR)/bn_mp_karatsuba_mul.c \
+ $(TOMMATH_DIR)/bn_mp_karatsuba_sqr.c \
+ $(TOMMATH_DIR)/bn_mp_lshd.c \
+ $(TOMMATH_DIR)/bn_mp_mod.c \
+ $(TOMMATH_DIR)/bn_mp_mod_2d.c \
+ $(TOMMATH_DIR)/bn_mp_mul.c \
+ $(TOMMATH_DIR)/bn_mp_mul_2.c \
+ $(TOMMATH_DIR)/bn_mp_mul_2d.c \
+ $(TOMMATH_DIR)/bn_mp_mul_d.c \
+ $(TOMMATH_DIR)/bn_mp_neg.c \
+ $(TOMMATH_DIR)/bn_mp_or.c \
+ $(TOMMATH_DIR)/bn_mp_radix_size.c \
+ $(TOMMATH_DIR)/bn_mp_radix_smap.c \
+ $(TOMMATH_DIR)/bn_mp_read_radix.c \
+ $(TOMMATH_DIR)/bn_mp_rshd.c \
+ $(TOMMATH_DIR)/bn_mp_set.c \
+ $(TOMMATH_DIR)/bn_mp_set_int.c \
+ $(TOMMATH_DIR)/bn_mp_set_long.c \
+ $(TOMMATH_DIR)/bn_mp_set_long_long.c \
+ $(TOMMATH_DIR)/bn_mp_shrink.c \
+ $(TOMMATH_DIR)/bn_mp_sqr.c \
+ $(TOMMATH_DIR)/bn_mp_sqrt.c \
+ $(TOMMATH_DIR)/bn_mp_sub.c \
+ $(TOMMATH_DIR)/bn_mp_sub_d.c \
+ $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c \
+ $(TOMMATH_DIR)/bn_mp_to_unsigned_bin_n.c \
+ $(TOMMATH_DIR)/bn_mp_toom_mul.c \
+ $(TOMMATH_DIR)/bn_mp_toom_sqr.c \
+ $(TOMMATH_DIR)/bn_mp_toradix_n.c \
+ $(TOMMATH_DIR)/bn_mp_unsigned_bin_size.c \
+ $(TOMMATH_DIR)/bn_mp_xor.c \
+ $(TOMMATH_DIR)/bn_mp_zero.c \
+ $(TOMMATH_DIR)/bn_s_mp_add.c \
+ $(TOMMATH_DIR)/bn_s_mp_mul_digs.c \
+ $(TOMMATH_DIR)/bn_s_mp_sqr.c \
+ $(TOMMATH_DIR)/bn_s_mp_sub.c
+
+UNIX_HDRS = \
+ $(UNIX_DIR)/tclUnixPort.h
+# $(UNIX_DIR)/tclConfig.h
+
+UNIX_SRCS = \
+ $(UNIX_DIR)/tclAppInit.c \
+ $(UNIX_DIR)/tclUnixChan.c \
+ $(UNIX_DIR)/tclUnixEvent.c \
+ $(UNIX_DIR)/tclUnixFCmd.c \
+ $(UNIX_DIR)/tclUnixFile.c \
+ $(UNIX_DIR)/tclUnixPipe.c \
+ $(UNIX_DIR)/tclUnixSock.c \
+ $(UNIX_DIR)/tclUnixTest.c \
+ $(UNIX_DIR)/tclUnixThrd.c \
+ $(UNIX_DIR)/tclUnixTime.c \
+ $(UNIX_DIR)/tclUnixInit.c \
+ $(UNIX_DIR)/tclUnixCompat.c
+
+NOTIFY_SRCS = \
+ $(UNIX_DIR)/tclEpollNotfy.c \
+ $(UNIX_DIR)/tclKqueueNotfy.c \
+ $(UNIX_DIR)/tclSelectNotfy.c
+
+DL_SRCS = \
+ $(UNIX_DIR)/tclLoadAix.c \
+ $(UNIX_DIR)/tclLoadDl.c \
+ $(UNIX_DIR)/tclLoadDl2.c \
+ $(UNIX_DIR)/tclLoadDld.c \
+ $(UNIX_DIR)/tclLoadDyld.c \
+ $(GENERIC_DIR)/tclLoadNone.c \
+ $(UNIX_DIR)/tclLoadOSF.c \
+ $(UNIX_DIR)/tclLoadShl.c
+
+MAC_OSX_SRCS = \
+ $(MAC_OSX_DIR)/tclMacOSXBundle.c \
+ $(MAC_OSX_DIR)/tclMacOSXFCmd.c \
+ $(MAC_OSX_DIR)/tclMacOSXNotify.c
+
+CYGWIN_SRCS = \
+ $(TOP_DIR)/win/tclWinError.c
+
+DTRACE_HDR = tclDTrace.h
+
+DTRACE_SRC = $(GENERIC_DIR)/tclDTrace.d
+
+ZLIB_SRCS = \
+ $(ZLIB_DIR)/adler32.c \
+ $(ZLIB_DIR)/compress.c \
+ $(ZLIB_DIR)/crc32.c \
+ $(ZLIB_DIR)/deflate.c \
+ $(ZLIB_DIR)/infback.c \
+ $(ZLIB_DIR)/inffast.c \
+ $(ZLIB_DIR)/inflate.c \
+ $(ZLIB_DIR)/inftrees.c \
+ $(ZLIB_DIR)/trees.c \
+ $(ZLIB_DIR)/uncompr.c \
+ $(ZLIB_DIR)/zutil.c
+
+# Note: don't include DL_SRCS or MAC_OSX_SRCS in SRCS: most of those files
+# won't compile on the current machine, and they will cause problems for
+# things like "make depend".
+
+SRCS = $(GENERIC_SRCS) $(TOMMATH_SRCS) $(UNIX_SRCS) $(NOTIFY_SRCS) \
+ $(OO_SRCS) $(STUB_SRCS) @PLAT_SRCS@ @ZLIB_SRCS@
+
+#--------------------------------------------------------------------------
+# Start of rules
+#--------------------------------------------------------------------------
+
+all: binaries libraries doc packages
+
+binaries: ${LIB_FILE} ${TCL_EXE}
+
+libraries:
+
+doc:
+
+# The following target is configured by autoconf to generate either a shared
+# library or non-shared library for Tcl.
+${LIB_FILE}: ${STUB_LIB_FILE} ${OBJS}
+ rm -f $@
+ @MAKE_LIB@
+
+${STUB_LIB_FILE}: ${STUB_LIB_OBJS}
+ @if test "x${LIB_FILE}" = "xlibtcl${MAJOR_VERSION}.${MINOR_VERSION}.dll"; then \
+ (cd ${TOP_DIR}/win; ${MAKE} winextensions); \
+ fi
+ rm -f $@
+ @MAKE_STUB_LIB@
+
+# Make target which outputs the list of the .o contained in the Tcl lib useful
+# to build a single big shared library containing Tcl and other extensions.
+# Used for the Tcl Plugin. -- dl
+# The dependency on OBJS is not there because we just want the list of objects
+# here, not actually building them
+tclLibObjs:
+ @echo ${OBJS}
+# This targets actually build the objects needed for the lib in the above case
+objs: ${OBJS}
+
+${TCL_EXE}: ${TCLSH_OBJS} ${TCL_LIB_FILE} ${TCL_STUB_LIB_FILE}
+ ${CC} ${CFLAGS} ${LDFLAGS} ${TCLSH_OBJS} \
+ @TCL_BUILD_LIB_SPEC@ ${TCL_STUB_LIB_FILE} ${LIBS} @EXTRA_TCLSH_LIBS@ \
+ ${CC_SEARCH_FLAGS} -o ${TCL_EXE}
+
+# Must be empty so it doesn't conflict with rule for ${TCL_EXE} above
+${NATIVE_TCLSH}:
+
+Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in
+ $(SHELL) config.status
+#tclConfig.h: $(UNIX_DIR)/tclConfig.h.in
+# $(SHELL) config.status
+
+clean: clean-packages
+ rm -rf *.a *.o libtcl* core errs *~ \#* TAGS *.E a.out \
+ errors ${TCL_EXE} ${TCLTEST_EXE} lib.exp Tcl @DTRACE_HDR@
+ cd dltest ; $(MAKE) clean
+
+distclean: distclean-packages clean
+ rm -rf Makefile config.status config.cache config.log tclConfig.sh \
+ tclConfig.h *.plist Tcl.framework tcl.pc
+ cd dltest ; $(MAKE) distclean
+
+depend:
+ makedepend -- $(DEPEND_SWITCHES) -- $(SRCS)
+
+#--------------------------------------------------------------------------
+# The following target outputs the name of the top-level source directory for
+# Tcl (it is used by Tk's configure script, for example). The .NO_PARALLEL
+# line is needed to avoid problems under Sun's "pmake". Note: this target is
+# now obsolete (use the autoconf variable TCL_SRC_DIR from tclConfig.sh
+# instead).
+#--------------------------------------------------------------------------
+
+.NO_PARALLEL: topDirName
+topDirName:
+ @cd $(TOP_DIR); pwd
+
+#--------------------------------------------------------------------------
+# Rules for testing
+#--------------------------------------------------------------------------
+
+# Resetting the LIB_RUNTIME_DIR below is required so that the generated
+# tcltest executable gets the build directory burned into its ld search path.
+# This keeps tcltest from picking up an already installed version of the Tcl
+# library.
+SHELL_ENV = @LD_LIBRARY_PATH_VAR@=`pwd`:${@LD_LIBRARY_PATH_VAR@} \
+ TCLLIBPATH="@abs_builddir@/pkgs" \
+ TCL_LIBRARY="${TCL_BUILDTIME_LIBRARY}"
+
+${TCLTEST_EXE}: ${TCLTEST_OBJS} ${TCL_LIB_FILE} ${TCL_STUB_LIB_FILE} ${BUILD_DLTEST}
+ $(MAKE) tcltest-real LIB_RUNTIME_DIR="`pwd`"
+
+tcltest-real:
+ ${CC} ${CFLAGS} ${LDFLAGS} ${TCLTEST_OBJS} \
+ @TCL_BUILD_LIB_SPEC@ ${TCL_STUB_LIB_FILE} ${LIBS} @EXTRA_TCLSH_LIBS@ \
+ ${CC_SEARCH_FLAGS} -o ${TCLTEST_EXE}
+
+# Note, in the targets below TCL_LIBRARY needs to be set or else "make test"
+# won't work in the case where the compilation directory isn't the same as the
+# source directory.
+#
+# Specifying TESTFLAGS on the command line is the standard way to pass args to
+# tcltest, ie:
+# % make test TESTFLAGS="-verbose bps -file fileName.test"
+
+test: test-tcl test-packages
+
+test-tcl: ${TCLTEST_EXE}
+ $(SHELL_ENV) ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl $(TESTFLAGS)
+
+gdb-test: ${TCLTEST_EXE}
+ @echo "set env @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}" > gdb.run
+ @echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run
+ @echo "set args $(TOP_DIR)/tests/all.tcl $(TESTFLAGS) -singleproc 1" >> gdb.run
+ $(GDB) ./${TCLTEST_EXE} --command=gdb.run
+ rm gdb.run
+
+# Useful target to launch a built tcltest with the proper path,...
+runtest: ${TCLTEST_EXE}
+ $(SHELL_ENV) ./${TCLTEST_EXE}
+
+# Useful target for running the test suite with an unwritable current
+# directory...
+ro-test: ${TCLTEST_EXE}
+ echo 'exec chmod -w .;package require tcltest;tcltest::temporaryDirectory /tmp;source ../tests/all.tcl;exec chmod +w .' | $(SHELL_ENV) ./${TCLTEST_EXE}
+
+# The following target generates the shared libraries in dltest/ that are used
+# for testing; they are included as part of the "tcltest" target (via the
+# BUILD_DLTEST variable) if dynamic loading is supported on this platform. The
+# Makefile in the dltest subdirectory creates the dltest.marker file in this
+# directory after a successful build.
+
+dltest.marker: ${STUB_LIB_FILE}
+ cd dltest ; $(MAKE)
+
+#--------------------------------------------------------------------------
+# Rules for running a shell before installation
+#--------------------------------------------------------------------------
+
+# This target can be used to run tclsh from the build directory
+# via `make shell SCRIPT=/tmp/foo.tcl`
+shell: ${TCL_EXE}
+ $(SHELL_ENV) ./${TCL_EXE} $(SCRIPT)
+
+# This target can be used to run tclsh inside either gdb or insight
+gdb: ${TCL_EXE}
+ $(SHELL_ENV) $(GDB) ./${TCL_EXE}
+
+valgrind: ${TCL_EXE} ${TCLTEST_EXE}
+ $(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl -singleproc 1 -constraints valgrind $(TESTFLAGS)
+
+valgrindshell: ${TCL_EXE}
+ $(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCL_EXE} $(SCRIPT)
+
+trace-shell: ${TCL_EXE}
+ $(SHELL_ENV) ${TRACE} $(TRACE_OPTS) ./${TCL_EXE} $(SCRIPT)
+
+trace-test: ${TCLTEST_EXE}
+ $(SHELL_ENV) ${TRACE} $(TRACE_OPTS) ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl -singleproc 1 $(TESTFLAGS)
+
+#--------------------------------------------------------------------------
+# Installation rules
+#--------------------------------------------------------------------------
+
+INSTALL_BASE_TARGETS = install-binaries install-libraries install-msgs $(INSTALL_TZDATA)
+INSTALL_DOC_TARGETS = install-doc
+INSTALL_PACKAGE_TARGETS = install-packages
+INSTALL_DEV_TARGETS = install-headers
+INSTALL_EXTRA_TARGETS = @EXTRA_INSTALL@
+INSTALL_TARGETS = $(INSTALL_BASE_TARGETS) $(INSTALL_DOC_TARGETS) $(INSTALL_DEV_TARGETS) \
+ $(INSTALL_PACKAGE_TARGETS) $(INSTALL_EXTRA_TARGETS)
+
+install: $(INSTALL_TARGETS)
+
+install-strip:
+ $(MAKE) $(INSTALL_TARGETS) \
+ INSTALL_PROGRAM="$(INSTALL_PROGRAM) ${INSTALL_STRIP_PROGRAM}" \
+ INSTALL_LIBRARY="$(INSTALL_LIBRARY) ${INSTALL_STRIP_LIBRARY}"
+
+install-binaries: binaries
+ @for i in "$(LIB_INSTALL_DIR)" "$(BIN_INSTALL_DIR)" \
+ "$(CONFIG_INSTALL_DIR)"; \
+ do \
+ if [ ! -d "$$i" ] ; then \
+ echo "Making directory $$i"; \
+ $(INSTALL_DATA_DIR) "$$i"; \
+ else true; \
+ fi; \
+ done;
+ @echo "Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/"
+ @@INSTALL_LIB@
+ @chmod 555 "$(DLL_INSTALL_DIR)/$(LIB_FILE)"
+ @echo "Installing ${TCL_EXE} as $(BIN_INSTALL_DIR)/tclsh$(VERSION)${EXE_SUFFIX}"
+ @$(INSTALL_PROGRAM) ${TCL_EXE} "$(BIN_INSTALL_DIR)/tclsh$(VERSION)${EXE_SUFFIX}"
+ @echo "Installing tclConfig.sh to $(CONFIG_INSTALL_DIR)/"
+ @$(INSTALL_DATA) tclConfig.sh "$(CONFIG_INSTALL_DIR)/tclConfig.sh"
+ @echo "Installing tclooConfig.sh to $(CONFIG_INSTALL_DIR)/"
+ @$(INSTALL_DATA) $(UNIX_DIR)/tclooConfig.sh \
+ "$(CONFIG_INSTALL_DIR)/tclooConfig.sh"
+ @if test "$(STUB_LIB_FILE)" != "" ; then \
+ echo "Installing $(STUB_LIB_FILE) to $(LIB_INSTALL_DIR)/"; \
+ @INSTALL_STUB_LIB@ ; \
+ fi
+ @EXTRA_INSTALL_BINARIES@
+ @echo "Installing pkg-config file to $(LIB_INSTALL_DIR)/pkgconfig/"
+ @$(INSTALL_DATA_DIR) $(LIB_INSTALL_DIR)/pkgconfig
+ @$(INSTALL_DATA) tcl.pc $(LIB_INSTALL_DIR)/pkgconfig/tcl.pc
+
+install-libraries: libraries
+ @for i in "$(SCRIPT_INSTALL_DIR)"; \
+ do \
+ if [ ! -d "$$i" ] ; then \
+ echo "Making directory $$i"; \
+ $(INSTALL_DATA_DIR) "$$i"; \
+ else true; \
+ fi; \
+ done;
+ @for i in opt0.4 http1.0 encoding ../tcl8 ../tcl8/8.4 ../tcl8/8.4/platform ../tcl8/8.5 ../tcl8/8.6; \
+ do \
+ if [ ! -d "$(SCRIPT_INSTALL_DIR)"/$$i ] ; then \
+ echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
+ $(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)"/$$i; \
+ else true; \
+ fi; \
+ done;
+ @echo "Installing library files to $(SCRIPT_INSTALL_DIR)/";
+ @for i in $(TOP_DIR)/library/*.tcl $(TOP_DIR)/library/tclIndex \
+ $(UNIX_DIR)/tclAppInit.c @LDAIX_SRC@ @DTRACE_SRC@; \
+ do \
+ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"; \
+ done;
+ @echo "Installing package http1.0 files to $(SCRIPT_INSTALL_DIR)/http1.0/";
+ @for i in $(TOP_DIR)/library/http1.0/*.tcl ; \
+ do \
+ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/http1.0; \
+ done;
+ @echo "Installing package http 2.8.12 as a Tcl Module";
+ @$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.6/http-2.8.12.tm;
+ @echo "Installing package opt0.4 files to $(SCRIPT_INSTALL_DIR)/opt0.4/";
+ @for i in $(TOP_DIR)/library/opt/*.tcl ; \
+ do \
+ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/opt0.4; \
+ done;
+ @echo "Installing package msgcat 1.6.1 as a Tcl Module";
+ @$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/msgcat-1.6.1.tm;
+ @echo "Installing package tcltest 2.4.0 as a Tcl Module";
+ @$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/tcltest-2.4.0.tm;
+
+ @echo "Installing package platform 1.0.14 as a Tcl Module";
+ @$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform-1.0.14.tm;
+ @echo "Installing package platform::shell 1.1.4 as a Tcl Module";
+ @$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.4/platform/shell-1.1.4.tm;
+
+ @echo "Installing encoding files to $(SCRIPT_INSTALL_DIR)/encoding/";
+ @for i in $(TOP_DIR)/library/encoding/*.enc ; do \
+ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/encoding; \
+ done;
+ @if [ -n "$(TCL_MODULE_PATH)" -a -f $(TOP_DIR)/library/tm.tcl ]; then \
+ echo "Customizing tcl module path"; \
+ echo "if {![interp issafe]} { ::tcl::tm::roots {$(TCL_MODULE_PATH)} }" >> \
+ "$(SCRIPT_INSTALL_DIR)"/tm.tcl; \
+ fi
+
+install-tzdata:
+ @for i in tzdata; \
+ do \
+ if [ ! -d "$(SCRIPT_INSTALL_DIR)"/$$i ] ; then \
+ echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
+ $(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)"/$$i; \
+ else true; \
+ fi; \
+ done;
+ @echo "Installing time zone files to $(SCRIPT_INSTALL_DIR)/tzdata/"
+ @for i in $(TOP_DIR)/library/tzdata/* ; do \
+ if [ -d $$i ] ; then \
+ ii=`basename $$i`; \
+ if [ ! -d "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii ] ; then \
+ $(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii; \
+ fi; \
+ for j in $$i/* ; do \
+ if [ -d $$j ] ; then \
+ jj=`basename $$j`; \
+ if [ ! -d "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii/$$jj ] ; then \
+ $(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii/$$jj; \
+ fi; \
+ for k in $$j/* ; do \
+ $(INSTALL_DATA) $$k "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii/$$jj; \
+ done; \
+ else \
+ $(INSTALL_DATA) $$j "$(SCRIPT_INSTALL_DIR)"/tzdata/$$ii; \
+ fi; \
+ done; \
+ else \
+ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/tzdata; \
+ fi; \
+ done;
+
+install-msgs:
+ @for i in msgs; \
+ do \
+ if [ ! -d "$(SCRIPT_INSTALL_DIR)"/$$i ] ; then \
+ echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \
+ $(INSTALL_DATA_DIR) "$(SCRIPT_INSTALL_DIR)"/$$i; \
+ else true; \
+ fi; \
+ done;
+ @echo "Installing message catalog files to $(SCRIPT_INSTALL_DIR)/msgs/"
+ @for i in $(TOP_DIR)/library/msgs/*.msg ; do \
+ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/msgs; \
+ done;
+
+install-doc: doc
+ @for i in "$(MAN_INSTALL_DIR)" "$(MAN1_INSTALL_DIR)" "$(MAN3_INSTALL_DIR)" "$(MANN_INSTALL_DIR)" ; \
+ do \
+ if [ ! -d "$$i" ] ; then \
+ echo "Making directory $$i"; \
+ $(INSTALL_DATA_DIR) "$$i"; \
+ else true; \
+ fi; \
+ done;
+ @echo "Installing and cross-linking top-level (.1) docs to $(MAN1_INSTALL_DIR)/";
+ @for i in $(TOP_DIR)/doc/*.1; do \
+ $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MAN1_INSTALL_DIR)"; \
+ done
+
+ @echo "Installing and cross-linking C API (.3) docs to $(MAN3_INSTALL_DIR)/";
+ @for i in $(TOP_DIR)/doc/*.3; do \
+ $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MAN3_INSTALL_DIR)"; \
+ done
+
+ @echo "Installing and cross-linking command (.n) docs to $(MANN_INSTALL_DIR)/";
+ @for i in $(TOP_DIR)/doc/*.n; do \
+ $(SHELL) $(UNIX_DIR)/installManPage $(MAN_FLAGS) $$i "$(MANN_INSTALL_DIR)"; \
+ done
+
+install-headers:
+ @for i in "$(INCLUDE_INSTALL_DIR)"; \
+ do \
+ if [ ! -d "$$i" ] ; then \
+ echo "Making directory $$i"; \
+ $(INSTALL_DATA_DIR) "$$i"; \
+ else true; \
+ fi; \
+ done;
+ @echo "Installing header files to $(INCLUDE_INSTALL_DIR)/";
+ @for i in $(GENERIC_DIR)/tcl.h $(GENERIC_DIR)/tclDecls.h \
+ $(GENERIC_DIR)/tclOO.h $(GENERIC_DIR)/tclOODecls.h \
+ $(GENERIC_DIR)/tclPlatDecls.h \
+ $(GENERIC_DIR)/tclTomMath.h \
+ $(GENERIC_DIR)/tclTomMathDecls.h ; \
+ do \
+ $(INSTALL_DATA) $$i "$(INCLUDE_INSTALL_DIR)"; \
+ done;
+
+# Optional target to install private headers
+install-private-headers:
+ @for i in "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
+ do \
+ if [ ! -d "$$i" ] ; then \
+ echo "Making directory $$i"; \
+ $(INSTALL_DATA_DIR) "$$i"; \
+ else true; \
+ fi; \
+ done;
+ @echo "Installing private header files to $(PRIVATE_INCLUDE_INSTALL_DIR)/";
+ @for i in $(GENERIC_DIR)/tclInt.h $(GENERIC_DIR)/tclIntDecls.h \
+ $(GENERIC_DIR)/tclIntPlatDecls.h $(GENERIC_DIR)/tclPort.h \
+ $(GENERIC_DIR)/tclOOInt.h $(GENERIC_DIR)/tclOOIntDecls.h \
+ $(UNIX_DIR)/tclUnixPort.h; \
+ do \
+ $(INSTALL_DATA) $$i "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
+ done;
+ @if test -f tclConfig.h; then\
+ $(INSTALL_DATA) tclConfig.h "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \
+ fi;
+
+#--------------------------------------------------------------------------
+# Rules for how to compile C files
+#--------------------------------------------------------------------------
+
+# Test binaries. The rules for tclTestInit.o and xtTestInit.o are complicated
+# because they are compiled from tclAppInit.c. Can't use the "-o" option
+# because this doesn't work on some strange compilers (e.g. UnixWare).
+#
+# To enable concurrent parallel make of tclsh and tcltest resp xttest, these
+# targets have to depend on tclsh, this ensures that linking of tclsh with
+# tclAppInit.o does not execute concurrently with the renaming and recompiling
+# of that same object file in the targets below.
+
+tclTestInit.o: $(UNIX_DIR)/tclAppInit.c ${TCL_EXE}
+ @if test -f tclAppInit.o ; then \
+ rm -f tclAppInit.sav; \
+ mv tclAppInit.o tclAppInit.sav; \
+ fi;
+ $(CC) -c $(APP_CC_SWITCHES) \
+ -DTCL_BUILDTIME_LIBRARY="\"${TCL_BUILDTIME_LIBRARY}\"" \
+ -DTCL_TEST $(UNIX_DIR)/tclAppInit.c
+ rm -f tclTestInit.o
+ mv tclAppInit.o tclTestInit.o
+ @if test -f tclAppInit.sav ; then \
+ mv tclAppInit.sav tclAppInit.o; \
+ fi;
+
+xtTestInit.o: $(UNIX_DIR)/tclAppInit.c ${TCL_EXE}
+ @if test -f tclAppInit.o ; then \
+ rm -f tclAppInit.sav; \
+ mv tclAppInit.o tclAppInit.sav; \
+ fi;
+ $(CC) -c $(APP_CC_SWITCHES) \
+ -DTCL_BUILDTIME_LIBRARY="\"${TCL_BUILDTIME_LIBRARY}\"" \
+ -DTCL_TEST -DTCL_XT_TEST $(UNIX_DIR)/tclAppInit.c
+ rm -f xtTestInit.o
+ mv tclAppInit.o xtTestInit.o
+ @if test -f tclAppInit.sav ; then \
+ mv tclAppInit.sav tclAppInit.o; \
+ fi;
+
+# Object files used on all Unix systems:
+
+REGHDRS=$(GENERIC_DIR)/regex.h $(GENERIC_DIR)/regguts.h \
+ $(GENERIC_DIR)/regcustom.h
+TCLREHDRS=$(GENERIC_DIR)/tclRegexp.h
+COMPILEHDR=$(GENERIC_DIR)/tclCompile.h
+FSHDR=$(GENERIC_DIR)/tclFileSystem.h
+IOHDR=$(GENERIC_DIR)/tclIO.h
+MATHHDRS=$(GENERIC_DIR)/tommath.h $(GENERIC_DIR)/tclTomMath.h
+PARSEHDR=$(GENERIC_DIR)/tclParse.h
+NREHDR=$(GENERIC_DIR)/tclInt.h
+TRIMHDR=$(GENERIC_DIR)/tclStringTrim.h
+
+regcomp.o: $(REGHDRS) $(GENERIC_DIR)/regcomp.c $(GENERIC_DIR)/regc_lex.c \
+ $(GENERIC_DIR)/regc_color.c $(GENERIC_DIR)/regc_locale.c \
+ $(GENERIC_DIR)/regc_nfa.c $(GENERIC_DIR)/regc_cvec.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regcomp.c
+
+regexec.o: $(REGHDRS) $(GENERIC_DIR)/regexec.c $(GENERIC_DIR)/rege_dfa.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regexec.c
+
+regfree.o: $(REGHDRS) $(GENERIC_DIR)/regfree.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regfree.c
+
+regerror.o: $(REGHDRS) $(GENERIC_DIR)/regerrs.h $(GENERIC_DIR)/regerror.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regerror.c
+
+tclAppInit.o: $(UNIX_DIR)/tclAppInit.c
+ $(CC) -c $(APP_CC_SWITCHES) $(UNIX_DIR)/tclAppInit.c
+
+tclAlloc.o: $(GENERIC_DIR)/tclAlloc.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAlloc.c
+
+tclAssembly.o: $(GENERIC_DIR)/tclAssembly.c $(COMPILEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAssembly.c
+
+tclAsync.o: $(GENERIC_DIR)/tclAsync.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAsync.c
+
+tclBasic.o: $(GENERIC_DIR)/tclBasic.c $(COMPILEHDR) $(MATHHDRS) $(NREHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclBasic.c
+
+tclBinary.o: $(GENERIC_DIR)/tclBinary.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclBinary.c
+
+tclCkalloc.o: $(GENERIC_DIR)/tclCkalloc.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCkalloc.c
+
+tclClock.o: $(GENERIC_DIR)/tclClock.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclClock.c
+
+tclCmdAH.o: $(GENERIC_DIR)/tclCmdAH.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdAH.c
+
+tclCmdIL.o: $(GENERIC_DIR)/tclCmdIL.c $(TCLREHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdIL.c
+
+tclCmdMZ.o: $(GENERIC_DIR)/tclCmdMZ.c $(TCLREHDRS) $(TRIMHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCmdMZ.c
+
+tclDate.o: $(GENERIC_DIR)/tclDate.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclDate.c
+
+tclCompCmds.o: $(GENERIC_DIR)/tclCompCmds.c $(COMPILEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmds.c
+
+tclCompCmdsGR.o: $(GENERIC_DIR)/tclCompCmdsGR.c $(COMPILEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmdsGR.c
+
+tclCompCmdsSZ.o: $(GENERIC_DIR)/tclCompCmdsSZ.c $(COMPILEHDR) $(TRIMHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompCmdsSZ.c
+
+tclCompExpr.o: $(GENERIC_DIR)/tclCompExpr.c $(COMPILEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompExpr.c
+
+tclCompile.o: $(GENERIC_DIR)/tclCompile.c $(COMPILEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclCompile.c
+
+tclConfig.o: $(GENERIC_DIR)/tclConfig.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclConfig.c
+
+tclDictObj.o: $(GENERIC_DIR)/tclDictObj.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclDictObj.c
+
+tclDisassemble.o: $(GENERIC_DIR)/tclDisassemble.c $(COMPILEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclDisassemble.c
+
+tclEncoding.o: $(GENERIC_DIR)/tclEncoding.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclEncoding.c
+
+tclEnsemble.o: $(GENERIC_DIR)/tclEnsemble.c $(COMPILEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclEnsemble.c
+
+tclEnv.o: $(GENERIC_DIR)/tclEnv.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclEnv.c
+
+tclEvent.o: $(GENERIC_DIR)/tclEvent.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclEvent.c
+
+tclExecute.o: $(GENERIC_DIR)/tclExecute.c $(COMPILEHDR) $(MATHHDRS) $(NREHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclExecute.c
+
+tclFCmd.o: $(GENERIC_DIR)/tclFCmd.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclFCmd.c
+
+tclFileName.o: $(GENERIC_DIR)/tclFileName.c $(FSHDR) $(TCLREHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclFileName.c
+
+tclGet.o: $(GENERIC_DIR)/tclGet.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclGet.c
+
+tclHash.o: $(GENERIC_DIR)/tclHash.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclHash.c
+
+tclHistory.o: $(GENERIC_DIR)/tclHistory.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclHistory.c
+
+tclIndexObj.o: $(GENERIC_DIR)/tclIndexObj.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIndexObj.c
+
+tclInterp.o: $(GENERIC_DIR)/tclInterp.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclInterp.c
+
+tclIO.o: $(GENERIC_DIR)/tclIO.c $(IOHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIO.c
+
+tclIOCmd.o: $(GENERIC_DIR)/tclIOCmd.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIOCmd.c
+
+tclIOGT.o: $(GENERIC_DIR)/tclIOGT.c $(IOHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIOGT.c
+
+tclIOSock.o: $(GENERIC_DIR)/tclIOSock.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIOSock.c
+
+tclIOUtil.o: $(GENERIC_DIR)/tclIOUtil.c $(FSHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIOUtil.c
+
+tclIORChan.o: $(GENERIC_DIR)/tclIORChan.c $(IOHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIORChan.c
+
+tclIORTrans.o: $(GENERIC_DIR)/tclIORTrans.c $(IOHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIORTrans.c
+
+tclLink.o: $(GENERIC_DIR)/tclLink.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclLink.c
+
+tclListObj.o: $(GENERIC_DIR)/tclListObj.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclListObj.c
+
+tclLiteral.o: $(GENERIC_DIR)/tclLiteral.c $(COMPILEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclLiteral.c
+
+tclObj.o: $(GENERIC_DIR)/tclObj.c $(COMPILEHDR) $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclObj.c
+
+tclOptimize.o: $(GENERIC_DIR)/tclOptimize.c $(COMPILEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOptimize.c
+
+tclLoad.o: $(GENERIC_DIR)/tclLoad.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclLoad.c
+
+tclLoadAix.o: $(UNIX_DIR)/tclLoadAix.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadAix.c
+
+tclLoadDl.o: $(UNIX_DIR)/tclLoadDl.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadDl.c
+
+tclLoadDl2.o: $(UNIX_DIR)/tclLoadDl2.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadDl2.c
+
+tclLoadDld.o: $(UNIX_DIR)/tclLoadDld.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadDld.c
+
+tclLoadDyld.o: $(UNIX_DIR)/tclLoadDyld.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadDyld.c
+
+tclLoadNone.o: $(GENERIC_DIR)/tclLoadNone.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclLoadNone.c
+
+tclLoadOSF.o: $(UNIX_DIR)/tclLoadOSF.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadOSF.c
+
+tclLoadShl.o: $(UNIX_DIR)/tclLoadShl.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclLoadShl.c
+
+tclMain.o: $(GENERIC_DIR)/tclMain.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclMain.c
+
+tclNamesp.o: $(GENERIC_DIR)/tclNamesp.c $(COMPILEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclNamesp.c
+
+tclNotify.o: $(GENERIC_DIR)/tclNotify.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclNotify.c
+
+tclOO.o: $(GENERIC_DIR)/tclOO.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOO.c
+
+tclOOBasic.o: $(GENERIC_DIR)/tclOOBasic.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOBasic.c
+
+tclOOCall.o: $(GENERIC_DIR)/tclOOCall.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOCall.c
+
+tclOODefineCmds.o: $(GENERIC_DIR)/tclOODefineCmds.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOODefineCmds.c
+
+tclOOInfo.o: $(GENERIC_DIR)/tclOOInfo.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOInfo.c
+
+tclOOMethod.o: $(GENERIC_DIR)/tclOOMethod.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOMethod.c
+
+tclOOStubInit.o: $(GENERIC_DIR)/tclOOStubInit.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOStubInit.c
+
+tclParse.o: $(GENERIC_DIR)/tclParse.c $(PARSEHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclParse.c
+
+tclPanic.o: $(GENERIC_DIR)/tclPanic.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPanic.c
+
+tclPathObj.o: $(GENERIC_DIR)/tclPathObj.c $(FSHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPathObj.c
+
+tclPipe.o: $(GENERIC_DIR)/tclPipe.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPipe.c
+
+tclPkg.o: $(GENERIC_DIR)/tclPkg.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPkg.c
+
+# TIP #59, embedding of configuration information into the binary library.
+#
+# Part of Tcl's configuration information are the paths where it was installed
+# and where it will look for its libraries (which can be different). We derive
+# this information from the variables which can be overridden by the user. As
+# every path can be configured separately we do not remember one general
+# prefix/exec_prefix but all the different paths individually.
+
+tclPkgConfig.o: $(GENERIC_DIR)/tclPkgConfig.c
+ $(CC) -c $(CC_SWITCHES) \
+ -DCFG_INSTALL_LIBDIR="\"$(LIB_INSTALL_DIR)\"" \
+ -DCFG_INSTALL_BINDIR="\"$(BIN_INSTALL_DIR)\"" \
+ -DCFG_INSTALL_SCRDIR="\"$(SCRIPT_INSTALL_DIR)\"" \
+ -DCFG_INSTALL_INCDIR="\"$(INCLUDE_INSTALL_DIR)\"" \
+ -DCFG_INSTALL_DOCDIR="\"$(MAN_INSTALL_DIR)\"" \
+ \
+ -DCFG_RUNTIME_LIBDIR="\"$(libdir)\"" \
+ -DCFG_RUNTIME_BINDIR="\"$(bindir)\"" \
+ -DCFG_RUNTIME_SCRDIR="\"$(TCL_LIBRARY)\"" \
+ -DCFG_RUNTIME_INCDIR="\"$(includedir)\"" \
+ -DCFG_RUNTIME_DOCDIR="\"$(mandir)\"" \
+ \
+ $(GENERIC_DIR)/tclPkgConfig.c
+
+tclPosixStr.o: $(GENERIC_DIR)/tclPosixStr.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPosixStr.c
+
+tclPreserve.o: $(GENERIC_DIR)/tclPreserve.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclPreserve.c
+
+tclProc.o: $(GENERIC_DIR)/tclProc.c $(COMPILEHDR) $(NREHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclProc.c
+
+tclRegexp.o: $(GENERIC_DIR)/tclRegexp.c $(TCLREHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclRegexp.c
+
+tclResolve.o: $(GENERIC_DIR)/tclResolve.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclResolve.c
+
+tclResult.o: $(GENERIC_DIR)/tclResult.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclResult.c
+
+tclScan.o: $(GENERIC_DIR)/tclScan.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclScan.c
+
+tclStringObj.o: $(GENERIC_DIR)/tclStringObj.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStringObj.c
+
+tclStrToD.o: $(GENERIC_DIR)/tclStrToD.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStrToD.c
+
+tclStubInit.o: $(GENERIC_DIR)/tclStubInit.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclStubInit.c
+
+tclTrace.o: $(GENERIC_DIR)/tclTrace.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclTrace.c
+
+tclUtil.o: $(GENERIC_DIR)/tclUtil.c $(PARSEHDR) $(TRIMHDR)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclUtil.c
+
+tclUtf.o: $(GENERIC_DIR)/tclUtf.c $(GENERIC_DIR)/tclUniData.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclUtf.c
+
+tclVar.o: $(GENERIC_DIR)/tclVar.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclVar.c
+
+tclZlib.o: $(GENERIC_DIR)/tclZlib.c
+ $(CC) -c $(CC_SWITCHES) $(ZLIB_INCLUDE) $(GENERIC_DIR)/tclZlib.c
+
+tclTest.o: $(GENERIC_DIR)/tclTest.c $(IOHDR) $(TCLREHDRS)
+ $(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTest.c
+
+tclTestObj.o: $(GENERIC_DIR)/tclTestObj.c $(MATHHDRS)
+ $(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTestObj.c
+
+tclTestProcBodyObj.o: $(GENERIC_DIR)/tclTestProcBodyObj.c
+ $(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTestProcBodyObj.c
+
+tclTimer.o: $(GENERIC_DIR)/tclTimer.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclTimer.c
+
+tclThread.o: $(GENERIC_DIR)/tclThread.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThread.c
+
+tclThreadAlloc.o: $(GENERIC_DIR)/tclThreadAlloc.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadAlloc.c
+
+tclThreadJoin.o: $(GENERIC_DIR)/tclThreadJoin.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadJoin.c
+
+tclThreadStorage.o: $(GENERIC_DIR)/tclThreadStorage.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadStorage.c
+
+tclThreadTest.o: $(GENERIC_DIR)/tclThreadTest.c
+ $(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclThreadTest.c
+
+tclTomMathInterface.o: $(GENERIC_DIR)/tclTomMathInterface.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclTomMathInterface.c
+
+bncore.o: $(TOMMATH_DIR)/bncore.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bncore.c
+
+bn_reverse.o: $(TOMMATH_DIR)/bn_reverse.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_reverse.c
+
+bn_fast_s_mp_mul_digs.o: $(TOMMATH_DIR)/bn_fast_s_mp_mul_digs.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_fast_s_mp_mul_digs.c
+
+bn_fast_s_mp_sqr.o: $(TOMMATH_DIR)/bn_fast_s_mp_sqr.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_fast_s_mp_sqr.c
+
+bn_mp_add.o: $(TOMMATH_DIR)/bn_mp_add.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_add.c
+
+bn_mp_add_d.o: $(TOMMATH_DIR)/bn_mp_add_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_add_d.c
+
+bn_mp_and.o: $(TOMMATH_DIR)/bn_mp_and.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_and.c
+
+bn_mp_clamp.o: $(TOMMATH_DIR)/bn_mp_clamp.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_clamp.c
+
+bn_mp_clear.o: $(TOMMATH_DIR)/bn_mp_clear.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_clear.c
+
+bn_mp_clear_multi.o: $(TOMMATH_DIR)/bn_mp_clear_multi.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_clear_multi.c
+
+bn_mp_cmp.o: $(TOMMATH_DIR)/bn_mp_cmp.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_cmp.c
+
+bn_mp_cmp_d.o: $(TOMMATH_DIR)/bn_mp_cmp_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_cmp_d.c
+
+bn_mp_cmp_mag.o: $(TOMMATH_DIR)/bn_mp_cmp_mag.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_cmp_mag.c
+
+bn_mp_cnt_lsb.o: $(TOMMATH_DIR)/bn_mp_cnt_lsb.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_cnt_lsb.c
+
+bn_mp_copy.o: $(TOMMATH_DIR)/bn_mp_copy.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_copy.c
+
+bn_mp_count_bits.o: $(TOMMATH_DIR)/bn_mp_count_bits.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_count_bits.c
+
+bn_mp_div.o: $(TOMMATH_DIR)/bn_mp_div.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div.c
+
+bn_mp_div_d.o: $(TOMMATH_DIR)/bn_mp_div_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_d.c
+
+bn_mp_div_2.o: $(TOMMATH_DIR)/bn_mp_div_2.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2.c
+
+bn_mp_div_2d.o: $(TOMMATH_DIR)/bn_mp_div_2d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_2d.c
+
+bn_mp_div_3.o: $(TOMMATH_DIR)/bn_mp_div_3.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_div_3.c
+
+bn_mp_exch.o: $(TOMMATH_DIR)/bn_mp_exch.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_exch.c
+
+bn_mp_expt_d.o: $(TOMMATH_DIR)/bn_mp_expt_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_expt_d.c
+
+bn_mp_expt_d_ex.o: $(TOMMATH_DIR)/bn_mp_expt_d_ex.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_expt_d_ex.c
+
+bn_mp_get_int.o: $(TOMMATH_DIR)/bn_mp_get_int.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_get_int.c
+
+bn_mp_get_long.o: $(TOMMATH_DIR)/bn_mp_get_long.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_get_long.c
+
+bn_mp_get_long_long.o: $(TOMMATH_DIR)/bn_mp_get_long_long.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_get_long_long.c
+
+bn_mp_grow.o: $(TOMMATH_DIR)/bn_mp_grow.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_grow.c
+
+bn_mp_init.o: $(TOMMATH_DIR)/bn_mp_init.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init.c
+
+bn_mp_init_copy.o: $(TOMMATH_DIR)/bn_mp_init_copy.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_copy.c
+
+bn_mp_init_multi.o: $(TOMMATH_DIR)/bn_mp_init_multi.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_multi.c
+
+bn_mp_init_set.o: $(TOMMATH_DIR)/bn_mp_init_set.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_set.c
+
+bn_mp_init_set_int.o: $(TOMMATH_DIR)/bn_mp_init_set_int.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_set_int.c
+
+bn_mp_init_size.o:$(TOMMATH_DIR)/bn_mp_init_size.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_init_size.c
+
+bn_mp_karatsuba_mul.o: $(TOMMATH_DIR)/bn_mp_karatsuba_mul.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_karatsuba_mul.c
+
+bn_mp_karatsuba_sqr.o: $(TOMMATH_DIR)/bn_mp_karatsuba_sqr.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_karatsuba_sqr.c
+
+bn_mp_lshd.o: $(TOMMATH_DIR)/bn_mp_lshd.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_lshd.c
+
+bn_mp_mod.o: $(TOMMATH_DIR)/bn_mp_mod.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mod.c
+
+bn_mp_mod_2d.o: $(TOMMATH_DIR)/bn_mp_mod_2d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mod_2d.c
+
+bn_mp_mul.o: $(TOMMATH_DIR)/bn_mp_mul.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul.c
+
+bn_mp_mul_2.o: $(TOMMATH_DIR)/bn_mp_mul_2.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul_2.c
+
+bn_mp_mul_2d.o: $(TOMMATH_DIR)/bn_mp_mul_2d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul_2d.c
+
+bn_mp_mul_d.o: $(TOMMATH_DIR)/bn_mp_mul_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_mul_d.c
+
+bn_mp_neg.o: $(TOMMATH_DIR)/bn_mp_neg.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_neg.c
+
+bn_mp_or.o: $(TOMMATH_DIR)/bn_mp_or.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_or.c
+
+bn_mp_radix_size.o: $(TOMMATH_DIR)/bn_mp_radix_size.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_radix_size.c
+
+bn_mp_radix_smap.o: $(TOMMATH_DIR)/bn_mp_radix_smap.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_radix_smap.c
+
+bn_mp_read_radix.o: $(TOMMATH_DIR)/bn_mp_read_radix.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_read_radix.c
+
+bn_mp_rshd.o: $(TOMMATH_DIR)/bn_mp_rshd.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_rshd.c
+
+bn_mp_set.o: $(TOMMATH_DIR)/bn_mp_set.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_set.c
+
+bn_mp_set_int.o: $(TOMMATH_DIR)/bn_mp_set_int.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_set_int.c
+
+bn_mp_set_long.o: $(TOMMATH_DIR)/bn_mp_set_long.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_set_long.c
+
+bn_mp_set_long_long.o: $(TOMMATH_DIR)/bn_mp_set_long_long.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_set_long_long.c
+
+bn_mp_shrink.o: $(TOMMATH_DIR)/bn_mp_shrink.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_shrink.c
+
+bn_mp_sqr.o: $(TOMMATH_DIR)/bn_mp_sqr.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sqr.c
+
+bn_mp_sqrt.o: $(TOMMATH_DIR)/bn_mp_sqrt.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sqrt.c
+
+bn_mp_sub.o: $(TOMMATH_DIR)/bn_mp_sub.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sub.c
+
+bn_mp_sub_d.o: $(TOMMATH_DIR)/bn_mp_sub_d.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sub_d.c
+
+bn_mp_to_unsigned_bin.o: $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c
+
+bn_mp_to_unsigned_bin_n.o: $(TOMMATH_DIR)/bn_mp_to_unsigned_bin_n.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_to_unsigned_bin_n.c
+
+bn_mp_toom_mul.o: $(TOMMATH_DIR)/bn_mp_toom_mul.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_toom_mul.c
+
+bn_mp_toom_sqr.o: $(TOMMATH_DIR)/bn_mp_toom_sqr.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_toom_sqr.c
+
+bn_mp_toradix_n.o: $(TOMMATH_DIR)/bn_mp_toradix_n.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_toradix_n.c
+
+bn_mp_unsigned_bin_size.o: $(TOMMATH_DIR)/bn_mp_unsigned_bin_size.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_unsigned_bin_size.c
+
+bn_mp_xor.o: $(TOMMATH_DIR)/bn_mp_xor.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_xor.c
+
+bn_mp_zero.o: $(TOMMATH_DIR)/bn_mp_zero.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_zero.c
+
+bn_s_mp_add.o: $(TOMMATH_DIR)/bn_s_mp_add.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_add.c
+
+bn_s_mp_mul_digs.o: $(TOMMATH_DIR)/bn_s_mp_mul_digs.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_mul_digs.c
+
+bn_s_mp_sqr.o: $(TOMMATH_DIR)/bn_s_mp_sqr.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_sqr.c
+
+bn_s_mp_sub.o: $(TOMMATH_DIR)/bn_s_mp_sub.c $(MATHHDRS)
+ $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_s_mp_sub.c
+
+tclUnixChan.o: $(UNIX_DIR)/tclUnixChan.c $(IOHDR)
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixChan.c
+
+tclUnixEvent.o: $(UNIX_DIR)/tclUnixEvent.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixEvent.c
+
+tclUnixFCmd.o: $(UNIX_DIR)/tclUnixFCmd.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixFCmd.c
+
+tclUnixFile.o: $(UNIX_DIR)/tclUnixFile.c $(FSHDR)
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixFile.c
+
+tclEpollNotfy.o: $(UNIX_DIR)/tclEpollNotfy.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclEpollNotfy.c
+
+tclKqueueNotfy.o: $(UNIX_DIR)/tclKqueueNotfy.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclKqueueNotfy.c
+
+tclSelectNotfy.o: $(UNIX_DIR)/tclSelectNotfy.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclSelectNotfy.c
+
+tclUnixPipe.o: $(UNIX_DIR)/tclUnixPipe.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixPipe.c
+
+tclUnixSock.o: $(UNIX_DIR)/tclUnixSock.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixSock.c
+
+tclUnixTest.o: $(UNIX_DIR)/tclUnixTest.c
+ $(CC) -c $(APP_CC_SWITCHES) $(UNIX_DIR)/tclUnixTest.c
+
+tclUnixThrd.o: $(UNIX_DIR)/tclUnixThrd.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixThrd.c
+
+tclUnixTime.o: $(UNIX_DIR)/tclUnixTime.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixTime.c
+
+TCL_LOCATIONS=-DTCL_LIBRARY="\"${TCL_LIBRARY}\"" -DTCL_PACKAGE_PATH="\"${TCL_PACKAGE_PATH}\""
+tclUnixInit.o: $(UNIX_DIR)/tclUnixInit.c tclConfig.sh
+ $(CC) -c $(CC_SWITCHES) $(TCL_LOCATIONS) $(UNIX_DIR)/tclUnixInit.c
+
+tclUnixCompat.o: $(UNIX_DIR)/tclUnixCompat.c
+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixCompat.c
+
+# The following are Mac OS X only sources:
+tclMacOSXBundle.o: $(MAC_OSX_DIR)/tclMacOSXBundle.c
+ $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXBundle.c
+
+tclMacOSXFCmd.o: $(MAC_OSX_DIR)/tclMacOSXFCmd.c
+ $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXFCmd.c
+
+tclMacOSXNotify.o: $(MAC_OSX_DIR)/tclMacOSXNotify.c
+ $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXNotify.c
+
+# The following is a CYGWIN only source:
+tclWinError.o: $(TOP_DIR)/win/tclWinError.c
+ $(CC) -c $(CC_SWITCHES) $(TOP_DIR)/win/tclWinError.c
+
+# DTrace support
+
+$(TCL_OBJS) $(STUB_LIB_OBJS) $(TCLSH_OBJS) $(TCLTEST_OBJS) $(XTTEST_OBJS) $(TOMMATH_OBJS): @DTRACE_HDR@
+
+$(DTRACE_HDR): $(DTRACE_SRC)
+ $(DTRACE) -h $(DTRACE_SWITCHES) -o $@ -s $(DTRACE_SRC)
+
+$(DTRACE_OBJ): $(DTRACE_SRC) $(TCL_OBJS)
+ $(DTRACE) -G $(DTRACE_SWITCHES) -o $@ -s $(DTRACE_SRC) $(TCL_OBJS)
+
+#--------------------------------------------------------------------------
+# The following targets are not completely general. They are provide purely
+# for documentation purposes so people who are interested in the Xt based
+# notifier can modify them to suit their own installation.
+#--------------------------------------------------------------------------
+
+xttest: ${XTTEST_OBJS} ${TCL_LIB_FILE} ${TCL_STUB_LIB_FILE} ${BUILD_DLTEST}
+ ${CC} ${CFLAGS} ${LDFLAGS} ${XTTEST_OBJS} \
+ @TCL_BUILD_LIB_SPEC@ ${TCL_STUB_LIB_FILE} ${LIBS} @EXTRA_TCLSH_LIBS@ \
+ ${CC_SEARCH_FLAGS} -L/usr/openwin/lib -lXt -o xttest
+
+tclXtNotify.o: $(UNIX_DIR)/tclXtNotify.c
+ $(CC) -c $(APP_CC_SWITCHES) -I/usr/openwin/include \
+ $(UNIX_DIR)/tclXtNotify.c
+
+tclXtTest.o: $(UNIX_DIR)/tclXtTest.c
+ $(CC) -c $(APP_CC_SWITCHES) -I/usr/openwin/include \
+ $(UNIX_DIR)/tclXtTest.c
+
+#--------------------------------------------------------------------------
+# Compat binaries, these must be compiled for use in a shared library even
+# though they may be placed in a static executable or library. Since they are
+# included in both the tcl library and the stub library, they need to be
+# relocatable.
+#--------------------------------------------------------------------------
+
+fixstrtod.o: $(COMPAT_DIR)/fixstrtod.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/fixstrtod.c
+
+opendir.o: $(COMPAT_DIR)/opendir.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/opendir.c
+
+mkstemp.o: $(COMPAT_DIR)/mkstemp.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/mkstemp.c
+
+memcmp.o: $(COMPAT_DIR)/memcmp.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/memcmp.c
+
+strncasecmp.o: $(COMPAT_DIR)/strncasecmp.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strncasecmp.c
+
+strstr.o: $(COMPAT_DIR)/strstr.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strstr.c
+
+strtod.o: $(COMPAT_DIR)/strtod.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strtod.c
+
+strtol.o: $(COMPAT_DIR)/strtol.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strtol.c
+
+strtoul.o: $(COMPAT_DIR)/strtoul.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strtoul.c
+
+waitpid.o: $(COMPAT_DIR)/waitpid.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/waitpid.c
+
+fake-rfc2553.o: $(COMPAT_DIR)/fake-rfc2553.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/fake-rfc2553.c
+
+# For building zlib, only used in some build configurations
+Zadler32.o: $(ZLIB_DIR)/adler32.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/adler32.c
+Zcompress.o: $(ZLIB_DIR)/compress.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/compress.c
+Zcrc32.o: $(ZLIB_DIR)/crc32.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/crc32.c
+Zdeflate.o: $(ZLIB_DIR)/deflate.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/deflate.c
+Zinfback.o: $(ZLIB_DIR)/infback.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/infback.c
+Zinffast.o: $(ZLIB_DIR)/inffast.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/inffast.c
+Zinflate.o: $(ZLIB_DIR)/inflate.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/inflate.c
+Zinftrees.o: $(ZLIB_DIR)/inftrees.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/inftrees.c
+Ztrees.o: $(ZLIB_DIR)/trees.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/trees.c
+Zuncompr.o: $(ZLIB_DIR)/uncompr.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/uncompr.c
+Zzutil.o: $(ZLIB_DIR)/zutil.c
+ $(CC) -c -o $@ $(CC_SWITCHES) -I$(ZLIB_DIR) $(ZLIB_DIR)/zutil.c
+
+#--------------------------------------------------------------------------
+# Stub library binaries, these must be compiled for use in a shared library
+# even though they will be placed in a static archive
+#--------------------------------------------------------------------------
+
+tclStubLib.o: $(GENERIC_DIR)/tclStubLib.c
+ $(CC) -c $(STUB_CC_SWITCHES) -DSTATIC_BUILD $(GENERIC_DIR)/tclStubLib.c
+
+tclTomMathStubLib.o: $(GENERIC_DIR)/tclTomMathStubLib.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(GENERIC_DIR)/tclTomMathStubLib.c
+
+tclOOStubLib.o: $(GENERIC_DIR)/tclOOStubLib.c
+ $(CC) -c $(STUB_CC_SWITCHES) $(GENERIC_DIR)/tclOOStubLib.c
+
+.c.o:
+ $(CC) -c $(CC_SWITCHES) $<
+
+#--------------------------------------------------------------------------
+# Bundled Package targets
+#--------------------------------------------------------------------------
+
+# Propagate configure args like --enable-64bit to package configure
+PKG_CFG_ARGS = @PKG_CFG_ARGS@
+# If PKG_DIR is changed to a different relative depth to the build dir, need
+# to adapt the ../.. relative paths below and at the top of configure.ac (we
+# cannot use absolute paths due to issues in nested configure when path to
+# build dir contains spaces).
+PKG_DIR = ./pkgs
+
+configure-packages:
+ @for i in $(PKGS_DIR)/*; do \
+ if [ -d $$i ]; then \
+ if [ -x $$i/configure ]; then \
+ pkg=`basename $$i`; \
+ echo "Configuring package '$$pkg'"; \
+ mkdir -p $(PKG_DIR)/$$pkg; \
+ if [ ! -f $(PKG_DIR)/$$pkg/Makefile ]; then \
+ ( cd $(PKG_DIR)/$$pkg; \
+ $$i/configure --with-tcl=../.. \
+ --with-tclinclude=$(GENERIC_DIR) \
+ $(PKG_CFG_ARGS) --libdir=$(PACKAGE_DIR) \
+ --enable-shared --enable-threads; ) || exit $$?; \
+ fi; \
+ fi; \
+ fi; \
+ done
+
+packages: configure-packages ${STUB_LIB_FILE}
+ @for i in $(PKGS_DIR)/*; do \
+ if [ -d $$i ]; then \
+ pkg=`basename $$i`; \
+ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \
+ echo "Building package '$$pkg'"; \
+ ( cd $(PKG_DIR)/$$pkg; $(MAKE); ) || exit $$?; \
+ fi; \
+ fi; \
+ done
+
+install-packages: packages
+ @for i in $(PKGS_DIR)/*; do \
+ if [ -d $$i ]; then \
+ pkg=`basename $$i`; \
+ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \
+ echo "Installing package '$$pkg'"; \
+ ( cd $(PKG_DIR)/$$pkg; $(MAKE) install \
+ "DESTDIR=$(INSTALL_ROOT)"; ) || exit $$?; \
+ fi; \
+ fi; \
+ done
+
+test-packages: ${TCLTEST_EXE} packages
+ @for i in $(PKGS_DIR)/*; do \
+ if [ -d $$i ]; then \
+ pkg=`basename $$i`; \
+ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \
+ echo "Testing package '$$pkg'"; \
+ ( cd $(PKG_DIR)/$$pkg; $(MAKE) \
+ "@LD_LIBRARY_PATH_VAR@=../..:$${@LD_LIBRARY_PATH_VAR@}" \
+ "TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" \
+ "TCLLIBPATH=../../pkgs" test \
+ "TCLSH_PROG=../../${TCLTEST_EXE}"; ) \
+ fi; \
+ fi; \
+ done
+
+clean-packages:
+ @for i in $(PKGS_DIR)/*; do \
+ if [ -d $$i ]; then \
+ pkg=`basename $$i`; \
+ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \
+ ( cd $(PKG_DIR)/$$pkg; $(MAKE) clean; ) \
+ fi; \
+ fi; \
+ done
+
+distclean-packages:
+ @for i in $(PKGS_DIR)/*; do \
+ if [ -d $$i ]; then \
+ pkg=`basename $$i`; \
+ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \
+ ( cd $(PKG_DIR)/$$pkg; $(MAKE) distclean; ) \
+ fi; \
+ rm -rf $(PKG_DIR)/$$pkg; \
+ fi; \
+ done; \
+ rm -rf $(PKG_DIR)
+
+dist-packages: configure-packages
+ @rm -rf $(DISTROOT)/pkgs; \
+ mkdir -p $(DISTROOT)/pkgs; \
+ for i in $(PKGS_DIR)/*; do \
+ if [ -d $$i ]; then \
+ pkg=`basename $$i`; \
+ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \
+ ( cd $(PKG_DIR)/$$pkg; $(MAKE) dist \
+ "DIST_ROOT=$(DISTROOT)/pkgs"; ) || exit $$?; \
+ fi; \
+ fi; \
+ done
+
+#--------------------------------------------------------------------------
+# Maintainer-only targets
+#--------------------------------------------------------------------------
+
+# The following target generates the file generic/tclDate.c from the yacc
+# grammar found in generic/tclGetDate.y. This is only run by hand as yacc is
+# not available in all environments. The name of the .c file is different than
+# the name of the .y file so that make doesn't try to automatically regenerate
+# the .c file.
+
+gendate:
+ bison --output-file=$(GENERIC_DIR)/tclDate.c \
+ --no-lines \
+ --name-prefix=TclDate \
+ $(GENERIC_DIR)/tclGetDate.y
+
+# yacc -l $(GENERIC_DIR)/tclGetDate.y
+# sed -e 's/yy/TclDate/g' -e '/^#include <values.h>/d' \
+# -e 's?SCCSID?RCS: @(#) ?' \
+# -e '/#ifdef __STDC__/,/#endif/d' -e '/TclDateerrlab:/d' \
+# -e '/TclDatenewstate:/d' -e '/#pragma/d' \
+# -e '/#include <inttypes.h>/d' \
+# -e '/#define YYNEW/s/malloc/TclDateAlloc/g' \
+# -e '/#define YYENLARGE/,/realloc/s/realloc/TclDateRealloc/g' \
+# <y.tab.c >$(GENERIC_DIR)/tclDate.c
+# rm y.tab.c
+
+# The following target generates the file generic/tclTomMath.h. It needs to be
+# run (and the results checked) after updating to a new release of libtommath.
+
+gentommath_h:
+ $(NATIVE_TCLSH) "$(TOOL_DIR)/fix_tommath_h.tcl" \
+ "$(TOMMATH_DIR)/tommath.h" \
+ > "$(GENERIC_DIR)/tclTomMath.h"
+
+#
+# Target to regenerate header files and stub files from the *.decls tables.
+#
+
+$(GENERIC_DIR)/tclStubInit.c: $(GENERIC_DIR)/tcl.decls \
+ $(GENERIC_DIR)/tclInt.decls $(GENERIC_DIR)/tclTomMath.decls
+ @echo "Warning: tclStubInit.c may be out of date."
+ @echo "Developers may want to run \"make genstubs\" to regenerate."
+ @echo "This warning can be safely ignored, do not report as a bug!"
+
+$(GENERIC_DIR)/tclOOStubInit.c: $(GENERIC_DIR)/tclOO.decls
+ @echo "Warning: tclOOStubInit.c may be out of date."
+ @echo "Developers may want to run \"make genstubs\" to regenerate."
+ @echo "This warning can be safely ignored, do not report as a bug!"
+
+genstubs:
+ $(NATIVE_TCLSH) $(TOOL_DIR)/genStubs.tcl $(GENERIC_DIR) \
+ $(GENERIC_DIR)/tcl.decls $(GENERIC_DIR)/tclInt.decls \
+ $(GENERIC_DIR)/tclTomMath.decls
+ $(NATIVE_TCLSH) $(TOOL_DIR)/genStubs.tcl $(GENERIC_DIR) \
+ $(GENERIC_DIR)/tclOO.decls
+
+#
+# Target to check that all exported functions have an entry in the stubs
+# tables.
+#
+
+checkstubs: $(TCL_LIB_FILE)
+ -@for i in `nm -p $(TCL_LIB_FILE) \
+ | awk '$$2 ~ /^[TDBCS]$$/ { sub("^_", "", $$3); print $$3 }' \
+ | sort -n`; do \
+ match=0; \
+ for j in $(TCL_DECLS); do \
+ if [ `grep -c "$$i *(" $$j` -gt 0 ]; then \
+ match=1; \
+ fi; \
+ done; \
+ if [ $$match -eq 0 ]; then echo $$i; fi \
+ done
+
+#
+# Target to check that all public APIs which are not command implementations
+# have an entry in section three of the distributed manpages.
+#
+
+checkdoc: $(TCL_LIB_FILE)
+ -@for i in `nm -p $(TCL_LIB_FILE) | awk '$$3 ~ /Tcl_/ { print $$3 }' \
+ | grep -v 'Cmd$$' | sort -n`; do \
+ match=0; \
+ for j in $(TOP_DIR)/doc/*.3; do \
+ if [ `grep '\-' $$j | grep -c $$i` -gt 0 ]; then \
+ match=1; \
+ fi; \
+ done; \
+ if [ $$match -eq 0 ]; then echo $$i; fi \
+ done
+
+#
+# Target to check for proper usage of UCHAR macro.
+#
+
+checkuchar:
+ -egrep isalnum\|isalpha\|iscntrl\|isdigit\|islower\|isprint\|ispunct\|isspace\|isupper\|isxdigit\|toupper\|tolower $(SRCS) | grep -v UCHAR
+
+#
+# Target to make sure that only symbols with "Tcl" prefixes are exported.
+#
+
+checkexports: $(TCL_LIB_FILE)
+ -@nm -p $(TCL_LIB_FILE) \
+ | awk '$$2 ~ /^[TDBCS]$$/ { sub("^_", "", $$3); print $$3 }' \
+ | sort -n | grep -E -v '^[Tt]cl' || true
+
+#--------------------------------------------------------------------------
+# Distribution building rules
+#--------------------------------------------------------------------------
+
+#
+# Target to create a Tcl RPM for Linux. Requires that you be on a Linux
+# system.
+#
+
+rpm: all
+ rm -f THIS.TCL.SPEC
+ echo "%define _builddir `pwd`" > THIS.TCL.SPEC
+ echo "%define _rpmdir `pwd`/RPMS" >> THIS.TCL.SPEC
+ cat tcl.spec >> THIS.TCL.SPEC
+ mkdir -p RPMS/i386
+ rpmbuild -bb THIS.TCL.SPEC
+ mv RPMS/i386/*.rpm .
+ rm -rf RPMS THIS.TCL.SPEC
+
+#
+# Target to create a proper Tcl distribution from information in the master
+# source directory. DISTDIR must be defined to indicate where to put the
+# distribution. DISTDIR must be an absolute path name.
+#
+
+DISTROOT = /tmp/dist
+DISTNAME = tcl${VERSION}${PATCH_LEVEL}
+ZIPNAME = tcl${MAJOR_VERSION}${MINOR_VERSION}${PATCH_LEVEL}-src.zip
+DISTDIR = $(DISTROOT)/$(DISTNAME)
+$(UNIX_DIR)/configure: $(UNIX_DIR)/configure.ac $(UNIX_DIR)/tcl.m4 \
+ $(UNIX_DIR)/aclocal.m4
+ cd $(UNIX_DIR); autoconf
+$(MAC_OSX_DIR)/configure: $(MAC_OSX_DIR)/configure.ac $(UNIX_DIR)/configure
+ cd $(MAC_OSX_DIR); autoconf
+$(UNIX_DIR)/tclConfig.h.in: $(MAC_OSX_DIR)/configure
+ cd $(MAC_OSX_DIR); autoheader; touch $@
+
+dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in $(MAC_OSX_DIR)/configure genstubs dist-packages ${NATIVE_TCLSH}
+ rm -rf $(DISTDIR)
+ mkdir -p $(DISTDIR)/unix
+ cp -p $(UNIX_DIR)/*.[ch] $(DISTDIR)/unix
+ cp $(UNIX_DIR)/Makefile.in $(DISTDIR)/unix
+ chmod 664 $(DISTDIR)/unix/Makefile.in
+ cp $(UNIX_DIR)/configure $(UNIX_DIR)/configure.ac \
+ $(UNIX_DIR)/tcl.m4 $(UNIX_DIR)/aclocal.m4 \
+ $(UNIX_DIR)/tclConfig.sh.in $(UNIX_DIR)/tclooConfig.sh \
+ $(UNIX_DIR)/install-sh \
+ $(UNIX_DIR)/README $(UNIX_DIR)/ldAix $(UNIX_DIR)/tcl.spec \
+ $(UNIX_DIR)/installManPage $(UNIX_DIR)/tclConfig.h.in \
+ $(UNIX_DIR)/tcl.pc.in $(DISTDIR)/unix
+ chmod 775 $(DISTDIR)/unix/configure $(DISTDIR)/unix/configure.ac
+ chmod 775 $(DISTDIR)/unix/ldAix
+ @mkdir $(DISTDIR)/generic
+ cp -p $(GENERIC_DIR)/*.[cdh] $(DISTDIR)/generic
+ cp -p $(GENERIC_DIR)/*.decls $(DISTDIR)/generic
+ cp -p $(GENERIC_DIR)/README $(DISTDIR)/generic
+ cp -p $(GENERIC_DIR)/tclGetDate.y $(DISTDIR)/generic
+ cp -p $(TOP_DIR)/changes $(TOP_DIR)/ChangeLog $(TOP_DIR)/README \
+ $(TOP_DIR)/ChangeLog.[12]??? $(TOP_DIR)/license.terms \
+ $(DISTDIR)
+ @mkdir $(DISTDIR)/library
+ cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/library/*.tcl \
+ $(TOP_DIR)/library/tclIndex $(DISTDIR)/library
+ for i in http1.0 http opt msgcat reg dde tcltest platform; \
+ do \
+ mkdir $(DISTDIR)/library/$$i ;\
+ cp -p $(TOP_DIR)/library/$$i/*.tcl $(DISTDIR)/library/$$i; \
+ done;
+ @mkdir $(DISTDIR)/library/encoding
+ cp -p $(TOP_DIR)/library/encoding/*.enc $(DISTDIR)/library/encoding
+ @mkdir $(DISTDIR)/library/msgs
+ cp -p $(TOP_DIR)/library/msgs/*.msg $(DISTDIR)/library/msgs
+ @echo cp -r $(TOP_DIR)/library/tzdata $(DISTDIR)/library/tzdata
+ @( cd $(TOP_DIR); \
+ find library/tzdata -name CVS -prune -o -type f -print ) \
+ | ( cd $(TOP_DIR) ; xargs tar cf - ) \
+ | ( cd $(DISTDIR) ; tar xfp - )
+ @mkdir $(DISTDIR)/doc
+ cp -p $(TOP_DIR)/license.terms $(TOP_DIR)/doc/*.[13n] \
+ $(TOP_DIR)/doc/man.macros $(DISTDIR)/doc
+ @mkdir $(DISTDIR)/compat
+ cp -p $(TOP_DIR)/license.terms $(COMPAT_DIR)/*.[ch] \
+ $(COMPAT_DIR)/README $(DISTDIR)/compat
+ @mkdir $(DISTDIR)/compat/zlib
+ ( cd $(COMPAT_DIR)/zlib; \
+ find . -name CVS -prune -o -type f -print ) \
+ | ( cd $(COMPAT_DIR)/zlib ; xargs tar cf - ) \
+ | ( cd $(DISTDIR)/compat/zlib ; tar xfp - )
+ @mkdir $(DISTDIR)/tests
+ cp -p $(TOP_DIR)/license.terms $(DISTDIR)/tests
+ cp -p $(TOP_DIR)/tests/*.test $(TOP_DIR)/tests/README \
+ $(TOP_DIR)/tests/httpd $(TOP_DIR)/tests/*.tcl \
+ $(DISTDIR)/tests
+ @mkdir $(DISTDIR)/win
+ cp $(TOP_DIR)/win/Makefile.in $(DISTDIR)/win
+ cp $(TOP_DIR)/win/configure.ac $(TOP_DIR)/win/configure \
+ $(TOP_DIR)/win/tclConfig.sh.in $(TOP_DIR)/win/tclooConfig.sh \
+ $(TOP_DIR)/win/tcl.m4 $(TOP_DIR)/win/aclocal.m4 \
+ $(TOP_DIR)/win/tclsh.exe.manifest.in \
+ $(DISTDIR)/win
+ cp -p $(TOP_DIR)/win/*.[ch] $(TOP_DIR)/win/*.ico $(TOP_DIR)/win/*.rc \
+ $(DISTDIR)/win
+ cp -p $(TOP_DIR)/win/*.bat $(DISTDIR)/win
+ cp -p $(TOP_DIR)/win/makefile.* $(DISTDIR)/win
+ cp -p $(TOP_DIR)/win/rules.vc $(DISTDIR)/win
+ cp -p $(TOP_DIR)/win/coffbase.txt $(DISTDIR)/win
+ cp -p $(TOP_DIR)/win/tcl.hpj.in $(DISTDIR)/win
+ cp -p $(TOP_DIR)/win/tcl.ds* $(DISTDIR)/win
+ cp -p $(TOP_DIR)/win/README $(DISTDIR)/win
+ cp -p $(TOP_DIR)/license.terms $(DISTDIR)/win
+ @mkdir $(DISTDIR)/macosx
+ cp -p $(MAC_OSX_DIR)/GNUmakefile $(MAC_OSX_DIR)/README \
+ $(MAC_OSX_DIR)/*.c $(MAC_OSX_DIR)/*.in \
+ $(MAC_OSX_DIR)/*.ac $(MAC_OSX_DIR)/*.xcconfig \
+ $(MAC_OSX_DIR)/configure $(DISTDIR)/macosx
+ cp -p $(TOP_DIR)/license.terms $(DISTDIR)/macosx
+ @mkdir $(DISTDIR)/macosx/Tcl.xcode
+ cp -p $(MAC_OSX_DIR)/Tcl.xcode/project.pbxproj \
+ $(MAC_OSX_DIR)/Tcl.xcode/default.pbxuser \
+ $(DISTDIR)/macosx/Tcl.xcode
+ @mkdir $(DISTDIR)/macosx/Tcl.xcodeproj
+ cp -p $(MAC_OSX_DIR)/Tcl.xcodeproj/project.pbxproj \
+ $(MAC_OSX_DIR)/Tcl.xcodeproj/default.pbxuser \
+ $(DISTDIR)/macosx/Tcl.xcodeproj
+ @mkdir $(DISTDIR)/unix/dltest
+ cp -p $(UNIX_DIR)/dltest/*.c $(UNIX_DIR)/dltest/Makefile.in \
+ $(UNIX_DIR)/dltest/README $(DISTDIR)/unix/dltest
+ @mkdir $(DISTDIR)/tools
+ cp -p $(TOOL_DIR)/Makefile.in $(TOOL_DIR)/README \
+ $(TOOL_DIR)/configure $(TOOL_DIR)/configure.ac \
+ $(TOOL_DIR)/*.tcl $(TOOL_DIR)/man2tcl.c \
+ $(TOOL_DIR)/*.bmp $(TOOL_DIR)/tcl.hpj.in \
+ $(DISTDIR)/tools
+ @mkdir $(DISTDIR)/libtommath
+ cp -p $(TOMMATH_SRCS) $(TOMMATH_DIR)/*.h $(DISTDIR)/libtommath
+ @mkdir $(DISTDIR)/pkgs
+ cp $(TOP_DIR)/pkgs/README $(DISTDIR)/pkgs
+ cp $(TOP_DIR)/pkgs/package.list.txt $(DISTDIR)/pkgs
+ for i in `ls $(DISTROOT)/pkgs/*.tar.gz 2> /dev/null`; do \
+ tar -C $(DISTDIR)/pkgs -xzf "$$i"; \
+ done
+
+alldist: dist
+ rm -f $(DISTROOT)/$(DISTNAME)-src.tar.gz $(DISTROOT)/$(ZIPNAME)
+ cd $(DISTROOT); tar cf $(DISTNAME)-src.tar $(DISTNAME); \
+ gzip -9 $(DISTNAME)-src.tar; zip -qr8 $(ZIPNAME) $(DISTNAME)
+
+#--------------------------------------------------------------------------
+# This target creates the HTML folder for Tcl & Tk and places it in
+# DISTDIR/html. It uses the tcltk-man2html.tcl tool from the Tcl group's tool
+# workspace. It depends on the Tcl & Tk being in directories called tcl8.* &
+# tk8.* up two directories from the TOOL_DIR.
+#
+# Note that for platforms where this is important, it is more common to use a
+# build of this HTML documentation that has already been placed online. As
+# such, this rule is not guaranteed to work well on all systems; it only needs
+# to function on those of the Tcl/Tk maintainers.
+#
+# Also note that the 8.6 tool build requires an installed 8.6 native Tcl
+# interpreter in order to be able to run.
+#--------------------------------------------------------------------------
+
+html: ${NATIVE_TCLSH}
+ $(BUILD_HTML)
+ @EXTRA_BUILD_HTML@
+
+html-tcl: ${NATIVE_TCLSH}
+ $(BUILD_HTML) --tcl
+ @EXTRA_BUILD_HTML@
+
+html-tk: ${NATIVE_TCLSH}
+ $(BUILD_HTML) --tk
+ @EXTRA_BUILD_HTML@
+
+# You'd better have these programs or you will have problems creating Makefile
+# from Makefile.in in the first place...
+HTML_VERSION = `basename $(TOP_DIR) | sed s/tcl//`
+BUILD_HTML = \
+ @${NATIVE_TCLSH} $(TOOL_DIR)/tcltk-man2html.tcl \
+ --useversion=$(HTML_VERSION) --htmldir="$(HTML_INSTALL_DIR)" \
+ --srcdir=$(TOP_DIR)/.. $(BUILD_HTML_FLAGS)
+
+#--------------------------------------------------------------------------
+# The list of all the targets that do not correspond to real files. This stops
+# 'make' from getting confused when someone makes an error in a rule.
+#--------------------------------------------------------------------------
+
+.PHONY: all binaries libraries objs doc html html-tcl html-tk test runtest
+.PHONY: install install-strip install-binaries install-libraries
+.PHONY: install-headers install-private-headers install-doc
+.PHONY: clean distclean depend genstubs checkstubs checkexports checkuchar
+.PHONY: shell gdb valgrind valgrindshell dist alldist rpm
+.PHONY: tclLibObjs tcltest-real test-tcl gdb-test ro-test trace-test xttest
+.PHONY: topDirName gendate gentommath_h trace-shell checkdoc
+.PHONY: install-tzdata install-msgs
+.PHONY: packages configure-packages test-packages clean-packages
+.PHONY: dist-packages distclean-packages install-packages
+
+#--------------------------------------------------------------------------
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/unix/README b/unix/README
new file mode 100644
index 0000000..d8f1090
--- /dev/null
+++ b/unix/README
@@ -0,0 +1,169 @@
+Tcl UNIX README
+---------------
+
+This is the directory where you configure, compile, test, and install UNIX
+versions of Tcl. This directory also contains source files for Tcl that are
+specific to UNIX. Some of the files in this directory are used on the PC or
+MacOSX platform too, but they all depend on UNIX (POSIX/ANSI C) interfaces and
+some of them only make sense under UNIX.
+
+Updated forms of the information found in this file is available at:
+ http://www.tcl.tk/doc/howto/compile.html#unix
+
+For information on platforms where Tcl is known to compile, along with any
+porting notes for getting it to work on those platforms, see:
+ http://www.tcl.tk/software/tcltk/platforms.html
+
+The rest of this file contains instructions on how to do this. The release
+should compile and run either "out of the box" or with trivial changes on any
+UNIX-like system that approximates POSIX, BSD, or System V. We know that it
+runs on workstations from Sun, H-P, DEC, IBM, and SGI, as well as PCs running
+Linux, BSDI, and SCO UNIX. To compile for a PC running Windows, see the README
+file in the directory ../win. To compile for MacOSX, see the README file in
+the directory ../macosx.
+
+How To Compile And Install Tcl:
+-------------------------------
+
+(a) If you have already compiled Tcl once in this directory and are now
+ preparing to compile again in the same directory but for a different
+ platform, or if you have applied patches, type "make distclean" to discard
+ all the configuration information computed previously.
+
+(b) If you need to reconfigure because you changed any of the .in or .m4
+ files, you will need to run autoconf to create a new ./configure script.
+ Most users will NOT need to do this since a configure script is already
+ provided.
+
+ (in the tcl/unix directory)
+ autoconf
+
+(c) Type "./configure". This runs a configuration script created by GNU
+ autoconf, which configures Tcl for your system and creates a Makefile. The
+ configure script allows you to customize the Tcl configuration for your
+ site; for details on how you can do this, type "./configure --help" or
+ refer to the autoconf documentation (not included here). Tcl's "configure"
+ supports the following special switches in addition to the standard ones:
+
+ --enable-threads If this switch is set, Tcl will compile itself
+ with multithreading support.
+ --disable-load If this switch is specified then Tcl will
+ configure itself not to allow dynamic loading,
+ even if your system appears to support it.
+ Normally you can leave this switch out and Tcl
+ will build itself for dynamic loading if your
+ system supports it.
+ --disable-dll-unloading Disables support for the [unload] command even
+ on platforms that can support it. Meaningless
+ when Tcl is compiled with --disable-load.
+ --enable-shared If this switch is specified, Tcl will compile
+ itself as a shared library if it can figure
+ out how to do that on this platform. This is
+ the default on platforms where we know how to
+ build shared libraries.
+ --disable-shared If this switch is specified, Tcl will compile
+ itself as a static library.
+ --enable-symbols Build with debugging symbols. By default
+ standard debugging symbols are used. You can
+ specify the value "mem" to include
+ TCL_MEM_DEBUG memory debugging, "compile" to
+ include TCL_COMPILE_DEBUG debugging, or "all"
+ to enable all internal debugging.
+ --disable-symbols Build without debugging symbols
+ --enable-64bit Enable 64bit support (where applicable)
+ --disable-64bit Disable 64bit support (where applicable)
+ --enable-64bit-vis Enable 64bit Sparc VIS support
+ --disable-64bit-vis Disable 64bit Sparc VIS support
+ --enable-langinfo Allows use of modern nl_langinfo check for
+ better localization support. This is on by
+ default on platforms where nl_langinfo is
+ found.
+ --disable-langinfo Specifically disables use of nl_langinfo.
+ --enable-man-symlinks Use symlinks for linking the manpages that
+ should be reachable under several names.
+ --enable-man-suffix[=STRING]
+ Append STRING to the names of installed manual
+ pages (prior to applying compression, if that
+ is also enabled). If STRING is omitted,
+ defaults to 'tcl'.
+ --enable-man-compression=PROG
+ Compress the manpages using PROG.
+ --enable-dtrace Enable tcl DTrace provider (if DTrace is
+ available on the platform), c.f. tclDTrace.d
+ for descriptions of the probes made available,
+ see http://wiki.tcl.tk/DTrace for more details
+ --with-encoding=ENCODING Specifies the encoding for compile-time
+ configuration values. Defaults to iso8859-1,
+ which is also sufficient for ASCII.
+ --with-tzdata=FLAG Specifies whether to install timezone data. By
+ default, the configure script tries to detect
+ whether a usable timezone database is present
+ on the system already.
+
+ Mac OS X only (i.e. completely unsupported on other platforms):
+
+ --enable-framework Package Tcl as a framework.
+ --disable-corefoundation Disable use of CoreFoundation API and revert
+ to standard select based notifier, required
+ when using naked fork (i.e. not followed by
+ execve).
+
+ Note: by default gcc will be used if it can be located on the PATH. If you
+ want to use cc instead of gcc, set the CC environment variable to "cc"
+ before running configure. It is not safe to edit the Makefile to use gcc
+ after configure is run. Also note that you should use the same compiler
+ when building extensions.
+
+ Note: be sure to use only absolute path names (those starting with "/") in
+ the --prefix and --exec-prefix options.
+
+(d) Type "make". This will create a library archive called "libtcl<version>.a"
+ or "libtcl<version>.so" and an interpreter application called "tclsh" that
+ allows you to type Tcl commands interactively or execute script files. It
+ will also create a stub library archive "libtclstub<version>.a" that
+ developers may link against other C code to produce loadable extensions
+ for Tcl.
+
+(e) If the make fails then you'll have to personalize the Makefile for your
+ site or possibly modify the distribution in other ways. First check the
+ porting Web page above to see if there are hints for compiling on your
+ system. If you need to modify Makefile, there are comments at the
+ beginning of it that describe the things you might want to change and how
+ to change them.
+
+(f) Type "make install" to install Tcl binaries and script files in standard
+ places. You'll need write permission on the installation directories to do
+ this. The installation directories are determined by the "configure"
+ script and may be specified with the standard --prefix and --exec-prefix
+ options to "configure". See the Makefile for information on what
+ directories were chosen; you can override these choices by modifying the
+ "prefix" and "exec_prefix" variables in the Makefile. The installed
+ binaries have embedded within them path values relative to the install
+ directory. If you change your mind about where Tcl should be installed,
+ start this procedure over again from step (a) so that the path embedded in
+ the binaries agrees with the install location.
+
+(g) At this point you can play with Tcl by running the installed "tclsh"
+ executable, or via the "make shell" target, and typing Tcl commands at the
+ interactive prompt.
+
+If you have trouble compiling Tcl, see the URL noted above about working
+platforms. It contains information that people have provided about changes
+they had to make to compile Tcl in various environments. We're also interested
+in hearing how to change the configuration setup so that Tcl compiles on
+additional platforms "out of the box".
+
+Test suite
+----------
+
+There is a relatively complete test suite for all of the Tcl core in the
+subdirectory "tests". To use it just type "make test" in this directory. You
+should then see a printout of the test files processed. If any errors occur,
+you'll see a much more substantial printout for each error. See the README
+file in the "tests" directory for more information on the test suite. Note:
+don't run the tests as superuser: this will cause several of them to fail. If
+a test is failing consistently, please send us a bug report with as much
+detail as you can manage to our tracker:
+
+ http://core.tcl.tk/tcl/reportlist
+
diff --git a/unix/aclocal.m4 b/unix/aclocal.m4
new file mode 100644
index 0000000..90d2e39
--- /dev/null
+++ b/unix/aclocal.m4
@@ -0,0 +1 @@
+builtin(include,../unix/tcl.m4)
diff --git a/unix/configure b/unix/configure
new file mode 100755
index 0000000..129c283
--- /dev/null
+++ b/unix/configure
@@ -0,0 +1,11611 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for tcl 8.7.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='tcl'
+PACKAGE_TARNAME='tcl'
+PACKAGE_VERSION='8.7'
+PACKAGE_STRING='tcl 8.7'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='DLTEST_SUFFIX
+DLTEST_LD
+EXTRA_TCLSH_LIBS
+EXTRA_BUILD_HTML
+EXTRA_INSTALL_BINARIES
+EXTRA_INSTALL
+EXTRA_APP_CC_SWITCHES
+EXTRA_CC_SWITCHES
+PACKAGE_DIR
+HTML_DIR
+PRIVATE_INCLUDE_DIR
+TCL_LIBRARY
+TCL_MODULE_PATH
+TCL_PACKAGE_PATH
+BUILD_DLTEST
+MAKEFILE_SHELL
+DTRACE_OBJ
+DTRACE_HDR
+DTRACE_SRC
+INSTALL_TZDATA
+TCL_HAS_LONGLONG
+TCL_UNSHARED_LIB_SUFFIX
+TCL_SHARED_LIB_SUFFIX
+TCL_LIB_VERSIONS_OK
+TCL_BUILD_LIB_SPEC
+LD_LIBRARY_PATH_VAR
+TCL_SHARED_BUILD
+CFG_TCL_UNSHARED_LIB_SUFFIX
+CFG_TCL_SHARED_LIB_SUFFIX
+TCL_SRC_DIR
+TCL_BUILD_STUB_LIB_PATH
+TCL_BUILD_STUB_LIB_SPEC
+TCL_INCLUDE_SPEC
+TCL_STUB_LIB_PATH
+TCL_STUB_LIB_SPEC
+TCL_STUB_LIB_FLAG
+TCL_STUB_LIB_FILE
+TCL_LIB_SPEC
+TCL_LIB_FLAG
+TCL_LIB_FILE
+PKG_CFG_ARGS
+TCL_YEAR
+TCL_PATCH_LEVEL
+TCL_MINOR_VERSION
+TCL_MAJOR_VERSION
+TCL_VERSION
+DTRACE
+LDFLAGS_DEFAULT
+CFLAGS_DEFAULT
+INSTALL_STUB_LIB
+DLL_INSTALL_DIR
+INSTALL_LIB
+MAKE_STUB_LIB
+MAKE_LIB
+SHLIB_SUFFIX
+SHLIB_CFLAGS
+SHLIB_LD_LIBS
+TK_SHLIB_LD_EXTRAS
+TCL_SHLIB_LD_EXTRAS
+SHLIB_LD
+STLIB_LD
+LD_SEARCH_FLAGS
+CC_SEARCH_FLAGS
+LDFLAGS_OPTIMIZE
+LDFLAGS_DEBUG
+CFLAGS_WARNING
+CFLAGS_OPTIMIZE
+CFLAGS_DEBUG
+LDAIX_SRC
+PLAT_SRCS
+PLAT_OBJS
+DL_OBJS
+DL_LIBS
+TCL_LIBS
+LIBOBJS
+AR
+RANLIB
+ZLIB_INCLUDE
+ZLIB_SRCS
+ZLIB_OBJS
+TCLSH_PROG
+TCL_THREADS
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+MAN_FLAGS
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_man_symlinks
+enable_man_compression
+enable_man_suffix
+enable_threads
+with_encoding
+enable_shared
+enable_64bit
+enable_64bit_vis
+enable_rpath
+enable_corefoundation
+enable_load
+enable_symbols
+enable_langinfo
+enable_dll_unloading
+with_tzdata
+enable_dtrace
+enable_framework
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures tcl 8.7 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/tcl]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of tcl 8.7:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-man-symlinks use symlinks for the manpages (default: off)
+ --enable-man-compression=PROG
+ compress the manpages with PROG (default: off)
+ --enable-man-suffix=STRING
+ use STRING as a suffix to manpage file names
+ (default: no, tcl if enabled without
+ specifying STRING)
+ --enable-threads build with threads (default: on)
+ --enable-shared build and link with shared libraries (default: on)
+ --enable-64bit enable 64bit support (default: off)
+ --enable-64bit-vis enable 64bit Sparc VIS support (default: off)
+ --disable-rpath disable rpath support (default: on)
+ --enable-corefoundation use CoreFoundation API on MacOSX (default: on)
+ --enable-load allow dynamic loading and "load" command (default:
+ on)
+ --enable-symbols build with debugging symbols (default: off)
+ --enable-langinfo use nl_langinfo if possible to determine encoding at
+ startup, otherwise use old heuristic (default: on)
+ --enable-dll-unloading enable the 'unload' command (default: on)
+ --enable-dtrace build with DTrace support (default: off)
+ --enable-framework package shared libraries in MacOSX frameworks
+ (default: off)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-encoding encoding for configuration values (default:
+ iso8859-1)
+ --with-tzdata install timezone data (default: autodetect)
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+tcl configure 8.7
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by tcl $as_me 8.7, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+TCL_VERSION=8.7
+TCL_MAJOR_VERSION=8
+TCL_MINOR_VERSION=7
+TCL_PATCH_LEVEL="a2"
+VERSION=${TCL_VERSION}
+
+EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"}
+EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"}
+
+#------------------------------------------------------------------------
+# Setup configure arguments for bundled packages
+#------------------------------------------------------------------------
+
+PKG_CFG_ARGS="$ac_configure_args ${PKG_CFG_ARGS}"
+
+if test -r "$cache_file" -a -f "$cache_file"; then
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) pkg_cache_file=$cache_file ;;
+ *) pkg_cache_file=../../$cache_file ;;
+ esac
+ PKG_CFG_ARGS="${PKG_CFG_ARGS} --cache-file=$pkg_cache_file"
+fi
+
+#------------------------------------------------------------------------
+# Empty slate for bundled packages, to avoid stale configuration
+#------------------------------------------------------------------------
+#rm -Rf pkgs
+if test -f Makefile; then
+ make distclean-packages
+fi
+
+#------------------------------------------------------------------------
+# Handle the --prefix=... option
+#------------------------------------------------------------------------
+
+if test "${prefix}" = "NONE"; then
+ prefix=/usr/local
+fi
+if test "${exec_prefix}" = "NONE"; then
+ exec_prefix=$prefix
+fi
+# Make sure srcdir is fully qualified!
+srcdir="`cd "$srcdir" ; pwd`"
+TCL_SRC_DIR="`cd "$srcdir"/..; pwd`"
+
+#------------------------------------------------------------------------
+# Compress and/or soft link the manpages?
+#------------------------------------------------------------------------
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use symlinks for manpages" >&5
+$as_echo_n "checking whether to use symlinks for manpages... " >&6; }
+ # Check whether --enable-man-symlinks was given.
+if test "${enable_man_symlinks+set}" = set; then :
+ enableval=$enable_man_symlinks; test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks"
+else
+ enableval="no"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
+$as_echo "$enableval" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compress the manpages" >&5
+$as_echo_n "checking whether to compress the manpages... " >&6; }
+ # Check whether --enable-man-compression was given.
+if test "${enable_man_compression+set}" = set; then :
+ enableval=$enable_man_compression; case $enableval in
+ yes) as_fn_error $? "missing argument to --enable-man-compression" "$LINENO" 5;;
+ no) ;;
+ *) MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
+ esac
+else
+ enableval="no"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
+$as_echo "$enableval" >&6; }
+ if test "$enableval" != "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compressed file suffix" >&5
+$as_echo_n "checking for compressed file suffix... " >&6; }
+ touch TeST
+ $enableval TeST
+ Z=`ls TeST* | sed 's/^....//'`
+ rm -f TeST*
+ MAN_FLAGS="$MAN_FLAGS --extension $Z"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $Z" >&5
+$as_echo "$Z" >&6; }
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to add a package name suffix for the manpages" >&5
+$as_echo_n "checking whether to add a package name suffix for the manpages... " >&6; }
+ # Check whether --enable-man-suffix was given.
+if test "${enable_man_suffix+set}" = set; then :
+ enableval=$enable_man_suffix; case $enableval in
+ yes) enableval="tcl" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
+ no) ;;
+ *) MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
+ esac
+else
+ enableval="no"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
+$as_echo "$enableval" >&6; }
+
+
+
+
+#------------------------------------------------------------------------
+# Standard compiler checks
+#------------------------------------------------------------------------
+
+# 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_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+
+#--------------------------------------------------------------------
+# 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
+# Do this early, otherwise an autoconf bug throws errors on configure
+#--------------------------------------------------------------------
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dirent.h" >&5
+$as_echo_n "checking dirent.h... " >&6; }
+if ${tcl_cv_dirent_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <dirent.h>
+int
+main ()
+{
+
+#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);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_dirent_h=yes
+else
+ tcl_cv_dirent_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_dirent_h" >&5
+$as_echo "$tcl_cv_dirent_h" >&6; }
+
+ if test $tcl_cv_dirent_h = no; then
+
+$as_echo "#define NO_DIRENT_H 1" >>confdefs.h
+
+ fi
+
+ ac_fn_c_check_header_mongrel "$LINENO" "float.h" "ac_cv_header_float_h" "$ac_includes_default"
+if test "x$ac_cv_header_float_h" = xyes; then :
+
+else
+
+$as_echo "#define NO_FLOAT_H 1" >>confdefs.h
+
+fi
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "values.h" "ac_cv_header_values_h" "$ac_includes_default"
+if test "x$ac_cv_header_values_h" = xyes; then :
+
+else
+
+$as_echo "#define NO_VALUES_H 1" >>confdefs.h
+
+fi
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdlib_h" = xyes; then :
+ tcl_ok=1
+else
+ tcl_ok=0
+fi
+
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "strtol" >/dev/null 2>&1; then :
+
+else
+ tcl_ok=0
+fi
+rm -f conftest*
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "strtoul" >/dev/null 2>&1; then :
+
+else
+ tcl_ok=0
+fi
+rm -f conftest*
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "strtod" >/dev/null 2>&1; then :
+
+else
+ tcl_ok=0
+fi
+rm -f conftest*
+
+ if test $tcl_ok = 0; then
+
+$as_echo "#define NO_STDLIB_H 1" >>confdefs.h
+
+ fi
+ ac_fn_c_check_header_mongrel "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default"
+if test "x$ac_cv_header_string_h" = xyes; then :
+ tcl_ok=1
+else
+ tcl_ok=0
+fi
+
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "strstr" >/dev/null 2>&1; then :
+
+else
+ tcl_ok=0
+fi
+rm -f conftest*
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "strerror" >/dev/null 2>&1; then :
+
+else
+ tcl_ok=0
+fi
+rm -f conftest*
+
+
+ # See also memmove check below for a place where NO_STRING_H can be
+ # set and why.
+
+ if test $tcl_ok = 0; then
+
+$as_echo "#define NO_STRING_H 1" >>confdefs.h
+
+ fi
+
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/wait.h" "ac_cv_header_sys_wait_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_wait_h" = xyes; then :
+
+else
+
+$as_echo "#define NO_SYS_WAIT_H 1" >>confdefs.h
+
+fi
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
+if test "x$ac_cv_header_dlfcn_h" = xyes; then :
+
+else
+
+$as_echo "#define NO_DLFCN_H 1" >>confdefs.h
+
+fi
+
+
+
+ # OS/390 lacks sys/param.h (and doesn't need it, by chance).
+ for ac_header in sys/param.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_param_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_PARAM_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+#--------------------------------------------------------------------
+# Determines the correct executable file extension (.exe)
+#--------------------------------------------------------------------
+
+
+
+#------------------------------------------------------------------------
+# 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" && test -n "$GCC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5
+$as_echo_n "checking if the compiler understands -pipe... " >&6; }
+if ${tcl_cv_cc_pipe+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_cc_pipe=yes
+else
+ tcl_cv_cc_pipe=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5
+$as_echo "$tcl_cv_cc_pipe" >&6; }
+ if test $tcl_cv_cc_pipe = yes; then
+ CFLAGS="$CFLAGS -pipe"
+ fi
+fi
+
+#------------------------------------------------------------------------
+# Threads support
+#------------------------------------------------------------------------
+
+
+ # Check whether --enable-threads was given.
+if test "${enable_threads+set}" = set; then :
+ enableval=$enable_threads; tcl_ok=$enableval
+else
+ tcl_ok=yes
+fi
+
+
+ if test "${TCL_THREADS}" = 1; then
+ tcl_threaded_core=1;
+ fi
+
+ if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
+ TCL_THREADS=1
+ # USE_THREAD_ALLOC tells us to try the special thread-based
+ # allocator that significantly reduces lock contention
+
+$as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h
+
+
+$as_echo "#define _REENTRANT 1" >>confdefs.h
+
+ if test "`uname -s`" = "SunOS" ; then
+
+$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+ fi
+
+$as_echo "#define _THREAD_SAFE 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5
+$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_mutex_init ();
+int
+main ()
+{
+return pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthread_pthread_mutex_init=yes
+else
+ ac_cv_lib_pthread_pthread_mutex_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ 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]
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5
+$as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char __pthread_mutex_init ();
+int
+main ()
+{
+return __pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthread___pthread_mutex_init=yes
+else
+ ac_cv_lib_pthread___pthread_mutex_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ fi
+
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -lpthread"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5
+$as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; }
+if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthreads $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_mutex_init ();
+int
+main ()
+{
+return pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthreads_pthread_mutex_init=yes
+else
+ ac_cv_lib_pthreads_pthread_mutex_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -lpthreads"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5
+$as_echo_n "checking for pthread_mutex_init in -lc... " >&6; }
+if ${ac_cv_lib_c_pthread_mutex_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_mutex_init ();
+int
+main ()
+{
+return pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_c_pthread_mutex_init=yes
+else
+ ac_cv_lib_c_pthread_mutex_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ if test "$tcl_ok" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5
+$as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; }
+if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc_r $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_mutex_init ();
+int
+main ()
+{
+return pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_c_r_pthread_mutex_init=yes
+else
+ ac_cv_lib_c_r_pthread_mutex_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -pthread"
+ else
+ TCL_THREADS=0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&5
+$as_echo "$as_me: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&2;}
+ fi
+ fi
+ fi
+ fi
+
+ # Does the pthread-implementation provide
+ # 'pthread_attr_setstacksize' ?
+
+ ac_saved_libs=$LIBS
+ LIBS="$LIBS $THREADS_LIBS"
+ for ac_func in pthread_attr_setstacksize pthread_atfork
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+ LIBS=$ac_saved_libs
+ else
+ TCL_THREADS=0
+ fi
+ # Do checking message here to not mess up interleaved configure output
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5
+$as_echo_n "checking for building with threads... " >&6; }
+ if test "${TCL_THREADS}" = 1; then
+
+$as_echo "#define TCL_THREADS 1" >>confdefs.h
+
+ if test "${tcl_threaded_core}" = 1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (threaded core)" >&5
+$as_echo "yes (threaded core)" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+
+
+
+
+#------------------------------------------------------------------------
+# Embedded configuration information, encoding to use for the values, TIP #59
+#------------------------------------------------------------------------
+
+
+
+# Check whether --with-encoding was given.
+if test "${with_encoding+set}" = set; then :
+ withval=$with_encoding; with_tcencoding=${withval}
+fi
+
+
+ if test x"${with_tcencoding}" != x ; then
+
+cat >>confdefs.h <<_ACEOF
+#define TCL_CFGVAL_ENCODING "${with_tcencoding}"
+_ACEOF
+
+ else
+
+$as_echo "#define TCL_CFGVAL_ENCODING \"iso8859-1\"" >>confdefs.h
+
+ fi
+
+
+#--------------------------------------------------------------------
+# Look for libraries that we will need when compiling the Tcl shell
+#--------------------------------------------------------------------
+
+
+ #--------------------------------------------------------------------
+ # 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_fn_c_check_func "$LINENO" "sin" "ac_cv_func_sin"
+if test "x$ac_cv_func_sin" = xyes; then :
+ MATH_LIBS=""
+else
+ MATH_LIBS="-lm"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lieee" >&5
+$as_echo_n "checking for main in -lieee... " >&6; }
+if ${ac_cv_lib_ieee_main+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lieee $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ieee_main=yes
+else
+ ac_cv_lib_ieee_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ieee_main" >&5
+$as_echo "$ac_cv_lib_ieee_main" >&6; }
+if test "x$ac_cv_lib_ieee_main" = xyes; then :
+ MATH_LIBS="-lieee $MATH_LIBS"
+fi
+
+
+ #--------------------------------------------------------------------
+ # Interactive UNIX requires -linet instead of -lsocket, plus it
+ # needs net/errno.h to define the socket-related error codes.
+ #--------------------------------------------------------------------
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5
+$as_echo_n "checking for main in -linet... " >&6; }
+if ${ac_cv_lib_inet_main+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-linet $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_inet_main=yes
+else
+ ac_cv_lib_inet_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5
+$as_echo "$ac_cv_lib_inet_main" >&6; }
+if test "x$ac_cv_lib_inet_main" = xyes; then :
+ LIBS="$LIBS -linet"
+fi
+
+ ac_fn_c_check_header_mongrel "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_errno_h" = xyes; then :
+
+
+$as_echo "#define HAVE_NET_ERRNO_H 1" >>confdefs.h
+
+fi
+
+
+
+ #--------------------------------------------------------------------
+ # 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_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
+if test "x$ac_cv_func_connect" = xyes; then :
+ tcl_checkSocket=0
+else
+ tcl_checkSocket=1
+fi
+
+ if test "$tcl_checkSocket" = 1; then
+ ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt"
+if test "x$ac_cv_func_setsockopt" = xyes; then :
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5
+$as_echo_n "checking for setsockopt in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_setsockopt+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char setsockopt ();
+int
+main ()
+{
+return setsockopt ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_socket_setsockopt=yes
+else
+ ac_cv_lib_socket_setsockopt=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5
+$as_echo "$ac_cv_lib_socket_setsockopt" >&6; }
+if test "x$ac_cv_lib_socket_setsockopt" = xyes; then :
+ LIBS="$LIBS -lsocket"
+else
+ tcl_checkBoth=1
+fi
+
+fi
+
+ fi
+ if test "$tcl_checkBoth" = 1; then
+ tk_oldLibs=$LIBS
+ LIBS="$LIBS -lsocket -lnsl"
+ ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept"
+if test "x$ac_cv_func_accept" = xyes; then :
+ tcl_checkNsl=0
+else
+ LIBS=$tk_oldLibs
+fi
+
+ fi
+ ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
+if test "x$ac_cv_func_gethostbyname" = xyes; then :
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
+$as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
+if ${ac_cv_lib_nsl_gethostbyname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_nsl_gethostbyname=yes
+else
+ ac_cv_lib_nsl_gethostbyname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
+$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
+if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then :
+ LIBS="$LIBS -lnsl"
+fi
+
+fi
+
+
+
+# Add the threads support libraries
+LIBS="$LIBS$THREADS_LIBS"
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5
+$as_echo_n "checking how to build libraries... " >&6; }
+ # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+ enableval=$enable_shared; tcl_ok=$enableval
+else
+ tcl_ok=yes
+fi
+
+
+ if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ tcl_ok=$enableval
+ else
+ tcl_ok=yes
+ fi
+
+ if test "$tcl_ok" = "yes" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5
+$as_echo "shared" >&6; }
+ SHARED_BUILD=1
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5
+$as_echo "static" >&6; }
+ SHARED_BUILD=0
+
+$as_echo "#define STATIC_BUILD 1" >>confdefs.h
+
+ fi
+
+
+#--------------------------------------------------------------------
+# Look for a native installed tclsh binary (if available)
+# If one cannot be found then use the binary we build (fails for
+# cross compiling). This is used for NATIVE_TCLSH in Makefile.
+#--------------------------------------------------------------------
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5
+$as_echo_n "checking for tclsh... " >&6; }
+ if ${ac_cv_path_tclsh+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ search_path=`echo ${PATH} | sed -e 's/:/ /g'`
+ for dir in $search_path ; do
+ for j in `ls -r $dir/tclsh[8-9]* 2> /dev/null` \
+ `ls -r $dir/tclsh* 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
+
+fi
+
+
+ if test -f "$ac_cv_path_tclsh" ; then
+ TCLSH_PROG="$ac_cv_path_tclsh"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TCLSH_PROG" >&5
+$as_echo "$TCLSH_PROG" >&6; }
+ else
+ # It is not an error if an installed version of Tcl can't be located.
+ TCLSH_PROG=""
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: No tclsh found on PATH" >&5
+$as_echo "No tclsh found on PATH" >&6; }
+ fi
+
+
+if test "$TCLSH_PROG" = ""; then
+ TCLSH_PROG='./${TCL_EXE}'
+fi
+
+#------------------------------------------------------------------------
+# Add stuff for zlib
+#------------------------------------------------------------------------
+
+zlib_ok=yes
+ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_zlib_h" = xyes; then :
+
+ ac_fn_c_check_type "$LINENO" "gz_header" "ac_cv_type_gz_header" "#include <zlib.h>
+"
+if test "x$ac_cv_type_gz_header" = xyes; then :
+
+else
+ zlib_ok=no
+fi
+
+else
+
+ zlib_ok=no
+fi
+
+
+if test $zlib_ok = yes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflateSetHeader" >&5
+$as_echo_n "checking for library containing deflateSetHeader... " >&6; }
+if ${ac_cv_search_deflateSetHeader+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char deflateSetHeader ();
+int
+main ()
+{
+return deflateSetHeader ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' z; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_deflateSetHeader=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_deflateSetHeader+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_deflateSetHeader+:} false; then :
+
+else
+ ac_cv_search_deflateSetHeader=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflateSetHeader" >&5
+$as_echo "$ac_cv_search_deflateSetHeader" >&6; }
+ac_res=$ac_cv_search_deflateSetHeader
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+
+ zlib_ok=no
+
+fi
+
+fi
+if test $zlib_ok = no; then :
+
+ ZLIB_OBJS=\${ZLIB_OBJS}
+
+ ZLIB_SRCS=\${ZLIB_SRCS}
+
+ ZLIB_INCLUDE=-I\${ZLIB_DIR}
+
+
+fi
+
+$as_echo "#define HAVE_ZLIB 1" >>confdefs.h
+
+
+#--------------------------------------------------------------------
+# The statements below define a collection of compile flags. This
+# macro depends on the value of SHARED_BUILD, and should be called
+# after SC_ENABLE_SHARED checks the configure switches.
+#--------------------------------------------------------------------
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+
+ # Step 0.a: Enable 64 bit support?
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5
+$as_echo_n "checking if 64bit support is requested... " >&6; }
+ # Check whether --enable-64bit was given.
+if test "${enable_64bit+set}" = set; then :
+ enableval=$enable_64bit; do64bit=$enableval
+else
+ do64bit=no
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5
+$as_echo "$do64bit" >&6; }
+
+ # Step 0.b: Enable Solaris 64 bit VIS support?
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5
+$as_echo_n "checking if 64bit Sparc VIS support is requested... " >&6; }
+ # Check whether --enable-64bit-vis was given.
+if test "${enable_64bit_vis+set}" = set; then :
+ enableval=$enable_64bit_vis; do64bitVIS=$enableval
+else
+ do64bitVIS=no
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5
+$as_echo "$do64bitVIS" >&6; }
+ # Force 64bit on with VIS
+ if test "$do64bitVIS" = "yes"; then :
+ do64bit=yes
+fi
+
+ # Step 0.c: Check if visibility support is available. Do this here so
+ # that platform specific alternatives can be used below if this fails.
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5
+$as_echo_n "checking if compiler supports visibility \"hidden\"... " >&6; }
+if ${tcl_cv_cc_visibility_hidden+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ extern __attribute__((__visibility__("hidden"))) void f(void);
+ void f(void) {}
+int
+main ()
+{
+f();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_cc_visibility_hidden=yes
+else
+ tcl_cv_cc_visibility_hidden=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5
+$as_echo "$tcl_cv_cc_visibility_hidden" >&6; }
+ if test $tcl_cv_cc_visibility_hidden = yes; then :
+
+
+$as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h
+
+
+$as_echo "#define HAVE_HIDDEN 1" >>confdefs.h
+
+
+fi
+
+ # Step 0.d: Disable -rpath support?
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5
+$as_echo_n "checking if rpath support is requested... " >&6; }
+ # Check whether --enable-rpath was given.
+if test "${enable_rpath+set}" = set; then :
+ enableval=$enable_rpath; doRpath=$enableval
+else
+ doRpath=yes
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5
+$as_echo "$doRpath" >&6; }
+
+ # Step 1: set the variable "system" to hold the name and version number
+ # for the system.
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5
+$as_echo_n "checking system version... " >&6; }
+if ${tcl_cv_sys_version+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ tcl_cv_sys_version=windows
+ else
+ tcl_cv_sys_version=`uname -s`-`uname -r`
+ if test "$?" -ne 0 ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5
+$as_echo "$as_me: WARNING: can't find uname command" >&2;}
+ tcl_cv_sys_version=unknown
+ else
+ if test "`uname -s`" = "AIX" ; then
+ tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
+ fi
+ fi
+ fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5
+$as_echo "$tcl_cv_sys_version" >&6; }
+ system=$tcl_cv_sys_version
+
+
+ # Step 2: check for existence of -ldl library. This is needed because
+ # Linux can use either -ldl or -ldld for dynamic loading.
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dl_dlopen=yes
+else
+ ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+ have_dl=yes
+else
+ have_dl=no
+fi
+
+
+ # Require ranlib early so we can override it in special cases below.
+
+
+
+ # Step 3: set configuration options based on system name and version.
+
+ do64bit_ok=no
+ # default to '{$LIBS}' and set to "" on per-platform necessary basis
+ SHLIB_LD_LIBS='${LIBS}'
+ LDFLAGS_ORIG="$LDFLAGS"
+ # When ld needs options to work in 64-bit mode, put them in
+ # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]
+ # is disabled by the user. [Bug 1016796]
+ LDFLAGS_ARCH=""
+ UNSHARED_LIB_SUFFIX=""
+ TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
+ ECHO_VERSION='`echo ${VERSION}`'
+ TCL_LIB_VERSIONS_OK=ok
+ CFLAGS_DEBUG=-g
+ if test "$GCC" = yes; then :
+
+ CFLAGS_OPTIMIZE=-O2
+ CFLAGS_WARNING="-Wall -Wwrite-strings -Wsign-compare -Wdeclaration-after-statement"
+
+else
+
+ CFLAGS_OPTIMIZE=-O
+ CFLAGS_WARNING=""
+
+fi
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+ STLIB_LD='${AR} cr'
+ LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
+ PLAT_OBJS=""
+ PLAT_SRCS=""
+ LDAIX_SRC=""
+ if test "x${SHLIB_VERSION}" = x; then :
+ SHLIB_VERSION="1.0"
+fi
+ case $system in
+ AIX-*)
+ if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then :
+
+ # AIX requires the _r compiler when gcc isn't being used
+ case "${CC}" in
+ *_r|*_r\ *)
+ # ok ...
+ ;;
+ *)
+ # Make sure only first arg gets _r
+ CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'`
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5
+$as_echo "Using $CC for compiling with threads" >&6; }
+
+fi
+ LIBS="$LIBS -lc"
+ SHLIB_CFLAGS=""
+ SHLIB_SUFFIX=".so"
+
+ DL_OBJS="tclLoadDl.o"
+ LD_LIBRARY_PATH_VAR="LIBPATH"
+
+ # ldAix No longer needed with use of -bexpall/-brtl
+ # but some extensions may still reference it
+ LDAIX_SRC='$(UNIX_DIR)/ldAix'
+
+ # Check to enable 64-bit flags for compiler/linker
+ if test "$do64bit" = yes; then :
+
+ if test "$GCC" = yes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}
+
+else
+
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -q64"
+ LDFLAGS_ARCH="-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 :
+
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+
+else
+
+ CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
+
+fi
+ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+
+else
+
+ if test "$GCC" = yes; then :
+
+ SHLIB_LD='${CC} -shared -Wl,-bexpall'
+
+else
+
+ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
+ LDFLAGS="$LDFLAGS -brtl"
+
+fi
+ SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+
+fi
+ ;;
+ BeOS*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -nostart'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+
+ #-----------------------------------------------------------
+ # Check for inet_ntoa in -lbind, for BeOS (which also needs
+ # -lsocket, even if the network functions are in -lnet which
+ # is always linked to, for compatibility.
+ #-----------------------------------------------------------
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5
+$as_echo_n "checking for inet_ntoa in -lbind... " >&6; }
+if ${ac_cv_lib_bind_inet_ntoa+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbind $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inet_ntoa ();
+int
+main ()
+{
+return inet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_bind_inet_ntoa=yes
+else
+ ac_cv_lib_bind_inet_ntoa=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5
+$as_echo "$ac_cv_lib_bind_inet_ntoa" >&6; }
+if test "x$ac_cv_lib_bind_inet_ntoa" = xyes; then :
+ LIBS="$LIBS -lbind -lsocket"
+fi
+
+ ;;
+ BSD/OS-2.1*|BSD/OS-3*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="shlicc -r"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ BSD/OS-4.*)
+ SHLIB_CFLAGS="-export-dynamic -fPIC"
+ SHLIB_LD='${CC} -shared'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -export-dynamic"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ CYGWIN_*|MINGW32*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD='${CC} -shared'
+ SHLIB_SUFFIX=".dll"
+ DL_OBJS="tclLoadDl.o"
+ PLAT_OBJS='${CYGWIN_OBJS}'
+ PLAT_SRCS='${CYGWIN_SRCS}'
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ TCL_NEEDS_EXP_FILE=1
+ TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Cygwin version of gcc" >&5
+$as_echo_n "checking for Cygwin version of gcc... " >&6; }
+if ${ac_cv_cygwin+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #ifdef __CYGWIN__
+ #error cygwin
+ #endif
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_cygwin=no
+else
+ ac_cv_cygwin=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cygwin" >&5
+$as_echo "$ac_cv_cygwin" >&6; }
+ if test "$ac_cv_cygwin" = "no"; then
+ as_fn_error $? "${CC} is not a cygwin compiler." "$LINENO" 5
+ fi
+ if test "x${TCL_THREADS}" = "x0"; then
+ as_fn_error $? "CYGWIN compile is only supported with --enable-threads" "$LINENO" 5
+ fi
+ do64bit_ok=yes
+ if test "x${SHARED_BUILD}" = "x1"; then
+ echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args"
+ # The eval makes quoting arguments work.
+ if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix
+ then :
+ else
+ { echo "configure: error: configure failed for ../win" 1>&2; exit 1; }
+ fi
+ fi
+ ;;
+ dgux*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD='${CC} -G'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ Haiku*)
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-lroot"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5
+$as_echo_n "checking for inet_ntoa in -lnetwork... " >&6; }
+if ${ac_cv_lib_network_inet_ntoa+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnetwork $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inet_ntoa ();
+int
+main ()
+{
+return inet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_network_inet_ntoa=yes
+else
+ ac_cv_lib_network_inet_ntoa=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5
+$as_echo "$ac_cv_lib_network_inet_ntoa" >&6; }
+if test "x$ac_cv_lib_network_inet_ntoa" = xyes; then :
+ LIBS="$LIBS -lnetwork"
+fi
+
+ ;;
+ HP-UX-*.11.*)
+ # Use updated header definitions where possible
+
+$as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h
+
+
+$as_echo "#define _XOPEN_SOURCE 1" >>confdefs.h
+
+ LIBS="$LIBS -lxnet" # Use the XOPEN network library
+
+ if test "`uname -m`" = ia64; then :
+
+ SHLIB_SUFFIX=".so"
+
+else
+
+ SHLIB_SUFFIX=".sl"
+
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dld_shl_load=yes
+else
+ ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ if test "$tcl_ok" = yes; then :
+
+ SHLIB_CFLAGS="+z"
+ SHLIB_LD="ld -b"
+ DL_OBJS="tclLoadShl.o"
+ DL_LIBS="-ldld"
+ LDFLAGS="$LDFLAGS -Wl,-E"
+ CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
+ LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
+ LD_LIBRARY_PATH_VAR="SHLIB_PATH"
+
+fi
+ if test "$GCC" = yes; then :
+
+ SHLIB_LD='${CC} -shared'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+
+else
+
+ CFLAGS="$CFLAGS -z"
+
+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 :
+
+ case `${CC} -dumpmachine` in
+ hppa64*)
+ # 64-bit gcc in use. Fix flags for GNU ld.
+ do64bit_ok=yes
+ SHLIB_LD='${CC} -shared'
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}
+ ;;
+ esac
+
+else
+
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS +DD64"
+ LDFLAGS_ARCH="+DD64"
+
+fi
+
+fi ;;
+ HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)
+ SHLIB_SUFFIX=".sl"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dld_shl_load=yes
+else
+ ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ 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"
+ CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
+ LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
+ LD_LIBRARY_PATH_VAR="SHLIB_PATH"
+
+fi ;;
+ IRIX-5.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ case " $LIBOBJS " in
+ *" mkstemp.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
+ ;;
+esac
+
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+ ;;
+ IRIX-6.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -n32 -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ case " $LIBOBJS " in
+ *" mkstemp.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
+ ;;
+esac
+
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+ 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_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ case " $LIBOBJS " in
+ *" mkstemp.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
+ ;;
+esac
+
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+
+ # Check to enable 64-bit flags for compiler/linker
+
+ if test "$do64bit" = yes; then :
+
+ if test "$GCC" = yes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;}
+
+else
+
+ do64bit_ok=yes
+ SHLIB_LD="ld -64 -shared -rdata_shared"
+ CFLAGS="$CFLAGS -64"
+ LDFLAGS_ARCH="-64"
+
+fi
+
+fi
+ ;;
+ Linux*|GNU*|NetBSD-Debian)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+
+ CFLAGS_OPTIMIZE="-O2"
+ # 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"
+
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ if test "`uname -m`" = "alpha"; then :
+ CFLAGS="$CFLAGS -mieee"
+fi
+ if test $do64bit = yes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5
+$as_echo_n "checking if compiler accepts -m64 flag... " >&6; }
+if ${tcl_cv_cc_m64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -m64"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_cc_m64=yes
+else
+ tcl_cv_cc_m64=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5
+$as_echo "$tcl_cv_cc_m64" >&6; }
+ if test $tcl_cv_cc_m64 = yes; then :
+
+ CFLAGS="$CFLAGS -m64"
+ do64bit_ok=yes
+
+fi
+
+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
+ ;;
+ Lynx*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ CFLAGS_OPTIMIZE=-02
+ SHLIB_LD='${CC} -shared'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-mshared -ldl"
+ LD_FLAGS="-Wl,--export-dynamic"
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ ;;
+ OpenBSD-*)
+ arch=`arch -s`
+ case "$arch" in
+ alpha|sparc64)
+ SHLIB_CFLAGS="-fPIC"
+ ;;
+ *)
+ SHLIB_CFLAGS="-fpic"
+ ;;
+ esac
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
+ LDFLAGS="-Wl,-export-dynamic"
+ CFLAGS_OPTIMIZE="-O2"
+ if test "${TCL_THREADS}" = "1"; then :
+
+ # On OpenBSD: Compile with -pthread
+ # Don't link with -lpthread
+ LIBS=`echo $LIBS | sed s/-lpthread//`
+ CFLAGS="$CFLAGS -pthread"
+
+fi
+ # OpenBSD doesn't do version numbers with dots.
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ NetBSD-*)
+ # NetBSD has ELF and can use 'cc -shared' to build shared libs
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ LDFLAGS="$LDFLAGS -export-dynamic"
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ 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
+ ;;
+ FreeBSD-*)
+ # This configuration from FreeBSD Ports.
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="${CC} -shared"
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ LDFLAGS=""
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ if test "${TCL_THREADS}" = "1"; then :
+
+ # The -pthread needs to go in the LDFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
+fi
+ case $system in
+ FreeBSD-3.*)
+ # Version numbers are dot-stripped by system policy.
+ TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
+ 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"
+ # To avoid discrepancies between what headers configure sees during
+ # preprocessing tests and compiling tests, move any -isysroot and
+ # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
+ CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
+ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
+ if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`"
+ CFLAGS="`echo " ${CFLAGS}" | \
+ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
+ if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`"
+ if test $do64bit = yes; then :
+
+ case `arch` in
+ ppc)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5
+$as_echo_n "checking if compiler accepts -arch ppc64 flag... " >&6; }
+if ${tcl_cv_cc_arch_ppc64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_cc_arch_ppc64=yes
+else
+ tcl_cv_cc_arch_ppc64=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5
+$as_echo "$tcl_cv_cc_arch_ppc64" >&6; }
+ if test $tcl_cv_cc_arch_ppc64 = yes; then :
+
+ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
+ do64bit_ok=yes
+
+fi;;
+ i386)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5
+$as_echo_n "checking if compiler accepts -arch x86_64 flag... " >&6; }
+if ${tcl_cv_cc_arch_x86_64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -arch x86_64"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_cc_arch_x86_64=yes
+else
+ tcl_cv_cc_arch_x86_64=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5
+$as_echo "$tcl_cv_cc_arch_x86_64" >&6; }
+ if test $tcl_cv_cc_arch_x86_64 = yes; then :
+
+ CFLAGS="$CFLAGS -arch x86_64"
+ do64bit_ok=yes
+
+fi;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5
+$as_echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};;
+ esac
+
+else
+
+ # Check for combined 32-bit and 64-bit fat build
+ if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
+ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then :
+
+ fat_32_64=yes
+fi
+
+fi
+ SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5
+$as_echo_n "checking if ld accepts -single_module flag... " >&6; }
+if ${tcl_cv_ld_single_module+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int i;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_ld_single_module=yes
+else
+ tcl_cv_ld_single_module=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$hold_ldflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5
+$as_echo "$tcl_cv_ld_single_module" >&6; }
+ if test $tcl_cv_ld_single_module = yes; then :
+
+ SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
+
+fi
+ SHLIB_SUFFIX=".dylib"
+ DL_OBJS="tclLoadDyld.o"
+ DL_LIBS=""
+ # Don't use -prebind when building for Mac OS X 10.4 or later only:
+ if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \
+ "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then :
+
+ LDFLAGS="$LDFLAGS -prebind"
+fi
+ LDFLAGS="$LDFLAGS -headerpad_max_install_names"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5
+$as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; }
+if ${tcl_cv_ld_search_paths_first+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int i;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_ld_search_paths_first=yes
+else
+ tcl_cv_ld_search_paths_first=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$hold_ldflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5
+$as_echo "$tcl_cv_ld_search_paths_first" >&6; }
+ if test $tcl_cv_ld_search_paths_first = yes; then :
+
+ LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+
+fi
+ if test "$tcl_cv_cc_visibility_hidden" != yes; then :
+
+
+$as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h
+
+
+fi
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
+
+$as_echo "#define MAC_OSX_TCL 1" >>confdefs.h
+
+ PLAT_OBJS='${MAC_OSX_OBJS}'
+ PLAT_SRCS='${MAC_OSX_SRCS}'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use CoreFoundation" >&5
+$as_echo_n "checking whether to use CoreFoundation... " >&6; }
+ # Check whether --enable-corefoundation was given.
+if test "${enable_corefoundation+set}" = set; then :
+ enableval=$enable_corefoundation; tcl_corefoundation=$enableval
+else
+ tcl_corefoundation=yes
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_corefoundation" >&5
+$as_echo "$tcl_corefoundation" >&6; }
+ if test $tcl_corefoundation = yes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CoreFoundation.framework" >&5
+$as_echo_n "checking for CoreFoundation.framework... " >&6; }
+if ${tcl_cv_lib_corefoundation+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_libs=$LIBS
+ if test "$fat_32_64" = yes; then :
+
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ # On Tiger there is no 64-bit CF, so remove 64-bit
+ # archs from CFLAGS et al. while testing for
+ # presence of CF. 64-bit CF is disabled in
+ # tclUnixPort.h if necessary.
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
+ done
+fi
+ LIBS="$LIBS -framework CoreFoundation"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <CoreFoundation/CoreFoundation.h>
+int
+main ()
+{
+CFBundleRef b = CFBundleGetMainBundle();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_lib_corefoundation=yes
+else
+ tcl_cv_lib_corefoundation=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ if test "$fat_32_64" = yes; then :
+
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done
+fi
+ LIBS=$hold_libs
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation" >&5
+$as_echo "$tcl_cv_lib_corefoundation" >&6; }
+ if test $tcl_cv_lib_corefoundation = yes; then :
+
+ LIBS="$LIBS -framework CoreFoundation"
+
+$as_echo "#define HAVE_COREFOUNDATION 1" >>confdefs.h
+
+
+else
+ tcl_corefoundation=no
+fi
+ if test "$fat_32_64" = yes -a $tcl_corefoundation = yes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit CoreFoundation" >&5
+$as_echo_n "checking for 64-bit CoreFoundation... " >&6; }
+if ${tcl_cv_lib_corefoundation_64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
+ done
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <CoreFoundation/CoreFoundation.h>
+int
+main ()
+{
+CFBundleRef b = CFBundleGetMainBundle();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_lib_corefoundation_64=yes
+else
+ tcl_cv_lib_corefoundation_64=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation_64" >&5
+$as_echo "$tcl_cv_lib_corefoundation_64" >&6; }
+ if test $tcl_cv_lib_corefoundation_64 = no; then :
+
+
+$as_echo "#define NO_COREFOUNDATION_64 1" >>confdefs.h
+
+ LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"
+
+fi
+
+fi
+
+fi
+ ;;
+ OS/390-*)
+ SHLIB_LD_LIBS=""
+ CFLAGS_OPTIMIZE="" # Optimizer is buggy
+
+$as_echo "#define _OE_SOCKETS 1" >>confdefs.h
+
+ ;;
+ 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_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+ 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=""
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ 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=""
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ SunOS-5.[0-6])
+ # Careful to not let 5.10+ fall into this case
+
+ # Note: If _REENTRANT isn't defined, then Solaris
+ # won't define thread-safe library routines.
+
+
+$as_echo "#define _REENTRANT 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+
+ SHLIB_CFLAGS="-KPIC"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ if test "$GCC" = yes; then :
+
+ SHLIB_LD='${CC} -shared'
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+
+else
+
+ SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+ CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+
+fi
+ ;;
+ SunOS-5*)
+ # Note: If _REENTRANT isn't defined, then Solaris
+ # won't define thread-safe library routines.
+
+
+$as_echo "#define _REENTRANT 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+
+ 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 "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;}
+
+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_ARCH="-xarch=v9a"
+
+else
+
+ CFLAGS="$CFLAGS -xarch=v9"
+ LDFLAGS_ARCH="-xarch=v9"
+
+fi
+ # Solaris 64 uses this as well
+ #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
+
+fi
+
+else
+ if test "$arch" = "amd64 i386"; then :
+
+ if test "$GCC" = yes; then :
+
+ case $system in
+ SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -m64"
+ LDFLAGS="$LDFLAGS -m64";;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};;
+ esac
+
+else
+
+ do64bit_ok=yes
+ case $system in
+ SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)
+ CFLAGS="$CFLAGS -m64"
+ LDFLAGS="$LDFLAGS -m64";;
+ *)
+ CFLAGS="$CFLAGS -xarch=amd64"
+ LDFLAGS="$LDFLAGS -xarch=amd64";;
+ esac
+
+fi
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;}
+fi
+fi
+
+fi
+
+ #--------------------------------------------------------------------
+ # On Solaris 5.x i386 with the sunpro compiler we need to link
+ # with sunmath to get floating point rounding control
+ #--------------------------------------------------------------------
+ if test "$GCC" = yes; then :
+ use_sunmath=no
+else
+
+ arch=`isainfo`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use -lsunmath for fp rounding control" >&5
+$as_echo_n "checking whether to use -lsunmath for fp rounding control... " >&6; }
+ if test "$arch" = "amd64 i386" -o "$arch" = "i386"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ MATH_LIBS="-lsunmath $MATH_LIBS"
+ ac_fn_c_check_header_mongrel "$LINENO" "sunmath.h" "ac_cv_header_sunmath_h" "$ac_includes_default"
+if test "x$ac_cv_header_sunmath_h" = xyes; then :
+
+fi
+
+
+ use_sunmath=yes
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ use_sunmath=no
+
+fi
+
+fi
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ if test "$GCC" = yes; then :
+
+ SHLIB_LD='${CC} -shared'
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ if test "$do64bit_ok" = yes; then :
+
+ if test "$arch" = "sparcv9 sparc"; then :
+
+ # We need to specify -static-libgcc or we need to
+ # add the path to the sparv9 libgcc.
+ 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` | ..."
+ #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"
+
+else
+ if test "$arch" = "amd64 i386"; then :
+
+ SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
+
+fi
+fi
+
+fi
+
+else
+
+ if test "$use_sunmath" = yes; then :
+ textmode=textoff
+else
+ textmode=text
+fi
+ case $system in
+ SunOS-5.[1-9][0-9]*|SunOS-5.[7-9])
+ SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";;
+ *)
+ SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";;
+ esac
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+
+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.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5
+$as_echo_n "checking for ld accepts -Bexport flag... " >&6; }
+if ${tcl_cv_ld_Bexport+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int i;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_ld_Bexport=yes
+else
+ tcl_cv_ld_Bexport=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$hold_ldflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5
+$as_echo "$tcl_cv_ld_Bexport" >&6; }
+ if test $tcl_cv_ld_Bexport = yes; then :
+
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+
+fi
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ esac
+
+ if test "$do64bit" = yes -a "$do64bit_ok" = no; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5
+$as_echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;}
+
+fi
+
+ if test "$do64bit" = yes -a "$do64bit_ok" = yes; then :
+
+
+$as_echo "#define TCL_CFG_DO64BIT 1" >>confdefs.h
+
+
+fi
+
+
+
+ # Step 4: disable dynamic loading if requested via a command-line switch.
+
+ # Check whether --enable-load was given.
+if test "${enable_load+set}" = set; then :
+ enableval=$enable_load; tcl_ok=$enableval
+else
+ tcl_ok=yes
+fi
+
+ if test "$tcl_ok" = no; then :
+ DL_OBJS=""
+fi
+
+ if test "x$DL_OBJS" != x; then :
+ BUILD_DLTEST="\$(DLTEST_TARGETS)"
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&5
+$as_echo "$as_me: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&2;}
+ SHLIB_CFLAGS=""
+ SHLIB_LD=""
+ SHLIB_SUFFIX=""
+ DL_OBJS="tclLoadNone.o"
+ DL_LIBS=""
+ LDFLAGS="$LDFLAGS_ORIG"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ BUILD_DLTEST=""
+
+fi
+ LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"
+
+ # 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" -a "$GCC" = yes; then :
+
+ case $system in
+ AIX-*) ;;
+ BSD/OS*) ;;
+ CYGWIN_*|MINGW32_*) ;;
+ IRIX*) ;;
+ NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
+ Darwin-*) ;;
+ SCO_SV-3.2*) ;;
+ *) SHLIB_CFLAGS="-fPIC" ;;
+ esac
+fi
+
+ if test "$tcl_cv_cc_visibility_hidden" != yes; then :
+
+
+$as_echo "#define MODULE_SCOPE extern" >>confdefs.h
+
+
+fi
+
+ if test "$SHARED_LIB_SUFFIX" = ""; then :
+
+ SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'
+fi
+ if test "$UNSHARED_LIB_SUFFIX" = ""; then :
+
+ UNSHARED_LIB_SUFFIX='${VERSION}.a'
+fi
+ DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"
+
+ if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then :
+
+ LIB_SUFFIX=${SHARED_LIB_SUFFIX}
+ MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
+ if test "${SHLIB_SUFFIX}" = ".dll"; then :
+
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;'
+ DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
+
+else
+
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
+
+fi
+
+else
+
+ LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
+
+ if test "$RANLIB" = ""; then :
+
+ MAKE_LIB='$(STLIB_LD) $@ ${OBJS}'
+
+else
+
+ MAKE_LIB='${STLIB_LD} $@ ${OBJS} ; ${RANLIB} $@'
+
+fi
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
+
+fi
+
+ # Stub lib does not depend on shared/static configuration
+ if test "$RANLIB" = ""; then :
+
+ MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS}'
+
+else
+
+ MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS} ; ${RANLIB} $@'
+
+fi
+ INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"'
+
+ # Define TCL_LIBS now that we know what DL_LIBS is.
+ # The trick here is that we don't want to change the value of TCL_LIBS if
+ # it is already set when tclConfig.sh had been loaded by Tk.
+ if test "x${TCL_LIBS}" = x; then :
+
+ TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"
+fi
+
+
+ # See if the compiler supports casting to a union type.
+ # This is used to stop gcc from printing a compiler
+ # warning when initializing a union member.
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5
+$as_echo_n "checking for cast to union support... " >&6; }
+if ${tcl_cv_cast_to_union+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ union foo { int i; double d; };
+ union foo f = (union foo) (int) 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_cast_to_union=yes
+else
+ tcl_cv_cast_to_union=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5
+$as_echo "$tcl_cv_cast_to_union" >&6; }
+ if test "$tcl_cv_cast_to_union" = "yes"; then
+
+$as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h
+
+ fi
+
+ # FIXME: This subst was left in only because the TCL_DL_LIBS
+ # entry in tclConfig.sh uses it. It is not clear why someone
+ # would use TCL_DL_LIBS instead of TCL_LIBS.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define TCL_SHLIB_EXT "${SHLIB_SUFFIX}"
+_ACEOF
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5
+$as_echo_n "checking for build with symbols... " >&6; }
+ # Check whether --enable-symbols was given.
+if test "${enable_symbols+set}" = set; then :
+ enableval=$enable_symbols; tcl_ok=$enableval
+else
+ tcl_ok=no
+fi
+
+# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
+ DBGX=""
+ if test "$tcl_ok" = "no"; then
+ CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
+ LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
+
+$as_echo "#define NDEBUG 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h
+
+ else
+ CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
+ LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
+ if test "$tcl_ok" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5
+$as_echo "yes (standard debugging)" >&6; }
+ fi
+ fi
+
+
+
+ if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
+
+$as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h
+
+ fi
+
+ if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then
+
+$as_echo "#define TCL_COMPILE_DEBUG 1" >>confdefs.h
+
+
+$as_echo "#define TCL_COMPILE_STATS 1" >>confdefs.h
+
+ fi
+
+ if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
+ if test "$tcl_ok" = "all"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem compile debugging" >&5
+$as_echo "enabled symbols mem compile debugging" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5
+$as_echo "enabled $tcl_ok debugging" >&6; }
+ fi
+ fi
+
+
+
+$as_echo "#define MP_PREC 4" >>confdefs.h
+
+
+#--------------------------------------------------------------------
+# Detect what compiler flags to set for 64-bit support.
+#--------------------------------------------------------------------
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5
+$as_echo_n "checking for required early compiler flags... " >&6; }
+ tcl_flags=""
+
+ if ${tcl_cv_flag__isoc99_source+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+int
+main ()
+{
+char *p = (char *)strtoll; char *q = (char *)strtoull;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__isoc99_source=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _ISOC99_SOURCE 1
+#include <stdlib.h>
+int
+main ()
+{
+char *p = (char *)strtoll; char *q = (char *)strtoull;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__isoc99_source=yes
+else
+ tcl_cv_flag__isoc99_source=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then
+
+$as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h
+
+ tcl_flags="$tcl_flags _ISOC99_SOURCE"
+ fi
+
+
+ if ${tcl_cv_flag__largefile64_source+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/stat.h>
+int
+main ()
+{
+struct stat64 buf; int i = stat64("/", &buf);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__largefile64_source=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGEFILE64_SOURCE 1
+#include <sys/stat.h>
+int
+main ()
+{
+struct stat64 buf; int i = stat64("/", &buf);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__largefile64_source=yes
+else
+ tcl_cv_flag__largefile64_source=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then
+
+$as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h
+
+ tcl_flags="$tcl_flags _LARGEFILE64_SOURCE"
+ fi
+
+
+ if ${tcl_cv_flag__largefile_source64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/stat.h>
+int
+main ()
+{
+char *p = (char *)open64;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__largefile_source64=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGEFILE_SOURCE64 1
+#include <sys/stat.h>
+int
+main ()
+{
+char *p = (char *)open64;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__largefile_source64=yes
+else
+ tcl_cv_flag__largefile_source64=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then
+
+$as_echo "#define _LARGEFILE_SOURCE64 1" >>confdefs.h
+
+ tcl_flags="$tcl_flags _LARGEFILE_SOURCE64"
+ fi
+
+ if test "x${tcl_flags}" = "x" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5
+$as_echo "${tcl_flags}" >&6; }
+ fi
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5
+$as_echo_n "checking for 64-bit integer type... " >&6; }
+ if ${tcl_cv_type_64bit+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ tcl_cv_type_64bit=none
+ # See if the compiler knows natively about __int64
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+__int64 value = (__int64) 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_type_64bit=__int64
+else
+ tcl_type_64bit="long long"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ # 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...
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+switch (0) {
+ case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ;
+ }
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_type_64bit=${tcl_type_64bit}
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ if test "${tcl_cv_type_64bit}" = none ; then
+
+$as_echo "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using long" >&5
+$as_echo "using long" >&6; }
+ else
+
+cat >>confdefs.h <<_ACEOF
+#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit}
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5
+$as_echo "${tcl_cv_type_64bit}" >&6; }
+
+ # Now check for auxiliary declarations
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5
+$as_echo_n "checking for struct dirent64... " >&6; }
+if ${tcl_cv_struct_dirent64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <dirent.h>
+int
+main ()
+{
+struct dirent64 p;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_struct_dirent64=yes
+else
+ tcl_cv_struct_dirent64=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5
+$as_echo "$tcl_cv_struct_dirent64" >&6; }
+ if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
+
+$as_echo "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h
+
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5
+$as_echo_n "checking for struct stat64... " >&6; }
+if ${tcl_cv_struct_stat64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/stat.h>
+int
+main ()
+{
+struct stat64 p;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_struct_stat64=yes
+else
+ tcl_cv_struct_stat64=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5
+$as_echo "$tcl_cv_struct_stat64" >&6; }
+ if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
+
+$as_echo "#define HAVE_STRUCT_STAT64 1" >>confdefs.h
+
+ fi
+
+ for ac_func in open64 lseek64
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5
+$as_echo_n "checking for off64_t... " >&6; }
+ if ${tcl_cv_type_off64_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+off64_t offset;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_type_off64_t=yes
+else
+ tcl_cv_type_off64_t=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ if test "x${tcl_cv_type_off64_t}" = "xyes" && \
+ test "x${ac_cv_func_lseek64}" = "xyes" && \
+ test "x${ac_cv_func_open64}" = "xyes" ; then
+
+$as_echo "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+ fi
+
+
+#--------------------------------------------------------------------
+# Check endianness because we can optimize comparisons of
+# Tcl_UniChar strings to memcmp on big-endian systems.
+#--------------------------------------------------------------------
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+
+#--------------------------------------------------------------------
+# Supply substitutes for missing POSIX library procedures, or
+# set flags so Tcl uses alternate procedures.
+#--------------------------------------------------------------------
+
+# Check if Posix compliant getcwd exists, if not we'll use getwd.
+for ac_func in getcwd
+do :
+ ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd"
+if test "x$ac_cv_func_getcwd" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GETCWD 1
+_ACEOF
+
+else
+
+$as_echo "#define USEGETWD 1" >>confdefs.h
+
+fi
+done
+
+# Nb: if getcwd uses popen and pwd(1) (like SunOS 4) we should really
+# define USEGETWD even if the posix getcwd exists. Add a test ?
+
+ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp"
+if test "x$ac_cv_func_mkstemp" = xyes; then :
+ $as_echo "#define HAVE_MKSTEMP 1" >>confdefs.h
+
+else
+ case " $LIBOBJS " in
+ *" mkstemp.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
+ ;;
+esac
+
+fi
+
+ac_fn_c_check_func "$LINENO" "opendir" "ac_cv_func_opendir"
+if test "x$ac_cv_func_opendir" = xyes; then :
+ $as_echo "#define HAVE_OPENDIR 1" >>confdefs.h
+
+else
+ case " $LIBOBJS " in
+ *" opendir.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS opendir.$ac_objext"
+ ;;
+esac
+
+fi
+
+ac_fn_c_check_func "$LINENO" "strtol" "ac_cv_func_strtol"
+if test "x$ac_cv_func_strtol" = xyes; then :
+ $as_echo "#define HAVE_STRTOL 1" >>confdefs.h
+
+else
+ case " $LIBOBJS " in
+ *" strtol.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strtol.$ac_objext"
+ ;;
+esac
+
+fi
+
+ac_fn_c_check_func "$LINENO" "waitpid" "ac_cv_func_waitpid"
+if test "x$ac_cv_func_waitpid" = xyes; then :
+ $as_echo "#define HAVE_WAITPID 1" >>confdefs.h
+
+else
+ case " $LIBOBJS " in
+ *" waitpid.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS waitpid.$ac_objext"
+ ;;
+esac
+
+fi
+
+
+ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
+if test "x$ac_cv_func_strerror" = xyes; then :
+
+else
+
+$as_echo "#define NO_STRERROR 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_func "$LINENO" "getwd" "ac_cv_func_getwd"
+if test "x$ac_cv_func_getwd" = xyes; then :
+
+else
+
+$as_echo "#define NO_GETWD 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_func "$LINENO" "wait3" "ac_cv_func_wait3"
+if test "x$ac_cv_func_wait3" = xyes; then :
+
+else
+
+$as_echo "#define NO_WAIT3 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_func "$LINENO" "uname" "ac_cv_func_uname"
+if test "x$ac_cv_func_uname" = xyes; then :
+
+else
+
+$as_echo "#define NO_UNAME 1" >>confdefs.h
+
+fi
+
+
+if test "`uname -s`" = "Darwin" && test "${TCL_THREADS}" = 1 && \
+ test "`uname -r | awk -F. '{print $1}'`" -lt 7; then
+ # prior to Darwin 7, realpath is not threadsafe, so don't
+ # use it when threads are enabled, c.f. bug # 711232
+ ac_cv_func_realpath=no
+fi
+ac_fn_c_check_func "$LINENO" "realpath" "ac_cv_func_realpath"
+if test "x$ac_cv_func_realpath" = xyes; then :
+
+else
+
+$as_echo "#define NO_REALPATH 1" >>confdefs.h
+
+fi
+
+
+
+ NEED_FAKE_RFC2553=0
+ for ac_func in getnameinfo getaddrinfo freeaddrinfo gai_strerror
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+ NEED_FAKE_RFC2553=1
+fi
+done
+
+ ac_fn_c_check_type "$LINENO" "struct addrinfo" "ac_cv_type_struct_addrinfo" "
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+"
+if test "x$ac_cv_type_struct_addrinfo" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_ADDRINFO 1
+_ACEOF
+
+
+else
+ NEED_FAKE_RFC2553=1
+fi
+ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" "
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+"
+if test "x$ac_cv_type_struct_in6_addr" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_IN6_ADDR 1
+_ACEOF
+
+
+else
+ NEED_FAKE_RFC2553=1
+fi
+ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+"
+if test "x$ac_cv_type_struct_sockaddr_in6" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_IN6 1
+_ACEOF
+
+
+else
+ NEED_FAKE_RFC2553=1
+fi
+ac_fn_c_check_type "$LINENO" "struct sockaddr_storage" "ac_cv_type_struct_sockaddr_storage" "
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+"
+if test "x$ac_cv_type_struct_sockaddr_storage" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+_ACEOF
+
+
+else
+ NEED_FAKE_RFC2553=1
+fi
+
+if test "x$NEED_FAKE_RFC2553" = "x1"; then
+
+$as_echo "#define NEED_FAKE_RFC2553 1" >>confdefs.h
+
+ case " $LIBOBJS " in
+ *" fake-rfc2553.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS fake-rfc2553.$ac_objext"
+ ;;
+esac
+
+ ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy"
+if test "x$ac_cv_func_strlcpy" = xyes; then :
+
+fi
+
+fi
+
+
+#--------------------------------------------------------------------
+# Look for thread-safe variants of some library functions.
+#--------------------------------------------------------------------
+
+if test "${TCL_THREADS}" = 1; then
+ ac_fn_c_check_func "$LINENO" "getpwuid_r" "ac_cv_func_getpwuid_r"
+if test "x$ac_cv_func_getpwuid_r" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwuid_r with 5 args" >&5
+$as_echo_n "checking for getpwuid_r with 5 args... " >&6; }
+if ${tcl_cv_api_getpwuid_r_5+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <pwd.h>
+
+int
+main ()
+{
+
+ uid_t uid;
+ struct passwd pw, *pwp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getpwuid_r(uid, &pw, buf, buflen, &pwp);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_getpwuid_r_5=yes
+else
+ tcl_cv_api_getpwuid_r_5=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwuid_r_5" >&5
+$as_echo "$tcl_cv_api_getpwuid_r_5" >&6; }
+ tcl_ok=$tcl_cv_api_getpwuid_r_5
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETPWUID_R_5 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwuid_r with 4 args" >&5
+$as_echo_n "checking for getpwuid_r with 4 args... " >&6; }
+if ${tcl_cv_api_getpwuid_r_4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <pwd.h>
+
+int
+main ()
+{
+
+ uid_t uid;
+ struct passwd pw;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getpwnam_r(uid, &pw, buf, buflen);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_getpwuid_r_4=yes
+else
+ tcl_cv_api_getpwuid_r_4=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwuid_r_4" >&5
+$as_echo "$tcl_cv_api_getpwuid_r_4" >&6; }
+ tcl_ok=$tcl_cv_api_getpwuid_r_4
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETPWUID_R_4 1" >>confdefs.h
+
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETPWUID_R 1" >>confdefs.h
+
+ fi
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "getpwnam_r" "ac_cv_func_getpwnam_r"
+if test "x$ac_cv_func_getpwnam_r" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwnam_r with 5 args" >&5
+$as_echo_n "checking for getpwnam_r with 5 args... " >&6; }
+if ${tcl_cv_api_getpwnam_r_5+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <pwd.h>
+
+int
+main ()
+{
+
+ char *name;
+ struct passwd pw, *pwp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getpwnam_r(name, &pw, buf, buflen, &pwp);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_getpwnam_r_5=yes
+else
+ tcl_cv_api_getpwnam_r_5=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwnam_r_5" >&5
+$as_echo "$tcl_cv_api_getpwnam_r_5" >&6; }
+ tcl_ok=$tcl_cv_api_getpwnam_r_5
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETPWNAM_R_5 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwnam_r with 4 args" >&5
+$as_echo_n "checking for getpwnam_r with 4 args... " >&6; }
+if ${tcl_cv_api_getpwnam_r_4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <pwd.h>
+
+int
+main ()
+{
+
+ char *name;
+ struct passwd pw;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getpwnam_r(name, &pw, buf, buflen);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_getpwnam_r_4=yes
+else
+ tcl_cv_api_getpwnam_r_4=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwnam_r_4" >&5
+$as_echo "$tcl_cv_api_getpwnam_r_4" >&6; }
+ tcl_ok=$tcl_cv_api_getpwnam_r_4
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETPWNAM_R_4 1" >>confdefs.h
+
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETPWNAM_R 1" >>confdefs.h
+
+ fi
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "getgrgid_r" "ac_cv_func_getgrgid_r"
+if test "x$ac_cv_func_getgrgid_r" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrgid_r with 5 args" >&5
+$as_echo_n "checking for getgrgid_r with 5 args... " >&6; }
+if ${tcl_cv_api_getgrgid_r_5+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <grp.h>
+
+int
+main ()
+{
+
+ gid_t gid;
+ struct group gr, *grp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getgrgid_r(gid, &gr, buf, buflen, &grp);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_getgrgid_r_5=yes
+else
+ tcl_cv_api_getgrgid_r_5=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrgid_r_5" >&5
+$as_echo "$tcl_cv_api_getgrgid_r_5" >&6; }
+ tcl_ok=$tcl_cv_api_getgrgid_r_5
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETGRGID_R_5 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrgid_r with 4 args" >&5
+$as_echo_n "checking for getgrgid_r with 4 args... " >&6; }
+if ${tcl_cv_api_getgrgid_r_4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <grp.h>
+
+int
+main ()
+{
+
+ gid_t gid;
+ struct group gr;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getgrgid_r(gid, &gr, buf, buflen);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_getgrgid_r_4=yes
+else
+ tcl_cv_api_getgrgid_r_4=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrgid_r_4" >&5
+$as_echo "$tcl_cv_api_getgrgid_r_4" >&6; }
+ tcl_ok=$tcl_cv_api_getgrgid_r_4
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETGRGID_R_4 1" >>confdefs.h
+
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETGRGID_R 1" >>confdefs.h
+
+ fi
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "getgrnam_r" "ac_cv_func_getgrnam_r"
+if test "x$ac_cv_func_getgrnam_r" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrnam_r with 5 args" >&5
+$as_echo_n "checking for getgrnam_r with 5 args... " >&6; }
+if ${tcl_cv_api_getgrnam_r_5+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <grp.h>
+
+int
+main ()
+{
+
+ char *name;
+ struct group gr, *grp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getgrnam_r(name, &gr, buf, buflen, &grp);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_getgrnam_r_5=yes
+else
+ tcl_cv_api_getgrnam_r_5=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrnam_r_5" >&5
+$as_echo "$tcl_cv_api_getgrnam_r_5" >&6; }
+ tcl_ok=$tcl_cv_api_getgrnam_r_5
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETGRNAM_R_5 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrnam_r with 4 args" >&5
+$as_echo_n "checking for getgrnam_r with 4 args... " >&6; }
+if ${tcl_cv_api_getgrnam_r_4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <grp.h>
+
+int
+main ()
+{
+
+ char *name;
+ struct group gr;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getgrnam_r(name, &gr, buf, buflen);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_getgrnam_r_4=yes
+else
+ tcl_cv_api_getgrnam_r_4=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrnam_r_4" >&5
+$as_echo "$tcl_cv_api_getgrnam_r_4" >&6; }
+ tcl_ok=$tcl_cv_api_getgrnam_r_4
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETGRNAM_R_4 1" >>confdefs.h
+
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETGRNAM_R 1" >>confdefs.h
+
+ fi
+
+fi
+
+ if test "`uname -s`" = "Darwin" && \
+ test "`uname -r | awk -F. '{print $1}'`" -gt 5; then
+ # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
+ # are actually MT-safe as they always return pointers
+ # from TSD instead of static storage.
+
+$as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h
+
+
+ elif test "`uname -s`" = "HP-UX" && \
+ test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then
+ # Starting with HPUX 11.00 (we believe), gethostbyX
+ # are actually MT-safe as they always return pointers
+ # from TSD instead of static storage.
+
+$as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h
+
+
+ else
+ ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r"
+if test "x$ac_cv_func_gethostbyname_r" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 6 args" >&5
+$as_echo_n "checking for gethostbyname_r with 6 args... " >&6; }
+if ${tcl_cv_api_gethostbyname_r_6+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <netdb.h>
+
+int
+main ()
+{
+
+ char *name;
+ struct hostent *he, *res;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_gethostbyname_r_6=yes
+else
+ tcl_cv_api_gethostbyname_r_6=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_6" >&5
+$as_echo "$tcl_cv_api_gethostbyname_r_6" >&6; }
+ tcl_ok=$tcl_cv_api_gethostbyname_r_6
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETHOSTBYNAME_R_6 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 5 args" >&5
+$as_echo_n "checking for gethostbyname_r with 5 args... " >&6; }
+if ${tcl_cv_api_gethostbyname_r_5+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <netdb.h>
+
+int
+main ()
+{
+
+ char *name;
+ struct hostent *he;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_gethostbyname_r_5=yes
+else
+ tcl_cv_api_gethostbyname_r_5=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_5" >&5
+$as_echo "$tcl_cv_api_gethostbyname_r_5" >&6; }
+ tcl_ok=$tcl_cv_api_gethostbyname_r_5
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETHOSTBYNAME_R_5 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 3 args" >&5
+$as_echo_n "checking for gethostbyname_r with 3 args... " >&6; }
+if ${tcl_cv_api_gethostbyname_r_3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <netdb.h>
+
+int
+main ()
+{
+
+ char *name;
+ struct hostent *he;
+ struct hostent_data data;
+
+ (void) gethostbyname_r(name, he, &data);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_gethostbyname_r_3=yes
+else
+ tcl_cv_api_gethostbyname_r_3=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_3" >&5
+$as_echo "$tcl_cv_api_gethostbyname_r_3" >&6; }
+ tcl_ok=$tcl_cv_api_gethostbyname_r_3
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETHOSTBYNAME_R_3 1" >>confdefs.h
+
+ fi
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h
+
+ fi
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "gethostbyaddr_r" "ac_cv_func_gethostbyaddr_r"
+if test "x$ac_cv_func_gethostbyaddr_r" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr_r with 7 args" >&5
+$as_echo_n "checking for gethostbyaddr_r with 7 args... " >&6; }
+if ${tcl_cv_api_gethostbyaddr_r_7+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <netdb.h>
+
+int
+main ()
+{
+
+ char *addr;
+ int length;
+ int type;
+ struct hostent *result;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
+ &h_errnop);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_gethostbyaddr_r_7=yes
+else
+ tcl_cv_api_gethostbyaddr_r_7=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyaddr_r_7" >&5
+$as_echo "$tcl_cv_api_gethostbyaddr_r_7" >&6; }
+ tcl_ok=$tcl_cv_api_gethostbyaddr_r_7
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETHOSTBYADDR_R_7 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr_r with 8 args" >&5
+$as_echo_n "checking for gethostbyaddr_r with 8 args... " >&6; }
+if ${tcl_cv_api_gethostbyaddr_r_8+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <netdb.h>
+
+int
+main ()
+{
+
+ char *addr;
+ int length;
+ int type;
+ struct hostent *result, *resultp;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
+ &resultp, &h_errnop);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_api_gethostbyaddr_r_8=yes
+else
+ tcl_cv_api_gethostbyaddr_r_8=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyaddr_r_8" >&5
+$as_echo "$tcl_cv_api_gethostbyaddr_r_8" >&6; }
+ tcl_ok=$tcl_cv_api_gethostbyaddr_r_8
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETHOSTBYADDR_R_8 1" >>confdefs.h
+
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+
+$as_echo "#define HAVE_GETHOSTBYADDR_R 1" >>confdefs.h
+
+ fi
+
+fi
+
+ fi
+fi
+
+#---------------------------------------------------------------------------
+# Check for serial port interface.
+#
+# termios.h is present on all POSIX systems.
+# sys/ioctl.h is almost always present, though what it contains
+# is system-specific.
+# sys/modem.h is needed on HP-UX.
+#---------------------------------------------------------------------------
+
+for ac_header in termios.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "termios.h" "ac_cv_header_termios_h" "$ac_includes_default"
+if test "x$ac_cv_header_termios_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_TERMIOS_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in sys/ioctl.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_ioctl_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_IOCTL_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in sys/modem.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/modem.h" "ac_cv_header_sys_modem_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_modem_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_MODEM_H 1
+_ACEOF
+
+fi
+
+done
+
+
+#--------------------------------------------------------------------
+# Include sys/select.h if it exists and if it supplies things
+# that appear to be useful and aren't already in sys/types.h.
+# This appears to be true only on the RS/6000 under AIX. Some
+# systems like OSF/1 have a sys/select.h that's of no use, and
+# other systems like SCO UNIX have a sys/select.h that's
+# pernicious. If "fd_set" isn't defined anywhere then set a
+# special flag.
+#--------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fd_set in sys/types" >&5
+$as_echo_n "checking for fd_set in sys/types... " >&6; }
+if ${tcl_cv_type_fd_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+fd_set readMask, writeMask;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_type_fd_set=yes
+else
+ tcl_cv_type_fd_set=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_fd_set" >&5
+$as_echo "$tcl_cv_type_fd_set" >&6; }
+tcl_ok=$tcl_cv_type_fd_set
+if test $tcl_ok = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fd_mask in sys/select" >&5
+$as_echo_n "checking for fd_mask in sys/select... " >&6; }
+if ${tcl_cv_grep_fd_mask+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/select.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "fd_mask" >/dev/null 2>&1; then :
+ tcl_cv_grep_fd_mask=present
+else
+ tcl_cv_grep_fd_mask=missing
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_fd_mask" >&5
+$as_echo "$tcl_cv_grep_fd_mask" >&6; }
+ if test $tcl_cv_grep_fd_mask = present; then
+
+$as_echo "#define HAVE_SYS_SELECT_H 1" >>confdefs.h
+
+ tcl_ok=yes
+ fi
+fi
+if test $tcl_ok = no; then
+
+$as_echo "#define NO_FD_SET 1" >>confdefs.h
+
+fi
+
+#------------------------------------------------------------------------
+# Options for the notifier. Checks for epoll(7) on Linux, and
+# kqueue(2) on {DragonFly,Free,Net,Open}BSD
+#------------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for advanced notifier support" >&5
+$as_echo_n "checking for advanced notifier support... " >&6; }
+case x`uname -s` in
+ xLinux)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: epoll(7)" >&5
+$as_echo "epoll(7)" >&6; }
+ for ac_header in sys/epoll.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/epoll.h" "ac_cv_header_sys_epoll_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_epoll_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_EPOLL_H 1
+_ACEOF
+
+$as_echo "#define NOTIFIER_EPOLL 1" >>confdefs.h
+
+fi
+
+done
+
+ for ac_header in sys/eventfd.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/eventfd.h" "ac_cv_header_sys_eventfd_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_eventfd_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_EVENTFD_H 1
+_ACEOF
+
+$as_echo "#define HAVE_EVENTFD 1" >>confdefs.h
+
+fi
+
+done
+;;
+ xDragonFlyBSD|xFreeBSD|xNetBSD|xOpenBSD)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: kqueue(2)" >&5
+$as_echo "kqueue(2)" >&6; }
+ # Messy because we want to check if *all* the headers are present, and not
+ # just *any*
+ tcl_kqueue_headers=x
+ for ac_header in sys/types.h sys/event.h sys/time.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ tcl_kqueue_headers=${tcl_kqueue_headers}y
+fi
+
+done
+
+ if test $tcl_kqueue_headers = xyyy; then :
+
+
+$as_echo "#define NOTIFIER_KQUEUE 1" >>confdefs.h
+
+fi;;
+ xDarwin)
+ # Assume that we've got CoreFoundation present (checked elsewhere because
+ # of wider impact).
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: OSX" >&5
+$as_echo "OSX" >&6; };;
+ *)
+ cat >>confdefs.h <<_ACEOF
+#define NOTIFIER_SELECT 1
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; };;
+esac
+
+#------------------------------------------------------------------------------
+# Find out all about time handling differences.
+#------------------------------------------------------------------------------
+
+
+ for ac_header in sys/time.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_time_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_TIME_H 1
+_ACEOF
+
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
+$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
+if ${ac_cv_header_time+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_time=yes
+else
+ ac_cv_header_time=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
+$as_echo "$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
+
+fi
+
+
+ for ac_func in gmtime_r localtime_r mktime
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking tm_tzadj in struct tm" >&5
+$as_echo_n "checking tm_tzadj in struct tm... " >&6; }
+if ${tcl_cv_member_tm_tzadj+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <time.h>
+int
+main ()
+{
+struct tm tm; tm.tm_tzadj;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_member_tm_tzadj=yes
+else
+ tcl_cv_member_tm_tzadj=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_member_tm_tzadj" >&5
+$as_echo "$tcl_cv_member_tm_tzadj" >&6; }
+ if test $tcl_cv_member_tm_tzadj = yes ; then
+
+$as_echo "#define HAVE_TM_TZADJ 1" >>confdefs.h
+
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking tm_gmtoff in struct tm" >&5
+$as_echo_n "checking tm_gmtoff in struct tm... " >&6; }
+if ${tcl_cv_member_tm_gmtoff+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <time.h>
+int
+main ()
+{
+struct tm tm; tm.tm_gmtoff;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_member_tm_gmtoff=yes
+else
+ tcl_cv_member_tm_gmtoff=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_member_tm_gmtoff" >&5
+$as_echo "$tcl_cv_member_tm_gmtoff" >&6; }
+ if test $tcl_cv_member_tm_gmtoff = yes ; then
+
+$as_echo "#define HAVE_TM_GMTOFF 1" >>confdefs.h
+
+ fi
+
+ #
+ # Its important to include time.h in this check, as some systems
+ # (like convex) have timezone functions, etc.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking long timezone variable" >&5
+$as_echo_n "checking long timezone variable... " >&6; }
+if ${tcl_cv_timezone_long+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <time.h>
+int
+main ()
+{
+extern long timezone;
+ timezone += 1;
+ exit (0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_timezone_long=yes
+else
+ tcl_cv_timezone_long=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_timezone_long" >&5
+$as_echo "$tcl_cv_timezone_long" >&6; }
+ if test $tcl_cv_timezone_long = yes ; then
+
+$as_echo "#define HAVE_TIMEZONE_VAR 1" >>confdefs.h
+
+ else
+ #
+ # On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking time_t timezone variable" >&5
+$as_echo_n "checking time_t timezone variable... " >&6; }
+if ${tcl_cv_timezone_time+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <time.h>
+int
+main ()
+{
+extern time_t timezone;
+ timezone += 1;
+ exit (0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_timezone_time=yes
+else
+ tcl_cv_timezone_time=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_timezone_time" >&5
+$as_echo "$tcl_cv_timezone_time" >&6; }
+ if test $tcl_cv_timezone_time = yes ; then
+
+$as_echo "#define HAVE_TIMEZONE_VAR 1" >>confdefs.h
+
+ fi
+ fi
+
+
+#--------------------------------------------------------------------
+# Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
+# we might be able to use fstatfs instead. Some systems (OpenBSD?) also
+# lack blkcnt_t.
+#--------------------------------------------------------------------
+
+if test "$ac_cv_cygwin" != "yes"; then
+ ac_fn_c_check_member "$LINENO" "struct stat" "st_blocks" "ac_cv_member_struct_stat_st_blocks" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_blocks" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_blksize" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+_ACEOF
+
+
+fi
+
+fi
+ac_fn_c_check_type "$LINENO" "blkcnt_t" "ac_cv_type_blkcnt_t" "$ac_includes_default"
+if test "x$ac_cv_type_blkcnt_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_BLKCNT_T 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_func "$LINENO" "fstatfs" "ac_cv_func_fstatfs"
+if test "x$ac_cv_func_fstatfs" = xyes; then :
+
+else
+
+$as_echo "#define NO_FSTATFS 1" >>confdefs.h
+
+fi
+
+
+#--------------------------------------------------------------------
+# Some system have no memcmp or it does not work with 8 bit data, this
+# checks it and add memcmp.o to LIBOBJS if needed
+#--------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5
+$as_echo_n "checking for working memcmp... " >&6; }
+if ${ac_cv_func_memcmp_working+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_memcmp_working=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Some versions of memcmp are not 8-bit clean. */
+ char c0 = '\100', c1 = '\200', c2 = '\201';
+ if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0)
+ return 1;
+
+ /* The Next x86 OpenStep bug shows up only when comparing 16 bytes
+ or more and with at least one buffer not starting on a 4-byte boundary.
+ William Lewis provided this test program. */
+ {
+ char foo[21];
+ char bar[21];
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ char *a = foo + i;
+ char *b = bar + i;
+ strcpy (a, "--------01111111");
+ strcpy (b, "--------10000000");
+ if (memcmp (a, b, 16) >= 0)
+ return 1;
+ }
+ return 0;
+ }
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_memcmp_working=yes
+else
+ ac_cv_func_memcmp_working=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5
+$as_echo "$ac_cv_func_memcmp_working" >&6; }
+test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in
+ *" memcmp.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS memcmp.$ac_objext"
+ ;;
+esac
+
+
+
+#--------------------------------------------------------------------
+# Some system like SunOS 4 and other BSD like systems have no memmove
+# (we assume they have bcopy instead). {The replacement define is in
+# compat/string.h}
+#--------------------------------------------------------------------
+
+ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove"
+if test "x$ac_cv_func_memmove" = xyes; then :
+
+else
+
+
+$as_echo "#define NO_MEMMOVE 1" >>confdefs.h
+
+
+$as_echo "#define NO_STRING_H 1" >>confdefs.h
+
+fi
+
+
+#--------------------------------------------------------------------
+# On some systems strstr is broken: it returns a pointer even even if
+# the original string is empty.
+#--------------------------------------------------------------------
+
+
+ ac_fn_c_check_func "$LINENO" "strstr" "ac_cv_func_strstr"
+if test "x$ac_cv_func_strstr" = xyes; then :
+ tcl_ok=1
+else
+ tcl_ok=0
+fi
+
+ if test "$tcl_ok" = 1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking proper strstr implementation" >&5
+$as_echo_n "checking proper strstr implementation... " >&6; }
+if ${tcl_cv_strstr_unbroken+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ tcl_cv_strstr_unbroken=unknown
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main() {
+ extern int strstr();
+ exit(strstr("\0test", "test") ? 1 : 0);
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ tcl_cv_strstr_unbroken=ok
+else
+ tcl_cv_strstr_unbroken=broken
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strstr_unbroken" >&5
+$as_echo "$tcl_cv_strstr_unbroken" >&6; }
+ if test "$tcl_cv_strstr_unbroken" = "ok"; then
+ tcl_ok=1
+ else
+ tcl_ok=0
+ fi
+ fi
+ if test "$tcl_ok" = 0; then
+ case " $LIBOBJS " in
+ *" strstr.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strstr.$ac_objext"
+ ;;
+esac
+
+ USE_COMPAT=1
+ fi
+
+
+#--------------------------------------------------------------------
+# Check for strtoul function. This is tricky because under some
+# versions of AIX strtoul returns an incorrect terminator
+# pointer for the string "0".
+#--------------------------------------------------------------------
+
+
+ ac_fn_c_check_func "$LINENO" "strtoul" "ac_cv_func_strtoul"
+if test "x$ac_cv_func_strtoul" = xyes; then :
+ tcl_ok=1
+else
+ tcl_ok=0
+fi
+
+ if test "$tcl_ok" = 1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking proper strtoul implementation" >&5
+$as_echo_n "checking proper strtoul implementation... " >&6; }
+if ${tcl_cv_strtoul_unbroken+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ tcl_cv_strtoul_unbroken=unknown
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main() {
+ extern int strtoul();
+ char *term, *string = "0";
+ exit(strtoul(string,&term,0) != 0 || term != string+1);
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ tcl_cv_strtoul_unbroken=ok
+else
+ tcl_cv_strtoul_unbroken=broken
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strtoul_unbroken" >&5
+$as_echo "$tcl_cv_strtoul_unbroken" >&6; }
+ if test "$tcl_cv_strtoul_unbroken" = "ok"; then
+ tcl_ok=1
+ else
+ tcl_ok=0
+ fi
+ fi
+ if test "$tcl_ok" = 0; then
+ case " $LIBOBJS " in
+ *" strtoul.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strtoul.$ac_objext"
+ ;;
+esac
+
+ USE_COMPAT=1
+ fi
+
+
+#--------------------------------------------------------------------
+# Check for the strtod function. This is tricky because in some
+# versions of Linux strtod mis-parses strings starting with "+".
+#--------------------------------------------------------------------
+
+
+ ac_fn_c_check_func "$LINENO" "strtod" "ac_cv_func_strtod"
+if test "x$ac_cv_func_strtod" = xyes; then :
+ tcl_ok=1
+else
+ tcl_ok=0
+fi
+
+ if test "$tcl_ok" = 1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking proper strtod implementation" >&5
+$as_echo_n "checking proper strtod implementation... " >&6; }
+if ${tcl_cv_strtod_unbroken+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ tcl_cv_strtod_unbroken=unknown
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main() {
+ extern double strtod();
+ char *term, *string = " +69";
+ exit(strtod(string,&term) != 69 || term != string+4);
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ tcl_cv_strtod_unbroken=ok
+else
+ tcl_cv_strtod_unbroken=broken
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strtod_unbroken" >&5
+$as_echo "$tcl_cv_strtod_unbroken" >&6; }
+ if test "$tcl_cv_strtod_unbroken" = "ok"; then
+ tcl_ok=1
+ else
+ tcl_ok=0
+ fi
+ fi
+ if test "$tcl_ok" = 0; then
+ case " $LIBOBJS " in
+ *" strtod.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strtod.$ac_objext"
+ ;;
+esac
+
+ USE_COMPAT=1
+ fi
+
+
+#--------------------------------------------------------------------
+# 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" that corrects the error.
+#--------------------------------------------------------------------
+
+
+ ac_fn_c_check_func "$LINENO" "strtod" "ac_cv_func_strtod"
+if test "x$ac_cv_func_strtod" = xyes; then :
+ tcl_strtod=1
+else
+ tcl_strtod=0
+fi
+
+ if test "$tcl_strtod" = 1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris2.4/Tru64 strtod bugs" >&5
+$as_echo_n "checking for Solaris2.4/Tru64 strtod bugs... " >&6; }
+if ${tcl_cv_strtod_buggy+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ if test "$cross_compiling" = yes; then :
+ tcl_cv_strtod_buggy=buggy
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ extern double strtod();
+ int main() {
+ char *infString="Inf", *nanString="NaN", *spaceString=" ";
+ char *term;
+ double value;
+ value = strtod(infString, &term);
+ if ((term != infString) && (term[-1] == 0)) {
+ exit(1);
+ }
+ value = strtod(nanString, &term);
+ if ((term != nanString) && (term[-1] == 0)) {
+ exit(1);
+ }
+ value = strtod(spaceString, &term);
+ if (term == (spaceString+1)) {
+ exit(1);
+ }
+ exit(0);
+ }
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ tcl_cv_strtod_buggy=ok
+else
+ tcl_cv_strtod_buggy=buggy
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strtod_buggy" >&5
+$as_echo "$tcl_cv_strtod_buggy" >&6; }
+ if test "$tcl_cv_strtod_buggy" = buggy; then
+ case " $LIBOBJS " in
+ *" fixstrtod.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS fixstrtod.$ac_objext"
+ ;;
+esac
+
+ USE_COMPAT=1
+
+$as_echo "#define strtod fixstrtod" >>confdefs.h
+
+ fi
+ fi
+
+
+#--------------------------------------------------------------------
+# Check for various typedefs and provide substitutes if
+# they don't exist.
+#--------------------------------------------------------------------
+
+ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default"
+if test "x$ac_cv_type_mode_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define mode_t int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
+if test "x$ac_cv_type_pid_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5
+$as_echo_n "checking for uid_t in sys/types.h... " >&6; }
+if ${ac_cv_type_uid_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "uid_t" >/dev/null 2>&1; then :
+ ac_cv_type_uid_t=yes
+else
+ ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5
+$as_echo "$ac_cv_type_uid_t" >&6; }
+if test $ac_cv_type_uid_t = no; then
+
+$as_echo "#define uid_t int" >>confdefs.h
+
+
+$as_echo "#define gid_t int" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5
+$as_echo_n "checking for socklen_t... " >&6; }
+if ${tcl_cv_type_socklen_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <sys/socket.h>
+
+int
+main ()
+{
+
+ socklen_t foo;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_type_socklen_t=yes
+else
+ tcl_cv_type_socklen_t=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_socklen_t" >&5
+$as_echo "$tcl_cv_type_socklen_t" >&6; }
+if test $tcl_cv_type_socklen_t = no; then
+
+$as_echo "#define socklen_t int" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default"
+if test "x$ac_cv_type_intptr_t" = xyes; then :
+
+
+$as_echo "#define HAVE_INTPTR_T 1" >>confdefs.h
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pointer-size signed integer type" >&5
+$as_echo_n "checking for pointer-size signed integer type... " >&6; }
+if ${tcl_cv_intptr_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ for tcl_cv_intptr_t in "int" "long" "long long" none; do
+ if test "$tcl_cv_intptr_t" != none; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_intptr_t))];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$tcl_ok" = yes && break; fi
+ done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_intptr_t" >&5
+$as_echo "$tcl_cv_intptr_t" >&6; }
+ if test "$tcl_cv_intptr_t" != none; then
+
+cat >>confdefs.h <<_ACEOF
+#define intptr_t $tcl_cv_intptr_t
+_ACEOF
+
+ fi
+
+fi
+
+ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default"
+if test "x$ac_cv_type_uintptr_t" = xyes; then :
+
+
+$as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pointer-size unsigned integer type" >&5
+$as_echo_n "checking for pointer-size unsigned integer type... " >&6; }
+if ${tcl_cv_uintptr_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
+ none; do
+ if test "$tcl_cv_uintptr_t" != none; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$tcl_ok" = yes && break; fi
+ done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_uintptr_t" >&5
+$as_echo "$tcl_cv_uintptr_t" >&6; }
+ if test "$tcl_cv_uintptr_t" != none; then
+
+cat >>confdefs.h <<_ACEOF
+#define uintptr_t $tcl_cv_uintptr_t
+_ACEOF
+
+ fi
+
+fi
+
+
+#--------------------------------------------------------------------
+# If a system doesn't have an opendir function (man, that's old!)
+# then we have to supply a different version of dirent.h which
+# is compatible with the substitute version of opendir that's
+# provided. This version only works with V7-style directories.
+#--------------------------------------------------------------------
+
+ac_fn_c_check_func "$LINENO" "opendir" "ac_cv_func_opendir"
+if test "x$ac_cv_func_opendir" = xyes; then :
+
+else
+
+$as_echo "#define USE_DIRENT2_H 1" >>confdefs.h
+
+fi
+
+
+#--------------------------------------------------------------------
+# The check below checks whether <sys/wait.h> defines the type
+# "union wait" correctly. It's needed because of weirdness in
+# HP-UX where "union wait" is defined in both the BSD and SYS-V
+# environments. Checking the usability of WIFEXITED seems to do
+# the trick.
+#--------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking union wait" >&5
+$as_echo_n "checking union wait... " >&6; }
+if ${tcl_cv_union_wait+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/wait.h>
+int
+main ()
+{
+
+union wait x;
+WIFEXITED(x); /* Generates compiler error if WIFEXITED
+ * uses an int. */
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_union_wait=yes
+else
+ tcl_cv_union_wait=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_union_wait" >&5
+$as_echo "$tcl_cv_union_wait" >&6; }
+if test $tcl_cv_union_wait = no; then
+
+$as_echo "#define NO_UNION_WAIT 1" >>confdefs.h
+
+fi
+
+#--------------------------------------------------------------------
+# Check whether there is an strncasecmp function on this system.
+# This is a bit tricky because under SCO it's in -lsocket and
+# under Sequent Dynix it's in -linet.
+#--------------------------------------------------------------------
+
+ac_fn_c_check_func "$LINENO" "strncasecmp" "ac_cv_func_strncasecmp"
+if test "x$ac_cv_func_strncasecmp" = xyes; then :
+ tcl_ok=1
+else
+ tcl_ok=0
+fi
+
+if test "$tcl_ok" = 0; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strncasecmp in -lsocket" >&5
+$as_echo_n "checking for strncasecmp in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_strncasecmp+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strncasecmp ();
+int
+main ()
+{
+return strncasecmp ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_socket_strncasecmp=yes
+else
+ ac_cv_lib_socket_strncasecmp=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_strncasecmp" >&5
+$as_echo "$ac_cv_lib_socket_strncasecmp" >&6; }
+if test "x$ac_cv_lib_socket_strncasecmp" = xyes; then :
+ tcl_ok=1
+else
+ tcl_ok=0
+fi
+
+fi
+if test "$tcl_ok" = 0; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strncasecmp in -linet" >&5
+$as_echo_n "checking for strncasecmp in -linet... " >&6; }
+if ${ac_cv_lib_inet_strncasecmp+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-linet $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strncasecmp ();
+int
+main ()
+{
+return strncasecmp ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_inet_strncasecmp=yes
+else
+ ac_cv_lib_inet_strncasecmp=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_strncasecmp" >&5
+$as_echo "$ac_cv_lib_inet_strncasecmp" >&6; }
+if test "x$ac_cv_lib_inet_strncasecmp" = xyes; then :
+ tcl_ok=1
+else
+ tcl_ok=0
+fi
+
+fi
+if test "$tcl_ok" = 0; then
+ case " $LIBOBJS " in
+ *" strncasecmp.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strncasecmp.$ac_objext"
+ ;;
+esac
+
+ USE_COMPAT=1
+fi
+
+#--------------------------------------------------------------------
+# The code below deals with several issues related to gettimeofday:
+# 1. Some systems don't provide a gettimeofday function at all
+# (set NO_GETTOD if this is the case).
+# 2. See if gettimeofday is declared in the <sys/time.h> header file.
+# if not, set the GETTOD_NOT_DECLARED flag so that tclPort.h can
+# declare it.
+#--------------------------------------------------------------------
+
+ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
+if test "x$ac_cv_func_gettimeofday" = xyes; then :
+
+else
+
+
+$as_echo "#define NO_GETTOD 1" >>confdefs.h
+
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gettimeofday declaration" >&5
+$as_echo_n "checking for gettimeofday declaration... " >&6; }
+if ${tcl_cv_grep_gettimeofday+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/time.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "gettimeofday" >/dev/null 2>&1; then :
+ tcl_cv_grep_gettimeofday=present
+else
+ tcl_cv_grep_gettimeofday=missing
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_gettimeofday" >&5
+$as_echo "$tcl_cv_grep_gettimeofday" >&6; }
+if test $tcl_cv_grep_gettimeofday = missing ; then
+
+$as_echo "#define GETTOD_NOT_DECLARED 1" >>confdefs.h
+
+fi
+
+#--------------------------------------------------------------------
+# The following code checks to see whether it is possible to get
+# signed chars on this platform. This is needed in order to
+# properly generate sign-extended ints from character values.
+#--------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5
+$as_echo_n "checking whether char is unsigned... " >&6; }
+if ${ac_cv_c_char_unsigned+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((char) -1) < 0)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_char_unsigned=no
+else
+ ac_cv_c_char_unsigned=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_char_unsigned" >&5
+$as_echo "$ac_cv_c_char_unsigned" >&6; }
+if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
+ $as_echo "#define __CHAR_UNSIGNED__ 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking signed char declarations" >&5
+$as_echo_n "checking signed char declarations... " >&6; }
+if ${tcl_cv_char_signed+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ signed char *p;
+ p = 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_char_signed=yes
+else
+ tcl_cv_char_signed=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_char_signed" >&5
+$as_echo "$tcl_cv_char_signed" >&6; }
+if test $tcl_cv_char_signed = yes; then
+
+$as_echo "#define HAVE_SIGNED_CHAR 1" >>confdefs.h
+
+fi
+
+#--------------------------------------------------------------------
+# Does putenv() copy or not? We need to know to avoid memory leaks.
+#--------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a putenv() that copies the buffer" >&5
+$as_echo_n "checking for a putenv() that copies the buffer... " >&6; }
+if ${tcl_cv_putenv_copy+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ if test "$cross_compiling" = yes; then :
+ tcl_cv_putenv_copy=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <stdlib.h>
+ #define OURVAR "havecopy=yes"
+ int main (int argc, char *argv[])
+ {
+ char *foo, *bar;
+ foo = (char *)strdup(OURVAR);
+ putenv(foo);
+ strcpy((char *)(strchr(foo, '=') + 1), "no");
+ bar = getenv("havecopy");
+ if (!strcmp(bar, "no")) {
+ /* doesnt copy */
+ return 0;
+ } else {
+ /* does copy */
+ return 1;
+ }
+ }
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ tcl_cv_putenv_copy=no
+else
+ tcl_cv_putenv_copy=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_putenv_copy" >&5
+$as_echo "$tcl_cv_putenv_copy" >&6; }
+if test $tcl_cv_putenv_copy = yes; then
+
+$as_echo "#define HAVE_PUTENV_THAT_COPIES 1" >>confdefs.h
+
+fi
+
+#--------------------------------------------------------------------
+# Check for support of nl_langinfo function
+#--------------------------------------------------------------------
+
+
+ # Check whether --enable-langinfo was given.
+if test "${enable_langinfo+set}" = set; then :
+ enableval=$enable_langinfo; langinfo_ok=$enableval
+else
+ langinfo_ok=yes
+fi
+
+
+ HAVE_LANGINFO=0
+ if test "$langinfo_ok" = "yes"; then
+ ac_fn_c_check_header_mongrel "$LINENO" "langinfo.h" "ac_cv_header_langinfo_h" "$ac_includes_default"
+if test "x$ac_cv_header_langinfo_h" = xyes; then :
+ langinfo_ok=yes
+else
+ langinfo_ok=no
+fi
+
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use nl_langinfo" >&5
+$as_echo_n "checking whether to use nl_langinfo... " >&6; }
+ if test "$langinfo_ok" = "yes"; then
+ if ${tcl_cv_langinfo_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <langinfo.h>
+int
+main ()
+{
+nl_langinfo(CODESET);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_langinfo_h=yes
+else
+ tcl_cv_langinfo_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_langinfo_h" >&5
+$as_echo "$tcl_cv_langinfo_h" >&6; }
+ if test $tcl_cv_langinfo_h = yes; then
+
+$as_echo "#define HAVE_LANGINFO 1" >>confdefs.h
+
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $langinfo_ok" >&5
+$as_echo "$langinfo_ok" >&6; }
+ fi
+
+
+#--------------------------------------------------------------------
+# Check for support of chflags and mkstemps functions
+#--------------------------------------------------------------------
+
+for ac_func in chflags mkstemps
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+#--------------------------------------------------------------------
+# Check for support of isnan() function or macro
+#--------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking isnan" >&5
+$as_echo_n "checking isnan... " >&6; }
+if ${tcl_cv_isnan+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <math.h>
+int
+main ()
+{
+
+isnan(0.0); /* Generates an error if isnan is missing */
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_isnan=yes
+else
+ tcl_cv_isnan=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_isnan" >&5
+$as_echo "$tcl_cv_isnan" >&6; }
+if test $tcl_cv_isnan = no; then
+
+$as_echo "#define NO_ISNAN 1" >>confdefs.h
+
+fi
+
+#--------------------------------------------------------------------
+# Darwin specific API checks and defines
+#--------------------------------------------------------------------
+
+if test "`uname -s`" = "Darwin" ; then
+ for ac_func in getattrlist
+do :
+ ac_fn_c_check_func "$LINENO" "getattrlist" "ac_cv_func_getattrlist"
+if test "x$ac_cv_func_getattrlist" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GETATTRLIST 1
+_ACEOF
+
+fi
+done
+
+ for ac_header in copyfile.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "copyfile.h" "ac_cv_header_copyfile_h" "$ac_includes_default"
+if test "x$ac_cv_header_copyfile_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_COPYFILE_H 1
+_ACEOF
+
+fi
+
+done
+
+ for ac_func in copyfile
+do :
+ ac_fn_c_check_func "$LINENO" "copyfile" "ac_cv_func_copyfile"
+if test "x$ac_cv_func_copyfile" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_COPYFILE 1
+_ACEOF
+
+fi
+done
+
+ if test $tcl_corefoundation = yes; then
+ for ac_header in libkern/OSAtomic.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "libkern/OSAtomic.h" "ac_cv_header_libkern_OSAtomic_h" "$ac_includes_default"
+if test "x$ac_cv_header_libkern_OSAtomic_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBKERN_OSATOMIC_H 1
+_ACEOF
+
+fi
+
+done
+
+ for ac_func in OSSpinLockLock
+do :
+ ac_fn_c_check_func "$LINENO" "OSSpinLockLock" "ac_cv_func_OSSpinLockLock"
+if test "x$ac_cv_func_OSSpinLockLock" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_OSSPINLOCKLOCK 1
+_ACEOF
+
+fi
+done
+
+ fi
+
+$as_echo "#define USE_VFORK 1" >>confdefs.h
+
+
+$as_echo "#define TCL_DEFAULT_ENCODING \"utf-8\"" >>confdefs.h
+
+
+$as_echo "#define TCL_LOAD_FROM_MEMORY 1" >>confdefs.h
+
+
+$as_echo "#define TCL_WIDE_CLICKS 1" >>confdefs.h
+
+ for ac_header in AvailabilityMacros.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "AvailabilityMacros.h" "ac_cv_header_AvailabilityMacros_h" "$ac_includes_default"
+if test "x$ac_cv_header_AvailabilityMacros_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_AVAILABILITYMACROS_H 1
+_ACEOF
+
+fi
+
+done
+
+ if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if weak import is available" >&5
+$as_echo_n "checking if weak import is available... " >&6; }
+if ${tcl_cv_cc_weak_import+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
+ #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
+ #endif
+ #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020
+ #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020
+ #endif
+ int rand(void) __attribute__((weak_import));
+
+int
+main ()
+{
+rand();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_cc_weak_import=yes
+else
+ tcl_cv_cc_weak_import=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_weak_import" >&5
+$as_echo "$tcl_cv_cc_weak_import" >&6; }
+ if test $tcl_cv_cc_weak_import = yes; then
+
+$as_echo "#define HAVE_WEAK_IMPORT 1" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Darwin SUSv3 extensions are available" >&5
+$as_echo_n "checking if Darwin SUSv3 extensions are available... " >&6; }
+if ${tcl_cv_cc_darwin_c_source+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
+ #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
+ #endif
+ #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ #endif
+ #define _DARWIN_C_SOURCE 1
+ #include <sys/cdefs.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_cc_darwin_c_source=yes
+else
+ tcl_cv_cc_darwin_c_source=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_darwin_c_source" >&5
+$as_echo "$tcl_cv_cc_darwin_c_source" >&6; }
+ if test $tcl_cv_cc_darwin_c_source = yes; then
+
+$as_echo "#define _DARWIN_C_SOURCE 1" >>confdefs.h
+
+ fi
+ fi
+ # Build .bundle dltest binaries in addition to .dylib
+ DLTEST_LD='${CC} -bundle -Wl,-w ${CFLAGS} ${LDFLAGS}'
+ DLTEST_SUFFIX=".bundle"
+else
+ DLTEST_LD='${SHLIB_LD}'
+ DLTEST_SUFFIX=""
+fi
+
+#--------------------------------------------------------------------
+# Check for support of fts functions (readdir replacement)
+#--------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fts" >&5
+$as_echo_n "checking for fts... " >&6; }
+if ${tcl_cv_api_fts+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/param.h>
+ #include <sys/stat.h>
+ #include <fts.h>
+
+int
+main ()
+{
+
+ char*const p[2] = {"/", NULL};
+ FTS *f = fts_open(p, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL);
+ FTSENT *e = fts_read(f); fts_close(f);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_api_fts=yes
+else
+ tcl_cv_api_fts=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_fts" >&5
+$as_echo "$tcl_cv_api_fts" >&6; }
+if test $tcl_cv_api_fts = yes; then
+
+$as_echo "#define HAVE_FTS 1" >>confdefs.h
+
+fi
+
+#--------------------------------------------------------------------
+# 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.
+#--------------------------------------------------------------------
+
+
+ for ac_header in sys/ioctl.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_ioctl_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_IOCTL_H 1
+_ACEOF
+
+fi
+
+done
+
+ for ac_header in sys/filio.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/filio.h" "ac_cv_header_sys_filio_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_filio_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_FILIO_H 1
+_ACEOF
+
+fi
+
+done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5
+$as_echo_n "checking system version... " >&6; }
+if ${tcl_cv_sys_version+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ tcl_cv_sys_version=windows
+ else
+ tcl_cv_sys_version=`uname -s`-`uname -r`
+ if test "$?" -ne 0 ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5
+$as_echo "$as_me: WARNING: can't find uname command" >&2;}
+ tcl_cv_sys_version=unknown
+ else
+ if test "`uname -s`" = "AIX" ; then
+ tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
+ fi
+ fi
+ fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5
+$as_echo "$tcl_cv_sys_version" >&6; }
+ system=$tcl_cv_sys_version
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking FIONBIO vs. O_NONBLOCK for nonblocking I/O" >&5
+$as_echo_n "checking FIONBIO vs. O_NONBLOCK for nonblocking I/O... " >&6; }
+ case $system in
+ OSF*)
+
+$as_echo "#define USE_FIONBIO 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: FIONBIO" >&5
+$as_echo "FIONBIO" >&6; }
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: O_NONBLOCK" >&5
+$as_echo "O_NONBLOCK" >&6; }
+ ;;
+ esac
+
+
+#------------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use dll unloading" >&5
+$as_echo_n "checking whether to use dll unloading... " >&6; }
+# Check whether --enable-dll-unloading was given.
+if test "${enable_dll_unloading+set}" = set; then :
+ enableval=$enable_dll_unloading; tcl_ok=$enableval
+else
+ tcl_ok=yes
+fi
+
+if test $tcl_ok = yes; then
+
+$as_echo "#define TCL_UNLOAD_DLLS 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_ok" >&5
+$as_echo "$tcl_ok" >&6; }
+
+#------------------------------------------------------------------------
+# Check whether the timezone data is supplied by the OS or has
+# to be installed by Tcl. The default is autodetection, but can
+# be overriden on the configure command line either way.
+#------------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for timezone data" >&5
+$as_echo_n "checking for timezone data... " >&6; }
+
+# Check whether --with-tzdata was given.
+if test "${with_tzdata+set}" = set; then :
+ withval=$with_tzdata; tcl_ok=$withval
+else
+ tcl_ok=auto
+fi
+
+#
+# Any directories that get added here must also be added to the
+# search path in ::tcl::clock::Initialize (library/clock.tcl).
+#
+case $tcl_ok in
+ no)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: supplied by OS vendor" >&5
+$as_echo "supplied by OS vendor" >&6; }
+ ;;
+ yes)
+ # nothing to do here
+ ;;
+ auto*)
+ if ${tcl_cv_dir_zoneinfo+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ for dir in /usr/share/zoneinfo \
+ /usr/share/lib/zoneinfo \
+ /usr/lib/zoneinfo
+ do
+ if test -f $dir/UTC -o -f $dir/GMT
+ then
+ tcl_cv_dir_zoneinfo="$dir"
+ break
+ fi
+ done
+fi
+
+ if test -n "$tcl_cv_dir_zoneinfo"; then
+ tcl_ok=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dir" >&5
+$as_echo "$dir" >&6; }
+ else
+ tcl_ok=yes
+ fi
+ ;;
+ *)
+ as_fn_error $? "invalid argument: $tcl_ok" "$LINENO" 5
+ ;;
+esac
+if test $tcl_ok = yes
+then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: supplied by Tcl" >&5
+$as_echo "supplied by Tcl" >&6; }
+ INSTALL_TZDATA=install-tzdata
+fi
+
+#--------------------------------------------------------------------
+# DTrace support
+#--------------------------------------------------------------------
+
+# Check whether --enable-dtrace was given.
+if test "${enable_dtrace+set}" = set; then :
+ enableval=$enable_dtrace; tcl_ok=$enableval
+else
+ tcl_ok=no
+fi
+
+if test $tcl_ok = yes; then
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/sdt.h" "ac_cv_header_sys_sdt_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_sdt_h" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+
+fi
+if test $tcl_ok = yes; then
+ # Extract the first word of "dtrace", so it can be a program name with args.
+set dummy dtrace; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_DTRACE+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $DTRACE in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="$PATH:/usr/sbin"
+for as_dir in $as_dummy
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+DTRACE=$ac_cv_path_DTRACE
+if test -n "$DTRACE"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5
+$as_echo "$DTRACE" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -z "$ac_cv_path_DTRACE" && tcl_ok=no
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable DTrace support" >&5
+$as_echo_n "checking whether to enable DTrace support... " >&6; }
+MAKEFILE_SHELL='/bin/sh'
+if test $tcl_ok = yes; then
+
+$as_echo "#define USE_DTRACE 1" >>confdefs.h
+
+ DTRACE_SRC="\${DTRACE_SRC}"
+ DTRACE_HDR="\${DTRACE_HDR}"
+ if test "`uname -s`" != "Darwin" ; then
+ DTRACE_OBJ="\${DTRACE_OBJ}"
+ if test "`uname -s`" = "SunOS" -a "$SHARED_BUILD" = "0" ; then
+ # Need to create an intermediate object file to ensure tclDTrace.o
+ # gets included when linking against the static tcl library.
+ STLIB_LD='stlib_ld () { /usr/ccs/bin/ld -r -o $${1%.a}.o "$${@:2}" && '"${STLIB_LD}"' $${1} $${1%.a}.o ; } && stlib_ld'
+ MAKEFILE_SHELL='/bin/bash'
+ # Force use of Sun ar and ranlib, the GNU versions choke on
+ # tclDTrace.o and the combined object file above.
+ AR='/usr/ccs/bin/ar'
+ RANLIB='/usr/ccs/bin/ranlib'
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_ok" >&5
+$as_echo "$tcl_ok" >&6; }
+
+#--------------------------------------------------------------------
+# The check below checks whether the cpuid instruction is usable.
+#--------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the cpuid instruction is usable" >&5
+$as_echo_n "checking whether the cpuid instruction is usable... " >&6; }
+if ${tcl_cv_cpuid+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ int index,regsPtr[4];
+ __asm__ __volatile__("mov %%ebx, %%edi \n\t"
+ "cpuid \n\t"
+ "mov %%ebx, %%esi \n\t"
+ "mov %%edi, %%ebx \n\t"
+ : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
+ : "a"(index) : "edi");
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_cpuid=yes
+else
+ tcl_cv_cpuid=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cpuid" >&5
+$as_echo "$tcl_cv_cpuid" >&6; }
+if test $tcl_cv_cpuid = yes; then
+
+$as_echo "#define HAVE_CPUID 1" >>confdefs.h
+
+fi
+
+#--------------------------------------------------------------------
+# The statements below define a collection of symbols related to
+# building libtcl as a shared library instead of a static library.
+#--------------------------------------------------------------------
+
+TCL_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
+TCL_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}
+eval "TCL_LIB_FILE=libtcl${LIB_SUFFIX}"
+
+# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
+# since on some platforms TCL_LIB_FILE contains shell escapes.
+# (See also: TCL_TRIM_DOTS).
+
+eval "TCL_LIB_FILE=${TCL_LIB_FILE}"
+
+TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)'
+PRIVATE_INCLUDE_DIR='$(includedir)'
+HTML_DIR='$(DISTDIR)/html'
+
+# Note: in the following variable, it's important to use the absolute
+# path name of the Tcl directory rather than "..": this is because
+# AIX remembers this path and will attempt to use it at run-time to look
+# up the Tcl library.
+
+if test "`uname -s`" = "Darwin" ; then
+
+ if test "`uname -s`" = "Darwin" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to package libraries" >&5
+$as_echo_n "checking how to package libraries... " >&6; }
+ # Check whether --enable-framework was given.
+if test "${enable_framework+set}" = set; then :
+ enableval=$enable_framework; enable_framework=$enableval
+else
+ enable_framework=no
+fi
+
+ if test $enable_framework = yes; then
+ if test $SHARED_BUILD = 0; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Frameworks can only be built if --enable-shared is yes" >&5
+$as_echo "$as_me: WARNING: Frameworks can only be built if --enable-shared is yes" >&2;}
+ enable_framework=no
+ fi
+ if test $tcl_corefoundation = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Frameworks can only be used when CoreFoundation is available" >&5
+$as_echo "$as_me: WARNING: Frameworks can only be used when CoreFoundation is available" >&2;}
+ enable_framework=no
+ fi
+ fi
+ if test $enable_framework = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: framework" >&5
+$as_echo "framework" >&6; }
+ FRAMEWORK_BUILD=1
+ else
+ if test $SHARED_BUILD = 1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared library" >&5
+$as_echo "shared library" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: static library" >&5
+$as_echo "static library" >&6; }
+ fi
+ FRAMEWORK_BUILD=0
+ fi
+ fi
+
+ TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk '{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}'`"
+ TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}'
+ echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xa000000'
+ TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist'
+ EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist'
+ EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic'
+ ac_config_files="$ac_config_files Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in"
+
+ TCL_YEAR="`date +%Y`"
+fi
+
+if test "$FRAMEWORK_BUILD" = "1" ; then
+
+$as_echo "#define TCL_FRAMEWORK 1" >>confdefs.h
+
+ # Construct a fake local framework structure to make linking with
+ # '-framework Tcl' and running of tcltest work
+ ac_config_commands="$ac_config_commands Tcl.framework"
+
+ LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH"
+ # default install directory for bundled packages
+ if test "${libdir}" = '${exec_prefix}/lib' -o "`basename ${libdir}`" = 'Frameworks'; then
+ PACKAGE_DIR="/Library/Tcl"
+ else
+ PACKAGE_DIR="$libdir"
+ fi
+ if test "${libdir}" = '${exec_prefix}/lib'; then
+ # override libdir default
+ libdir="/Library/Frameworks"
+ fi
+ TCL_LIB_FILE="Tcl"
+ TCL_LIB_FLAG="-framework Tcl"
+ TCL_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tcl"
+ TCL_LIB_SPEC="-F${libdir} -framework Tcl"
+ libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
+ TCL_LIBRARY="${libdir}/Resources/Scripts"
+ includedir="${libdir}/Headers"
+ PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
+ HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl"
+ EXTRA_INSTALL="install-private-headers html-tcl"
+ EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TclTOC.html'
+ EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
+ EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
+ EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
+ # Don't use AC_DEFINE for the following as the framework version define
+ # needs to go into the Makefile even when using autoheader, so that we
+ # can pick up a potential make override of VERSION. Also, don't put this
+ # into CFLAGS as it should not go into tclConfig.sh
+ EXTRA_CC_SWITCHES='-DTCL_FRAMEWORK_VERSION=\"$(VERSION)\"'
+else
+ # libdir must be a fully qualified path and not ${exec_prefix}/lib
+ eval libdir="$libdir"
+ # default install directory for bundled packages
+ PACKAGE_DIR="$libdir"
+ if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
+ TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
+ else
+ TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
+ fi
+ TCL_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_LIB_FLAG}"
+ TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
+fi
+VERSION='${VERSION}'
+eval "CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}"
+eval "CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}"
+VERSION=${TCL_VERSION}
+
+#--------------------------------------------------------------------
+# The statements below define the symbol TCL_PACKAGE_PATH, which
+# gives a list of directories that may contain packages. The list
+# consists of one directory for machine-dependent binaries and
+# another for platform-independent scripts.
+#--------------------------------------------------------------------
+
+if test "$FRAMEWORK_BUILD" = "1" ; then
+ test -z "$TCL_PACKAGE_PATH" && \
+ TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /System/Library/Frameworks"
+ test -z "$TCL_MODULE_PATH" && \
+ TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl"
+elif test "$prefix/lib" != "$libdir"; then
+ TCL_PACKAGE_PATH="${libdir} ${prefix}/lib ${TCL_PACKAGE_PATH}"
+else
+ TCL_PACKAGE_PATH="${prefix}/lib ${TCL_PACKAGE_PATH}"
+fi
+
+#--------------------------------------------------------------------
+# The statements below define various symbols relating to Tcl
+# stub support.
+#--------------------------------------------------------------------
+
+# Replace ${VERSION} with contents of ${TCL_VERSION}
+# double-eval to account for TCL_TRIM_DOTS.
+#
+eval "TCL_STUB_LIB_FILE=libtclstub${TCL_UNSHARED_LIB_SUFFIX}"
+eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
+eval "TCL_STUB_LIB_DIR=${libdir}"
+
+if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
+ TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}"
+else
+ TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`"
+fi
+
+TCL_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
+TCL_STUB_LIB_SPEC="-L${TCL_STUB_LIB_DIR} ${TCL_STUB_LIB_FLAG}"
+TCL_BUILD_STUB_LIB_PATH="`pwd`/${TCL_STUB_LIB_FILE}"
+TCL_STUB_LIB_PATH="${TCL_STUB_LIB_DIR}/${TCL_STUB_LIB_FILE}"
+
+# Install time header dir can be set via --includedir
+eval "TCL_INCLUDE_SPEC=\"-I${includedir}\""
+
+#------------------------------------------------------------------------
+# tclConfig.sh refers to this by a different name
+#------------------------------------------------------------------------
+
+TCL_SHARED_BUILD=${SHARED_BUILD}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile:../unix/Makefile.in dltest/Makefile:../unix/dltest/Makefile.in tclConfig.sh:../unix/tclConfig.sh.in tcl.pc:../unix/tcl.pc.in"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+
+CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by tcl $as_me 8.7, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+tcl config.status 8.7
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+VERSION=${TCL_VERSION}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "Tcl-Info.plist") CONFIG_FILES="$CONFIG_FILES Tcl-Info.plist:../macosx/Tcl-Info.plist.in" ;;
+ "Tclsh-Info.plist") CONFIG_FILES="$CONFIG_FILES Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in" ;;
+ "Tcl.framework") CONFIG_COMMANDS="$CONFIG_COMMANDS Tcl.framework" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile:../unix/Makefile.in" ;;
+ "dltest/Makefile") CONFIG_FILES="$CONFIG_FILES dltest/Makefile:../unix/dltest/Makefile.in" ;;
+ "tclConfig.sh") CONFIG_FILES="$CONFIG_FILES tclConfig.sh:../unix/tclConfig.sh.in" ;;
+ "tcl.pc") CONFIG_FILES="$CONFIG_FILES tcl.pc:../unix/tcl.pc.in" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "Tcl.framework":C) n=Tcl &&
+ f=$n.framework && v=Versions/$VERSION &&
+ rm -rf $f && mkdir -p $f/$v/Resources &&
+ ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
+ ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
+ unset n f v
+ ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
diff --git a/unix/configure.ac b/unix/configure.ac
new file mode 100644
index 0000000..e14d85e
--- /dev/null
+++ b/unix/configure.ac
@@ -0,0 +1,1028 @@
+#! /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.
+
+AC_INIT([tcl],[8.7])
+AC_PREREQ(2.69)
+
+dnl This is only used when included from macosx/configure.ac
+m4_ifdef([SC_USE_CONFIG_HEADERS], [
+ AC_CONFIG_HEADERS([tclConfig.h:../unix/tclConfig.h.in])
+ AC_CONFIG_COMMANDS_PRE([DEFS="-DHAVE_TCL_CONFIG_H -imacros tclConfig.h"])
+ AH_TOP([
+ #ifndef _TCLCONFIG
+ #define _TCLCONFIG])
+ AH_BOTTOM([
+ /* Undef unused package specific autoheader defines so that we can
+ * include both tclConfig.h and tkConfig.h at the same time: */
+ /* override */ #undef PACKAGE_NAME
+ /* override */ #undef PACKAGE_STRING
+ /* override */ #undef PACKAGE_TARNAME
+ #endif /* _TCLCONFIG */])
+])
+
+TCL_VERSION=8.7
+TCL_MAJOR_VERSION=8
+TCL_MINOR_VERSION=7
+TCL_PATCH_LEVEL="a2"
+VERSION=${TCL_VERSION}
+
+EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"}
+EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"}
+
+#------------------------------------------------------------------------
+# Setup configure arguments for bundled packages
+#------------------------------------------------------------------------
+
+PKG_CFG_ARGS="$ac_configure_args ${PKG_CFG_ARGS}"
+
+if test -r "$cache_file" -a -f "$cache_file"; then
+ case $cache_file in
+ [[\\/]]* | ?:[[\\/]]* ) pkg_cache_file=$cache_file ;;
+ *) pkg_cache_file=../../$cache_file ;;
+ esac
+ PKG_CFG_ARGS="${PKG_CFG_ARGS} --cache-file=$pkg_cache_file"
+fi
+
+#------------------------------------------------------------------------
+# Empty slate for bundled packages, to avoid stale configuration
+#------------------------------------------------------------------------
+#rm -Rf pkgs
+if test -f Makefile; then
+ make distclean-packages
+fi
+
+#------------------------------------------------------------------------
+# Handle the --prefix=... option
+#------------------------------------------------------------------------
+
+if test "${prefix}" = "NONE"; then
+ prefix=/usr/local
+fi
+if test "${exec_prefix}" = "NONE"; then
+ exec_prefix=$prefix
+fi
+# Make sure srcdir is fully qualified!
+srcdir="`cd "$srcdir" ; pwd`"
+TCL_SRC_DIR="`cd "$srcdir"/..; pwd`"
+
+#------------------------------------------------------------------------
+# Compress and/or soft link the manpages?
+#------------------------------------------------------------------------
+
+SC_CONFIG_MANPAGES
+
+#------------------------------------------------------------------------
+# Standard compiler checks
+#------------------------------------------------------------------------
+
+# 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_C_INLINE
+
+#--------------------------------------------------------------------
+# 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
+# Do this early, otherwise an autoconf bug throws errors on configure
+#--------------------------------------------------------------------
+
+SC_MISSING_POSIX_HEADERS
+
+#--------------------------------------------------------------------
+# Determines the correct executable file extension (.exe)
+#--------------------------------------------------------------------
+
+AC_EXEEXT
+
+#------------------------------------------------------------------------
+# 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" && test -n "$GCC"; then
+ AC_CACHE_CHECK([if the compiler understands -pipe],
+ tcl_cv_cc_pipe, [
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
+ AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no)
+ CFLAGS=$hold_cflags])
+ if test $tcl_cv_cc_pipe = yes; then
+ CFLAGS="$CFLAGS -pipe"
+ fi
+fi
+
+#------------------------------------------------------------------------
+# Threads support
+#------------------------------------------------------------------------
+
+SC_ENABLE_THREADS
+
+#------------------------------------------------------------------------
+# Embedded configuration information, encoding to use for the values, TIP #59
+#------------------------------------------------------------------------
+
+SC_TCL_CFG_ENCODING
+
+#--------------------------------------------------------------------
+# Look for libraries that we will need when compiling the Tcl shell
+#--------------------------------------------------------------------
+
+SC_TCL_LINK_LIBS
+
+# Add the threads support libraries
+LIBS="$LIBS$THREADS_LIBS"
+
+SC_ENABLE_SHARED
+
+#--------------------------------------------------------------------
+# Look for a native installed tclsh binary (if available)
+# If one cannot be found then use the binary we build (fails for
+# cross compiling). This is used for NATIVE_TCLSH in Makefile.
+#--------------------------------------------------------------------
+
+SC_PROG_TCLSH
+if test "$TCLSH_PROG" = ""; then
+ TCLSH_PROG='./${TCL_EXE}'
+fi
+
+#------------------------------------------------------------------------
+# Add stuff for zlib
+#------------------------------------------------------------------------
+
+zlib_ok=yes
+AC_CHECK_HEADER([zlib.h],[
+ AC_CHECK_TYPE([gz_header],[],[zlib_ok=no],[#include <zlib.h>])],[
+ zlib_ok=no])
+AS_IF([test $zlib_ok = yes], [
+ AC_SEARCH_LIBS([deflateSetHeader],[z],[],[
+ zlib_ok=no
+ ])])
+AS_IF([test $zlib_ok = no], [
+ AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}])
+ AC_SUBST(ZLIB_SRCS,[\${ZLIB_SRCS}])
+ AC_SUBST(ZLIB_INCLUDE,[-I\${ZLIB_DIR}])
+])
+AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?])
+
+#--------------------------------------------------------------------
+# The statements below define a collection of compile flags. This
+# macro depends on the value of SHARED_BUILD, and should be called
+# after SC_ENABLE_SHARED checks the configure switches.
+#--------------------------------------------------------------------
+
+SC_CONFIG_CFLAGS
+
+SC_ENABLE_SYMBOLS(bccdebug)
+
+AC_DEFINE(MP_PREC, 4, [Default libtommath precision.])
+
+#--------------------------------------------------------------------
+# Detect what compiler flags to set for 64-bit support.
+#--------------------------------------------------------------------
+
+SC_TCL_EARLY_FLAGS
+
+SC_TCL_64BIT_FLAGS
+
+#--------------------------------------------------------------------
+# Check endianness because we can optimize comparisons of
+# Tcl_UniChar strings to memcmp on big-endian systems.
+#--------------------------------------------------------------------
+
+AC_C_BIGENDIAN
+
+#--------------------------------------------------------------------
+# Supply substitutes for missing POSIX library procedures, or
+# set flags so Tcl uses alternate procedures.
+#--------------------------------------------------------------------
+
+# Check if Posix compliant getcwd exists, if not we'll use getwd.
+AC_CHECK_FUNCS(getcwd, , [AC_DEFINE(USEGETWD, 1, [Is getcwd Posix-compliant?])])
+# Nb: if getcwd uses popen and pwd(1) (like SunOS 4) we should really
+# define USEGETWD even if the posix getcwd exists. Add a test ?
+
+AC_REPLACE_FUNCS(mkstemp opendir strtol waitpid)
+AC_CHECK_FUNC(strerror, , [AC_DEFINE(NO_STRERROR, 1, [Do we have strerror()])])
+AC_CHECK_FUNC(getwd, , [AC_DEFINE(NO_GETWD, 1, [Do we have getwd()])])
+AC_CHECK_FUNC(wait3, , [AC_DEFINE(NO_WAIT3, 1, [Do we have wait3()])])
+AC_CHECK_FUNC(uname, , [AC_DEFINE(NO_UNAME, 1, [Do we have uname()])])
+
+if test "`uname -s`" = "Darwin" && test "${TCL_THREADS}" = 1 && \
+ test "`uname -r | awk -F. '{print [$]1}'`" -lt 7; then
+ # prior to Darwin 7, realpath is not threadsafe, so don't
+ # use it when threads are enabled, c.f. bug # 711232
+ ac_cv_func_realpath=no
+fi
+AC_CHECK_FUNC(realpath, , [AC_DEFINE(NO_REALPATH, 1, [Do we have realpath()])])
+
+SC_TCL_IPV6
+
+#--------------------------------------------------------------------
+# Look for thread-safe variants of some library functions.
+#--------------------------------------------------------------------
+
+if test "${TCL_THREADS}" = 1; then
+ SC_TCL_GETPWUID_R
+ SC_TCL_GETPWNAM_R
+ SC_TCL_GETGRGID_R
+ SC_TCL_GETGRNAM_R
+ if test "`uname -s`" = "Darwin" && \
+ test "`uname -r | awk -F. '{print [$]1}'`" -gt 5; then
+ # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX
+ # are actually MT-safe as they always return pointers
+ # from TSD instead of static storage.
+ AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1,
+ [Do we have MT-safe gethostbyname() ?])
+ AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1,
+ [Do we have MT-safe gethostbyaddr() ?])
+
+ elif test "`uname -s`" = "HP-UX" && \
+ test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then
+ # Starting with HPUX 11.00 (we believe), gethostbyX
+ # are actually MT-safe as they always return pointers
+ # from TSD instead of static storage.
+ AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1,
+ [Do we have MT-safe gethostbyname() ?])
+ AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1,
+ [Do we have MT-safe gethostbyaddr() ?])
+
+ else
+ SC_TCL_GETHOSTBYNAME_R
+ SC_TCL_GETHOSTBYADDR_R
+ fi
+fi
+
+#---------------------------------------------------------------------------
+# Check for serial port interface.
+#
+# termios.h is present on all POSIX systems.
+# sys/ioctl.h is almost always present, though what it contains
+# is system-specific.
+# sys/modem.h is needed on HP-UX.
+#---------------------------------------------------------------------------
+
+AC_CHECK_HEADERS(termios.h)
+AC_CHECK_HEADERS(sys/ioctl.h)
+AC_CHECK_HEADERS(sys/modem.h)
+
+#--------------------------------------------------------------------
+# Include sys/select.h if it exists and if it supplies things
+# that appear to be useful and aren't already in sys/types.h.
+# This appears to be true only on the RS/6000 under AIX. Some
+# systems like OSF/1 have a sys/select.h that's of no use, and
+# other systems like SCO UNIX have a sys/select.h that's
+# pernicious. If "fd_set" isn't defined anywhere then set a
+# special flag.
+#--------------------------------------------------------------------
+
+AC_CACHE_CHECK([for fd_set in sys/types], tcl_cv_type_fd_set, [
+ AC_TRY_COMPILE([#include <sys/types.h>],[fd_set readMask, writeMask;],
+ tcl_cv_type_fd_set=yes, tcl_cv_type_fd_set=no)])
+tcl_ok=$tcl_cv_type_fd_set
+if test $tcl_ok = no; then
+ AC_CACHE_CHECK([for fd_mask in sys/select], tcl_cv_grep_fd_mask, [
+ AC_EGREP_HEADER(fd_mask, sys/select.h,
+ tcl_cv_grep_fd_mask=present, tcl_cv_grep_fd_mask=missing)])
+ if test $tcl_cv_grep_fd_mask = present; then
+ AC_DEFINE(HAVE_SYS_SELECT_H, 1, [Should we include <sys/select.h>?])
+ tcl_ok=yes
+ fi
+fi
+if test $tcl_ok = no; then
+ AC_DEFINE(NO_FD_SET, 1, [Do we have fd_set?])
+fi
+
+#------------------------------------------------------------------------
+# Options for the notifier. Checks for epoll(7) on Linux, and
+# kqueue(2) on {DragonFly,Free,Net,Open}BSD
+#------------------------------------------------------------------------
+
+AC_MSG_CHECKING([for advanced notifier support])
+case x`uname -s` in
+ xLinux)
+ AC_MSG_RESULT([epoll(7)])
+ AC_CHECK_HEADERS([sys/epoll.h],
+ [AC_DEFINE(NOTIFIER_EPOLL, [1], [Is epoll(7) supported?])])
+ AC_CHECK_HEADERS([sys/eventfd.h],
+ [AC_DEFINE(HAVE_EVENTFD, [1], [Is eventfd(2) supported?])]);;
+ xDragonFlyBSD|xFreeBSD|xNetBSD|xOpenBSD)
+ AC_MSG_RESULT([kqueue(2)])
+ # Messy because we want to check if *all* the headers are present, and not
+ # just *any*
+ tcl_kqueue_headers=x
+ AC_CHECK_HEADERS([sys/types.h sys/event.h sys/time.h],
+ [tcl_kqueue_headers=${tcl_kqueue_headers}y])
+ AS_IF([test $tcl_kqueue_headers = xyyy], [
+ AC_DEFINE(NOTIFIER_KQUEUE, [1], [Is kqueue(2) supported?])]);;
+ xDarwin)
+ # Assume that we've got CoreFoundation present (checked elsewhere because
+ # of wider impact).
+ AC_MSG_RESULT([OSX]);;
+ *)
+ AC_DEFINE_UNQUOTED(NOTIFIER_SELECT)
+ AC_MSG_RESULT([none]);;
+esac
+
+#------------------------------------------------------------------------------
+# Find out all about time handling differences.
+#------------------------------------------------------------------------------
+
+SC_TIME_HANDLER
+
+#--------------------------------------------------------------------
+# Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But
+# we might be able to use fstatfs instead. Some systems (OpenBSD?) also
+# lack blkcnt_t.
+#--------------------------------------------------------------------
+
+if test "$ac_cv_cygwin" != "yes"; then
+ AC_CHECK_MEMBERS([struct stat.st_blocks, struct stat.st_blksize])
+fi
+AC_CHECK_TYPES([blkcnt_t])
+AC_CHECK_FUNC(fstatfs, , [AC_DEFINE(NO_FSTATFS, 1, [Do we have fstatfs()?])])
+
+#--------------------------------------------------------------------
+# Some system have no memcmp or it does not work with 8 bit data, this
+# checks it and add memcmp.o to LIBOBJS if needed
+#--------------------------------------------------------------------
+
+AC_FUNC_MEMCMP
+
+#--------------------------------------------------------------------
+# Some system like SunOS 4 and other BSD like systems have no memmove
+# (we assume they have bcopy instead). {The replacement define is in
+# compat/string.h}
+#--------------------------------------------------------------------
+
+AC_CHECK_FUNC(memmove, , [
+ AC_DEFINE(NO_MEMMOVE, 1, [Do we have memmove()?])
+ AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?]) ])
+
+#--------------------------------------------------------------------
+# On some systems strstr is broken: it returns a pointer even even if
+# the original string is empty.
+#--------------------------------------------------------------------
+
+SC_TCL_CHECK_BROKEN_FUNC(strstr, [
+ extern int strstr();
+ exit(strstr("\0test", "test") ? 1 : 0);
+])
+
+#--------------------------------------------------------------------
+# Check for strtoul function. This is tricky because under some
+# versions of AIX strtoul returns an incorrect terminator
+# pointer for the string "0".
+#--------------------------------------------------------------------
+
+SC_TCL_CHECK_BROKEN_FUNC(strtoul, [
+ extern int strtoul();
+ char *term, *string = "0";
+ exit(strtoul(string,&term,0) != 0 || term != string+1);
+])
+
+#--------------------------------------------------------------------
+# Check for the strtod function. This is tricky because in some
+# versions of Linux strtod mis-parses strings starting with "+".
+#--------------------------------------------------------------------
+
+SC_TCL_CHECK_BROKEN_FUNC(strtod, [
+ extern double strtod();
+ char *term, *string = " +69";
+ exit(strtod(string,&term) != 69 || term != string+4);
+])
+
+#--------------------------------------------------------------------
+# 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" that corrects the error.
+#--------------------------------------------------------------------
+
+SC_BUGGY_STRTOD
+
+#--------------------------------------------------------------------
+# Check for various typedefs and provide substitutes if
+# they don't exist.
+#--------------------------------------------------------------------
+
+AC_TYPE_MODE_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_UID_T
+
+AC_CACHE_CHECK([for socklen_t], tcl_cv_type_socklen_t, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ ],[
+ socklen_t foo;
+ ],[tcl_cv_type_socklen_t=yes],[tcl_cv_type_socklen_t=no])])
+if test $tcl_cv_type_socklen_t = no; then
+ AC_DEFINE(socklen_t, int, [Define as int if socklen_t is not available])
+fi
+
+AC_CHECK_TYPE([intptr_t], [
+ AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [
+ AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [
+ for tcl_cv_intptr_t in "int" "long" "long long" none; do
+ if test "$tcl_cv_intptr_t" != none; then
+ AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
+ [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])],
+ [tcl_ok=yes], [tcl_ok=no])
+ test "$tcl_ok" = yes && break; fi
+ done])
+ if test "$tcl_cv_intptr_t" != none; then
+ AC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer
+ type wide enough to hold a pointer.])
+ fi
+])
+AC_CHECK_TYPE([uintptr_t], [
+ AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [
+ AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [
+ for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \
+ none; do
+ if test "$tcl_cv_uintptr_t" != none; then
+ AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],
+ [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])],
+ [tcl_ok=yes], [tcl_ok=no])
+ test "$tcl_ok" = yes && break; fi
+ done])
+ if test "$tcl_cv_uintptr_t" != none; then
+ AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer
+ type wide enough to hold a pointer.])
+ fi
+])
+
+#--------------------------------------------------------------------
+# If a system doesn't have an opendir function (man, that's old!)
+# then we have to supply a different version of dirent.h which
+# is compatible with the substitute version of opendir that's
+# provided. This version only works with V7-style directories.
+#--------------------------------------------------------------------
+
+AC_CHECK_FUNC(opendir, , [AC_DEFINE(USE_DIRENT2_H, 1, [May we include <dirent2.h>?])])
+
+#--------------------------------------------------------------------
+# The check below checks whether <sys/wait.h> defines the type
+# "union wait" correctly. It's needed because of weirdness in
+# HP-UX where "union wait" is defined in both the BSD and SYS-V
+# environments. Checking the usability of WIFEXITED seems to do
+# the trick.
+#--------------------------------------------------------------------
+
+AC_CACHE_CHECK([union wait], tcl_cv_union_wait, [
+ AC_TRY_LINK([#include <sys/types.h>
+#include <sys/wait.h>], [
+union wait x;
+WIFEXITED(x); /* Generates compiler error if WIFEXITED
+ * uses an int. */
+ ], tcl_cv_union_wait=yes, tcl_cv_union_wait=no)])
+if test $tcl_cv_union_wait = no; then
+ AC_DEFINE(NO_UNION_WAIT, 1, [Do we have a usable 'union wait'?])
+fi
+
+#--------------------------------------------------------------------
+# Check whether there is an strncasecmp function on this system.
+# This is a bit tricky because under SCO it's in -lsocket and
+# under Sequent Dynix it's in -linet.
+#--------------------------------------------------------------------
+
+AC_CHECK_FUNC(strncasecmp, tcl_ok=1, tcl_ok=0)
+if test "$tcl_ok" = 0; then
+ AC_CHECK_LIB(socket, strncasecmp, tcl_ok=1, tcl_ok=0)
+fi
+if test "$tcl_ok" = 0; then
+ AC_CHECK_LIB(inet, strncasecmp, tcl_ok=1, tcl_ok=0)
+fi
+if test "$tcl_ok" = 0; then
+ AC_LIBOBJ([strncasecmp])
+ USE_COMPAT=1
+fi
+
+#--------------------------------------------------------------------
+# The code below deals with several issues related to gettimeofday:
+# 1. Some systems don't provide a gettimeofday function at all
+# (set NO_GETTOD if this is the case).
+# 2. See if gettimeofday is declared in the <sys/time.h> header file.
+# if not, set the GETTOD_NOT_DECLARED flag so that tclPort.h can
+# declare it.
+#--------------------------------------------------------------------
+
+AC_CHECK_FUNC(gettimeofday,[],[
+ AC_DEFINE(NO_GETTOD, 1, [Do we have gettimeofday()?])
+])
+AC_CACHE_CHECK([for gettimeofday declaration], tcl_cv_grep_gettimeofday, [
+ AC_EGREP_HEADER(gettimeofday, sys/time.h,
+ tcl_cv_grep_gettimeofday=present, tcl_cv_grep_gettimeofday=missing)])
+if test $tcl_cv_grep_gettimeofday = missing ; then
+ AC_DEFINE(GETTOD_NOT_DECLARED, 1, [Is gettimeofday() actually declared in <sys/time.h>?])
+fi
+
+#--------------------------------------------------------------------
+# The following code checks to see whether it is possible to get
+# signed chars on this platform. This is needed in order to
+# properly generate sign-extended ints from character values.
+#--------------------------------------------------------------------
+
+AC_C_CHAR_UNSIGNED
+AC_CACHE_CHECK([signed char declarations], tcl_cv_char_signed, [
+ AC_TRY_COMPILE(, [
+ signed char *p;
+ p = 0;
+ ], tcl_cv_char_signed=yes, tcl_cv_char_signed=no)])
+if test $tcl_cv_char_signed = yes; then
+ AC_DEFINE(HAVE_SIGNED_CHAR, 1, [Are characters signed?])
+fi
+
+#--------------------------------------------------------------------
+# Does putenv() copy or not? We need to know to avoid memory leaks.
+#--------------------------------------------------------------------
+
+AC_CACHE_CHECK([for a putenv() that copies the buffer], tcl_cv_putenv_copy, [
+ AC_TRY_RUN([
+ #include <stdlib.h>
+ #define OURVAR "havecopy=yes"
+ int main (int argc, char *argv[])
+ {
+ char *foo, *bar;
+ foo = (char *)strdup(OURVAR);
+ putenv(foo);
+ strcpy((char *)(strchr(foo, '=') + 1), "no");
+ bar = getenv("havecopy");
+ if (!strcmp(bar, "no")) {
+ /* doesnt copy */
+ return 0;
+ } else {
+ /* does copy */
+ return 1;
+ }
+ }
+ ],
+ tcl_cv_putenv_copy=no,
+ tcl_cv_putenv_copy=yes,
+ tcl_cv_putenv_copy=no)])
+if test $tcl_cv_putenv_copy = yes; then
+ AC_DEFINE(HAVE_PUTENV_THAT_COPIES, 1,
+ [Does putenv() copy strings or incorporate them by reference?])
+fi
+
+#--------------------------------------------------------------------
+# Check for support of nl_langinfo function
+#--------------------------------------------------------------------
+
+SC_ENABLE_LANGINFO
+
+#--------------------------------------------------------------------
+# Check for support of chflags and mkstemps functions
+#--------------------------------------------------------------------
+
+AC_CHECK_FUNCS(chflags mkstemps)
+
+#--------------------------------------------------------------------
+# Check for support of isnan() function or macro
+#--------------------------------------------------------------------
+
+AC_CACHE_CHECK([isnan], tcl_cv_isnan, [
+ AC_TRY_LINK([#include <math.h>], [
+isnan(0.0); /* Generates an error if isnan is missing */
+], tcl_cv_isnan=yes, tcl_cv_isnan=no)])
+if test $tcl_cv_isnan = no; then
+ AC_DEFINE(NO_ISNAN, 1, [Do we have a usable 'isnan'?])
+fi
+
+#--------------------------------------------------------------------
+# Darwin specific API checks and defines
+#--------------------------------------------------------------------
+
+if test "`uname -s`" = "Darwin" ; then
+ AC_CHECK_FUNCS(getattrlist)
+ AC_CHECK_HEADERS(copyfile.h)
+ AC_CHECK_FUNCS(copyfile)
+ if test $tcl_corefoundation = yes; then
+ AC_CHECK_HEADERS(libkern/OSAtomic.h)
+ AC_CHECK_FUNCS(OSSpinLockLock)
+ fi
+ AC_DEFINE(USE_VFORK, 1, [Should we use vfork() instead of fork()?])
+ AC_DEFINE(TCL_DEFAULT_ENCODING, "utf-8",
+ [Are we to override what our default encoding is?])
+ AC_DEFINE(TCL_LOAD_FROM_MEMORY, 1,
+ [Can this platform load code from memory?])
+ AC_DEFINE(TCL_WIDE_CLICKS, 1,
+ [Does this platform have wide high-resolution clicks?])
+ AC_CHECK_HEADERS(AvailabilityMacros.h)
+ if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
+ AC_CACHE_CHECK([if weak import is available], tcl_cv_cc_weak_import, [
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ AC_TRY_LINK([
+ #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
+ #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020
+ #endif
+ #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020
+ #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020
+ #endif
+ int rand(void) __attribute__((weak_import));
+ ], [rand();],
+ tcl_cv_cc_weak_import=yes, tcl_cv_cc_weak_import=no)
+ CFLAGS=$hold_cflags])
+ if test $tcl_cv_cc_weak_import = yes; then
+ AC_DEFINE(HAVE_WEAK_IMPORT, 1, [Is weak import available?])
+ fi
+ AC_CACHE_CHECK([if Darwin SUSv3 extensions are available],
+ tcl_cv_cc_darwin_c_source, [
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ AC_TRY_COMPILE([
+ #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
+ #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
+ #endif
+ #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ #endif
+ #define _DARWIN_C_SOURCE 1
+ #include <sys/cdefs.h>
+ ],,tcl_cv_cc_darwin_c_source=yes, tcl_cv_cc_darwin_c_source=no)
+ CFLAGS=$hold_cflags])
+ if test $tcl_cv_cc_darwin_c_source = yes; then
+ AC_DEFINE(_DARWIN_C_SOURCE, 1,
+ [Are Darwin SUSv3 extensions available?])
+ fi
+ fi
+ # Build .bundle dltest binaries in addition to .dylib
+ DLTEST_LD='${CC} -bundle -Wl,-w ${CFLAGS} ${LDFLAGS}'
+ DLTEST_SUFFIX=".bundle"
+else
+ DLTEST_LD='${SHLIB_LD}'
+ DLTEST_SUFFIX=""
+fi
+
+#--------------------------------------------------------------------
+# Check for support of fts functions (readdir replacement)
+#--------------------------------------------------------------------
+
+AC_CACHE_CHECK([for fts], tcl_cv_api_fts, [
+ AC_TRY_LINK([
+ #include <sys/param.h>
+ #include <sys/stat.h>
+ #include <fts.h>
+ ], [
+ char*const p[2] = {"/", NULL};
+ FTS *f = fts_open(p, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL);
+ FTSENT *e = fts_read(f); fts_close(f);
+ ], tcl_cv_api_fts=yes, tcl_cv_api_fts=no)])
+if test $tcl_cv_api_fts = yes; then
+ AC_DEFINE(HAVE_FTS, 1, [Do we have fts functions?])
+fi
+
+#--------------------------------------------------------------------
+# 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.
+#--------------------------------------------------------------------
+
+SC_BLOCKING_STYLE
+
+#------------------------------------------------------------------------
+
+AC_MSG_CHECKING([whether to use dll unloading])
+AC_ARG_ENABLE(dll-unloading,
+ AC_HELP_STRING([--enable-dll-unloading],
+ [enable the 'unload' command (default: on)]),
+ [tcl_ok=$enableval], [tcl_ok=yes])
+if test $tcl_ok = yes; then
+ AC_DEFINE(TCL_UNLOAD_DLLS, 1, [Do we allow unloading of shared libraries?])
+fi
+AC_MSG_RESULT([$tcl_ok])
+
+#------------------------------------------------------------------------
+# Check whether the timezone data is supplied by the OS or has
+# to be installed by Tcl. The default is autodetection, but can
+# be overriden on the configure command line either way.
+#------------------------------------------------------------------------
+
+AC_MSG_CHECKING([for timezone data])
+AC_ARG_WITH(tzdata,
+ AC_HELP_STRING([--with-tzdata],
+ [install timezone data (default: autodetect)]),
+ [tcl_ok=$withval], [tcl_ok=auto])
+#
+# Any directories that get added here must also be added to the
+# search path in ::tcl::clock::Initialize (library/clock.tcl).
+#
+case $tcl_ok in
+ no)
+ AC_MSG_RESULT([supplied by OS vendor])
+ ;;
+ yes)
+ # nothing to do here
+ ;;
+ auto*)
+ AC_CACHE_VAL([tcl_cv_dir_zoneinfo], [
+ for dir in /usr/share/zoneinfo \
+ /usr/share/lib/zoneinfo \
+ /usr/lib/zoneinfo
+ do
+ if test -f $dir/UTC -o -f $dir/GMT
+ then
+ tcl_cv_dir_zoneinfo="$dir"
+ break
+ fi
+ done])
+ if test -n "$tcl_cv_dir_zoneinfo"; then
+ tcl_ok=no
+ AC_MSG_RESULT([$dir])
+ else
+ tcl_ok=yes
+ fi
+ ;;
+ *)
+ AC_MSG_ERROR([invalid argument: $tcl_ok])
+ ;;
+esac
+if test $tcl_ok = yes
+then
+ AC_MSG_RESULT([supplied by Tcl])
+ INSTALL_TZDATA=install-tzdata
+fi
+
+#--------------------------------------------------------------------
+# DTrace support
+#--------------------------------------------------------------------
+
+AC_ARG_ENABLE(dtrace,
+ AC_HELP_STRING([--enable-dtrace],
+ [build with DTrace support (default: off)]),
+ [tcl_ok=$enableval], [tcl_ok=no])
+if test $tcl_ok = yes; then
+ AC_CHECK_HEADER(sys/sdt.h, [tcl_ok=yes], [tcl_ok=no])
+fi
+if test $tcl_ok = yes; then
+ AC_PATH_PROG(DTRACE, dtrace,, [$PATH:/usr/sbin])
+ test -z "$ac_cv_path_DTRACE" && tcl_ok=no
+fi
+AC_MSG_CHECKING([whether to enable DTrace support])
+MAKEFILE_SHELL='/bin/sh'
+if test $tcl_ok = yes; then
+ AC_DEFINE(USE_DTRACE, 1, [Are we building with DTrace support?])
+ DTRACE_SRC="\${DTRACE_SRC}"
+ DTRACE_HDR="\${DTRACE_HDR}"
+ if test "`uname -s`" != "Darwin" ; then
+ DTRACE_OBJ="\${DTRACE_OBJ}"
+ if test "`uname -s`" = "SunOS" -a "$SHARED_BUILD" = "0" ; then
+ # Need to create an intermediate object file to ensure tclDTrace.o
+ # gets included when linking against the static tcl library.
+ STLIB_LD='stlib_ld () { /usr/ccs/bin/ld -r -o $${1%.a}.o "$${@:2}" && '"${STLIB_LD}"' $${1} $${1%.a}.o ; } && stlib_ld'
+ MAKEFILE_SHELL='/bin/bash'
+ # Force use of Sun ar and ranlib, the GNU versions choke on
+ # tclDTrace.o and the combined object file above.
+ AR='/usr/ccs/bin/ar'
+ RANLIB='/usr/ccs/bin/ranlib'
+ fi
+ fi
+fi
+AC_MSG_RESULT([$tcl_ok])
+
+#--------------------------------------------------------------------
+# The check below checks whether the cpuid instruction is usable.
+#--------------------------------------------------------------------
+
+AC_CACHE_CHECK([whether the cpuid instruction is usable], tcl_cv_cpuid, [
+ AC_TRY_LINK(, [
+ int index,regsPtr[4];
+ __asm__ __volatile__("mov %%ebx, %%edi \n\t"
+ "cpuid \n\t"
+ "mov %%ebx, %%esi \n\t"
+ "mov %%edi, %%ebx \n\t"
+ : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
+ : "a"(index) : "edi");
+ ], tcl_cv_cpuid=yes, tcl_cv_cpuid=no)])
+if test $tcl_cv_cpuid = yes; then
+ AC_DEFINE(HAVE_CPUID, 1, [Is the cpuid instruction usable?])
+fi
+
+#--------------------------------------------------------------------
+# The statements below define a collection of symbols related to
+# building libtcl as a shared library instead of a static library.
+#--------------------------------------------------------------------
+
+TCL_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
+TCL_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX}
+eval "TCL_LIB_FILE=libtcl${LIB_SUFFIX}"
+
+# tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed
+# since on some platforms TCL_LIB_FILE contains shell escapes.
+# (See also: TCL_TRIM_DOTS).
+
+eval "TCL_LIB_FILE=${TCL_LIB_FILE}"
+
+TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)'
+PRIVATE_INCLUDE_DIR='$(includedir)'
+HTML_DIR='$(DISTDIR)/html'
+
+# Note: in the following variable, it's important to use the absolute
+# path name of the Tcl directory rather than "..": this is because
+# AIX remembers this path and will attempt to use it at run-time to look
+# up the Tcl library.
+
+if test "`uname -s`" = "Darwin" ; then
+ SC_ENABLE_FRAMEWORK
+ TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk ['{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}']`"
+ TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}'
+ echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xa000000'
+ TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist'
+ EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist'
+ EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic'
+ AC_CONFIG_FILES([Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in])
+ TCL_YEAR="`date +%Y`"
+fi
+
+if test "$FRAMEWORK_BUILD" = "1" ; then
+ AC_DEFINE(TCL_FRAMEWORK, 1, [Is Tcl built as a framework?])
+ # Construct a fake local framework structure to make linking with
+ # '-framework Tcl' and running of tcltest work
+ AC_CONFIG_COMMANDS([Tcl.framework], [n=Tcl &&
+ f=$n.framework && v=Versions/$VERSION &&
+ rm -rf $f && mkdir -p $f/$v/Resources &&
+ ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v &&
+ ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist &&
+ unset n f v
+ ], VERSION=${TCL_VERSION})
+ LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH"
+ # default install directory for bundled packages
+ if test "${libdir}" = '${exec_prefix}/lib' -o "`basename ${libdir}`" = 'Frameworks'; then
+ PACKAGE_DIR="/Library/Tcl"
+ else
+ PACKAGE_DIR="$libdir"
+ fi
+ if test "${libdir}" = '${exec_prefix}/lib'; then
+ # override libdir default
+ libdir="/Library/Frameworks"
+ fi
+ TCL_LIB_FILE="Tcl"
+ TCL_LIB_FLAG="-framework Tcl"
+ TCL_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tcl"
+ TCL_LIB_SPEC="-F${libdir} -framework Tcl"
+ libdir="${libdir}/Tcl.framework/Versions/\${VERSION}"
+ TCL_LIBRARY="${libdir}/Resources/Scripts"
+ includedir="${libdir}/Headers"
+ PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders"
+ HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl"
+ EXTRA_INSTALL="install-private-headers html-tcl"
+ EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TclTOC.html'
+ EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
+ EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
+ EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
+ # Don't use AC_DEFINE for the following as the framework version define
+ # needs to go into the Makefile even when using autoheader, so that we
+ # can pick up a potential make override of VERSION. Also, don't put this
+ # into CFLAGS as it should not go into tclConfig.sh
+ EXTRA_CC_SWITCHES='-DTCL_FRAMEWORK_VERSION=\"$(VERSION)\"'
+else
+ # libdir must be a fully qualified path and not ${exec_prefix}/lib
+ eval libdir="$libdir"
+ # default install directory for bundled packages
+ PACKAGE_DIR="$libdir"
+ if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
+ TCL_LIB_FLAG="-ltcl${TCL_VERSION}"
+ else
+ TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`"
+ fi
+ TCL_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_LIB_FLAG}"
+ TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}"
+fi
+VERSION='${VERSION}'
+eval "CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}"
+eval "CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}"
+VERSION=${TCL_VERSION}
+
+#--------------------------------------------------------------------
+# The statements below define the symbol TCL_PACKAGE_PATH, which
+# gives a list of directories that may contain packages. The list
+# consists of one directory for machine-dependent binaries and
+# another for platform-independent scripts.
+#--------------------------------------------------------------------
+
+if test "$FRAMEWORK_BUILD" = "1" ; then
+ test -z "$TCL_PACKAGE_PATH" && \
+ TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /System/Library/Frameworks"
+ test -z "$TCL_MODULE_PATH" && \
+ TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl"
+elif test "$prefix/lib" != "$libdir"; then
+ TCL_PACKAGE_PATH="${libdir} ${prefix}/lib ${TCL_PACKAGE_PATH}"
+else
+ TCL_PACKAGE_PATH="${prefix}/lib ${TCL_PACKAGE_PATH}"
+fi
+
+#--------------------------------------------------------------------
+# The statements below define various symbols relating to Tcl
+# stub support.
+#--------------------------------------------------------------------
+
+# Replace ${VERSION} with contents of ${TCL_VERSION}
+# double-eval to account for TCL_TRIM_DOTS.
+#
+eval "TCL_STUB_LIB_FILE=libtclstub${TCL_UNSHARED_LIB_SUFFIX}"
+eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
+eval "TCL_STUB_LIB_DIR=${libdir}"
+
+if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
+ TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}"
+else
+ TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`"
+fi
+
+TCL_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
+TCL_STUB_LIB_SPEC="-L${TCL_STUB_LIB_DIR} ${TCL_STUB_LIB_FLAG}"
+TCL_BUILD_STUB_LIB_PATH="`pwd`/${TCL_STUB_LIB_FILE}"
+TCL_STUB_LIB_PATH="${TCL_STUB_LIB_DIR}/${TCL_STUB_LIB_FILE}"
+
+# Install time header dir can be set via --includedir
+eval "TCL_INCLUDE_SPEC=\"-I${includedir}\""
+
+#------------------------------------------------------------------------
+# tclConfig.sh refers to this by a different name
+#------------------------------------------------------------------------
+
+TCL_SHARED_BUILD=${SHARED_BUILD}
+
+AC_SUBST(TCL_VERSION)
+AC_SUBST(TCL_MAJOR_VERSION)
+AC_SUBST(TCL_MINOR_VERSION)
+AC_SUBST(TCL_PATCH_LEVEL)
+AC_SUBST(TCL_YEAR)
+AC_SUBST(PKG_CFG_ARGS)
+
+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_STUB_LIB_PATH)
+AC_SUBST(TCL_INCLUDE_SPEC)
+AC_SUBST(TCL_BUILD_STUB_LIB_SPEC)
+AC_SUBST(TCL_BUILD_STUB_LIB_PATH)
+
+AC_SUBST(TCL_SRC_DIR)
+AC_SUBST(CFG_TCL_SHARED_LIB_SUFFIX)
+AC_SUBST(CFG_TCL_UNSHARED_LIB_SUFFIX)
+
+AC_SUBST(TCL_SHARED_BUILD)
+AC_SUBST(LD_LIBRARY_PATH_VAR)
+
+AC_SUBST(TCL_BUILD_LIB_SPEC)
+
+AC_SUBST(TCL_LIB_VERSIONS_OK)
+AC_SUBST(TCL_SHARED_LIB_SUFFIX)
+AC_SUBST(TCL_UNSHARED_LIB_SUFFIX)
+
+AC_SUBST(TCL_HAS_LONGLONG)
+
+AC_SUBST(INSTALL_TZDATA)
+
+AC_SUBST(DTRACE_SRC)
+AC_SUBST(DTRACE_HDR)
+AC_SUBST(DTRACE_OBJ)
+AC_SUBST(MAKEFILE_SHELL)
+
+AC_SUBST(BUILD_DLTEST)
+AC_SUBST(TCL_PACKAGE_PATH)
+AC_SUBST(TCL_MODULE_PATH)
+
+AC_SUBST(TCL_LIBRARY)
+AC_SUBST(PRIVATE_INCLUDE_DIR)
+AC_SUBST(HTML_DIR)
+AC_SUBST(PACKAGE_DIR)
+
+AC_SUBST(EXTRA_CC_SWITCHES)
+AC_SUBST(EXTRA_APP_CC_SWITCHES)
+AC_SUBST(EXTRA_INSTALL)
+AC_SUBST(EXTRA_INSTALL_BINARIES)
+AC_SUBST(EXTRA_BUILD_HTML)
+AC_SUBST(EXTRA_TCLSH_LIBS)
+
+AC_SUBST(DLTEST_LD)
+AC_SUBST(DLTEST_SUFFIX)
+
+dnl Disable the automake-friendly normalization of LIBOBJS
+dnl performed by autoconf 2.53 and later. It's not correct for us.
+define([_AC_LIBOBJS_NORMALIZE],[])
+AC_CONFIG_FILES([
+ Makefile:../unix/Makefile.in
+ dltest/Makefile:../unix/dltest/Makefile.in
+ tclConfig.sh:../unix/tclConfig.sh.in
+ tcl.pc:../unix/tcl.pc.in
+])
+AC_OUTPUT
+
+dnl Local Variables:
+dnl mode: autoconf
+dnl End:
diff --git a/unix/dltest/Makefile.in b/unix/dltest/Makefile.in
new file mode 100644
index 0000000..25b9376
--- /dev/null
+++ b/unix/dltest/Makefile.in
@@ -0,0 +1,110 @@
+# This Makefile is used to create several test cases for Tcl's load
+# command. It also illustrates how to take advantage of configuration
+# exported by Tcl to set up Makefiles for shared libraries.
+
+CC = @CC@
+LIBS = @TCL_BUILD_STUB_LIB_SPEC@ @TCL_LIBS@
+AC_FLAGS = @DEFS@
+SHLIB_LD = @SHLIB_LD@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@
+SHLIB_LD_LIBS = @SHLIB_LD_LIBS@
+SHLIB_SUFFIX = @SHLIB_SUFFIX@
+DLTEST_LD = @DLTEST_LD@
+DLTEST_SUFFIX = @DLTEST_SUFFIX@
+SRC_DIR = @TCL_SRC_DIR@/unix/dltest
+BUILD_DIR = @builddir@
+TCL_VERSION= @TCL_VERSION@
+
+CFLAGS_DEBUG = @CFLAGS_DEBUG@
+CFLAGS_OPTIMIZE = @CFLAGS_OPTIMIZE@
+CFLAGS = @CFLAGS_DEFAULT@ @CFLAGS@
+LDFLAGS_DEBUG = @LDFLAGS_DEBUG@
+LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@
+LDFLAGS = @LDFLAGS_DEFAULT@ @LDFLAGS@
+
+CC_SWITCHES = $(CFLAGS) -I${SRC_DIR}/../../generic -DTCL_MEM_DEBUG \
+ ${SHLIB_CFLAGS} -DUSE_TCL_STUBS ${AC_FLAGS}
+
+all: pkga${SHLIB_SUFFIX} pkgb${SHLIB_SUFFIX} pkgc${SHLIB_SUFFIX} pkgd${SHLIB_SUFFIX} pkge${SHLIB_SUFFIX} pkgua${SHLIB_SUFFIX} pkgooa${SHLIB_SUFFIX}
+ @if test -n "$(DLTEST_SUFFIX)"; then $(MAKE) dltest_suffix; fi
+ @touch ../dltest.marker
+
+dltest_suffix: pkga${DLTEST_SUFFIX} pkgb${DLTEST_SUFFIX} pkgc${DLTEST_SUFFIX} pkgd${DLTEST_SUFFIX} pkge${DLTEST_SUFFIX} pkgua${DLTEST_SUFFIX} pkgooa${DLTEST_SUFFIX}
+ @touch ../dltest.marker
+
+pkga.o: $(SRC_DIR)/pkga.c
+ $(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkga.c
+
+pkgb.o: $(SRC_DIR)/pkgb.c
+ $(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgb.c
+
+pkgc.o: $(SRC_DIR)/pkgc.c
+ $(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgc.c
+
+pkgd.o: $(SRC_DIR)/pkgd.c
+ $(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgd.c
+
+pkge.o: $(SRC_DIR)/pkge.c
+ $(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkge.c
+
+pkgua.o: $(SRC_DIR)/pkgua.c
+ $(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgua.c
+
+pkgooa.o: $(SRC_DIR)/pkgooa.c
+ $(CC) -c $(CC_SWITCHES) $(SRC_DIR)/pkgooa.c
+
+pkga${SHLIB_SUFFIX}: pkga.o
+ ${SHLIB_LD} -o pkga${SHLIB_SUFFIX} pkga.o ${SHLIB_LD_LIBS}
+
+pkgb${SHLIB_SUFFIX}: pkgb.o
+ ${SHLIB_LD} -o pkgb${SHLIB_SUFFIX} pkgb.o ${SHLIB_LD_LIBS}
+
+pkgc${SHLIB_SUFFIX}: pkgc.o
+ ${SHLIB_LD} -o pkgc${SHLIB_SUFFIX} pkgc.o ${SHLIB_LD_LIBS}
+
+pkgd${SHLIB_SUFFIX}: pkgd.o
+ ${SHLIB_LD} -o pkgd${SHLIB_SUFFIX} pkgd.o ${SHLIB_LD_LIBS}
+
+pkge${SHLIB_SUFFIX}: pkge.o
+ ${SHLIB_LD} -o pkge${SHLIB_SUFFIX} pkge.o ${SHLIB_LD_LIBS}
+
+pkgua${SHLIB_SUFFIX}: pkgua.o
+ ${SHLIB_LD} -o pkgua${SHLIB_SUFFIX} pkgua.o ${SHLIB_LD_LIBS}
+
+pkgooa${SHLIB_SUFFIX}: pkgooa.o
+ ${SHLIB_LD} -o pkgooa${SHLIB_SUFFIX} pkgooa.o ${SHLIB_LD_LIBS}
+
+pkga${DLTEST_SUFFIX}: pkga.o
+ ${DLTEST_LD} -o pkga${DLTEST_SUFFIX} pkga.o ${SHLIB_LD_LIBS}
+
+pkgb${DLTEST_SUFFIX}: pkgb.o
+ ${DLTEST_LD} -o pkgb${DLTEST_SUFFIX} pkgb.o ${SHLIB_LD_LIBS}
+
+pkgc${DLTEST_SUFFIX}: pkgc.o
+ ${DLTEST_LD} -o pkgc${DLTEST_SUFFIX} pkgc.o ${SHLIB_LD_LIBS}
+
+pkgd${DLTEST_SUFFIX}: pkgd.o
+ ${DLTEST_LD} -o pkgd${DLTEST_SUFFIX} pkgd.o ${SHLIB_LD_LIBS}
+
+pkge${DLTEST_SUFFIX}: pkge.o
+ ${DLTEST_LD} -o pkge${DLTEST_SUFFIX} pkge.o ${SHLIB_LD_LIBS}
+
+pkgua${DLTEST_SUFFIX}: pkgua.o
+ ${DLTEST_LD} -o pkgua${DLTEST_SUFFIX} pkgua.o ${SHLIB_LD_LIBS}
+
+pkgooa${DLTEST_SUFFIX}: pkgooa.o
+ ${DLTEST_LD} -o pkgooa${DLTEST_SUFFIX} pkgooa.o ${SHLIB_LD_LIBS}
+
+clean:
+ rm -f *.o lib.exp ../dltest.marker
+ @if test "$(SHLIB_SUFFIX)" != ""; then \
+ echo "rm -f *${SHLIB_SUFFIX}" ; \
+ rm -f *${SHLIB_SUFFIX} ; \
+ fi
+ @if test "$(DLTEST_SUFFIX)" != ""; then \
+ echo "rm -f *${DLTEST_SUFFIX}" ; \
+ rm -f *${DLTEST_SUFFIX} ; \
+ fi
+
+distclean: clean
+ rm -f Makefile
diff --git a/unix/dltest/README b/unix/dltest/README
new file mode 100644
index 0000000..3210f13
--- /dev/null
+++ b/unix/dltest/README
@@ -0,0 +1,4 @@
+This directory contains several files for testing Tcl's dynamic
+loading/unloading capabilities. If shared libraries are supported
+then the build system in the parent directory will create
+the shared libs and load them into the tcltest executable.
diff --git a/unix/dltest/pkga.c b/unix/dltest/pkga.c
new file mode 100644
index 0000000..5bf3c1e
--- /dev/null
+++ b/unix/dltest/pkga.c
@@ -0,0 +1,137 @@
+/*
+ * pkga.c --
+ *
+ * This file contains a simple Tcl package "pkga" that is intended for
+ * testing the Tcl dynamic loading facilities.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#undef STATIC_BUILD
+#include "tcl.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static int Pkga_EqObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+static int Pkga_QuoteObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkga_EqObjCmd --
+ *
+ * This procedure is invoked to process the "pkga_eq" Tcl command. It
+ * expects two arguments and returns 1 if they are the same, 0 if they
+ * are different.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Pkga_EqObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int result;
+ const char *str1, *str2;
+ int len1, len2;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string1 string2");
+ return TCL_ERROR;
+ }
+
+ str1 = Tcl_GetStringFromObj(objv[1], &len1);
+ str2 = Tcl_GetStringFromObj(objv[2], &len2);
+ if (len1 == len2) {
+ result = (Tcl_UtfNcmp(str1, str2, len1) == 0);
+ } else {
+ result = 0;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkga_QuoteObjCmd --
+ *
+ * This procedure is invoked to process the "pkga_quote" Tcl command. It
+ * expects one argument, which it returns as result.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Pkga_QuoteObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "value");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkga_Init --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkga_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ int code;
+
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ code = Tcl_PkgProvide(interp, "Pkga", "1.0");
+ if (code != TCL_OK) {
+ return code;
+ }
+ Tcl_CreateObjCommand(interp, "pkga_eq", Pkga_EqObjCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "pkga_quote", Pkga_QuoteObjCmd, NULL,
+ NULL);
+ return TCL_OK;
+}
diff --git a/unix/dltest/pkgb.c b/unix/dltest/pkgb.c
new file mode 100644
index 0000000..f102496
--- /dev/null
+++ b/unix/dltest/pkgb.c
@@ -0,0 +1,190 @@
+/*
+ * pkgb.c --
+ *
+ * This file contains a simple Tcl package "pkgb" that is intended for
+ * testing the Tcl dynamic loading facilities. It can be used in both
+ * safe and unsafe interpreters.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#undef STATIC_BUILD
+#include "tcl.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static int Pkgb_SubObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+static int Pkgb_UnsafeObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+static int Pkgb_DemoObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgb_SubObjCmd --
+ *
+ * This procedure is invoked to process the "pkgb_sub" Tcl command. It
+ * expects two arguments and returns their difference.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifndef Tcl_GetErrorLine
+# define Tcl_GetErrorLine(interp) ((interp)->errorLine)
+#endif
+
+static int
+Pkgb_SubObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int first, second;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "num num");
+ return TCL_ERROR;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {
+ char buf[TCL_INTEGER_SPACE];
+ sprintf(buf, "%d", Tcl_GetErrorLine(interp));
+ Tcl_AppendResult(interp, " in line: ", buf, NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(first - second));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgb_UnsafeObjCmd --
+ *
+ * This procedure is invoked to process the "pkgb_unsafe" Tcl command. It
+ * just returns a constant string.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Pkgb_UnsafeObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ return Tcl_EvalEx(interp, "list unsafe command invoked", -1, TCL_EVAL_GLOBAL);
+}
+
+static int
+Pkgb_DemoObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+#if (TCL_MAJOR_VERSION > 8) || (TCL_MINOR_VERSION > 4)
+ Tcl_Obj *first;
+
+ if (Tcl_ListObjIndex(NULL, Tcl_GetEncodingSearchPath(), 0, &first)
+ == TCL_OK) {
+ Tcl_SetObjResult(interp, first);
+ }
+#else
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetDefaultEncodingDir(), -1));
+#endif
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgb_Init --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkgb_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ int code;
+
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ code = Tcl_PkgProvide(interp, "Pkgb", "2.3");
+ if (code != TCL_OK) {
+ return code;
+ }
+ Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "pkgb_unsafe", Pkgb_UnsafeObjCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "pkgb_demo", Pkgb_DemoObjCmd, NULL, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgb_SafeInit --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to a safe interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkgb_SafeInit(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ int code;
+
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ code = Tcl_PkgProvide(interp, "Pkgb", "2.3");
+ if (code != TCL_OK) {
+ return code;
+ }
+ Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd, NULL, NULL);
+ return TCL_OK;
+}
diff --git a/unix/dltest/pkgc.c b/unix/dltest/pkgc.c
new file mode 100644
index 0000000..983fcf3
--- /dev/null
+++ b/unix/dltest/pkgc.c
@@ -0,0 +1,162 @@
+/*
+ * pkgc.c --
+ *
+ * This file contains a simple Tcl package "pkgc" that is intended for
+ * testing the Tcl dynamic loading facilities. It can be used in both
+ * safe and unsafe interpreters.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#undef STATIC_BUILD
+#include "tcl.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static int Pkgc_SubObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+static int Pkgc_UnsafeObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgc_SubObjCmd --
+ *
+ * This procedure is invoked to process the "pkgc_sub" Tcl command. It
+ * expects two arguments and returns their difference.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Pkgc_SubObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int first, second;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "num num");
+ return TCL_ERROR;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(first - second));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgc_UnsafeCmd --
+ *
+ * This procedure is invoked to process the "pkgc_unsafe" Tcl command. It
+ * just returns a constant string.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Pkgc_UnsafeObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgc_Init --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkgc_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ int code;
+
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2");
+ if (code != TCL_OK) {
+ return code;
+ }
+ Tcl_CreateObjCommand(interp, "pkgc_sub", Pkgc_SubObjCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "pkgc_unsafe", Pkgc_UnsafeObjCmd, NULL,
+ NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgc_SafeInit --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to a safe interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkgc_SafeInit(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ int code;
+
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2");
+ if (code != TCL_OK) {
+ return code;
+ }
+ Tcl_CreateObjCommand(interp, "pkgc_sub", Pkgc_SubObjCmd, NULL, NULL);
+ return TCL_OK;
+}
diff --git a/unix/dltest/pkgd.c b/unix/dltest/pkgd.c
new file mode 100644
index 0000000..c708df0
--- /dev/null
+++ b/unix/dltest/pkgd.c
@@ -0,0 +1,162 @@
+/*
+ * pkgd.c --
+ *
+ * This file contains a simple Tcl package "pkgd" that is intended for
+ * testing the Tcl dynamic loading facilities. It can be used in both
+ * safe and unsafe interpreters.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#undef STATIC_BUILD
+#include "tcl.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static int Pkgd_SubObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+static int Pkgd_UnsafeObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgd_SubObjCmd --
+ *
+ * This procedure is invoked to process the "pkgd_sub" Tcl command. It
+ * expects two arguments and returns their difference.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Pkgd_SubObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int first, second;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "num num");
+ return TCL_ERROR;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(first - second));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgd_UnsafeCmd --
+ *
+ * This procedure is invoked to process the "pkgd_unsafe" Tcl command. It
+ * just returns a constant string.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Pkgd_UnsafeObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("unsafe command invoked", -1));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgd_Init --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkgd_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ int code;
+
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ code = Tcl_PkgProvide(interp, "Pkgd", "7.3");
+ if (code != TCL_OK) {
+ return code;
+ }
+ Tcl_CreateObjCommand(interp, "pkgd_sub", Pkgd_SubObjCmd, NULL, NULL);
+ Tcl_CreateObjCommand(interp, "pkgd_unsafe", Pkgd_UnsafeObjCmd, NULL,
+ NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgd_SafeInit --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to a safe interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkgd_SafeInit(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ int code;
+
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ code = Tcl_PkgProvide(interp, "Pkgd", "7.3");
+ if (code != TCL_OK) {
+ return code;
+ }
+ Tcl_CreateObjCommand(interp, "pkgd_sub", Pkgd_SubObjCmd, NULL, NULL);
+ return TCL_OK;
+}
diff --git a/unix/dltest/pkge.c b/unix/dltest/pkge.c
new file mode 100644
index 0000000..f46ca74
--- /dev/null
+++ b/unix/dltest/pkge.c
@@ -0,0 +1,45 @@
+/*
+ * pkge.c --
+ *
+ * This file contains a simple Tcl package "pkge" that is intended for
+ * testing the Tcl dynamic loading facilities. Its Init procedure returns
+ * an error in order to test how this is handled.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#undef STATIC_BUILD
+#include "tcl.h"
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkge_Init --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
+ *
+ * Results:
+ * Returns TCL_ERROR and leaves an error message in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkge_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ static const char script[] = "if 44 {open non_existent}";
+
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ return Tcl_EvalEx(interp, script, -1, 0);
+}
diff --git a/unix/dltest/pkgooa.c b/unix/dltest/pkgooa.c
new file mode 100644
index 0000000..5a0b0ef
--- /dev/null
+++ b/unix/dltest/pkgooa.c
@@ -0,0 +1,141 @@
+/*
+ * pkgooa.c --
+ *
+ * This file contains a simple Tcl package "pkgooa" that is intended for
+ * testing the Tcl dynamic loading facilities.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#undef STATIC_BUILD
+#include "tclOO.h"
+#include <string.h>
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgooa_StubsOKObjCmd --
+ *
+ * This procedure is invoked to process the "pkgooa_stubsok" Tcl command.
+ * It gives 1 if stubs are used correctly, 0 if stubs are not OK.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+Pkgooa_StubsOKObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(
+ Tcl_CopyObjectInstance == tclOOStubsPtr->tcl_CopyObjectInstance));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgooa_Init --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+extern void *tclOOIntStubsPtr;
+
+static TclOOStubs stubsCopy = {
+ TCL_STUB_MAGIC,
+ NULL,
+ /* It doesn't really matter what implementation of
+ * Tcl_CopyObjectInstance is put in the "pseudo"
+ * stub table, since the test-case never actually
+ * calls this function. All that matters is that it's
+ * a function with a different memory address than
+ * the real Tcl_CopyObjectInstance function in Tcl. */
+ (Tcl_Object (*) (Tcl_Interp *, Tcl_Object, const char *,
+ const char *t)) Pkgooa_StubsOKObjCmd
+ /* More entries could be here, but those are not used
+ * for this test-case. So, being NULL is OK. */
+};
+
+extern DLLEXPORT int
+Pkgooa_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ int code;
+
+ /* Any TclOO extension which uses stubs, calls
+ * both Tcl_InitStubs and Tcl_OOInitStubs() and
+ * does not use any Tcl 8.6 features should be
+ * loadable in Tcl 8.5 as well, provided the
+ * TclOO extension (for Tcl 8.5) is installed.
+ * This worked in Tcl 8.6.0, and is expected
+ * to keep working in all future Tcl 8.x releases.
+ */
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ if (tclStubsPtr == NULL) {
+ Tcl_AppendResult(interp, "Tcl stubs are not inialized, "
+ "did you compile using -DUSE_TCL_STUBS? ");
+ return TCL_ERROR;
+ }
+ if (Tcl_OOInitStubs(interp) == NULL) {
+ return TCL_ERROR;
+ }
+ if (tclOOStubsPtr == NULL) {
+ Tcl_AppendResult(interp, "TclOO stubs are not inialized");
+ return TCL_ERROR;
+ }
+ if (tclOOIntStubsPtr == NULL) {
+ Tcl_AppendResult(interp, "TclOO internal stubs are not inialized");
+ return TCL_ERROR;
+ }
+
+ /* Test case for Bug [f51efe99a7].
+ *
+ * Let tclOOStubsPtr point to an alternate stub table
+ * (with only a single function, that's enough for
+ * this test). This way, the function "pkgooa_stubsok"
+ * can check whether the TclOO function calls really
+ * use the stub table, or only pretend to.
+ *
+ * On platforms without backlinking (Windows, Cygwin,
+ * AIX), this code doesn't even compile without using
+ * stubs, but on UNIX ELF systems, the problem is
+ * less visible.
+ */
+
+ tclOOStubsPtr = &stubsCopy;
+
+ code = Tcl_PkgProvide(interp, "Pkgooa", "1.0");
+ if (code != TCL_OK) {
+ return code;
+ }
+ Tcl_CreateObjCommand(interp, "pkgooa_stubsok", Pkgooa_StubsOKObjCmd, NULL, NULL);
+ return TCL_OK;
+}
diff --git a/unix/dltest/pkgua.c b/unix/dltest/pkgua.c
new file mode 100644
index 0000000..9d5a9d9
--- /dev/null
+++ b/unix/dltest/pkgua.c
@@ -0,0 +1,332 @@
+/*
+ * pkgua.c --
+ *
+ * This file contains a simple Tcl package "pkgua" that is intended for
+ * testing the Tcl dynamic unloading facilities.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ * Copyright (c) 2004 Georgios Petasis
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tcl.h"
+
+/*
+ * Prototypes for procedures defined later in this file:
+ */
+
+static int PkguaEqObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+static int PkguaQuoteObjCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+
+/*
+ * In the following hash table we are going to store a struct that holds all
+ * the command tokens created by Tcl_CreateObjCommand in an interpreter,
+ * indexed by the interpreter. In this way, we can find which command tokens
+ * we have registered in a specific interpreter, in order to unload them. We
+ * need to keep the various command tokens we have registered, as they are the
+ * only safe way to unregister our registered commands, even if they have been
+ * renamed.
+ *
+ * Note that this code is utterly single-threaded.
+ */
+
+static Tcl_HashTable interpTokenMap;
+static int interpTokenMapInitialised = 0;
+#define MAX_REGISTERED_COMMANDS 2
+
+
+static void
+PkguaInitTokensHashTable(void)
+{
+ if (interpTokenMapInitialised) {
+ return;
+ }
+ Tcl_InitHashTable(&interpTokenMap, TCL_ONE_WORD_KEYS);
+ interpTokenMapInitialised = 1;
+}
+
+static void
+PkguaFreeTokensHashTable(void)
+{
+ Tcl_HashSearch search;
+ Tcl_HashEntry *entryPtr;
+
+ for (entryPtr = Tcl_FirstHashEntry(&interpTokenMap, &search);
+ entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
+ }
+ interpTokenMapInitialised = 0;
+}
+
+static Tcl_Command *
+PkguaInterpToTokens(
+ Tcl_Interp *interp)
+{
+ int newEntry;
+ Tcl_Command *cmdTokens;
+ Tcl_HashEntry *entryPtr =
+ Tcl_CreateHashEntry(&interpTokenMap, interp, &newEntry);
+
+ if (newEntry) {
+ cmdTokens = (Tcl_Command *)
+ Tcl_Alloc(sizeof(Tcl_Command) * (MAX_REGISTERED_COMMANDS+1));
+ for (newEntry=0 ; newEntry<MAX_REGISTERED_COMMANDS+1 ; ++newEntry) {
+ cmdTokens[newEntry] = NULL;
+ }
+ Tcl_SetHashValue(entryPtr, cmdTokens);
+ } else {
+ cmdTokens = (Tcl_Command *) Tcl_GetHashValue(entryPtr);
+ }
+ return cmdTokens;
+}
+
+static void
+PkguaDeleteTokens(
+ Tcl_Interp *interp)
+{
+ Tcl_HashEntry *entryPtr =
+ Tcl_FindHashEntry(&interpTokenMap, interp);
+
+ if (entryPtr) {
+ Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PkguaEqObjCmd --
+ *
+ * This procedure is invoked to process the "pkgua_eq" Tcl command. It
+ * expects two arguments and returns 1 if they are the same, 0 if they
+ * are different.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PkguaEqObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int result;
+ const char *str1, *str2;
+ int len1, len2;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "string1 string2");
+ return TCL_ERROR;
+ }
+
+ str1 = Tcl_GetStringFromObj(objv[1], &len1);
+ str2 = Tcl_GetStringFromObj(objv[2], &len2);
+ if (len1 == len2) {
+ result = (Tcl_UtfNcmp(str1, str2, len1) == 0);
+ } else {
+ result = 0;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PkguaQuoteObjCmd --
+ *
+ * This procedure is invoked to process the "pkgua_quote" Tcl command. It
+ * expects one argument, which it returns as result.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PkguaQuoteObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument strings. */
+{
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "value");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgua_Init --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkgua_Init(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ int code, cmdIndex = 0;
+ Tcl_Command *cmdTokens;
+
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Initialise our Hash table, where we store the registered command tokens
+ * for each interpreter.
+ */
+
+ PkguaInitTokensHashTable();
+
+ code = Tcl_PkgProvide(interp, "Pkgua", "1.0");
+ if (code != TCL_OK) {
+ return code;
+ }
+
+ Tcl_SetVar2(interp, "::pkgua_loaded", NULL, ".", TCL_APPEND_VALUE);
+
+ cmdTokens = PkguaInterpToTokens(interp);
+ cmdTokens[cmdIndex++] =
+ Tcl_CreateObjCommand(interp, "pkgua_eq", PkguaEqObjCmd, NULL,
+ NULL);
+ cmdTokens[cmdIndex++] =
+ Tcl_CreateObjCommand(interp, "pkgua_quote", PkguaQuoteObjCmd,
+ NULL, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgua_SafeInit --
+ *
+ * This is a package initialization procedure, which is called by Tcl
+ * when this package is to be added to a safe interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkgua_SafeInit(
+ Tcl_Interp *interp) /* Interpreter in which the package is to be
+ * made available. */
+{
+ return Pkgua_Init(interp);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgua_Unload --
+ *
+ * This is a package unloading initialization procedure, which is called
+ * by Tcl when this package is to be unloaded from an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkgua_Unload(
+ Tcl_Interp *interp, /* Interpreter from which the package is to be
+ * unloaded. */
+ int flags) /* Flags passed by the unloading mechanism */
+{
+ int code, cmdIndex;
+ Tcl_Command *cmdTokens = PkguaInterpToTokens(interp);
+
+ for (cmdIndex=0 ; cmdIndex<MAX_REGISTERED_COMMANDS ; cmdIndex++) {
+ if (cmdTokens[cmdIndex] == NULL) {
+ continue;
+ }
+ code = Tcl_DeleteCommandFromToken(interp, cmdTokens[cmdIndex]);
+ if (code != TCL_OK) {
+ return code;
+ }
+ }
+
+ PkguaDeleteTokens(interp);
+
+ Tcl_SetVar2(interp, "::pkgua_detached", NULL, ".", TCL_APPEND_VALUE);
+
+ if (flags == TCL_UNLOAD_DETACH_FROM_PROCESS) {
+ /*
+ * Tcl is ready to detach this library from the running application.
+ * We should free all the memory that is not related to any
+ * interpreter.
+ */
+
+ PkguaFreeTokensHashTable();
+ Tcl_SetVar2(interp, "::pkgua_unloaded", NULL, ".", TCL_APPEND_VALUE);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Pkgua_SafeUnload --
+ *
+ * This is a package unloading initialization procedure, which is called
+ * by Tcl when this package is to be unloaded from an interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+DLLEXPORT int
+Pkgua_SafeUnload(
+ Tcl_Interp *interp, /* Interpreter from which the package is to be
+ * unloaded. */
+ int flags) /* Flags passed by the unloading mechanism */
+{
+ return Pkgua_Unload(interp, flags);
+}
diff --git a/unix/install-sh b/unix/install-sh
new file mode 100755
index 0000000..7c34c3f
--- /dev/null
+++ b/unix/install-sh
@@ -0,0 +1,528 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2011-04-20.01; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -S $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -S) stripcmd="$stripprog $2"
+ shift;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ do_exit='(exit $ret); exit $ret'
+ trap "ret=129; $do_exit" 1
+ trap "ret=130; $do_exit" 2
+ trap "ret=141; $do_exit" 13
+ trap "ret=143; $do_exit" 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/unix/installManPage b/unix/installManPage
new file mode 100755
index 0000000..1f1cbde
--- /dev/null
+++ b/unix/installManPage
@@ -0,0 +1,117 @@
+#!/bin/sh
+
+########################################################################
+### Parse Options
+###
+
+Gzip=:
+SymOrLoc=""
+Gz=""
+Suffix=""
+
+while true; do
+ case $1 in
+ -s | --symlinks ) SymOrLoc="-s " ;;
+ -z | --compress ) Gzip=$2; shift ;;
+ -e | --extension ) Gz=$2; shift ;;
+ -x | --suffix ) Suffix=$2; shift ;;
+ -*) cat <<EOF
+Unknown option "$1". Supported options:
+ -s Use symbolic links for manpages with multiple names.
+ -z PROG Use PROG to compress manual pages.
+ -e EXT Defines the extension added by -z PROG when compressing.
+ -x SUFF Defines an extra extension suffix to use.
+Option names may not be combined getopt-style.
+EOF
+ exit 1 ;;
+ *) break ;;
+ esac
+ shift
+done
+if test "$#" != 2; then
+ echo "Usage: installManPages <options> file dir"
+ exit 1
+fi
+
+########################################################################
+### Parse Required Arguments
+###
+
+ManPage=$1
+Dir=$2
+if test -f $ManPage ; then : ; else
+ echo "source manual page file must exist"
+ exit 1
+fi
+if test -d $Dir ; then : ; else
+ echo "target directory must exist"
+ exit 1
+fi
+test -z "$SymOrLoc" && SymOrLoc="$Dir/"
+
+########################################################################
+### Extract Target Names from Manual Page
+###
+
+# A sed script to parse the alternative names out of a man page.
+#
+# Backslashes are trippled in the sed script, because it is in
+# backticks which doesn't pass backslashes literally.
+#
+Names=`sed -n '
+# Look for a line that starts with .SH NAME
+ /^\.SH NAME/{
+# Read next line
+ n
+# Remove all commas ...
+ s/,//g
+# ... and backslash-escaped spaces.
+ s/\\\ //g
+# Delete from \- to the end of line
+ s/ \\\-.*//
+# Convert all non-space non-alphanum sequences
+# to single underscores.
+ s/[^ A-Za-z0-9][^ A-Za-z0-9]*/_/g
+# print the result and exit
+ p;q
+ }' $ManPage`
+
+if test -z "$Names" ; then
+ echo "warning: no target names found in $ManPage"
+fi
+
+########################################################################
+### Remaining Set Up
+###
+
+case $ManPage in
+ *.1) Section=1 ;;
+ *.3) Section=3 ;;
+ *.n) Section=n ;;
+ *) echo "unknown section for $ManPage"
+ exit 2 ;;
+esac
+
+SrcDir=`dirname $ManPage`
+
+########################################################################
+### Process Page to Create Target Pages
+###
+
+First=""
+for Target in $Names; do
+ Target=$Target.$Section$Suffix
+ rm -f $Dir/$Target $Dir/$Target.*
+ if test -z "$First" ; then
+ First=$Target
+ sed -e "/man\.macros/r $SrcDir/man.macros" -e "/man\.macros/d" \
+ $ManPage > $Dir/$First
+ chmod 644 $Dir/$First
+ $Gzip $Dir/$First
+ else
+ ln $SymOrLoc$First$Gz $Dir/$Target$Gz
+ fi
+done
+
+########################################################################
+exit 0
diff --git a/unix/ldAix b/unix/ldAix
new file mode 100755
index 0000000..f115ea8
--- /dev/null
+++ b/unix/ldAix
@@ -0,0 +1,58 @@
+#!/bin/sh
+#
+# ldAix ldCmd ldArg ldArg ...
+#
+# This shell script provides a wrapper for ld under AIX in order to
+# create the .exp file required for linking. Its arguments consist
+# of the name and arguments that would normally be provided to the
+# ld command. This script extracts the names of the object files
+# from the argument list, creates a .exp file describing all of the
+# symbols exported by those files, and then invokes "ldCmd" to
+# perform the real link.
+
+# Extract from the arguments the names of all of the object files.
+
+args=$*
+ofiles=""
+for i do
+ x=`echo $i | grep '[^.].o$'`
+ if test "$x" != ""; then
+ ofiles="$ofiles $i"
+ fi
+done
+
+# Extract the name of the object file that we're linking.
+outputFile=`echo $args | sed -e 's/.*-o \([^ ]*\).*/\1/'`
+
+# Create the export file from all of the object files, using nm followed
+# by sed editing. Here are some tricky aspects of this:
+#
+# - Use the -X32_64 switch to nm to handle 32 or 64bit compiles.
+# - Eliminate lines that end in ":": these are the names of object files
+# - Eliminate entries with the "U" key letter; these are undefined symbols
+# - If a line starts with ".", delete the leading ".", since this will just
+# cause confusion later
+# - Eliminate everything after the first field in a line, so that we're
+# left with just the symbol name
+
+nmopts="-g -C -h -X32_64"
+rm -f lib.exp
+echo "#! $outputFile" >lib.exp
+/usr/ccs/bin/nm $nmopts $ofiles | sed -e '/:$/d' -e '/ U /d' -e 's/^\.//' -e 's/[ |].*//' | sort | uniq >>lib.exp
+
+# If we're linking a .a file, then link all the objects together into a
+# single file "shr.o" and then put that into the archive. Otherwise link
+# the object files directly into the .a file.
+
+noDotA=`echo $outputFile | sed -e '/\.a$/d'`
+echo "noDotA=\"$noDotA\""
+if test "$noDotA" = "" ; then
+ linkArgs=`echo $args | sed -e 's/-o .*\.a /-o shr.o /'`
+ echo $linkArgs
+ eval $linkArgs
+ echo ar cr $outputFile shr.o
+ ar cr $outputFile shr.o
+ rm -f shr.o
+else
+ eval $args
+fi
diff --git a/unix/tcl.m4 b/unix/tcl.m4
new file mode 100644
index 0000000..45922e0
--- /dev/null
+++ b/unix/tcl.m4
@@ -0,0 +1,3019 @@
+#------------------------------------------------------------------------
+# SC_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([SC_PATH_TCLCONFIG], [
+ #
+ # 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,
+ AC_HELP_STRING([--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
+
+ # on Darwin, check in Framework installation locations
+ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
+ `ls -d /Library/Frameworks 2>/dev/null` \
+ `ls -d /Network/Library/Frameworks 2>/dev/null` \
+ `ls -d /System/Library/Frameworks 2>/dev/null` \
+ ; do
+ if test -f "$i/Tcl.framework/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/Tcl.framework; 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 ${libdir} 2>/dev/null` \
+ `ls -d ${exec_prefix}/lib 2>/dev/null` \
+ `ls -d ${prefix}/lib 2>/dev/null` \
+ `ls -d /usr/contrib/lib 2>/dev/null` \
+ `ls -d /usr/local/lib 2>/dev/null` \
+ `ls -d /usr/pkg/lib 2>/dev/null` \
+ `ls -d /usr/lib 2>/dev/null` \
+ `ls -d /usr/lib64 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_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh])
+ else
+ no_tcl=
+ TCL_BIN_DIR="${ac_cv_c_tclconfig}"
+ AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh])
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_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([SC_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,
+ AC_HELP_STRING([--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
+
+ # on Darwin, check in Framework installation locations
+ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
+ `ls -d /Library/Frameworks 2>/dev/null` \
+ `ls -d /Network/Library/Frameworks 2>/dev/null` \
+ `ls -d /System/Library/Frameworks 2>/dev/null` \
+ ; do
+ if test -f "$i/Tk.framework/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/Tk.framework; 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 ${libdir} 2>/dev/null` \
+ `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` \
+ `ls -d /usr/lib64 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_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh])
+ else
+ no_tk=
+ TK_BIN_DIR="${ac_cv_c_tkconfig}"
+ AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh])
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_LOAD_TCLCONFIG --
+#
+# Load the tclConfig.sh file
+#
+# Arguments:
+#
+# Requires the following vars to be set:
+# TCL_BIN_DIR
+#
+# Results:
+#
+# Substitutes the following vars:
+# TCL_BIN_DIR
+# TCL_SRC_DIR
+# TCL_LIB_FILE
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_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([could not find ${TCL_BIN_DIR}/tclConfig.sh])
+ fi
+
+ # eval is required to do the TCL_DBGX substitution
+ eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
+ eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
+
+ # 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}"
+ elif test "`uname -s`" = "Darwin"; then
+ # If Tcl was built as a framework, attempt to use the libraries
+ # from the framework at the given location so that linking works
+ # against Tcl.framework installed in an arbitrary location.
+ case ${TCL_DEFS} in
+ *TCL_FRAMEWORK*)
+ if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then
+ for i in "`cd "${TCL_BIN_DIR}"; pwd`" \
+ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do
+ if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then
+ TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}"
+ break
+ fi
+ done
+ fi
+ if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then
+ TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
+ TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"
+ fi
+ ;;
+ esac
+ fi
+
+ # eval is required to do the TCL_DBGX substitution
+ eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
+ eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
+ 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_PATCH_LEVEL)
+ 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)
+])
+
+#------------------------------------------------------------------------
+# SC_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([SC_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
+
+ # eval is required to do the TK_DBGX substitution
+ eval "TK_LIB_FILE=\"${TK_LIB_FILE}\""
+ eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\""
+
+ # 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}"
+ elif test "`uname -s`" = "Darwin"; then
+ # If Tk was built as a framework, attempt to use the libraries
+ # from the framework at the given location so that linking works
+ # against Tk.framework installed in an arbitrary location.
+ case ${TK_DEFS} in
+ *TK_FRAMEWORK*)
+ if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then
+ for i in "`cd "${TK_BIN_DIR}"; pwd`" \
+ "`cd "${TK_BIN_DIR}"/../..; pwd`"; do
+ if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then
+ TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}"
+ break
+ fi
+ done
+ fi
+ if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then
+ TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}"
+ TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"
+ fi
+ ;;
+ esac
+ fi
+
+ # eval is required to do the TK_DBGX substitution
+ eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\""
+ eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\""
+ 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)
+])
+
+#------------------------------------------------------------------------
+# SC_PROG_TCLSH
+# Locate a tclsh shell installed on the system path. This macro
+# will only find a Tcl shell that already exists on the system.
+# It will not find a Tcl shell in the Tcl build directory or
+# a Tcl shell that has been installed from the Tcl build directory.
+# If a Tcl shell can't be located on the PATH, then TCLSH_PROG will
+# be set to "". Extensions should take care not to create Makefile
+# rules that are run by default and depend on TCLSH_PROG. An
+# extension can't assume that an executable Tcl shell exists at
+# build time.
+#
+# Arguments:
+# none
+#
+# Results:
+# Substitutes the following vars:
+# TCLSH_PROG
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_PROG_TCLSH], [
+ AC_MSG_CHECKING([for tclsh])
+ AC_CACHE_VAL(ac_cv_path_tclsh, [
+ search_path=`echo ${PATH} | sed -e 's/:/ /g'`
+ for dir in $search_path ; do
+ for j in `ls -r $dir/tclsh[[8-9]]* 2> /dev/null` \
+ `ls -r $dir/tclsh* 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
+ # It is not an error if an installed version of Tcl can't be located.
+ TCLSH_PROG=""
+ AC_MSG_RESULT([No tclsh found on PATH])
+ fi
+ AC_SUBST(TCLSH_PROG)
+])
+
+#------------------------------------------------------------------------
+# SC_BUILD_TCLSH
+# Determine the fully qualified path name of the tclsh executable
+# in the Tcl build directory. This macro will correctly determine
+# the name of the tclsh executable even if tclsh has not yet
+# been built in the build directory. The build tclsh must be used
+# when running tests from an extension build directory. It is not
+# correct to use the TCLSH_PROG in cases like this.
+#
+# Arguments:
+# none
+#
+# Results:
+# Substitutes the following values:
+# BUILD_TCLSH
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_BUILD_TCLSH], [
+ AC_MSG_CHECKING([for tclsh in Tcl build directory])
+ BUILD_TCLSH="${TCL_BIN_DIR}"/tclsh
+ AC_MSG_RESULT([$BUILD_TCLSH])
+ AC_SUBST(BUILD_TCLSH)
+])
+
+#------------------------------------------------------------------------
+# SC_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([SC_ENABLE_SHARED], [
+ AC_MSG_CHECKING([how to build libraries])
+ AC_ARG_ENABLE(shared,
+ AC_HELP_STRING([--enable-shared],
+ [build and link with shared libraries (default: on)]),
+ [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
+])
+
+#------------------------------------------------------------------------
+# SC_ENABLE_FRAMEWORK --
+#
+# Allows the building of shared libraries into frameworks
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-framework=yes|no
+#
+# Sets the following vars:
+# FRAMEWORK_BUILD Value of 1 or 0
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_ENABLE_FRAMEWORK], [
+ if test "`uname -s`" = "Darwin" ; then
+ AC_MSG_CHECKING([how to package libraries])
+ AC_ARG_ENABLE(framework,
+ AC_HELP_STRING([--enable-framework],
+ [package shared libraries in MacOSX frameworks (default: off)]),
+ [enable_framework=$enableval], [enable_framework=no])
+ if test $enable_framework = yes; then
+ if test $SHARED_BUILD = 0; then
+ AC_MSG_WARN([Frameworks can only be built if --enable-shared is yes])
+ enable_framework=no
+ fi
+ if test $tcl_corefoundation = no; then
+ AC_MSG_WARN([Frameworks can only be used when CoreFoundation is available])
+ enable_framework=no
+ fi
+ fi
+ if test $enable_framework = yes; then
+ AC_MSG_RESULT([framework])
+ FRAMEWORK_BUILD=1
+ else
+ if test $SHARED_BUILD = 1; then
+ AC_MSG_RESULT([shared library])
+ else
+ AC_MSG_RESULT([static library])
+ fi
+ FRAMEWORK_BUILD=0
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_ENABLE_THREADS --
+#
+# Specify if thread support should be enabled
+#
+# 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
+# _THREAD_SAFE
+#------------------------------------------------------------------------
+
+AC_DEFUN([SC_ENABLE_THREADS], [
+ AC_ARG_ENABLE(threads,
+ AC_HELP_STRING([--enable-threads],
+ [build with threads (default: on)]),
+ [tcl_ok=$enableval], [tcl_ok=yes])
+
+ if test "${TCL_THREADS}" = 1; then
+ tcl_threaded_core=1;
+ fi
+
+ if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
+ TCL_THREADS=1
+ # USE_THREAD_ALLOC tells us to try the special thread-based
+ # allocator that significantly reduces lock contention
+ 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?])
+ if test "`uname -s`" = "SunOS" ; then
+ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
+ [Do we really want to follow the standard? Yes we do!])
+ fi
+ 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 - you must disable thread support or edit the LIBS in the Makefile...])
+ 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 pthread_atfork)
+ LIBS=$ac_saved_libs
+ 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?])
+ if test "${tcl_threaded_core}" = 1; then
+ AC_MSG_RESULT([yes (threaded core)])
+ else
+ AC_MSG_RESULT([yes])
+ fi
+ else
+ AC_MSG_RESULT([no])
+ fi
+
+ AC_SUBST(TCL_THREADS)
+])
+
+#------------------------------------------------------------------------
+# SC_ENABLE_SYMBOLS --
+#
+# Specify if debugging symbols should be used.
+# Memory (TCL_MEM_DEBUG) and compile (TCL_COMPILE_DEBUG) debugging
+# can also be enabled.
+#
+# Arguments:
+# none
+#
+# Requires the following vars to be set in the Makefile:
+# 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([SC_ENABLE_SYMBOLS], [
+ AC_MSG_CHECKING([for build with symbols])
+ AC_ARG_ENABLE(symbols,
+ AC_HELP_STRING([--enable-symbols],
+ [build with debugging symbols (default: off)]),
+ [tcl_ok=$enableval], [tcl_ok=no])
+# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
+ DBGX=""
+ if test "$tcl_ok" = "no"; then
+ CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
+ LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
+ AC_DEFINE(NDEBUG, 1, [Is no debugging enabled?])
+ AC_MSG_RESULT([no])
+ AC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?])
+ else
+ CFLAGS_DEFAULT='$(CFLAGS_DEBUG)'
+ LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)'
+ if test "$tcl_ok" = "yes"; then
+ AC_MSG_RESULT([yes (standard debugging)])
+ fi
+ fi
+ 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
+
+ ifelse($1,bccdebug,dnl Only enable 'compile' for the Tcl core itself
+ if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then
+ AC_DEFINE(TCL_COMPILE_DEBUG, 1, [Is bytecode debugging enabled?])
+ AC_DEFINE(TCL_COMPILE_STATS, 1, [Are bytecode statistics enabled?])
+ fi)
+
+ if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
+ if test "$tcl_ok" = "all"; then
+ AC_MSG_RESULT([enabled symbols mem ]ifelse($1,bccdebug,[compile ])[debugging])
+ else
+ AC_MSG_RESULT([enabled $tcl_ok debugging])
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# SC_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([SC_ENABLE_LANGINFO], [
+ AC_ARG_ENABLE(langinfo,
+ AC_HELP_STRING([--enable-langinfo],
+ [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
+ [langinfo_ok=$enableval], [langinfo_ok=yes])
+
+ HAVE_LANGINFO=0
+ if test "$langinfo_ok" = "yes"; then
+ AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
+ fi
+ AC_MSG_CHECKING([whether to use nl_langinfo])
+ if test "$langinfo_ok" = "yes"; then
+ AC_CACHE_VAL(tcl_cv_langinfo_h, [
+ AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);],
+ [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])
+ AC_MSG_RESULT([$tcl_cv_langinfo_h])
+ if test $tcl_cv_langinfo_h = yes; then
+ AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
+ fi
+ else
+ AC_MSG_RESULT([$langinfo_ok])
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_CONFIG_MANPAGES
+#
+# Decide whether to use symlinks for linking the manpages,
+# whether to compress the manpages after installation, and
+# whether to add a package name suffix to the installed
+# manpages to avoidfile name clashes.
+# If compression is enabled also find out what file name suffix
+# the given compression program is using.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-man-symlinks
+# --enable-man-compression=PROG
+# --enable-man-suffix[=STRING]
+#
+# Defines the following variable:
+#
+# MAN_FLAGS - The apropriate flags for installManPage
+# according to the user's selection.
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_CONFIG_MANPAGES], [
+ AC_MSG_CHECKING([whether to use symlinks for manpages])
+ AC_ARG_ENABLE(man-symlinks,
+ AC_HELP_STRING([--enable-man-symlinks],
+ [use symlinks for the manpages (default: off)]),
+ test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks",
+ enableval="no")
+ AC_MSG_RESULT([$enableval])
+
+ AC_MSG_CHECKING([whether to compress the manpages])
+ AC_ARG_ENABLE(man-compression,
+ AC_HELP_STRING([--enable-man-compression=PROG],
+ [compress the manpages with PROG (default: off)]),
+ [case $enableval in
+ yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);;
+ no) ;;
+ *) MAN_FLAGS="$MAN_FLAGS --compress $enableval";;
+ esac],
+ enableval="no")
+ AC_MSG_RESULT([$enableval])
+ if test "$enableval" != "no"; then
+ AC_MSG_CHECKING([for compressed file suffix])
+ touch TeST
+ $enableval TeST
+ Z=`ls TeST* | sed 's/^....//'`
+ rm -f TeST*
+ MAN_FLAGS="$MAN_FLAGS --extension $Z"
+ AC_MSG_RESULT([$Z])
+ fi
+
+ AC_MSG_CHECKING([whether to add a package name suffix for the manpages])
+ AC_ARG_ENABLE(man-suffix,
+ AC_HELP_STRING([--enable-man-suffix=STRING],
+ [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]),
+ [case $enableval in
+ yes) enableval="AC_PACKAGE_NAME" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
+ no) ;;
+ *) MAN_FLAGS="$MAN_FLAGS --suffix $enableval";;
+ esac],
+ enableval="no")
+ AC_MSG_RESULT([$enableval])
+
+ AC_SUBST(MAN_FLAGS)
+])
+
+#--------------------------------------------------------------------
+# SC_CONFIG_SYSTEM
+#
+# Determine what the system is (some things cannot be easily checked
+# on a feature-driven basis, alas). This can usually be done via the
+# "uname" command.
+#
+# Arguments:
+# none
+#
+# Results:
+# Defines the following var:
+#
+# system - System/platform/version identification code.
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_CONFIG_SYSTEM], [
+ AC_CACHE_CHECK([system version], tcl_cv_sys_version, [
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ tcl_cv_sys_version=windows
+ else
+ tcl_cv_sys_version=`uname -s`-`uname -r`
+ if test "$?" -ne 0 ; then
+ AC_MSG_WARN([can't find uname command])
+ tcl_cv_sys_version=unknown
+ else
+ if test "`uname -s`" = "AIX" ; then
+ tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
+ fi
+ fi
+ fi
+ ])
+ system=$tcl_cv_sys_version
+])
+
+#--------------------------------------------------------------------
+# SC_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 and substitutes 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. Could
+# be the same as CC_SEARCH_FLAGS if ${CC} is used to link.
+# CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/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.
+# MAKE_LIB - Command to execute to build the a library;
+# differs when building shared or static.
+# MAKE_STUB_LIB -
+# Command to execute to build a stub library.
+# INSTALL_LIB - Command to execute to install a library;
+# differs when building shared or static.
+# INSTALL_STUB_LIB -
+# Command to execute to install a stub library.
+# STLIB_LD - Base command to use for combining object files
+# into a static library.
+# 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 defaults to
+# "${LIBS}" if all of the dependent libraries should
+# be specified when creating a shared library. If
+# dependent libraries should not be specified (as on some
+# SunOS systems, 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_SHLIB_LD_EXTRAS - Additional element which are added to SHLIB_LD_LIBS
+# TK_SHLIB_LD_EXTRAS for the build of Tcl and Tk, but not recorded in the
+# tclConfig.sh, since they are only used for the build
+# of Tcl and Tk.
+# Examples: MacOS X records the library version and
+# compatibility version in the shared library. But
+# of course the Tcl version of this is only used for Tcl.
+# LIB_SUFFIX - Specifies everything that comes after the "libfoo"
+# in a static or shared library name, using the $VERSION variable
+# to put the version in the right place. This is used
+# by platforms that need non-standard library names.
+# Examples: ${VERSION}.so.1.1 on NetBSD, since it needs
+# to have a version after the .so, and ${VERSION}.a
+# on AIX, since a shared library needs to have
+# a .a extension whereas shared objects for loadable
+# extensions have a .so extension. Defaults to
+# ${VERSION}${SHLIB_SUFFIX}.
+# TCL_LIBS -
+# Libs to use when linking Tcl shell or some other
+# shell that includes Tcl libs.
+# CFLAGS_DEBUG -
+# Flags used when running the compiler in debug mode
+# CFLAGS_OPTIMIZE -
+# Flags used when running the compiler in optimize mode
+# CFLAGS - Additional CFLAGS added as necessary (usually 64-bit)
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_CONFIG_CFLAGS], [
+
+ # Step 0.a: Enable 64 bit support?
+
+ AC_MSG_CHECKING([if 64bit support is requested])
+ AC_ARG_ENABLE(64bit,
+ AC_HELP_STRING([--enable-64bit],
+ [enable 64bit support (default: off)]),
+ [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,
+ AC_HELP_STRING([--enable-64bit-vis],
+ [enable 64bit Sparc VIS support (default: off)]),
+ [do64bitVIS=$enableval], [do64bitVIS=no])
+ AC_MSG_RESULT([$do64bitVIS])
+ # Force 64bit on with VIS
+ AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])
+
+ # Step 0.c: Check if visibility support is available. Do this here so
+ # that platform specific alternatives can be used below if this fails.
+
+ AC_CACHE_CHECK([if compiler supports visibility "hidden"],
+ tcl_cv_cc_visibility_hidden, [
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ AC_TRY_LINK([
+ extern __attribute__((__visibility__("hidden"))) void f(void);
+ void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,
+ tcl_cv_cc_visibility_hidden=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
+ AC_DEFINE(MODULE_SCOPE,
+ [extern __attribute__((__visibility__("hidden")))],
+ [Compiler support for module scope symbols])
+ AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols])
+ ])
+
+ # Step 0.d: Disable -rpath support?
+
+ AC_MSG_CHECKING([if rpath support is requested])
+ AC_ARG_ENABLE(rpath,
+ AC_HELP_STRING([--disable-rpath],
+ [disable rpath support (default: on)]),
+ [doRpath=$enableval], [doRpath=yes])
+ AC_MSG_RESULT([$doRpath])
+
+ # Step 1: set the variable "system" to hold the name and version number
+ # for the system.
+
+ SC_CONFIG_SYSTEM
+
+ # 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)
+
+ # Require ranlib early so we can override it in special cases below.
+
+ AC_REQUIRE([AC_PROG_RANLIB])
+
+ # Step 3: set configuration options based on system name and version.
+
+ do64bit_ok=no
+ # default to '{$LIBS}' and set to "" on per-platform necessary basis
+ SHLIB_LD_LIBS='${LIBS}'
+ LDFLAGS_ORIG="$LDFLAGS"
+ # When ld needs options to work in 64-bit mode, put them in
+ # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]
+ # is disabled by the user. [Bug 1016796]
+ LDFLAGS_ARCH=""
+ UNSHARED_LIB_SUFFIX=""
+ TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`'
+ ECHO_VERSION='`echo ${VERSION}`'
+ TCL_LIB_VERSIONS_OK=ok
+ CFLAGS_DEBUG=-g
+ AS_IF([test "$GCC" = yes], [
+ CFLAGS_OPTIMIZE=-O2
+ CFLAGS_WARNING="-Wall -Wwrite-strings -Wsign-compare -Wdeclaration-after-statement"
+ ], [
+ CFLAGS_OPTIMIZE=-O
+ CFLAGS_WARNING=""
+ ])
+ AC_CHECK_TOOL(AR, ar)
+ STLIB_LD='${AR} cr'
+ LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
+ PLAT_OBJS=""
+ PLAT_SRCS=""
+ LDAIX_SRC=""
+ AS_IF([test "x${SHLIB_VERSION}" = x], [SHLIB_VERSION="1.0"])
+ case $system in
+ AIX-*)
+ AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [
+ # AIX requires the _r compiler when gcc isn't being used
+ case "${CC}" in
+ *_r|*_r\ *)
+ # ok ...
+ ;;
+ *)
+ # Make sure only first arg gets _r
+ CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'`
+ ;;
+ esac
+ AC_MSG_RESULT([Using $CC for compiling with threads])
+ ])
+ LIBS="$LIBS -lc"
+ SHLIB_CFLAGS=""
+ SHLIB_SUFFIX=".so"
+
+ DL_OBJS="tclLoadDl.o"
+ LD_LIBRARY_PATH_VAR="LIBPATH"
+
+ # ldAix No longer needed with use of -bexpall/-brtl
+ # but some extensions may still reference it
+ LDAIX_SRC='$(UNIX_DIR)/ldAix'
+
+ # Check to enable 64-bit flags for compiler/linker
+ AS_IF([test "$do64bit" = yes], [
+ AS_IF([test "$GCC" = yes], [
+ AC_MSG_WARN([64bit mode not supported with GCC on $system])
+ ], [
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -q64"
+ LDFLAGS_ARCH="-q64"
+ RANLIB="${RANLIB} -X64"
+ AR="${AR} -X64"
+ SHLIB_LD_FLAGS="-b64"
+ ])
+ ])
+
+ AS_IF([test "`uname -m`" = ia64], [
+ # 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=""
+ AS_IF([test "$GCC" = yes], [
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ ], [
+ CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
+ ])
+ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ ], [
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared -Wl,-bexpall'
+ ], [
+ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
+ LDFLAGS="$LDFLAGS -brtl"
+ ])
+ SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ])
+ ;;
+ BeOS*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -nostart'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+
+ #-----------------------------------------------------------
+ # Check for inet_ntoa in -lbind, for BeOS (which also needs
+ # -lsocket, even if the network functions are in -lnet which
+ # is always linked to, for compatibility.
+ #-----------------------------------------------------------
+ AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"])
+ ;;
+ BSD/OS-2.1*|BSD/OS-3*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="shlicc -r"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ BSD/OS-4.*)
+ SHLIB_CFLAGS="-export-dynamic -fPIC"
+ SHLIB_LD='${CC} -shared'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -export-dynamic"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ CYGWIN_*|MINGW32*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD='${CC} -shared'
+ SHLIB_SUFFIX=".dll"
+ DL_OBJS="tclLoadDl.o"
+ PLAT_OBJS='${CYGWIN_OBJS}'
+ PLAT_SRCS='${CYGWIN_SRCS}'
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ TCL_NEEDS_EXP_FILE=1
+ TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a"
+ AC_CACHE_CHECK(for Cygwin version of gcc,
+ ac_cv_cygwin,
+ AC_TRY_COMPILE([
+ #ifdef __CYGWIN__
+ #error cygwin
+ #endif
+ ], [],
+ ac_cv_cygwin=no,
+ ac_cv_cygwin=yes)
+ )
+ if test "$ac_cv_cygwin" = "no"; then
+ AC_MSG_ERROR([${CC} is not a cygwin compiler.])
+ fi
+ if test "x${TCL_THREADS}" = "x0"; then
+ AC_MSG_ERROR([CYGWIN compile is only supported with --enable-threads])
+ fi
+ do64bit_ok=yes
+ if test "x${SHARED_BUILD}" = "x1"; then
+ echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args"
+ # The eval makes quoting arguments work.
+ if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix
+ then :
+ else
+ { echo "configure: error: configure failed for ../win" 1>&2; exit 1; }
+ fi
+ fi
+ ;;
+ dgux*)
+ SHLIB_CFLAGS="-K PIC"
+ SHLIB_LD='${CC} -G'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ Haiku*)
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-lroot"
+ AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"])
+ ;;
+ HP-UX-*.11.*)
+ # Use updated header definitions where possible
+ AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])
+ AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])
+ LIBS="$LIBS -lxnet" # Use the XOPEN network library
+
+ AS_IF([test "`uname -m`" = ia64], [
+ SHLIB_SUFFIX=".so"
+ ], [
+ SHLIB_SUFFIX=".sl"
+ ])
+ AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
+ AS_IF([test "$tcl_ok" = yes], [
+ SHLIB_CFLAGS="+z"
+ SHLIB_LD="ld -b"
+ DL_OBJS="tclLoadShl.o"
+ DL_LIBS="-ldld"
+ LDFLAGS="$LDFLAGS -Wl,-E"
+ CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
+ LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
+ LD_LIBRARY_PATH_VAR="SHLIB_PATH"
+ ])
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ], [
+ CFLAGS="$CFLAGS -z"
+ ])
+
+ # 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
+ AS_IF([test "$do64bit" = "yes"], [
+ AS_IF([test "$GCC" = yes], [
+ case `${CC} -dumpmachine` in
+ hppa64*)
+ # 64-bit gcc in use. Fix flags for GNU ld.
+ do64bit_ok=yes
+ SHLIB_LD='${CC} -shared'
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ;;
+ *)
+ AC_MSG_WARN([64bit mode not supported with GCC on $system])
+ ;;
+ esac
+ ], [
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS +DD64"
+ LDFLAGS_ARCH="+DD64"
+ ])
+ ]) ;;
+ HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*)
+ SHLIB_SUFFIX=".sl"
+ AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
+ AS_IF([test "$tcl_ok" = yes], [
+ SHLIB_CFLAGS="+z"
+ SHLIB_LD="ld -b"
+ SHLIB_LD_LIBS=""
+ DL_OBJS="tclLoadShl.o"
+ DL_LIBS="-ldld"
+ LDFLAGS="$LDFLAGS -Wl,-E"
+ CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
+ LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
+ LD_LIBRARY_PATH_VAR="SHLIB_PATH"
+ ]) ;;
+ IRIX-5.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AC_LIBOBJ(mkstemp)
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ ;;
+ IRIX-6.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -n32 -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AC_LIBOBJ(mkstemp)
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ AS_IF([test "$GCC" = yes], [
+ CFLAGS="$CFLAGS -mabi=n32"
+ LDFLAGS="$LDFLAGS -mabi=n32"
+ ], [
+ 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"
+ ])
+ ;;
+ IRIX64-6.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -n32 -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AC_LIBOBJ(mkstemp)
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+
+ # Check to enable 64-bit flags for compiler/linker
+
+ AS_IF([test "$do64bit" = yes], [
+ AS_IF([test "$GCC" = yes], [
+ AC_MSG_WARN([64bit mode not supported by gcc])
+ ], [
+ do64bit_ok=yes
+ SHLIB_LD="ld -64 -shared -rdata_shared"
+ CFLAGS="$CFLAGS -64"
+ LDFLAGS_ARCH="-64"
+ ])
+ ])
+ ;;
+ Linux*|GNU*|NetBSD-Debian)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+
+ CFLAGS_OPTIMIZE="-O2"
+ # 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"
+
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
+ AS_IF([test $do64bit = yes], [
+ AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -m64"
+ AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_m64 = yes], [
+ CFLAGS="$CFLAGS -m64"
+ do64bit_ok=yes
+ ])
+ ])
+
+ # 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.
+
+ AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"])
+ ;;
+ Lynx*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ CFLAGS_OPTIMIZE=-02
+ SHLIB_LD='${CC} -shared'
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-mshared -ldl"
+ LD_FLAGS="-Wl,--export-dynamic"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ ;;
+ OpenBSD-*)
+ arch=`arch -s`
+ case "$arch" in
+ alpha|sparc64)
+ SHLIB_CFLAGS="-fPIC"
+ ;;
+ *)
+ SHLIB_CFLAGS="-fpic"
+ ;;
+ esac
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
+ LDFLAGS="-Wl,-export-dynamic"
+ CFLAGS_OPTIMIZE="-O2"
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # On OpenBSD: Compile with -pthread
+ # Don't link with -lpthread
+ LIBS=`echo $LIBS | sed s/-lpthread//`
+ CFLAGS="$CFLAGS -pthread"
+ ])
+ # OpenBSD doesn't do version numbers with dots.
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ NetBSD-*)
+ # NetBSD has ELF and can use 'cc -shared' to build shared libs
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ LDFLAGS="$LDFLAGS -export-dynamic"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # The -pthread needs to go in the CFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS -pthread"
+ LDFLAGS="$LDFLAGS -pthread"
+ ])
+ ;;
+ FreeBSD-*)
+ # This configuration from FreeBSD Ports.
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="${CC} -shared"
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$[@]"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ LDFLAGS=""
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # The -pthread needs to go in the LDFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
+ case $system in
+ FreeBSD-3.*)
+ # Version numbers are dot-stripped by system policy.
+ TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
+ 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"
+ # To avoid discrepancies between what headers configure sees during
+ # preprocessing tests and compiling tests, move any -isysroot and
+ # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
+ CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
+ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
+ if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`"
+ CFLAGS="`echo " ${CFLAGS}" | \
+ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
+ if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`"
+ AS_IF([test $do64bit = yes], [
+ case `arch` in
+ ppc)
+ AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
+ tcl_cv_cc_arch_ppc64, [
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
+ AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,
+ tcl_cv_cc_arch_ppc64=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
+ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
+ do64bit_ok=yes
+ ]);;
+ i386)
+ AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
+ tcl_cv_cc_arch_x86_64, [
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -arch x86_64"
+ AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,
+ tcl_cv_cc_arch_x86_64=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
+ CFLAGS="$CFLAGS -arch x86_64"
+ do64bit_ok=yes
+ ]);;
+ *)
+ AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
+ esac
+ ], [
+ # Check for combined 32-bit and 64-bit fat build
+ AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
+ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
+ fat_32_64=yes])
+ ])
+ SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${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])
+ AS_IF([test $tcl_cv_ld_single_module = yes], [
+ SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
+ ])
+ SHLIB_SUFFIX=".dylib"
+ DL_OBJS="tclLoadDyld.o"
+ DL_LIBS=""
+ # Don't use -prebind when building for Mac OS X 10.4 or later only:
+ AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
+ "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [
+ LDFLAGS="$LDFLAGS -prebind"])
+ LDFLAGS="$LDFLAGS -headerpad_max_install_names"
+ 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])
+ AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
+ LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+ ])
+ AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
+ AC_DEFINE(MODULE_SCOPE, [__private_extern__],
+ [Compiler support for module scope symbols])
+ ])
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
+ AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?])
+ PLAT_OBJS='${MAC_OSX_OBJS}'
+ PLAT_SRCS='${MAC_OSX_SRCS}'
+ AC_MSG_CHECKING([whether to use CoreFoundation])
+ AC_ARG_ENABLE(corefoundation,
+ AC_HELP_STRING([--enable-corefoundation],
+ [use CoreFoundation API on MacOSX (default: on)]),
+ [tcl_corefoundation=$enableval], [tcl_corefoundation=yes])
+ AC_MSG_RESULT([$tcl_corefoundation])
+ AS_IF([test $tcl_corefoundation = yes], [
+ AC_CACHE_CHECK([for CoreFoundation.framework],
+ tcl_cv_lib_corefoundation, [
+ hold_libs=$LIBS
+ AS_IF([test "$fat_32_64" = yes], [
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ # On Tiger there is no 64-bit CF, so remove 64-bit
+ # archs from CFLAGS et al. while testing for
+ # presence of CF. 64-bit CF is disabled in
+ # tclUnixPort.h if necessary.
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
+ done])
+ LIBS="$LIBS -framework CoreFoundation"
+ AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>],
+ [CFBundleRef b = CFBundleGetMainBundle();],
+ tcl_cv_lib_corefoundation=yes,
+ tcl_cv_lib_corefoundation=no)
+ AS_IF([test "$fat_32_64" = yes], [
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done])
+ LIBS=$hold_libs])
+ AS_IF([test $tcl_cv_lib_corefoundation = yes], [
+ LIBS="$LIBS -framework CoreFoundation"
+ AC_DEFINE(HAVE_COREFOUNDATION, 1,
+ [Do we have access to Darwin CoreFoundation.framework?])
+ ], [tcl_corefoundation=no])
+ AS_IF([test "$fat_32_64" = yes -a $tcl_corefoundation = yes],[
+ AC_CACHE_CHECK([for 64-bit CoreFoundation],
+ tcl_cv_lib_corefoundation_64, [
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
+ done
+ AC_TRY_LINK([#include <CoreFoundation/CoreFoundation.h>],
+ [CFBundleRef b = CFBundleGetMainBundle();],
+ tcl_cv_lib_corefoundation_64=yes,
+ tcl_cv_lib_corefoundation_64=no)
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done])
+ AS_IF([test $tcl_cv_lib_corefoundation_64 = no], [
+ AC_DEFINE(NO_COREFOUNDATION_64, 1,
+ [Is Darwin CoreFoundation unavailable for 64-bit?])
+ LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"
+ ])
+ ])
+ ])
+ ;;
+ OS/390-*)
+ SHLIB_LD_LIBS=""
+ 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-V*)
+ # Digital OSF/1
+ SHLIB_CFLAGS=""
+ AS_IF([test "$SHARED_BUILD" = 1], [
+ SHLIB_LD='ld -shared -expect_unresolved "*"'
+ ], [
+ SHLIB_LD='ld -non_shared -expect_unresolved "*"'
+ ])
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [
+ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"])
+ # see pthread_intro(3) for pthread support on osf1, k.furukawa
+ AS_IF([test "${TCL_THREADS}" = 1], [
+ CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
+ CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
+ LIBS=`echo $LIBS | sed s/-lpthreads//`
+ AS_IF([test "$GCC" = yes], [
+ LIBS="$LIBS -lpthread -lmach -lexc"
+ ], [
+ CFLAGS="$CFLAGS -pthread"
+ LDFLAGS="$LDFLAGS -pthread"
+ ])
+ ])
+ ;;
+ 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=""
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ 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.
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_CFLAGS="-fPIC -melf"
+ LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
+ ], [
+ SHLIB_CFLAGS="-Kpic -belf"
+ LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
+ ])
+ SHLIB_LD="ld -G"
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS=""
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ SunOS-5.[[0-6]])
+ # Careful to not let 5.10+ fall into this case
+
+ # 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"
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ], [
+ SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+ CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ])
+ ;;
+ 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
+ AS_IF([test "$do64bit" = yes], [
+ arch=`isainfo`
+ AS_IF([test "$arch" = "sparcv9 sparc"], [
+ AS_IF([test "$GCC" = yes], [
+ AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [
+ AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])
+ ], [
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -m64 -mcpu=v9"
+ LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
+ SHLIB_CFLAGS="-fPIC"
+ ])
+ ], [
+ do64bit_ok=yes
+ AS_IF([test "$do64bitVIS" = yes], [
+ CFLAGS="$CFLAGS -xarch=v9a"
+ LDFLAGS_ARCH="-xarch=v9a"
+ ], [
+ CFLAGS="$CFLAGS -xarch=v9"
+ LDFLAGS_ARCH="-xarch=v9"
+ ])
+ # Solaris 64 uses this as well
+ #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
+ ])
+ ], [AS_IF([test "$arch" = "amd64 i386"], [
+ AS_IF([test "$GCC" = yes], [
+ case $system in
+ SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -m64"
+ LDFLAGS="$LDFLAGS -m64";;
+ *)
+ AC_MSG_WARN([64bit mode not supported with GCC on $system]);;
+ esac
+ ], [
+ do64bit_ok=yes
+ case $system in
+ SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
+ CFLAGS="$CFLAGS -m64"
+ LDFLAGS="$LDFLAGS -m64";;
+ *)
+ CFLAGS="$CFLAGS -xarch=amd64"
+ LDFLAGS="$LDFLAGS -xarch=amd64";;
+ esac
+ ])
+ ], [AC_MSG_WARN([64bit mode not supported for $arch])])])
+ ])
+
+ #--------------------------------------------------------------------
+ # On Solaris 5.x i386 with the sunpro compiler we need to link
+ # with sunmath to get floating point rounding control
+ #--------------------------------------------------------------------
+ AS_IF([test "$GCC" = yes],[use_sunmath=no],[
+ arch=`isainfo`
+ AC_MSG_CHECKING([whether to use -lsunmath for fp rounding control])
+ AS_IF([test "$arch" = "amd64 i386" -o "$arch" = "i386"], [
+ AC_MSG_RESULT([yes])
+ MATH_LIBS="-lsunmath $MATH_LIBS"
+ AC_CHECK_HEADER(sunmath.h)
+ use_sunmath=yes
+ ], [
+ AC_MSG_RESULT([no])
+ use_sunmath=no
+ ])
+ ])
+ SHLIB_SUFFIX=".so"
+ DL_OBJS="tclLoadDl.o"
+ DL_LIBS="-ldl"
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "$do64bit_ok" = yes], [
+ AS_IF([test "$arch" = "sparcv9 sparc"], [
+ # We need to specify -static-libgcc or we need to
+ # add the path to the sparv9 libgcc.
+ 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` | ..."
+ #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"
+ ], [AS_IF([test "$arch" = "amd64 i386"], [
+ SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
+ ])])
+ ])
+ ], [
+ AS_IF([test "$use_sunmath" = yes], [textmode=textoff],[textmode=text])
+ case $system in
+ SunOS-5.[[1-9]][[0-9]]*|SunOS-5.[[7-9]])
+ SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";;
+ *)
+ SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";;
+ esac
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ ])
+ ;;
+ 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.
+ AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+ AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)
+ LDFLAGS=$hold_ldflags])
+ AS_IF([test $tcl_cv_ld_Bexport = yes], [
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+ ])
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ esac
+
+ AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [
+ AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform])
+ ])
+
+ AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = yes], [
+ AC_DEFINE(TCL_CFG_DO64BIT, 1, [Is this a 64-bit build?])
+ ])
+
+dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so
+dnl # until the end of configure, as configure's compile and link tests use
+dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
+dnl # preprocessing tests use only CPPFLAGS.
+ AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])
+
+ # Step 4: disable dynamic loading if requested via a command-line switch.
+
+ AC_ARG_ENABLE(load,
+ AC_HELP_STRING([--enable-load],
+ [allow dynamic loading and "load" command (default: on)]),
+ [tcl_ok=$enableval], [tcl_ok=yes])
+ AS_IF([test "$tcl_ok" = no], [DL_OBJS=""])
+
+ AS_IF([test "x$DL_OBJS" != x], [BUILD_DLTEST="\$(DLTEST_TARGETS)"], [
+ AC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.])
+ SHLIB_CFLAGS=""
+ SHLIB_LD=""
+ SHLIB_SUFFIX=""
+ DL_OBJS="tclLoadNone.o"
+ DL_LIBS=""
+ LDFLAGS="$LDFLAGS_ORIG"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ BUILD_DLTEST=""
+ ])
+ LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"
+
+ # 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.
+
+ AS_IF([test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes], [
+ case $system in
+ AIX-*) ;;
+ BSD/OS*) ;;
+ CYGWIN_*|MINGW32_*) ;;
+ IRIX*) ;;
+ NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
+ Darwin-*) ;;
+ SCO_SV-3.2*) ;;
+ *) SHLIB_CFLAGS="-fPIC" ;;
+ esac])
+
+ AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
+ AC_DEFINE(MODULE_SCOPE, [extern],
+ [No Compiler support for module scope symbols])
+ ])
+
+ AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
+ SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'])
+ AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
+ UNSHARED_LIB_SUFFIX='${VERSION}.a'])
+ DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)"
+
+ AS_IF([test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""], [
+ LIB_SUFFIX=${SHARED_LIB_SUFFIX}
+ MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
+ AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;'
+ DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
+ ], [
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
+ ])
+ ], [
+ LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}
+
+ AS_IF([test "$RANLIB" = ""], [
+ MAKE_LIB='$(STLIB_LD) [$]@ ${OBJS}'
+ ], [
+ MAKE_LIB='${STLIB_LD} [$]@ ${OBJS} ; ${RANLIB} [$]@'
+ ])
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
+ ])
+
+ # Stub lib does not depend on shared/static configuration
+ AS_IF([test "$RANLIB" = ""], [
+ MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS}'
+ ], [
+ MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS} ; ${RANLIB} [$]@'
+ ])
+ INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"'
+
+ # Define TCL_LIBS now that we know what DL_LIBS is.
+ # The trick here is that we don't want to change the value of TCL_LIBS if
+ # it is already set when tclConfig.sh had been loaded by Tk.
+ AS_IF([test "x${TCL_LIBS}" = x], [
+ TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"])
+ AC_SUBST(TCL_LIBS)
+
+ # See if the compiler supports casting to a union type.
+ # This is used to stop gcc from printing a compiler
+ # warning when initializing a union member.
+
+ AC_CACHE_CHECK(for cast to union support,
+ tcl_cv_cast_to_union,
+ AC_TRY_COMPILE([],
+ [
+ union foo { int i; double d; };
+ union foo f = (union foo) (int) 0;
+ ],
+ tcl_cv_cast_to_union=yes,
+ tcl_cv_cast_to_union=no)
+ )
+ if test "$tcl_cv_cast_to_union" = "yes"; then
+ AC_DEFINE(HAVE_CAST_TO_UNION, 1,
+ [Defined when compiler supports casting to union type.])
+ fi
+
+ # FIXME: This subst was left in only because the TCL_DL_LIBS
+ # entry in tclConfig.sh uses it. It is not clear why someone
+ # would use TCL_DL_LIBS instead of TCL_LIBS.
+ AC_SUBST(DL_LIBS)
+
+ AC_SUBST(DL_OBJS)
+ AC_SUBST(PLAT_OBJS)
+ AC_SUBST(PLAT_SRCS)
+ AC_SUBST(LDAIX_SRC)
+ AC_SUBST(CFLAGS)
+ AC_SUBST(CFLAGS_DEBUG)
+ AC_SUBST(CFLAGS_OPTIMIZE)
+ AC_SUBST(CFLAGS_WARNING)
+
+ AC_SUBST(LDFLAGS)
+ AC_SUBST(LDFLAGS_DEBUG)
+ AC_SUBST(LDFLAGS_OPTIMIZE)
+ AC_SUBST(CC_SEARCH_FLAGS)
+ AC_SUBST(LD_SEARCH_FLAGS)
+
+ AC_SUBST(STLIB_LD)
+ AC_SUBST(SHLIB_LD)
+ AC_SUBST(TCL_SHLIB_LD_EXTRAS)
+ AC_SUBST(TK_SHLIB_LD_EXTRAS)
+ AC_SUBST(SHLIB_LD_LIBS)
+ AC_SUBST(SHLIB_CFLAGS)
+ AC_SUBST(SHLIB_SUFFIX)
+ AC_DEFINE_UNQUOTED(TCL_SHLIB_EXT,"${SHLIB_SUFFIX}",
+ [What is the default extension for shared libraries?])
+
+ AC_SUBST(MAKE_LIB)
+ AC_SUBST(MAKE_STUB_LIB)
+ AC_SUBST(INSTALL_LIB)
+ AC_SUBST(DLL_INSTALL_DIR)
+ AC_SUBST(INSTALL_STUB_LIB)
+ AC_SUBST(RANLIB)
+])
+
+#--------------------------------------------------------------------
+# SC_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_VALUES_H
+# NO_STDLIB_H
+# NO_STRING_H
+# NO_SYS_WAIT_H
+# NO_DLFCN_H
+# HAVE_SYS_PARAM_H
+#
+# HAVE_STRING_H ?
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_MISSING_POSIX_HEADERS], [
+ AC_CACHE_CHECK([dirent.h], 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_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(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)
+])
+
+#--------------------------------------------------------------------
+# SC_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.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Sets the following vars:
+# XINCLUDES
+# XLIBSW
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_PATH_X], [
+ AC_PATH_X
+ not_really_there=""
+ if test "$no_x" = ""; then
+ if test "$x_includes" = ""; then
+ AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes")
+ else
+ if test ! -r $x_includes/X11/Xlib.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])
+ found_xincludes="no"
+ AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no")
+ if test "$found_xincludes" = "no"; 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/Xlib.h; then
+ AC_MSG_RESULT([$i])
+ XINCLUDES=" -I$i"
+ found_xincludes="yes"
+ break
+ fi
+ done
+ fi
+ else
+ if test "$x_includes" != ""; then
+ XINCLUDES="-I$x_includes"
+ found_xincludes="yes"
+ fi
+ fi
+ if test "$found_xincludes" = "no"; then
+ AC_MSG_RESULT([couldn't find any!])
+ 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 -o -r $i/libX11.dylib; 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
+])
+
+#--------------------------------------------------------------------
+# SC_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([SC_BLOCKING_STYLE], [
+ AC_CHECK_HEADERS(sys/ioctl.h)
+ AC_CHECK_HEADERS(sys/filio.h)
+ SC_CONFIG_SYSTEM
+ AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O])
+ case $system in
+ OSF*)
+ AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
+ AC_MSG_RESULT([FIONBIO])
+ ;;
+ *)
+ AC_MSG_RESULT([O_NONBLOCK])
+ ;;
+ esac
+])
+
+#--------------------------------------------------------------------
+# SC_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([SC_TIME_HANDLER], [
+ AC_CHECK_HEADERS(sys/time.h)
+ AC_HEADER_TIME
+
+ AC_CHECK_FUNCS(gmtime_r localtime_r mktime)
+
+ AC_CACHE_CHECK([tm_tzadj in struct tm], 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)])
+ 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_CACHE_CHECK([tm_gmtoff in struct tm], 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)])
+ 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_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [
+ AC_TRY_COMPILE([#include <time.h>],
+ [extern long timezone;
+ timezone += 1;
+ exit (0);],
+ tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)])
+ 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_CACHE_CHECK([time_t timezone variable], 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)])
+ if test $tcl_cv_timezone_time = yes ; then
+ AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
+ fi
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_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([SC_BUGGY_STRTOD], [
+ AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0)
+ if test "$tcl_strtod" = 1; then
+ AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[
+ AC_TRY_RUN([
+ extern double strtod();
+ int main() {
+ char *infString="Inf", *nanString="NaN", *spaceString=" ";
+ char *term;
+ double value;
+ value = strtod(infString, &term);
+ if ((term != infString) && (term[-1] == 0)) {
+ exit(1);
+ }
+ value = strtod(nanString, &term);
+ if ((term != nanString) && (term[-1] == 0)) {
+ exit(1);
+ }
+ value = strtod(spaceString, &term);
+ if (term == (spaceString+1)) {
+ exit(1);
+ }
+ exit(0);
+ }], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy,
+ tcl_cv_strtod_buggy=buggy)])
+ if test "$tcl_cv_strtod_buggy" = buggy; then
+ AC_LIBOBJ([fixstrtod])
+ USE_COMPAT=1
+ AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])
+ fi
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_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:
+# None.
+#
+# Results:
+#
+# Might append to the following vars:
+# LIBS
+# MATH_LIBS
+#
+# Might define the following vars:
+# HAVE_NET_ERRNO_H
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_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"])])
+])
+
+#--------------------------------------------------------------------
+# SC_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
+# _LARGEFILE_SOURCE64
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_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([SC_TCL_EARLY_FLAGS],[
+ AC_MSG_CHECKING([for required early compiler flags])
+ tcl_flags=""
+ SC_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>],
+ [char *p = (char *)strtoll; char *q = (char *)strtoull;])
+ SC_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],
+ [struct stat64 buf; int i = stat64("/", &buf);])
+ SC_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>],
+ [char *p = (char *)open64;])
+ if test "x${tcl_flags}" = "x" ; then
+ AC_MSG_RESULT([none])
+ else
+ AC_MSG_RESULT([${tcl_flags}])
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_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([SC_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])
+ 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_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
+ AC_TRY_COMPILE([#include <sys/types.h>
+#include <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_CACHE_CHECK([for struct stat64], 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_CHECK_FUNCS(open64 lseek64)
+ 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)])
+ dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the
+ dnl functions lseek64 and open64 are defined.
+ if test "x${tcl_cv_type_off64_t}" = "xyes" && \
+ test "x${ac_cv_func_lseek64}" = "xyes" && \
+ test "x${ac_cv_func_open64}" = "xyes" ; then
+ AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_TCL_CFG_ENCODING TIP #59
+#
+# Declare the encoding to use for embedded configuration information.
+#
+# Arguments:
+# None.
+#
+# Results:
+# Might append to the following vars:
+# DEFS (implicit)
+#
+# Will define the following vars:
+# TCL_CFGVAL_ENCODING
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_CFG_ENCODING], [
+ AC_ARG_WITH(encoding,
+ AC_HELP_STRING([--with-encoding],
+ [encoding for configuration values (default: iso8859-1)]),
+ with_tcencoding=${withval})
+
+ if test x"${with_tcencoding}" != x ; then
+ AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}",
+ [What encoding should be used for embedded configuration info?])
+ else
+ AC_DEFINE(TCL_CFGVAL_ENCODING,"iso8859-1",
+ [What encoding should be used for embedded configuration info?])
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_TCL_CHECK_BROKEN_FUNC
+#
+# Check for broken function.
+#
+# Arguments:
+# funcName - function to test for
+# advancedTest - the advanced test to run if the function is present
+#
+# Results:
+# Might cause compatibility versions of the function to be used.
+# Might affect the following vars:
+# USE_COMPAT (implicit)
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_CHECK_BROKEN_FUNC],[
+ AC_CHECK_FUNC($1, tcl_ok=1, tcl_ok=0)
+ if test ["$tcl_ok"] = 1; then
+ AC_CACHE_CHECK([proper ]$1[ implementation], [tcl_cv_]$1[_unbroken],
+ AC_TRY_RUN([[int main() {]$2[}]],[tcl_cv_]$1[_unbroken]=ok,
+ [tcl_cv_]$1[_unbroken]=broken,[tcl_cv_]$1[_unbroken]=unknown))
+ if test ["$tcl_cv_]$1[_unbroken"] = "ok"; then
+ tcl_ok=1
+ else
+ tcl_ok=0
+ fi
+ fi
+ if test ["$tcl_ok"] = 0; then
+ AC_LIBOBJ($1)
+ USE_COMPAT=1
+ fi
+])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETHOSTBYADDR_R
+#
+# Check if we have MT-safe variant of gethostbyaddr().
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETHOSTBYADDR_R
+# HAVE_GETHOSTBYADDR_R_7
+# HAVE_GETHOSTBYADDR_R_8
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETHOSTBYADDR_R], [AC_CHECK_FUNC(gethostbyaddr_r, [
+ AC_CACHE_CHECK([for gethostbyaddr_r with 7 args], tcl_cv_api_gethostbyaddr_r_7, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ char *addr;
+ int length;
+ int type;
+ struct hostent *result;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
+ &h_errnop);
+ ], tcl_cv_api_gethostbyaddr_r_7=yes, tcl_cv_api_gethostbyaddr_r_7=no)])
+ tcl_ok=$tcl_cv_api_gethostbyaddr_r_7
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYADDR_R_7, 1,
+ [Define to 1 if gethostbyaddr_r takes 7 args.])
+ else
+ AC_CACHE_CHECK([for gethostbyaddr_r with 8 args], tcl_cv_api_gethostbyaddr_r_8, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ char *addr;
+ int length;
+ int type;
+ struct hostent *result, *resultp;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen,
+ &resultp, &h_errnop);
+ ], tcl_cv_api_gethostbyaddr_r_8=yes, tcl_cv_api_gethostbyaddr_r_8=no)])
+ tcl_ok=$tcl_cv_api_gethostbyaddr_r_8
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYADDR_R_8, 1,
+ [Define to 1 if gethostbyaddr_r takes 8 args.])
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYADDR_R, 1,
+ [Define to 1 if gethostbyaddr_r is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETHOSTBYNAME_R
+#
+# Check to see what variant of gethostbyname_r() we have.
+# Based on David Arnold's example from the comp.programming.threads
+# FAQ Q213
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETHOSTBYADDR_R
+# HAVE_GETHOSTBYADDR_R_3
+# HAVE_GETHOSTBYADDR_R_5
+# HAVE_GETHOSTBYADDR_R_6
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETHOSTBYNAME_R], [AC_CHECK_FUNC(gethostbyname_r, [
+ AC_CACHE_CHECK([for gethostbyname_r with 6 args], tcl_cv_api_gethostbyname_r_6, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ char *name;
+ struct hostent *he, *res;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop);
+ ], tcl_cv_api_gethostbyname_r_6=yes, tcl_cv_api_gethostbyname_r_6=no)])
+ tcl_ok=$tcl_cv_api_gethostbyname_r_6
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYNAME_R_6, 1,
+ [Define to 1 if gethostbyname_r takes 6 args.])
+ else
+ AC_CACHE_CHECK([for gethostbyname_r with 5 args], tcl_cv_api_gethostbyname_r_5, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ char *name;
+ struct hostent *he;
+ char buffer[2048];
+ int buflen = 2048;
+ int h_errnop;
+
+ (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop);
+ ], tcl_cv_api_gethostbyname_r_5=yes, tcl_cv_api_gethostbyname_r_5=no)])
+ tcl_ok=$tcl_cv_api_gethostbyname_r_5
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYNAME_R_5, 1,
+ [Define to 1 if gethostbyname_r takes 5 args.])
+ else
+ AC_CACHE_CHECK([for gethostbyname_r with 3 args], tcl_cv_api_gethostbyname_r_3, [
+ AC_TRY_COMPILE([
+ #include <netdb.h>
+ ], [
+ char *name;
+ struct hostent *he;
+ struct hostent_data data;
+
+ (void) gethostbyname_r(name, he, &data);
+ ], tcl_cv_api_gethostbyname_r_3=yes, tcl_cv_api_gethostbyname_r_3=no)])
+ tcl_ok=$tcl_cv_api_gethostbyname_r_3
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYNAME_R_3, 1,
+ [Define to 1 if gethostbyname_r takes 3 args.])
+ fi
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1,
+ [Define to 1 if gethostbyname_r is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETPWUID_R
+#
+# Check if we have MT-safe variant of getpwuid() and if yes,
+# which one exactly.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETPWUID_R
+# HAVE_GETPWUID_R_4
+# HAVE_GETPWUID_R_5
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETPWUID_R], [AC_CHECK_FUNC(getpwuid_r, [
+ AC_CACHE_CHECK([for getpwuid_r with 5 args], tcl_cv_api_getpwuid_r_5, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <pwd.h>
+ ], [
+ uid_t uid;
+ struct passwd pw, *pwp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getpwuid_r(uid, &pw, buf, buflen, &pwp);
+ ], tcl_cv_api_getpwuid_r_5=yes, tcl_cv_api_getpwuid_r_5=no)])
+ tcl_ok=$tcl_cv_api_getpwuid_r_5
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWUID_R_5, 1,
+ [Define to 1 if getpwuid_r takes 5 args.])
+ else
+ AC_CACHE_CHECK([for getpwuid_r with 4 args], tcl_cv_api_getpwuid_r_4, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <pwd.h>
+ ], [
+ uid_t uid;
+ struct passwd pw;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getpwnam_r(uid, &pw, buf, buflen);
+ ], tcl_cv_api_getpwuid_r_4=yes, tcl_cv_api_getpwuid_r_4=no)])
+ tcl_ok=$tcl_cv_api_getpwuid_r_4
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWUID_R_4, 1,
+ [Define to 1 if getpwuid_r takes 4 args.])
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWUID_R, 1,
+ [Define to 1 if getpwuid_r is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETPWNAM_R
+#
+# Check if we have MT-safe variant of getpwnam() and if yes,
+# which one exactly.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETPWNAM_R
+# HAVE_GETPWNAM_R_4
+# HAVE_GETPWNAM_R_5
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETPWNAM_R], [AC_CHECK_FUNC(getpwnam_r, [
+ AC_CACHE_CHECK([for getpwnam_r with 5 args], tcl_cv_api_getpwnam_r_5, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <pwd.h>
+ ], [
+ char *name;
+ struct passwd pw, *pwp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getpwnam_r(name, &pw, buf, buflen, &pwp);
+ ], tcl_cv_api_getpwnam_r_5=yes, tcl_cv_api_getpwnam_r_5=no)])
+ tcl_ok=$tcl_cv_api_getpwnam_r_5
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWNAM_R_5, 1,
+ [Define to 1 if getpwnam_r takes 5 args.])
+ else
+ AC_CACHE_CHECK([for getpwnam_r with 4 args], tcl_cv_api_getpwnam_r_4, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <pwd.h>
+ ], [
+ char *name;
+ struct passwd pw;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getpwnam_r(name, &pw, buf, buflen);
+ ], tcl_cv_api_getpwnam_r_4=yes, tcl_cv_api_getpwnam_r_4=no)])
+ tcl_ok=$tcl_cv_api_getpwnam_r_4
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWNAM_R_4, 1,
+ [Define to 1 if getpwnam_r takes 4 args.])
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETPWNAM_R, 1,
+ [Define to 1 if getpwnam_r is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETGRGID_R
+#
+# Check if we have MT-safe variant of getgrgid() and if yes,
+# which one exactly.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETGRGID_R
+# HAVE_GETGRGID_R_4
+# HAVE_GETGRGID_R_5
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETGRGID_R], [AC_CHECK_FUNC(getgrgid_r, [
+ AC_CACHE_CHECK([for getgrgid_r with 5 args], tcl_cv_api_getgrgid_r_5, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <grp.h>
+ ], [
+ gid_t gid;
+ struct group gr, *grp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getgrgid_r(gid, &gr, buf, buflen, &grp);
+ ], tcl_cv_api_getgrgid_r_5=yes, tcl_cv_api_getgrgid_r_5=no)])
+ tcl_ok=$tcl_cv_api_getgrgid_r_5
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRGID_R_5, 1,
+ [Define to 1 if getgrgid_r takes 5 args.])
+ else
+ AC_CACHE_CHECK([for getgrgid_r with 4 args], tcl_cv_api_getgrgid_r_4, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <grp.h>
+ ], [
+ gid_t gid;
+ struct group gr;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getgrgid_r(gid, &gr, buf, buflen);
+ ], tcl_cv_api_getgrgid_r_4=yes, tcl_cv_api_getgrgid_r_4=no)])
+ tcl_ok=$tcl_cv_api_getgrgid_r_4
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRGID_R_4, 1,
+ [Define to 1 if getgrgid_r takes 4 args.])
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRGID_R, 1,
+ [Define to 1 if getgrgid_r is available.])
+ fi
+])])
+
+#--------------------------------------------------------------------
+# SC_TCL_GETGRNAM_R
+#
+# Check if we have MT-safe variant of getgrnam() and if yes,
+# which one exactly.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# HAVE_GETGRNAM_R
+# HAVE_GETGRNAM_R_4
+# HAVE_GETGRNAM_R_5
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_TCL_GETGRNAM_R], [AC_CHECK_FUNC(getgrnam_r, [
+ AC_CACHE_CHECK([for getgrnam_r with 5 args], tcl_cv_api_getgrnam_r_5, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <grp.h>
+ ], [
+ char *name;
+ struct group gr, *grp;
+ char buf[512];
+ int buflen = 512;
+
+ (void) getgrnam_r(name, &gr, buf, buflen, &grp);
+ ], tcl_cv_api_getgrnam_r_5=yes, tcl_cv_api_getgrnam_r_5=no)])
+ tcl_ok=$tcl_cv_api_getgrnam_r_5
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRNAM_R_5, 1,
+ [Define to 1 if getgrnam_r takes 5 args.])
+ else
+ AC_CACHE_CHECK([for getgrnam_r with 4 args], tcl_cv_api_getgrnam_r_4, [
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <grp.h>
+ ], [
+ char *name;
+ struct group gr;
+ char buf[512];
+ int buflen = 512;
+
+ (void)getgrnam_r(name, &gr, buf, buflen);
+ ], tcl_cv_api_getgrnam_r_4=yes, tcl_cv_api_getgrnam_r_4=no)])
+ tcl_ok=$tcl_cv_api_getgrnam_r_4
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRNAM_R_4, 1,
+ [Define to 1 if getgrnam_r takes 4 args.])
+ fi
+ fi
+ if test "$tcl_ok" = yes; then
+ AC_DEFINE(HAVE_GETGRNAM_R, 1,
+ [Define to 1 if getgrnam_r is available.])
+ fi
+])])
+
+AC_DEFUN([SC_TCL_IPV6],[
+ NEED_FAKE_RFC2553=0
+ AC_CHECK_FUNCS(getnameinfo getaddrinfo freeaddrinfo gai_strerror,,[NEED_FAKE_RFC2553=1])
+ AC_CHECK_TYPES([
+ struct addrinfo,
+ struct in6_addr,
+ struct sockaddr_in6,
+ struct sockaddr_storage],,[NEED_FAKE_RFC2553=1],[[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+]])
+if test "x$NEED_FAKE_RFC2553" = "x1"; then
+ AC_DEFINE([NEED_FAKE_RFC2553], 1,
+ [Use compat implementation of getaddrinfo() and friends])
+ AC_LIBOBJ([fake-rfc2553])
+ AC_CHECK_FUNC(strlcpy)
+fi
+])
+# Local Variables:
+# mode: autoconf
+# End:
diff --git a/unix/tcl.pc.in b/unix/tcl.pc.in
new file mode 100644
index 0000000..846cb11
--- /dev/null
+++ b/unix/tcl.pc.in
@@ -0,0 +1,15 @@
+# tcl pkg-config source file
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Tool Command Language
+Description: Tcl is a powerful, easy-to-learn dynamic programming language, suitable for a wide range of uses.
+URL: http://www.tcl.tk/
+Version: @TCL_VERSION@@TCL_PATCH_LEVEL@
+Requires.private: zlib >= 1.2.3
+Libs: -L${libdir} @TCL_LIB_FLAG@ @TCL_STUB_LIB_FLAG@
+Libs.private: @TCL_LIBS@
+Cflags: -I${includedir}
diff --git a/unix/tcl.spec b/unix/tcl.spec
new file mode 100644
index 0000000..265e4df
--- /dev/null
+++ b/unix/tcl.spec
@@ -0,0 +1,52 @@
+# This file is the basis for a binary Tcl RPM for Linux.
+
+%{!?directory:%define directory /usr/local}
+
+Name: tcl
+Summary: Tcl scripting language development environment
+Version: 8.7a2
+Release: 2
+License: BSD
+Group: Development/Languages
+Source: http://prdownloads.sourceforge.net/tcl/tcl%{version}-src.tar.gz
+URL: http://www.tcl.tk/
+Buildroot: /var/tmp/%{name}%{version}
+
+%description
+The Tcl (Tool Command Language) provides a powerful platform for
+creating integration applications that tie together diverse
+applications, protocols, devices, and frameworks. When paired with
+the Tk toolkit, Tcl provides the fastest and most powerful way to
+create GUI applications that run on PCs, Unix, and Mac OS X. Tcl
+can also be used for a variety of web-related tasks and for creating
+powerful command languages for applications.
+
+%prep
+%setup -q -n %{name}%{version}
+
+%build
+cd unix
+CFLAGS="%optflags" ./configure \
+ --prefix=%{directory} \
+ --exec-prefix=%{directory} \
+ --libdir=%{directory}/%{_lib}
+make
+
+%install
+cd unix
+make INSTALL_ROOT=%{buildroot} install
+
+%clean
+rm -rf %buildroot
+
+%files
+%defattr(-,root,root)
+%if %{_lib} != lib
+%{directory}/%{_lib}
+%endif
+%{directory}/lib
+%{directory}/bin
+%{directory}/include
+%{directory}/man/man1
+%{directory}/man/man3
+%{directory}/man/mann
diff --git a/unix/tclAppInit.c b/unix/tclAppInit.c
new file mode 100644
index 0000000..9bbc88b
--- /dev/null
+++ b/unix/tclAppInit.c
@@ -0,0 +1,169 @@
+/*
+ * tclAppInit.c --
+ *
+ * Provides a default version of the main program and Tcl_AppInit
+ * procedure for tclsh and other Tcl-based applications (without Tk).
+ *
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#undef BUILD_tcl
+#undef STATIC_BUILD
+#include "tcl.h"
+
+#ifdef TCL_TEST
+extern Tcl_PackageInitProc Tcltest_Init;
+extern Tcl_PackageInitProc Tcltest_SafeInit;
+#endif /* TCL_TEST */
+
+#ifdef TCL_XT_TEST
+extern void XtToolkitInitialize(void);
+extern Tcl_PackageInitProc Tclxttest_Init;
+#endif /* TCL_XT_TEST */
+
+/*
+ * The following #if block allows you to change the AppInit function by using
+ * a #define of TCL_LOCAL_APPINIT instead of rewriting this entire file. The
+ * #if checks for that #define and uses Tcl_AppInit if it does not exist.
+ */
+
+#ifndef TCL_LOCAL_APPINIT
+#define TCL_LOCAL_APPINIT Tcl_AppInit
+#endif
+#ifndef MODULE_SCOPE
+# define MODULE_SCOPE extern
+#endif
+MODULE_SCOPE int TCL_LOCAL_APPINIT(Tcl_Interp *);
+MODULE_SCOPE int main(int, char **);
+
+/*
+ * The following #if block allows you to change how Tcl finds the startup
+ * script, prime the library or encoding paths, fiddle with the argv, etc.,
+ * without needing to rewrite Tcl_Main()
+ */
+
+#ifdef TCL_LOCAL_MAIN_HOOK
+MODULE_SCOPE int TCL_LOCAL_MAIN_HOOK(int *argc, char ***argv);
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * main --
+ *
+ * This is the main program for the application.
+ *
+ * Results:
+ * None: Tcl_Main never returns here, so this procedure never returns
+ * either.
+ *
+ * Side effects:
+ * Just about anything, since from here we call arbitrary Tcl code.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+main(
+ int argc, /* Number of command-line arguments. */
+ char *argv[]) /* Values of command-line arguments. */
+{
+#ifdef TCL_XT_TEST
+ XtToolkitInitialize();
+#endif
+
+#ifdef TCL_LOCAL_MAIN_HOOK
+ TCL_LOCAL_MAIN_HOOK(&argc, &argv);
+#endif
+
+ Tcl_Main(argc, argv, TCL_LOCAL_APPINIT);
+ return 0; /* Needed only to prevent compiler warning. */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppInit --
+ *
+ * This procedure performs application-specific initialization. Most
+ * applications, especially those that incorporate additional packages,
+ * will have their own version of this procedure.
+ *
+ * Results:
+ * Returns a standard Tcl completion code, and leaves an error message in
+ * the interp's result if an error occurs.
+ *
+ * Side effects:
+ * Depends on the startup script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_AppInit(
+ Tcl_Interp *interp) /* Interpreter for application. */
+{
+ if ((Tcl_Init)(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+#ifdef TCL_XT_TEST
+ if (Tclxttest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+#endif
+
+#ifdef TCL_TEST
+ if (Tcltest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit);
+#endif /* TCL_TEST */
+
+ /*
+ * Call the init procedures for included packages. Each call should look
+ * like this:
+ *
+ * if (Mod_Init(interp) == TCL_ERROR) {
+ * return TCL_ERROR;
+ * }
+ *
+ * where "Mod" is the name of the module. (Dynamically-loadable packages
+ * should have the same entry-point name.)
+ */
+
+ /*
+ * Call Tcl_CreateCommand for application-specific commands, if they
+ * weren't already created by the init procedures called above.
+ */
+
+ /*
+ * Specify a user-specific startup file to invoke if the application is
+ * run interactively. Typically the startup file is "~/.apprc" where "app"
+ * is the name of the application. If this line is deleted then no
+ * user-specific startup file will be run under any conditions.
+ */
+
+#ifdef DJGPP
+ (Tcl_ObjSetVar2)(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL,
+ Tcl_NewStringObj("~/tclsh.rc", -1), TCL_GLOBAL_ONLY);
+#else
+ (Tcl_ObjSetVar2)(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL,
+ Tcl_NewStringObj("~/.tclshrc", -1), TCL_GLOBAL_ONLY);
+#endif
+
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclConfig.h.in b/unix/tclConfig.h.in
new file mode 100644
index 0000000..adbc80d
--- /dev/null
+++ b/unix/tclConfig.h.in
@@ -0,0 +1,508 @@
+/* ../unix/tclConfig.h.in. Generated from configure.ac by autoheader. */
+
+
+ #ifndef _TCLCONFIG
+ #define _TCLCONFIG
+
+/* Is gettimeofday() actually declared in <sys/time.h>? */
+#undef GETTOD_NOT_DECLARED
+
+/* Define to 1 if you have the <AvailabilityMacros.h> header file. */
+#undef HAVE_AVAILABILITYMACROS_H
+
+/* Define to 1 if the system has the type `blkcnt_t'. */
+#undef HAVE_BLKCNT_T
+
+/* Defined when compiler supports casting to union type. */
+#undef HAVE_CAST_TO_UNION
+
+/* Define to 1 if you have the `chflags' function. */
+#undef HAVE_CHFLAGS
+
+/* Define to 1 if you have the `copyfile' function. */
+#undef HAVE_COPYFILE
+
+/* Define to 1 if you have the <copyfile.h> header file. */
+#undef HAVE_COPYFILE_H
+
+/* Do we have access to Darwin CoreFoundation.framework? */
+#undef HAVE_COREFOUNDATION
+
+/* Is the cpuid instruction usable? */
+#undef HAVE_CPUID
+
+/* Define to 1 if you have the `freeaddrinfo' function. */
+#undef HAVE_FREEADDRINFO
+
+/* Do we have fts functions? */
+#undef HAVE_FTS
+
+/* Define to 1 if you have the `gai_strerror' function. */
+#undef HAVE_GAI_STRERROR
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `getattrlist' function. */
+#undef HAVE_GETATTRLIST
+
+/* Define to 1 if you have the `getcwd' function. */
+#undef HAVE_GETCWD
+
+/* Define to 1 if getgrgid_r is available. */
+#undef HAVE_GETGRGID_R
+
+/* Define to 1 if getgrgid_r takes 4 args. */
+#undef HAVE_GETGRGID_R_4
+
+/* Define to 1 if getgrgid_r takes 5 args. */
+#undef HAVE_GETGRGID_R_5
+
+/* Define to 1 if getgrnam_r is available. */
+#undef HAVE_GETGRNAM_R
+
+/* Define to 1 if getgrnam_r takes 4 args. */
+#undef HAVE_GETGRNAM_R_4
+
+/* Define to 1 if getgrnam_r takes 5 args. */
+#undef HAVE_GETGRNAM_R_5
+
+/* Define to 1 if gethostbyaddr_r is available. */
+#undef HAVE_GETHOSTBYADDR_R
+
+/* Define to 1 if gethostbyaddr_r takes 7 args. */
+#undef HAVE_GETHOSTBYADDR_R_7
+
+/* Define to 1 if gethostbyaddr_r takes 8 args. */
+#undef HAVE_GETHOSTBYADDR_R_8
+
+/* Define to 1 if gethostbyname_r is available. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define to 1 if gethostbyname_r takes 3 args. */
+#undef HAVE_GETHOSTBYNAME_R_3
+
+/* Define to 1 if gethostbyname_r takes 5 args. */
+#undef HAVE_GETHOSTBYNAME_R_5
+
+/* Define to 1 if gethostbyname_r takes 6 args. */
+#undef HAVE_GETHOSTBYNAME_R_6
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define to 1 if getpwnam_r is available. */
+#undef HAVE_GETPWNAM_R
+
+/* Define to 1 if getpwnam_r takes 4 args. */
+#undef HAVE_GETPWNAM_R_4
+
+/* Define to 1 if getpwnam_r takes 5 args. */
+#undef HAVE_GETPWNAM_R_5
+
+/* Define to 1 if getpwuid_r is available. */
+#undef HAVE_GETPWUID_R
+
+/* Define to 1 if getpwuid_r takes 4 args. */
+#undef HAVE_GETPWUID_R_4
+
+/* Define to 1 if getpwuid_r takes 5 args. */
+#undef HAVE_GETPWUID_R_5
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#undef HAVE_GMTIME_R
+
+/* Compiler support for module scope symbols */
+#undef HAVE_HIDDEN
+
+/* Do we have the intptr_t type? */
+#undef HAVE_INTPTR_T
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Do we have nl_langinfo()? */
+#undef HAVE_LANGINFO
+
+/* Define to 1 if you have the <libkern/OSAtomic.h> header file. */
+#undef HAVE_LIBKERN_OSATOMIC_H
+
+/* Define to 1 if you have the `localtime_r' function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define to 1 if you have the `lseek64' function. */
+#undef HAVE_LSEEK64
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mkstemp' function. */
+#undef HAVE_MKSTEMP
+
+/* Define to 1 if you have the `mkstemps' function. */
+#undef HAVE_MKSTEMPS
+
+/* Define to 1 if you have the `mktime' function. */
+#undef HAVE_MKTIME
+
+/* Do we have MT-safe gethostbyaddr() ? */
+#undef HAVE_MTSAFE_GETHOSTBYADDR
+
+/* Do we have MT-safe gethostbyname() ? */
+#undef HAVE_MTSAFE_GETHOSTBYNAME
+
+/* Do we have <net/errno.h>? */
+#undef HAVE_NET_ERRNO_H
+
+/* Define to 1 if you have the `open64' function. */
+#undef HAVE_OPEN64
+
+/* Define to 1 if you have the `opendir' function. */
+#undef HAVE_OPENDIR
+
+/* Define to 1 if you have the `OSSpinLockLock' function. */
+#undef HAVE_OSSPINLOCKLOCK
+
+/* Define to 1 if you have the `pthread_atfork' function. */
+#undef HAVE_PTHREAD_ATFORK
+
+/* Define to 1 if you have the `pthread_attr_setstacksize' function. */
+#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE
+
+/* Does putenv() copy strings or incorporate them by reference? */
+#undef HAVE_PUTENV_THAT_COPIES
+
+/* Are characters signed? */
+#undef HAVE_SIGNED_CHAR
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if the system has the type `struct addrinfo'. */
+#undef HAVE_STRUCT_ADDRINFO
+
+/* Is 'struct dirent64' in <sys/types.h>? */
+#undef HAVE_STRUCT_DIRENT64
+
+/* Define to 1 if the system has the type `struct in6_addr'. */
+#undef HAVE_STRUCT_IN6_ADDR
+
+/* Define to 1 if the system has the type `struct sockaddr_in6'. */
+#undef HAVE_STRUCT_SOCKADDR_IN6
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* Is 'struct stat64' in <sys/stat.h>? */
+#undef HAVE_STRUCT_STAT64
+
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLKSIZE
+
+/* Define to 1 if `st_blocks' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLOCKS
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#undef HAVE_SYS_FILIO_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/modem.h> header file. */
+#undef HAVE_SYS_MODEM_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Should we include <sys/select.h>? */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Should we use the global timezone variable? */
+#undef HAVE_TIMEZONE_VAR
+
+/* Should we use the tm_gmtoff field of struct tm? */
+#undef HAVE_TM_GMTOFF
+
+/* Should we use the tm_tzadj field of struct tm? */
+#undef HAVE_TM_TZADJ
+
+/* Is off64_t in <sys/types.h>? */
+#undef HAVE_TYPE_OFF64_T
+
+/* Do we have the uintptr_t type? */
+#undef HAVE_UINTPTR_T
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `waitpid' function. */
+#undef HAVE_WAITPID
+
+/* Is weak import available? */
+#undef HAVE_WEAK_IMPORT
+
+/* Is there an installed zlib? */
+#undef HAVE_ZLIB
+
+/* Is this a Mac I see before me? */
+#undef MAC_OSX_TCL
+
+/* No Compiler support for module scope symbols */
+#undef MODULE_SCOPE
+
+/* Default libtommath precision. */
+#undef MP_PREC
+
+/* Is no debugging enabled? */
+#undef NDEBUG
+
+/* Use compat implementation of getaddrinfo() and friends */
+#undef NEED_FAKE_RFC2553
+
+/* Is Darwin CoreFoundation unavailable for 64-bit? */
+#undef NO_COREFOUNDATION_64
+
+/* Do we have <dirent.h>? */
+#undef NO_DIRENT_H
+
+/* Do we have <dlfcn.h>? */
+#undef NO_DLFCN_H
+
+/* Do we have fd_set? */
+#undef NO_FD_SET
+
+/* Do we have <float.h>? */
+#undef NO_FLOAT_H
+
+/* Do we have fstatfs()? */
+#undef NO_FSTATFS
+
+/* Do we have gettimeofday()? */
+#undef NO_GETTOD
+
+/* Do we have getwd() */
+#undef NO_GETWD
+
+/* Do we have a usable 'isnan'? */
+#undef NO_ISNAN
+
+/* Do we have memmove()? */
+#undef NO_MEMMOVE
+
+/* Do we have realpath() */
+#undef NO_REALPATH
+
+/* Do we have <stdlib.h>? */
+#undef NO_STDLIB_H
+
+/* Do we have strerror() */
+#undef NO_STRERROR
+
+/* Do we have <string.h>? */
+#undef NO_STRING_H
+
+/* Do we have <sys/wait.h>? */
+#undef NO_SYS_WAIT_H
+
+/* Do we have uname() */
+#undef NO_UNAME
+
+/* Do we have a usable 'union wait'? */
+#undef NO_UNION_WAIT
+
+/* Do we have <values.h>? */
+#undef NO_VALUES_H
+
+/* Do we have wait3() */
+#undef NO_WAIT3
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Is this a static build? */
+#undef STATIC_BUILD
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* What encoding should be used for embedded configuration info? */
+#undef TCL_CFGVAL_ENCODING
+
+/* Is this a 64-bit build? */
+#undef TCL_CFG_DO64BIT
+
+/* Is this an optimized build? */
+#undef TCL_CFG_OPTIMIZED
+
+/* Is bytecode debugging enabled? */
+#undef TCL_COMPILE_DEBUG
+
+/* Are bytecode statistics enabled? */
+#undef TCL_COMPILE_STATS
+
+/* Are we to override what our default encoding is? */
+#undef TCL_DEFAULT_ENCODING
+
+/* Is Tcl built as a framework? */
+#undef TCL_FRAMEWORK
+
+/* Can this platform load code from memory? */
+#undef TCL_LOAD_FROM_MEMORY
+
+/* Is memory debugging enabled? */
+#undef TCL_MEM_DEBUG
+
+/* What is the default extension for shared libraries? */
+#undef TCL_SHLIB_EXT
+
+/* Are we building with threads enabled? */
+#undef TCL_THREADS
+
+/* Do we allow unloading of shared libraries? */
+#undef TCL_UNLOAD_DLLS
+
+/* Does this platform have wide high-resolution clicks? */
+#undef TCL_WIDE_CLICKS
+
+/* Are wide integers to be implemented with C 'long's? */
+#undef TCL_WIDE_INT_IS_LONG
+
+/* What type should be used to define wide integers? */
+#undef TCL_WIDE_INT_TYPE
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Is getcwd Posix-compliant? */
+#undef USEGETWD
+
+/* May we include <dirent2.h>? */
+#undef USE_DIRENT2_H
+
+/* Are we building with DTrace support? */
+#undef USE_DTRACE
+
+/* Should we use FIONBIO? */
+#undef USE_FIONBIO
+
+/* Do we want to use the threaded memory allocator? */
+#undef USE_THREAD_ALLOC
+
+/* Should we use vfork() instead of fork()? */
+#undef USE_VFORK
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Are Darwin SUSv3 extensions available? */
+#undef _DARWIN_C_SOURCE
+
+/* Add the _ISOC99_SOURCE flag when building */
+#undef _ISOC99_SOURCE
+
+/* Add the _LARGEFILE64_SOURCE flag when building */
+#undef _LARGEFILE64_SOURCE
+
+/* Add the _LARGEFILE_SOURCE64 flag when building */
+#undef _LARGEFILE_SOURCE64
+
+/* # needed in sys/socket.h Should OS/390 do the right thing with sockets? */
+#undef _OE_SOCKETS
+
+/* Do we really want to follow the standard? Yes we do! */
+#undef _POSIX_PTHREAD_SEMANTICS
+
+/* Do we want the reentrant OS API? */
+#undef _REENTRANT
+
+/* Do we want the thread-safe OS API? */
+#undef _THREAD_SAFE
+
+/* Do we want to use the XOPEN network library? */
+#undef _XOPEN_SOURCE
+
+/* Do we want to use the XOPEN network library? */
+#undef _XOPEN_SOURCE_EXTENDED
+
+/* Define to 1 if type `char' is unsigned and you are not using gcc. */
+#ifndef __CHAR_UNSIGNED__
+# undef __CHAR_UNSIGNED__
+#endif
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Signed integer type wide enough to hold a pointer. */
+#undef intptr_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef mode_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define as int if socklen_t is not available */
+#undef socklen_t
+
+/* Do we want to use the strtod() in compat? */
+#undef strtod
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Unsigned integer type wide enough to hold a pointer. */
+#undef uintptr_t
+
+
+ /* Undef unused package specific autoheader defines so that we can
+ * include both tclConfig.h and tkConfig.h at the same time: */
+ /* override */ #undef PACKAGE_NAME
+ /* override */ #undef PACKAGE_STRING
+ /* override */ #undef PACKAGE_TARNAME
+ #endif /* _TCLCONFIG */
diff --git a/unix/tclConfig.sh.in b/unix/tclConfig.sh.in
new file mode 100644
index 0000000..fdc56b7
--- /dev/null
+++ b/unix/tclConfig.sh.in
@@ -0,0 +1,169 @@
+# tclConfig.sh --
+#
+# This shell script (for sh) is generated automatically by Tcl's
+# configure script. It will create shell variables for most of
+# the configuration options discovered by the configure script.
+# This script is intended to be included by the configure scripts
+# for Tcl extensions so that they don't have to figure this all
+# out for themselves.
+#
+# The information in this file is specific to a single platform.
+
+# Tcl's version number.
+TCL_VERSION='@TCL_VERSION@'
+TCL_MAJOR_VERSION='@TCL_MAJOR_VERSION@'
+TCL_MINOR_VERSION='@TCL_MINOR_VERSION@'
+TCL_PATCH_LEVEL='@TCL_PATCH_LEVEL@'
+
+# C compiler to use for compilation.
+TCL_CC='@CC@'
+
+# -D flags for use with the C compiler.
+TCL_DEFS='@DEFS@'
+
+# TCL_DBGX used to be used to distinguish debug vs. non-debug builds.
+# This was a righteous pain so the core doesn't do that any more.
+TCL_DBGX=
+
+# Default flags used in an optimized and debuggable build, respectively.
+TCL_CFLAGS_DEBUG='@CFLAGS_DEBUG@'
+TCL_CFLAGS_OPTIMIZE='@CFLAGS_OPTIMIZE@'
+
+# Default linker flags used in an optimized and debuggable build, respectively.
+TCL_LDFLAGS_DEBUG='@LDFLAGS_DEBUG@'
+TCL_LDFLAGS_OPTIMIZE='@LDFLAGS_OPTIMIZE@'
+
+# Flag, 1: we built a shared lib, 0 we didn't
+TCL_SHARED_BUILD=@TCL_SHARED_BUILD@
+
+# The name of the Tcl library (may be either a .a file or a shared library):
+TCL_LIB_FILE='@TCL_LIB_FILE@'
+
+# Additional libraries to use when linking Tcl.
+TCL_LIBS='@TCL_LIBS@'
+
+# Top-level directory in which Tcl's platform-independent files are
+# installed.
+TCL_PREFIX='@prefix@'
+
+# Top-level directory in which Tcl's platform-specific files (e.g.
+# executables) are installed.
+TCL_EXEC_PREFIX='@exec_prefix@'
+
+# Flags to pass to cc when compiling the components of a shared library:
+TCL_SHLIB_CFLAGS='@SHLIB_CFLAGS@'
+
+# Flags to pass to cc to get warning messages
+TCL_CFLAGS_WARNING='@CFLAGS_WARNING@'
+
+# Extra flags to pass to cc:
+TCL_EXTRA_CFLAGS='@CFLAGS@'
+
+# Base command to use for combining object files into a shared library:
+TCL_SHLIB_LD='@SHLIB_LD@'
+
+# Base command to use for combining object files into a static library:
+TCL_STLIB_LD='@STLIB_LD@'
+
+# Either '$LIBS' (if dependent libraries should be included when linking
+# shared libraries) or an empty string. See Tcl's configure.ac for more
+# explanation.
+TCL_SHLIB_LD_LIBS='@SHLIB_LD_LIBS@'
+
+# Suffix to use for the name of a shared library.
+TCL_SHLIB_SUFFIX='@SHLIB_SUFFIX@'
+
+# Library file(s) to include in tclsh and other base applications
+# in order to provide facilities needed by DLOBJ above.
+TCL_DL_LIBS='@DL_LIBS@'
+
+# Flags to pass to the compiler when linking object files into
+# an executable tclsh or tcltest binary.
+TCL_LD_FLAGS='@LDFLAGS@'
+
+# Flags to pass to cc/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. Used when linking applications. Only works if there
+# is a variable "LIB_RUNTIME_DIR" defined in the Makefile.
+TCL_CC_SEARCH_FLAGS='@CC_SEARCH_FLAGS@'
+TCL_LD_SEARCH_FLAGS='@LD_SEARCH_FLAGS@'
+
+# Additional object files linked with Tcl to provide compatibility
+# with standard facilities from ANSI C or POSIX.
+TCL_COMPAT_OBJS='@LIBOBJS@'
+
+# Name of the ranlib program to use.
+TCL_RANLIB='@RANLIB@'
+
+# -l flag to pass to the linker to pick up the Tcl library
+TCL_LIB_FLAG='@TCL_LIB_FLAG@'
+
+# String to pass to linker to pick up the Tcl library from its
+# build directory.
+TCL_BUILD_LIB_SPEC='@TCL_BUILD_LIB_SPEC@'
+
+# String to pass to linker to pick up the Tcl library from its
+# installed directory.
+TCL_LIB_SPEC='@TCL_LIB_SPEC@'
+
+# String to pass to the compiler so that an extension can
+# find installed Tcl headers.
+TCL_INCLUDE_SPEC='@TCL_INCLUDE_SPEC@'
+
+# Indicates whether a version numbers should be used in -l switches
+# ("ok" means it's safe to use switches like -ltcl7.5; "nodots" means
+# use switches like -ltcl75). SunOS and FreeBSD require "nodots", for
+# example.
+TCL_LIB_VERSIONS_OK='@TCL_LIB_VERSIONS_OK@'
+
+# String that can be evaluated to generate the part of a shared library
+# name that comes after the "libxxx" (includes version number, if any,
+# extension, and anything else needed). May depend on the variables
+# VERSION and SHLIB_SUFFIX. On most UNIX systems this is
+# ${VERSION}${SHLIB_SUFFIX}.
+TCL_SHARED_LIB_SUFFIX='@CFG_TCL_SHARED_LIB_SUFFIX@'
+
+# String that can be evaluated to generate the part of an unshared library
+# name that comes after the "libxxx" (includes version number, if any,
+# extension, and anything else needed). May depend on the variable
+# VERSION. On most UNIX systems this is ${VERSION}.a.
+TCL_UNSHARED_LIB_SUFFIX='@CFG_TCL_UNSHARED_LIB_SUFFIX@'
+
+# Location of the top-level source directory from which Tcl was built.
+# This is the directory that contains a README file as well as
+# subdirectories such as generic, unix, etc. If Tcl was compiled in a
+# different place than the directory containing the source files, this
+# points to the location of the sources, not the location where Tcl was
+# compiled.
+TCL_SRC_DIR='@TCL_SRC_DIR@'
+
+# List of standard directories in which to look for packages during
+# "package require" commands. Contains the "prefix" directory plus also
+# the "exec_prefix" directory, if it is different.
+TCL_PACKAGE_PATH='@TCL_PACKAGE_PATH@'
+
+# Tcl supports stub.
+TCL_SUPPORTS_STUBS=1
+
+# The name of the Tcl stub library (.a):
+TCL_STUB_LIB_FILE='@TCL_STUB_LIB_FILE@'
+
+# -l flag to pass to the linker to pick up the Tcl stub library
+TCL_STUB_LIB_FLAG='@TCL_STUB_LIB_FLAG@'
+
+# String to pass to linker to pick up the Tcl stub library from its
+# build directory.
+TCL_BUILD_STUB_LIB_SPEC='@TCL_BUILD_STUB_LIB_SPEC@'
+
+# String to pass to linker to pick up the Tcl stub library from its
+# installed directory.
+TCL_STUB_LIB_SPEC='@TCL_STUB_LIB_SPEC@'
+
+# Path to the Tcl stub library in the build directory.
+TCL_BUILD_STUB_LIB_PATH='@TCL_BUILD_STUB_LIB_PATH@'
+
+# Path to the Tcl stub library in the install directory.
+TCL_STUB_LIB_PATH='@TCL_STUB_LIB_PATH@'
+
+# Flag, 1: we built Tcl with threads enabled, 0 we didn't
+TCL_THREADS=@TCL_THREADS@
diff --git a/unix/tclEpollNotfy.c b/unix/tclEpollNotfy.c
new file mode 100644
index 0000000..088f314
--- /dev/null
+++ b/unix/tclEpollNotfy.c
@@ -0,0 +1,806 @@
+/*
+ * tclEpollNotfy.c --
+ *
+ * This file contains the implementation of the epoll()-based
+ * Linux-specific notifier, which is the lowest-level part of the
+ * Tcl event loop. This file works together with generic/tclNotify.c.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifdef NOTIFIER_EPOLL
+
+#define _GNU_SOURCE /* For pipe2(2) */
+#include "tclInt.h"
+#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
+ * in tclMacOSXNotify.c */
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/epoll.h>
+#ifdef HAVE_EVENTFD
+#include <sys/eventfd.h>
+#endif /* HAVE_EVENTFD */
+#include <sys/queue.h>
+#include <unistd.h>
+
+/*
+ * This structure is used to keep track of the notifier info for a registered
+ * file.
+ */
+
+struct PlatformEventData;
+typedef struct FileHandler {
+ int fd;
+ int mask; /* Mask of desired events: TCL_READABLE,
+ * etc. */
+ int readyMask; /* Mask of events that have been seen since
+ * the last time file handlers were invoked
+ * for this file. */
+ Tcl_FileProc *proc; /* Function to call, in the style of
+ * Tcl_CreateFileHandler. */
+ ClientData clientData; /* Argument to pass to proc. */
+ struct FileHandler *nextPtr;/* Next in list of all files we care about. */
+ LIST_ENTRY(FileHandler) readyNode;
+ /* Next/previous in list of FileHandlers asso-
+ * ciated with regular files (S_IFREG) that are
+ * ready for I/O. */
+ struct PlatformEventData *pedPtr;
+ /* Pointer to PlatformEventData associating this
+ * FileHandler with epoll(7) events. */
+} FileHandler;
+
+/*
+ * The following structure associates a FileHandler and the thread that owns it
+ * with the file descriptors of interest and their event masks passed to epoll_ctl(2)
+ * and their corresponding event(s) returned by epoll_wait(2).
+ */
+
+struct ThreadSpecificData;
+struct PlatformEventData {
+ FileHandler *filePtr;
+ struct ThreadSpecificData *tsdPtr;
+};
+
+/*
+ * The following structure is what is added to the Tcl event queue when file
+ * handlers are ready to fire.
+ */
+
+typedef struct {
+ Tcl_Event header; /* Information that is standard for all
+ * events. */
+ int fd; /* File descriptor that is ready. Used to find
+ * the FileHandler structure for the file
+ * (can't point directly to the FileHandler
+ * structure because it could go away while
+ * the event is queued). */
+} FileHandlerEvent;
+
+/*
+ * The following static structure contains the state information for the
+ * epoll based implementation of the Tcl notifier. One of these structures is
+ * created for each thread that is using the notifier.
+ */
+
+LIST_HEAD(PlatformReadyFileHandlerList, FileHandler);
+typedef struct ThreadSpecificData {
+ FileHandler *firstFileHandlerPtr;
+ /* Pointer to head of file handler list. */
+ struct PlatformReadyFileHandlerList firstReadyFileHandlerPtr;
+ /* Pointer to head of list of FileHandlers
+ * associated with regular files (S_IFREG)
+ * that are ready for I/O. */
+ pthread_mutex_t notifierMutex;
+ /* Mutex protecting notifier termination in
+ * PlatformEventsFinalize. */
+#ifdef HAVE_EVENTFD
+ int triggerEventFd; /* eventfd(2) used by other threads to wake
+ * up this thread for inter-thread IPC. */
+#else
+ int triggerPipe[2]; /* pipe(2) used by other threads to wake
+ * up this thread for inter-thread IPC. */
+#endif /* HAVE_EVENTFD */
+ int eventsFd; /* epoll(7) file descriptor used to wait for fds */
+ struct epoll_event *readyEvents;
+ /* Pointer to at most maxReadyEvents events
+ * returned by epoll_wait(2). */
+ size_t maxReadyEvents; /* Count of epoll_events in readyEvents. */
+} ThreadSpecificData;
+
+static Tcl_ThreadDataKey dataKey;
+
+void PlatformEventsControl(FileHandler *filePtr, ThreadSpecificData *tsdPtr, int op, int isNew);
+static void PlatformEventsFinalize(void);
+void PlatformEventsInit(void);
+static int PlatformEventsTranslate(struct epoll_event *event);
+static int PlatformEventsWait(struct epoll_event *events, size_t numEvents, struct timeval *timePtr);
+
+#include "tclUnixNotfy.c"
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InitNotifier --
+ *
+ * Initializes the platform specific notifier state.
+ *
+ * Results:
+ * Returns a handle to the notifier state for this thread.
+ *
+ * Side effects:
+ * If no initNotifierProc notifier hook exists, PlatformEventsInit
+ * is called.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_InitNotifier(void)
+{
+ if (tclNotifierHooks.initNotifierProc) {
+ return tclNotifierHooks.initNotifierProc();
+ } else {
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ PlatformEventsInit();
+ return tsdPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FinalizeNotifier --
+ *
+ * This function is called to cleanup the notifier state before a thread
+ * is terminated.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If no finalizeNotifierProc notifier hook exists, PlatformEvents-
+ * Finalize is called.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_FinalizeNotifier(
+ ClientData clientData) /* Not used. */
+{
+ if (tclNotifierHooks.finalizeNotifierProc) {
+ tclNotifierHooks.finalizeNotifierProc(clientData);
+ return;
+ } else {
+ PlatformEventsFinalize();
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlatformEventsControl --
+ *
+ * This function registers interest for the file descriptor and the mask
+ * of TCL_* bits associated with filePtr on the epoll file descriptor
+ * associated with tsdPtr.
+ * Future calls to epoll_wait will return filePtr and tsdPtr alongside with
+ * the event registered here via the PlatformEventData struct.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If adding a new file descriptor, a PlatformEventData struct will be
+ * allocated and associated with filePtr.
+ * fstat is called on the file descriptor; if it is associated with
+ * a regular file (S_IFREG,) filePtr is considered to be ready for I/O
+ * and added to or deleted from the corresponding list in tsdPtr.
+ * If it is not associated with a regular file, the file descriptor is
+ * added, modified concerning its mask of events of interest, or deleted
+ * from the epoll file descriptor of the calling thread.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+PlatformEventsControl(
+ FileHandler *filePtr,
+ ThreadSpecificData *tsdPtr,
+ int op,
+ int isNew)
+{
+ struct epoll_event newEvent;
+ struct PlatformEventData *newPedPtr;
+ struct stat fdStat;
+
+ newEvent.events = 0;
+ if (filePtr->mask & (TCL_READABLE | TCL_EXCEPTION)) {
+ newEvent.events |= EPOLLIN;
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ newEvent.events |= EPOLLOUT;
+ }
+ if (isNew) {
+ newPedPtr = ckalloc(sizeof(*newPedPtr));
+ newPedPtr->filePtr = filePtr;
+ newPedPtr->tsdPtr = tsdPtr;
+ filePtr->pedPtr = newPedPtr;
+ }
+ newEvent.data.ptr = filePtr->pedPtr;
+
+ /*
+ * N.B. As discussed in Tcl_WaitForEvent(), epoll(7) does not sup-
+ * port regular files (S_IFREG.) Therefore, filePtr is in these
+ * cases simply added or deleted from the list of FileHandlers
+ * associated with regular files belonging to tsdPtr.
+ */
+
+ if (fstat(filePtr->fd, &fdStat) == -1) {
+ Tcl_Panic("fstat: %s", strerror(errno));
+ } else if ((fdStat.st_mode & S_IFMT) == S_IFREG) {
+ switch (op) {
+ case EPOLL_CTL_ADD:
+ if (isNew) {
+ LIST_INSERT_HEAD(&tsdPtr->firstReadyFileHandlerPtr, filePtr, readyNode);
+ }
+ break;
+ case EPOLL_CTL_DEL:
+ LIST_REMOVE(filePtr, readyNode);
+ break;
+ }
+ return;
+ } else if (epoll_ctl(tsdPtr->eventsFd, op, filePtr->fd, &newEvent) == -1) {
+ Tcl_Panic("epoll_ctl: %s", strerror(errno));
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlatformEventsFinalize --
+ *
+ * This function closes the eventfd and the epoll file descriptor and
+ * frees the epoll_event structs owned by the thread of the caller.
+ * The above operations are protected by tsdPtr->notifierMutex, which
+ * is destroyed thereafter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * While tsdPtr->notifierMutex is held:
+ * The per-thread eventfd(2) is closed, if non-zero, and set to -1.
+ * The per-thread epoll(7) fd is closed, if non-zero, and set to 0.
+ * The per-thread epoll_event structs are freed, if any, and set to 0.
+ *
+ * tsdPtr->notifierMutex is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+PlatformEventsFinalize(
+ void)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ pthread_mutex_lock(&tsdPtr->notifierMutex);
+#ifdef HAVE_EVENTFD
+ if (tsdPtr->triggerEventFd) {
+ close(tsdPtr->triggerEventFd);
+ tsdPtr->triggerEventFd = -1;
+ }
+#else
+ if (tsdPtr->triggerPipe[0]) {
+ close(tsdPtr->triggerPipe[0]);
+ tsdPtr->triggerPipe[0] = -1;
+ }
+ if (tsdPtr->triggerPipe[1]) {
+ close(tsdPtr->triggerPipe[1]);
+ tsdPtr->triggerPipe[1] = -1;
+ }
+#endif /* HAVE_EVENTFD */
+ if (tsdPtr->eventsFd > 0) {
+ close(tsdPtr->eventsFd);
+ tsdPtr->eventsFd = 0;
+ }
+ if (tsdPtr->readyEvents) {
+ ckfree(tsdPtr->readyEvents);
+ tsdPtr->maxReadyEvents = 0;
+ }
+ pthread_mutex_unlock(&tsdPtr->notifierMutex);
+ if ((errno = pthread_mutex_destroy(&tsdPtr->notifierMutex))) {
+ Tcl_Panic("pthread_mutex_destroy: %s", strerror(errno));
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlatformEventsInit --
+ *
+ * This function abstracts creating a kqueue fd via the epoll_create
+ * system call and allocating memory for the epoll_event structs in
+ * tsdPtr for the thread of the caller.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The following per-thread entities are initialised:
+ * notifierMutex is initialised.
+ * The eventfd(2) is created w/ EFD_CLOEXEC and EFD_NONBLOCK.
+ * The epoll(7) fd is created w/ EPOLL_CLOEXEC.
+ * A FileHandler struct is allocated and initialised for the event-
+ * fd(2), registering interest for TCL_READABLE on it via Platform-
+ * EventsControl().
+ * readyEvents and maxReadyEvents are initialised with 512 epoll_events.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+PlatformEventsInit(
+ void)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr;
+
+ errno = pthread_mutex_init(&tsdPtr->notifierMutex, NULL);
+ if (errno) {
+ Tcl_Panic("Tcl_InitNotifier: %s", "could not create mutex");
+ }
+ filePtr = ckalloc(sizeof(*filePtr));
+#ifdef HAVE_EVENTFD
+ if ((tsdPtr->triggerEventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)) <= 0) {
+ Tcl_Panic("Tcl_InitNotifier: %s", "could not create trigger eventfd");
+ }
+ filePtr->fd = tsdPtr->triggerEventFd;
+#else
+ if (pipe2(tsdPtr->triggerPipe, O_CLOEXEC | O_NONBLOCK) != 0) {
+ Tcl_Panic("Tcl_InitNotifier: %s", "could not create trigger pipe");
+ }
+ filePtr->fd = tsdPtr->triggerPipe[0];
+#endif
+ if ((tsdPtr->eventsFd = epoll_create1(EPOLL_CLOEXEC)) == -1) {
+ Tcl_Panic("epoll_create1: %s", strerror(errno));
+ }
+ filePtr->mask = TCL_READABLE;
+ PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_ADD, 1);
+ if (!tsdPtr->readyEvents) {
+ tsdPtr->maxReadyEvents = 512;
+ tsdPtr->readyEvents = ckalloc(tsdPtr->maxReadyEvents
+ * sizeof(tsdPtr->readyEvents[0]));
+ }
+ LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlatformEventsTranslate --
+ *
+ * This function translates the platform-specific mask of returned
+ * events in eventPtr to a mask of TCL_* bits.
+ *
+ * Results:
+ * Returns the translated mask.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+PlatformEventsTranslate(
+ struct epoll_event *eventPtr)
+{
+ int mask;
+
+ mask = 0;
+ if (eventPtr->events & (EPOLLIN | EPOLLHUP)) {
+ mask |= TCL_READABLE;
+ }
+ if (eventPtr->events & EPOLLOUT) {
+ mask |= TCL_WRITABLE;
+ }
+ if (eventPtr->events & EPOLLERR) {
+ mask |= TCL_EXCEPTION;
+ }
+ return mask;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlatformEventsWait --
+ *
+ * This function abstracts waiting for I/O events via epoll_wait.
+ *
+ * Results:
+ * Returns -1 if epoll_wait failed. Returns 0 if polling and if no
+ * events became available whilst polling. Returns a pointer to and
+ * the count of all returned events in all other cases.
+ *
+ * Side effects:
+ * gettimeofday(2), epoll_wait(2), and gettimeofday(2) are called,
+ * in the specified order.
+ * If timePtr specifies a positive value, it is updated to reflect
+ * the amount of time that has passed; if its value would {under,
+ * over}flow, it is set to zero.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+PlatformEventsWait(
+ struct epoll_event *events,
+ size_t numEvents,
+ struct timeval *timePtr)
+{
+ int numFound;
+ struct timeval tv0, tv1, tv_delta;
+ int timeout;
+
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ /*
+ * If timePtr is NULL, epoll_wait(2) will wait indefinitely. If it
+ * specifies a timeout of {0,0}, epoll_wait(2) will poll. Otherwise,
+ * the timeout will simply be converted to milliseconds.
+ */
+
+ if (!timePtr) {
+ timeout = -1;
+ } else if (!timePtr->tv_sec && !timePtr->tv_usec) {
+ timeout = 0;
+ } else {
+ timeout = (int)timePtr->tv_sec;
+ }
+
+ /*
+ * Call (and possibly block on) epoll_wait(2) and substract the delta
+ * of gettimeofday(2) before and after the call from timePtr if the
+ * latter is not NULL. Return the number of events returned by epoll_wait(2).
+ */
+
+ gettimeofday(&tv0, NULL);
+ numFound = epoll_wait(tsdPtr->eventsFd, events, (int)numEvents, timeout);
+ gettimeofday(&tv1, NULL);
+ if (timePtr && (timePtr->tv_sec && timePtr->tv_usec)) {
+ timersub(&tv1, &tv0, &tv_delta);
+ if (!timercmp(&tv_delta, timePtr, >)) {
+ timersub(timePtr, &tv_delta, timePtr);
+ } else {
+ timePtr->tv_sec = 0;
+ timePtr->tv_usec = 0;
+ }
+ }
+ return numFound;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateFileHandler --
+ *
+ * This function registers a file handler with the epoll notifier
+ * of the thread of the caller.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates a new file handler structure.
+ * PlatformEventsControl() is called for the new file handler structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_CreateFileHandler(
+ int fd, /* Handle of stream to watch. */
+ int mask, /* OR'ed combination of TCL_READABLE,
+ * TCL_WRITABLE, and TCL_EXCEPTION: indicates
+ * conditions under which proc should be
+ * called. */
+ Tcl_FileProc *proc, /* Function to call for each selected
+ * event. */
+ ClientData clientData) /* Arbitrary data to pass to proc. */
+{
+ int isNew;
+
+ if (tclNotifierHooks.createFileHandlerProc) {
+ tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
+ return;
+ } else {
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr;
+
+ for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
+ filePtr = filePtr->nextPtr) {
+ if (filePtr->fd == fd) {
+ break;
+ }
+ }
+ if (filePtr == NULL) {
+ filePtr = ckalloc(sizeof(FileHandler));
+ filePtr->fd = fd;
+ filePtr->readyMask = 0;
+ filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
+ tsdPtr->firstFileHandlerPtr = filePtr;
+ isNew = 1;
+ } else {
+ isNew = 0;
+ }
+ filePtr->proc = proc;
+ filePtr->clientData = clientData;
+ filePtr->mask = mask;
+
+ PlatformEventsControl(filePtr, tsdPtr, isNew ?
+ EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteFileHandler --
+ *
+ * Cancel a previously-arranged callback arrangement for a file on
+ * the epoll file descriptor of the thread of the caller.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If a callback was previously registered on file, remove it.
+ * PlatformEventsControl() is called for the file handler structure.
+ * The PlatformEventData struct associated with the new file handler
+ * structure is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteFileHandler(
+ int fd) /* Stream id for which to remove callback
+ * function. */
+{
+ if (tclNotifierHooks.deleteFileHandlerProc) {
+ tclNotifierHooks.deleteFileHandlerProc(fd);
+ return;
+ } else {
+ FileHandler *filePtr, *prevPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ /*
+ * Find the entry for the given file (and return if there isn't one).
+ */
+
+ for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
+ prevPtr = filePtr, filePtr = filePtr->nextPtr) {
+ if (filePtr == NULL) {
+ return;
+ }
+ if (filePtr->fd == fd) {
+ break;
+ }
+ }
+
+ /*
+ * Update the check masks for this file.
+ */
+
+ PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_DEL, 0);
+ if (filePtr->pedPtr) {
+ ckfree(filePtr->pedPtr);
+ }
+
+ /*
+ * Clean up information in the callback record.
+ */
+
+ if (prevPtr == NULL) {
+ tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = filePtr->nextPtr;
+ }
+ ckfree(filePtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_WaitForEvent --
+ *
+ * This function is called by Tcl_DoOneEvent to wait for new events on
+ * the message queue. If the block time is 0, then Tcl_WaitForEvent just
+ * polls without blocking.
+ * The waiting logic is implemented in PlatformEventsWait.
+ *
+ * Results:
+ * Returns -1 if PlatformEventsWait() would block forever, otherwise
+ * returns 0.
+ *
+ * Side effects:
+ * Queues file events that are detected by PlatformEventsWait().
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_WaitForEvent(
+ const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
+{
+ if (tclNotifierHooks.waitForEventProc) {
+ return tclNotifierHooks.waitForEventProc(timePtr);
+ } else {
+ FileHandler *filePtr;
+ int mask;
+ Tcl_Time vTime;
+ /*
+ * Impl. notes: timeout & timeoutPtr are used if, and only if threads
+ * are not enabled. They are the arguments for the regular epoll_wait()
+ * used when the core is not thread-enabled.
+ */
+
+ struct timeval timeout, *timeoutPtr;
+ int numFound, numEvent;
+ struct PlatformEventData *pedPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ int numQueued;
+ ssize_t i;
+
+ /*
+ * Set up the timeout structure. Note that if there are no events to
+ * check for, we return with a negative result rather than blocking
+ * forever.
+ */
+
+ if (timePtr != NULL) {
+ /*
+ * TIP #233 (Virtualized Time). Is virtual time in effect? And do
+ * we actually have something to scale? If yes to both then we
+ * call the handler to do this scaling.
+ */
+
+ if (timePtr->sec != 0 || timePtr->usec != 0) {
+ vTime = *timePtr;
+ tclScaleTimeProcPtr(&vTime, tclTimeClientData);
+ timePtr = &vTime;
+ }
+ timeout.tv_sec = timePtr->sec;
+ timeout.tv_usec = timePtr->usec;
+ timeoutPtr = &timeout;
+ } else {
+ timeoutPtr = NULL;
+ }
+
+ /*
+ * Walk the list of FileHandlers associated with regular files
+ * (S_IFREG) belonging to tsdPtr, queue Tcl events for them, and
+ * update their mask of events of interest.
+ * As epoll(7) does not support regular files, the behaviour of
+ * {select,poll}(2) is simply simulated here: fds associated with
+ * regular files are added to this list by PlatformEventsControl()
+ * and processed here before calling (and possibly blocking) on
+ * PlatformEventsWait().
+ */
+
+ numQueued = 0;
+ LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) {
+ mask = 0;
+ if (filePtr->mask & TCL_READABLE) {
+ mask |= TCL_READABLE;
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ mask |= TCL_WRITABLE;
+ }
+
+ /*
+ * Don't bother to queue an event if the mask was previously
+ * non-zero since an event must still be on the queue.
+ */
+
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr =
+ ckalloc(sizeof(FileHandlerEvent));
+
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
+ numQueued++;
+ }
+ filePtr->readyMask = mask;
+ }
+
+ /*
+ * If any events were queued in the above loop, force PlatformEvents-
+ * Wait() to poll as there already are events that need to be processed
+ * at this point.
+ */
+
+ if (numQueued) {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ timeoutPtr = &timeout;
+ }
+
+ /*
+ * Wait or poll for new events, queue Tcl events for the FileHandlers
+ * corresponding to them, and update the FileHandlers' mask of events
+ * of interest registered by the last call to Tcl_CreateFileHandler().
+ *
+ * Events for the eventfd(2)/trigger pipe are processed here in order
+ * to facilitate inter-thread IPC. If another thread intends to wake
+ * up this thread whilst it's blocking on PlatformEventsWait(), it
+ * write(2)s to the eventfd(2)/trigger pipe (see Tcl_AlertNotifier(),)
+ * which in turn will cause PlatformEventsWait() to return immediately.
+ */
+
+ numFound = PlatformEventsWait(tsdPtr->readyEvents, tsdPtr->maxReadyEvents, timeoutPtr);
+ for (numEvent = 0; numEvent < numFound; numEvent++) {
+ pedPtr = tsdPtr->readyEvents[numEvent].data.ptr;
+ filePtr = pedPtr->filePtr;
+ mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
+#ifdef HAVE_EVENTFD
+ if (filePtr->fd == tsdPtr->triggerEventFd) {
+ uint64_t eventFdVal;
+ i = read(tsdPtr->triggerEventFd, &eventFdVal, sizeof(eventFdVal));
+ if ((i != sizeof(eventFdVal)) && (errno != EAGAIN)) {
+#else
+ if (filePtr->fd == tsdPtr->triggerPipe[0]) {
+ char triggerPipeVal;
+ i = read(tsdPtr->triggerPipe[0], &triggerPipeVal, sizeof(triggerPipeVal));
+ if ((i != sizeof(triggerPipeVal)) && (errno != EAGAIN)) {
+#endif
+ Tcl_Panic("Tcl_WaitForEvent: "
+ "read from %p->triggerEventFd: %s",
+ (void *)tsdPtr, strerror(errno));
+ } else {
+ continue;
+ }
+ }
+ if (!mask) {
+ continue;
+ }
+
+ /*
+ * Don't bother to queue an event if the mask was previously
+ * non-zero since an event must still be on the queue.
+ */
+
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr =
+ ckalloc(sizeof(FileHandlerEvent));
+
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
+ }
+ filePtr->readyMask = mask;
+ }
+ return 0;
+ }
+}
+
+#endif /* !HAVE_COREFOUNDATION */
+
+#endif /* NOTIFIER_EPOLL */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclKqueueNotfy.c b/unix/tclKqueueNotfy.c
new file mode 100644
index 0000000..049829e
--- /dev/null
+++ b/unix/tclKqueueNotfy.c
@@ -0,0 +1,842 @@
+/*
+ * tclKqueueNotfy.c --
+ *
+ * This file contains the implementation of the kqueue()-based
+ * DragonFly/Free/Net/OpenBSD-specific notifier, which is the lowest-
+ * level part of the Tcl event loop. This file works together with
+ * generic/tclNotify.c.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifdef NOTIFIER_KQUEUE
+
+#include "tclInt.h"
+#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
+ * in tclMacOSXNotify.c */
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+/*
+ * This structure is used to keep track of the notifier info for a registered
+ * file.
+ */
+
+struct PlatformEventData;
+typedef struct FileHandler {
+ int fd;
+ int mask; /* Mask of desired events: TCL_READABLE,
+ * etc. */
+ int readyMask; /* Mask of events that have been seen since
+ * the last time file handlers were invoked
+ * for this file. */
+ Tcl_FileProc *proc; /* Function to call, in the style of
+ * Tcl_CreateFileHandler. */
+ ClientData clientData; /* Argument to pass to proc. */
+ struct FileHandler *nextPtr;/* Next in list of all files we care about. */
+ LIST_ENTRY(FileHandler) readyNode;
+ /* Next/previous in list of FileHandlers asso-
+ * ciated with regular files (S_IFREG) that are
+ * ready for I/O. */
+ struct PlatformEventData *pedPtr;
+ /* Pointer to PlatformEventData associating this
+ * FileHandler with kevent(2) events. */
+} FileHandler;
+
+/*
+ * The following structure associates a FileHandler and the thread that owns it
+ * with the file descriptors of interest and their event masks passed to kevent(2)
+ * and their corresponding event(s) returned by kevent(2).
+ */
+
+struct ThreadSpecificData;
+struct PlatformEventData {
+ FileHandler *filePtr;
+ struct ThreadSpecificData *tsdPtr;
+};
+
+/*
+ * The following structure is what is added to the Tcl event queue when file
+ * handlers are ready to fire.
+ */
+
+typedef struct {
+ Tcl_Event header; /* Information that is standard for all
+ * events. */
+ int fd; /* File descriptor that is ready. Used to find
+ * the FileHandler structure for the file
+ * (can't point directly to the FileHandler
+ * structure because it could go away while
+ * the event is queued). */
+} FileHandlerEvent;
+
+/*
+ * The following static structure contains the state information for the
+ * kqueue based implementation of the Tcl notifier. One of these structures is
+ * created for each thread that is using the notifier.
+ */
+
+LIST_HEAD(PlatformReadyFileHandlerList, FileHandler);
+typedef struct ThreadSpecificData {
+ FileHandler *firstFileHandlerPtr;
+ /* Pointer to head of file handler list. */
+ struct PlatformReadyFileHandlerList firstReadyFileHandlerPtr;
+ /* Pointer to head of list of FileHandlers
+ * associated with regular files (S_IFREG)
+ * that are ready for I/O. */
+ pthread_mutex_t notifierMutex;
+ /* Mutex protecting notifier termination in
+ * PlatformEventsFinalize. */
+ int triggerPipe[2]; /* pipe(2) used by other threads to wake
+ * up this thread for inter-thread IPC. */
+ int eventsFd; /* kqueue(2) file descriptor used to wait for fds. */
+ struct kevent *readyEvents; /* Pointer to at most maxReadyEvents events
+ * returned by kevent(2). */
+ size_t maxReadyEvents; /* Count of kevents in readyEvents. */
+} ThreadSpecificData;
+
+static Tcl_ThreadDataKey dataKey;
+
+void PlatformEventsControl(FileHandler *filePtr, ThreadSpecificData *tsdPtr, int op, int isNew);
+static void PlatformEventsFinalize(void);
+void PlatformEventsInit(void);
+static int PlatformEventsTranslate(struct kevent *eventPtr);
+static int PlatformEventsWait(struct kevent *events, size_t numEvents, struct timeval *timePtr);
+
+#include "tclUnixNotfy.c"
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InitNotifier --
+ *
+ * Initializes the platform specific notifier state.
+ *
+ * Results:
+ * Returns a handle to the notifier state for this thread.
+ *
+ * Side effects:
+ * If no initNotifierProc notifier hook exists, PlatformEventsInit
+ * is called.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_InitNotifier(void)
+{
+ if (tclNotifierHooks.initNotifierProc) {
+ return tclNotifierHooks.initNotifierProc();
+ } else {
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ PlatformEventsInit();
+ return tsdPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FinalizeNotifier --
+ *
+ * This function is called to cleanup the notifier state before a thread
+ * is terminated.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If no finalizeNotifierProc notifier hook exists, PlatformEvents-
+ * Finalize is called.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_FinalizeNotifier(
+ ClientData clientData) /* Not used. */
+{
+ if (tclNotifierHooks.finalizeNotifierProc) {
+ tclNotifierHooks.finalizeNotifierProc(clientData);
+ return;
+ } else {
+ PlatformEventsFinalize();
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlatformEventsControl --
+ *
+ * This function registers interest for the file descriptor and the mask
+ * of TCL_* bits associated with filePtr on the kqueue file descriptor
+ * associated with tsdPtr.
+ * Future calls to kevent will return filePtr and tsdPtr alongside with
+ * the event registered here via the PlatformEventData struct.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If adding a new file descriptor, a PlatformEventData struct will be
+ * allocated and associated with filePtr.
+ * fstat is called on the file descriptor; if it is associated with
+ * a regular file (S_IFREG,) filePtr is considered to be ready for I/O
+ * and added to or deleted from the corresponding list in tsdPtr.
+ * If it is not associated with a regular file, the file descriptor is
+ * added, modified concerning its mask of events of interest, or deleted
+ * from the epoll file descriptor of the calling thread.
+ * If deleting a file descriptor, kevent(2) is called twice specifying
+ * EVFILT_READ first and then EVFILT_WRITE (see note below.)
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+PlatformEventsControl(
+ FileHandler *filePtr,
+ ThreadSpecificData *tsdPtr,
+ int op,
+ int isNew)
+{
+ int numChanges;
+ struct kevent changeList[2];
+ struct PlatformEventData *newPedPtr;
+ struct stat fdStat;
+
+ if (isNew) {
+ newPedPtr = ckalloc(sizeof(*newPedPtr));
+ newPedPtr->filePtr = filePtr;
+ newPedPtr->tsdPtr = tsdPtr;
+ filePtr->pedPtr = newPedPtr;
+ }
+
+ /*
+ * N.B. As discussed in Tcl_WaitForEvent(), kqueue(2) does not repro-
+ * duce the `always ready' {select,poll}(2) behaviour for regular
+ * files (S_IFREG) prior to FreeBSD 11.0-RELEASE. Therefore, file-
+ * Ptr is in these cases simply added or deleted from the list of
+ * FileHandlers associated with regular files belonging to tsdPtr.
+ */
+
+ if (fstat(filePtr->fd, &fdStat) == -1) {
+ Tcl_Panic("fstat: %s", strerror(errno));
+ } else if ((fdStat.st_mode & S_IFMT) == S_IFREG) {
+ switch (op) {
+ case EV_ADD:
+ if (isNew) {
+ LIST_INSERT_HEAD(&tsdPtr->firstReadyFileHandlerPtr, filePtr, readyNode);
+ }
+ break;
+ case EV_DELETE:
+ LIST_REMOVE(filePtr, readyNode);
+ break;
+ }
+ return;
+ }
+
+ numChanges = 0;
+ switch (op) {
+ case EV_ADD:
+ if (filePtr->mask & (TCL_READABLE | TCL_EXCEPTION)) {
+ EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd, EVFILT_READ,
+ op, 0, 0, filePtr->pedPtr);
+ numChanges++;
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd, EVFILT_WRITE,
+ op, 0, 0, filePtr->pedPtr);
+ numChanges++;
+ }
+ if (numChanges) {
+ if (kevent(tsdPtr->eventsFd, changeList, numChanges, NULL, 0, NULL) == -1) {
+ Tcl_Panic("kevent: %s", strerror(errno));
+ }
+ }
+ break;
+ case EV_DELETE:
+ /*
+ * N.B. kqueue(2) has separate filters for readability and writabi-
+ * lity fd events. We therefore need to ensure that fds are
+ * ompletely removed from the kqueue(2) fd when deleting.
+ * This is exacerbated by changes to filePtr->mask w/o calls
+ * to PlatforEventsControl() after e.g. an exec(3) in a child
+ * process.
+ * As one of these calls can fail, two separate kevent(2) calls
+ * are made for EVFILT_{READ,WRITE}.
+ */
+ EV_SET(&changeList[0], (uintptr_t)filePtr->fd, EVFILT_READ, op, 0, 0, NULL);
+ if ((kevent(tsdPtr->eventsFd, changeList, 1, NULL, 0, NULL) == -1)
+ && (errno != ENOENT)) {
+ Tcl_Panic("kevent: %s", strerror(errno));
+ }
+ EV_SET(&changeList[0], (uintptr_t)filePtr->fd, EVFILT_WRITE, op, 0, 0, NULL);
+ if ((kevent(tsdPtr->eventsFd, changeList, 1, NULL, 0, NULL) == -1)
+ && (errno != ENOENT)) {
+ Tcl_Panic("kevent: %s", strerror(errno));
+ }
+ break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlatformEventsFinalize --
+ *
+ * This function closes the pipe and the kqueue file descriptors
+ * and frees the kevent structs owned by the thread of the caller.
+ * The above operations are protected by tsdPtr->notifierMutex, which
+ * is destroyed thereafter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * While tsdPtr->notifierMutex is held:
+ * The per-thread pipe(2) fds are closed, if non-zero, and set to -1.
+ * The per-thread kqueue(2) fd is closed, if non-zero, and set to 0.
+ * The per-thread kevent structs are freed, if any, and set to 0.
+ *
+ * tsdPtr->notifierMutex is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+PlatformEventsFinalize(
+ void)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ pthread_mutex_lock(&tsdPtr->notifierMutex);
+ if (tsdPtr->triggerPipe[0]) {
+ close(tsdPtr->triggerPipe[0]);
+ tsdPtr->triggerPipe[0] = -1;
+ }
+ if (tsdPtr->triggerPipe[1]) {
+ close(tsdPtr->triggerPipe[1]);
+ tsdPtr->triggerPipe[1] = -1;
+ }
+ if (tsdPtr->eventsFd > 0) {
+ close(tsdPtr->eventsFd);
+ tsdPtr->eventsFd = 0;
+ }
+ if (tsdPtr->readyEvents) {
+ ckfree(tsdPtr->readyEvents);
+ tsdPtr->maxReadyEvents = 0;
+ }
+ pthread_mutex_unlock(&tsdPtr->notifierMutex);
+ if ((errno = pthread_mutex_destroy(&tsdPtr->notifierMutex))) {
+ Tcl_Panic("pthread_mutex_destroy: %s", strerror(errno));
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlatformEventsInit --
+ *
+ * This function abstracts creating a kqueue fd via the kqueue
+ * system call and allocating memory for the kevents structs in
+ * tsdPtr for the thread of the caller.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The following per-thread entities are initialised:
+ * notifierMutex is initialised.
+ * The pipe(2) is created; fcntl(2) is called on both fds to set
+ * FD_CLOEXEC and O_NONBLOCK.
+ * The kqueue(2) fd is created; fcntl(2) is called on it to set
+ * FD_CLOEXEC.
+ * A FileHandler struct is allocated and initialised for the event-
+ * fd(2), registering interest for TCL_READABLE on it via Platform-
+ * EventsControl().
+ * readyEvents and maxReadyEvents are initialised with 512 kevents.
+
+ *----------------------------------------------------------------------
+ */
+
+void
+PlatformEventsInit(
+ void)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ int i, fdFl;
+ FileHandler *filePtr;
+
+ errno = pthread_mutex_init(&tsdPtr->notifierMutex, NULL);
+ if (errno) {
+ Tcl_Panic("Tcl_InitNotifier: %s", "could not create mutex");
+ }
+ if (pipe(tsdPtr->triggerPipe) != 0) {
+ Tcl_Panic("Tcl_InitNotifier: %s", "could not create trigger pipe");
+ } else for (i = 0; i < 2; i++) {
+ if (fcntl(tsdPtr->triggerPipe[i], F_SETFD, FD_CLOEXEC) == -1) {
+ Tcl_Panic("fcntl: %s", strerror(errno));
+ } else {
+ fdFl = fcntl(tsdPtr->triggerPipe[i], F_GETFL);
+ fdFl |= O_NONBLOCK;
+ }
+ if (fcntl(tsdPtr->triggerPipe[i], F_SETFL, fdFl) == -1) {
+ Tcl_Panic("fcntl: %s", strerror(errno));
+ }
+ }
+ if ((tsdPtr->eventsFd = kqueue()) == -1) {
+ Tcl_Panic("kqueue: %s", strerror(errno));
+ } else if (fcntl(tsdPtr->eventsFd, F_SETFD, FD_CLOEXEC) == -1) {
+ Tcl_Panic("fcntl: %s", strerror(errno));
+ }
+ filePtr = ckalloc(sizeof(*filePtr));
+ filePtr->fd = tsdPtr->triggerPipe[0];
+ filePtr->mask = TCL_READABLE;
+ PlatformEventsControl(filePtr, tsdPtr, EV_ADD, 1);
+ if (!tsdPtr->readyEvents) {
+ tsdPtr->maxReadyEvents = 512;
+ tsdPtr->readyEvents = ckalloc(tsdPtr->maxReadyEvents
+ * sizeof(tsdPtr->readyEvents[0]));
+ }
+ LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlatformEventsTranslate --
+ *
+ * This function translates the platform-specific mask of returned
+ * events in eventPtr to a mask of TCL_* bits.
+ *
+ * Results:
+ * Returns the translated mask.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+PlatformEventsTranslate(
+ struct kevent *eventPtr)
+{
+ int mask;
+
+ mask = 0;
+ if (eventPtr->filter == EVFILT_READ) {
+ mask |= TCL_READABLE;
+ if (eventPtr->flags & EV_ERROR) {
+ mask |= TCL_EXCEPTION;
+ }
+ }
+ if (eventPtr->filter == EVFILT_WRITE) {
+ mask |= TCL_WRITABLE;
+ if (eventPtr->flags & EV_ERROR) {
+ mask |= TCL_EXCEPTION;
+ }
+ }
+ return mask;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PlatformEventsWait --
+ *
+ * This function abstracts waiting for I/O events via the kevent
+ * system call.
+ *
+ * Results:
+ * Returns -1 if kevent failed. Returns 0 if polling and if no events
+ * became available whilst polling. Returns a pointer to and the count
+ * of all returned events in all other cases.
+ *
+ * Side effects:
+ * gettimeofday(2), kevent(2), and gettimeofday(2) are called,
+ * in the specified order.
+ * If timePtr specifies a positive value, it is updated to reflect
+ * the amount of time that has passed; if its value would {under,
+ * over}flow, it is set to zero.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+PlatformEventsWait(
+ struct kevent *events,
+ size_t numEvents,
+ struct timeval *timePtr)
+{
+ int numFound;
+ struct timeval tv0, tv1, tv_delta;
+ struct timespec timeout, *timeoutPtr;
+
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ /*
+ * If timePtr is NULL, kevent(2) will wait indefinitely. If it speci-
+ * fies a timeout of {0,0}, kevent(2) will poll. Otherwise, the time-
+ * out will simply be converted to a timespec.
+ */
+
+ if (!timePtr) {
+ timeoutPtr = NULL;
+ } else if (!timePtr->tv_sec && !timePtr->tv_usec) {
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 0;
+ timeoutPtr = &timeout;
+ } else {
+ timeout.tv_sec = timePtr->tv_sec;
+ timeout.tv_nsec = timePtr->tv_usec * 1000;
+ timeoutPtr = &timeout;
+ }
+
+ /*
+ * Call (and possibly block on) kevent(2) and substract the delta of
+ * gettimeofday(2) before and after the call from timePtr if the latter
+ * is not NULL. Return the number of events returned by kevent(2).
+ */
+
+ gettimeofday(&tv0, NULL);
+ numFound = kevent(tsdPtr->eventsFd, NULL, 0, events, (int)numEvents, timeoutPtr);
+ gettimeofday(&tv1, NULL);
+ if (timePtr && (timePtr->tv_sec && timePtr->tv_usec)) {
+ timersub(&tv1, &tv0, &tv_delta);
+ if (!timercmp(&tv_delta, timePtr, >)) {
+ timersub(timePtr, &tv_delta, timePtr);
+ } else {
+ timePtr->tv_sec = 0;
+ timePtr->tv_usec = 0;
+ }
+ }
+ return numFound;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateFileHandler --
+ *
+ * This function registers a file handler with the kqueue notifier
+ * of the thread of the caller.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates a new file handler structure.
+ * PlatformEventsControl() is called for the new file handler structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_CreateFileHandler(
+ int fd, /* Handle of stream to watch. */
+ int mask, /* OR'ed combination of TCL_READABLE,
+ * TCL_WRITABLE, and TCL_EXCEPTION: indicates
+ * conditions under which proc should be
+ * called. */
+ Tcl_FileProc *proc, /* Function to call for each selected
+ * event. */
+ ClientData clientData) /* Arbitrary data to pass to proc. */
+{
+ int isNew;
+
+ if (tclNotifierHooks.createFileHandlerProc) {
+ tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
+ return;
+ } else {
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr;
+
+ for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
+ filePtr = filePtr->nextPtr) {
+ if (filePtr->fd == fd) {
+ break;
+ }
+ }
+ if (filePtr == NULL) {
+ filePtr = ckalloc(sizeof(FileHandler));
+ filePtr->fd = fd;
+ filePtr->readyMask = 0;
+ filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
+ tsdPtr->firstFileHandlerPtr = filePtr;
+ isNew = 1;
+ } else {
+ isNew = 0;
+ }
+ filePtr->proc = proc;
+ filePtr->clientData = clientData;
+ filePtr->mask = mask;
+
+ PlatformEventsControl(filePtr, tsdPtr, EV_ADD, isNew);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteFileHandler --
+ *
+ * Cancel a previously-arranged callback arrangement for a file on
+ * the kqueue of the thread of the caller.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If a callback was previously registered on file, remove it.
+ * PlatformEventsControl() is called for the file handler structure.
+ * The PlatformEventData struct associated with the new file handler
+ * structure is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteFileHandler(
+ int fd) /* Stream id for which to remove callback
+ * function. */
+{
+ if (tclNotifierHooks.deleteFileHandlerProc) {
+ tclNotifierHooks.deleteFileHandlerProc(fd);
+ return;
+ } else {
+ FileHandler *filePtr, *prevPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ /*
+ * Find the entry for the given file (and return if there isn't one).
+ */
+
+ for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
+ prevPtr = filePtr, filePtr = filePtr->nextPtr) {
+ if (filePtr == NULL) {
+ return;
+ }
+ if (filePtr->fd == fd) {
+ break;
+ }
+ }
+
+ /*
+ * Update the check masks for this file.
+ */
+
+ PlatformEventsControl(filePtr, tsdPtr, EV_DELETE, 0);
+ if (filePtr->pedPtr) {
+ ckfree(filePtr->pedPtr);
+ }
+
+ /*
+ * Clean up information in the callback record.
+ */
+
+ if (prevPtr == NULL) {
+ tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = filePtr->nextPtr;
+ }
+ ckfree(filePtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_WaitForEvent --
+ *
+ * This function is called by Tcl_DoOneEvent to wait for new events on
+ * the message queue. If the block time is 0, then Tcl_WaitForEvent just
+ * polls without blocking.
+ * The waiting logic is implemented in PlatformEventsWait.
+ *
+ * Results:
+ * Returns -1 if PlatformEventsWait() would block forever, otherwise
+ * returns 0.
+ *
+ * Side effects:
+ * Queues file events that are detected by PlatformEventsWait().
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_WaitForEvent(
+ const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
+{
+ if (tclNotifierHooks.waitForEventProc) {
+ return tclNotifierHooks.waitForEventProc(timePtr);
+ } else {
+ FileHandler *filePtr;
+ int mask;
+ Tcl_Time vTime;
+ /*
+ * Impl. notes: timeout & timeoutPtr are used if, and only if threads
+ * are not enabled. They are the arguments for the regular epoll_wait()
+ * used when the core is not thread-enabled.
+ */
+
+ struct timeval timeout, *timeoutPtr;
+ int numFound, numEvent;
+ struct PlatformEventData *pedPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ int numQueued;
+ ssize_t i;
+ char buf[1];
+
+ /*
+ * Set up the timeout structure. Note that if there are no events to
+ * check for, we return with a negative result rather than blocking
+ * forever.
+ */
+
+ if (timePtr != NULL) {
+ /*
+ * TIP #233 (Virtualized Time). Is virtual time in effect? And do
+ * we actually have something to scale? If yes to both then we
+ * call the handler to do this scaling.
+ */
+
+ if (timePtr->sec != 0 || timePtr->usec != 0) {
+ vTime = *timePtr;
+ tclScaleTimeProcPtr(&vTime, tclTimeClientData);
+ timePtr = &vTime;
+ }
+ timeout.tv_sec = timePtr->sec;
+ timeout.tv_usec = timePtr->usec;
+ timeoutPtr = &timeout;
+ } else {
+ timeoutPtr = NULL;
+ }
+
+ /*
+ * Walk the list of FileHandlers associated with regular files
+ * (S_IFREG) belonging to tsdPtr, queue Tcl events for them, and
+ * update their mask of events of interest.
+ * kqueue(2), unlike epoll(7), does support regular files, but
+ * EVFILT_READ only `[r]eturns when the file pointer is not at
+ * the end of file' as opposed to unconditionally. While FreeBSD
+ * 11.0-RELEASE adds support for this mode (NOTE_FILE_POLL,) this
+ * is not used for reasons of compatibility.
+ * Therefore, the behaviour of {select,poll}(2) is simply simulated
+ * here: fds associated with regular files are added to this list by
+ * PlatformEventsControl() and processed here before calling (and
+ * possibly blocking) on PlatformEventsWait().
+ */
+
+ numQueued = 0;
+ LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) {
+ mask = 0;
+ if (filePtr->mask & TCL_READABLE) {
+ mask |= TCL_READABLE;
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ mask |= TCL_WRITABLE;
+ }
+
+ /*
+ * Don't bother to queue an event if the mask was previously
+ * non-zero since an event must still be on the queue.
+ */
+
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr =
+ ckalloc(sizeof(FileHandlerEvent));
+
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
+ numQueued++;
+ }
+ filePtr->readyMask = mask;
+ }
+
+ /*
+ * If any events were queued in the above loop, force PlatformEvents-
+ * Wait() to poll as there already are events that need to be processed
+ * at this point.
+ */
+
+ if (numQueued) {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ timeoutPtr = &timeout;
+ }
+
+ /*
+ * Wait or poll for new events, queue Tcl events for the FileHandlers
+ * corresponding to them, and update the FileHandlers' mask of events
+ * of interest registered by the last call to Tcl_CreateFileHandler().
+ *
+ * Events for the trigger pipe are processed here in order to facilitate
+ * inter-thread IPC. If another thread intends to wake up this thread
+ * whilst it's blocking on PlatformEventsWait(), it write(2)s to the
+ * other end of the pipe (see Tcl_AlertNotifier(),) which in turn will
+ * cause PlatformEventsWait() to return immediately.
+ */
+
+ numFound = PlatformEventsWait(tsdPtr->readyEvents, tsdPtr->maxReadyEvents, timeoutPtr);
+ for (numEvent = 0; numEvent < numFound; numEvent++) {
+ pedPtr = (struct PlatformEventData *)tsdPtr->readyEvents[numEvent].udata;
+ filePtr = pedPtr->filePtr;
+ mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
+ if (filePtr->fd == tsdPtr->triggerPipe[0]) {
+ do {
+ i = read(tsdPtr->triggerPipe[0], buf, 1);
+ if ((i == -1) && (errno != EAGAIN)) {
+ Tcl_Panic("Tcl_WaitForEvent: "
+ "read from %p->triggerPipe: %s",
+ (void *)tsdPtr, strerror(errno));
+ } else {
+ break;
+ }
+ } while (1);
+ continue;
+ }
+ if (!mask) {
+ continue;
+ }
+
+ /*
+ * Don't bother to queue an event if the mask was previously
+ * non-zero since an event must still be on the queue.
+ */
+
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr =
+ ckalloc(sizeof(FileHandlerEvent));
+
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
+ }
+ filePtr->readyMask |= mask;
+ }
+ return 0;
+ }
+}
+
+#endif /* !HAVE_COREFOUNDATION */
+
+#endif /* NOTIFIER_KQUEUE */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclLoadAix.c b/unix/tclLoadAix.c
new file mode 100644
index 0000000..88e6b50
--- /dev/null
+++ b/unix/tclLoadAix.c
@@ -0,0 +1,630 @@
+/*
+ * tclLoadAix.c --
+ *
+ * This file implements the dlopen and dlsym APIs under the AIX operating
+ * system, to enable the Tcl "load" command to work. This code was
+ * provided by Jens-Uwe Mager.
+ *
+ * This file is subject to the following copyright notice, which is
+ * different from the notice used elsewhere in Tcl. The file has been
+ * modified to incorporate the file dlfcn.h in-line.
+ *
+ * Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH
+ * Not derived from licensed software.
+ *
+ * Permission is granted to freely use, copy, modify, and redistribute
+ * this software, provided that the author is not construed to be liable
+ * for any results of using the software, alterations are clearly marked
+ * as such, and this notice is not modified.
+ *
+ * Note: this file has been altered from the original in a few ways in order
+ * to work properly with Tcl.
+ */
+
+/*
+ * @(#)dlfcn.c 1.7 revision of 95/08/14 19:08:38
+ * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH
+ * 30159 Hannover, Germany
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ldr.h>
+#include <a.out.h>
+#include <ldfcn.h>
+#include "../compat/dlfcn.h"
+
+/*
+ * We simulate dlopen() et al. through a call to load. Because AIX has no call
+ * to find an exported symbol we read the loader section of the loaded module
+ * and build a list of exported symbols and their virtual address.
+ */
+
+typedef struct {
+ char *name; /* The symbols's name. */
+ void *addr; /* Its relocated virtual address. */
+} Export, *ExportPtr;
+
+/*
+ * xlC uses the following structure to list its constructors and destructors.
+ * This is gleaned from the output of munch.
+ */
+
+typedef struct {
+ void (*init)(void); /* call static constructors */
+ void (*term)(void); /* call static destructors */
+} Cdtor, *CdtorPtr;
+
+/*
+ * The void * handle returned from dlopen is actually a ModulePtr.
+ */
+
+typedef struct Module {
+ struct Module *next;
+ char *name; /* module name for refcounting */
+ int refCnt; /* the number of references */
+ void *entry; /* entry point from load */
+ struct dl_info *info; /* optional init/terminate functions */
+ CdtorPtr cdtors; /* optional C++ constructors */
+ int nExports; /* the number of exports found */
+ ExportPtr exports; /* the array of exports */
+} Module, *ModulePtr;
+
+/*
+ * We keep a list of all loaded modules to be able to call the fini handlers
+ * and destructors at atexit() time.
+ */
+
+static ModulePtr modList;
+
+/*
+ * The last error from one of the dl* routines is kept in static variables
+ * here. Each error is returned only once to the caller.
+ */
+
+static char errbuf[BUFSIZ];
+static int errvalid;
+
+static void caterr(char *);
+static int readExports(ModulePtr);
+static void terminate(void);
+static void *findMain(void);
+
+void *
+dlopen(
+ const char *path,
+ int mode)
+{
+ register ModulePtr mp;
+ static void *mainModule;
+
+ /*
+ * Upon the first call register a terminate handler that will close all
+ * libraries. Also get a reference to the main module for use with
+ * loadbind.
+ */
+
+ if (!mainModule) {
+ mainModule = findMain();
+ if (mainModule == NULL) {
+ return NULL;
+ }
+ atexit(terminate);
+ }
+
+ /*
+ * Scan the list of modules if we have the module already loaded.
+ */
+
+ for (mp = modList; mp; mp = mp->next) {
+ if (strcmp(mp->name, path) == 0) {
+ mp->refCnt++;
+ return (void *) mp;
+ }
+ }
+
+ mp = (ModulePtr) calloc(1, sizeof(*mp));
+ if (mp == NULL) {
+ errvalid++;
+ strcpy(errbuf, "calloc: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+ }
+
+ mp->name = malloc((unsigned) (strlen(path) + 1));
+ strcpy(mp->name, path);
+
+ /*
+ * load should be declared load(const char *...). Thus we cast the path to
+ * a normal char *. Ugly.
+ */
+
+ mp->entry = (void *) load((char *)path, L_NOAUTODEFER, NULL);
+ if (mp->entry == NULL) {
+ free(mp->name);
+ free(mp);
+ errvalid++;
+ strcpy(errbuf, "dlopen: ");
+ strcat(errbuf, path);
+ strcat(errbuf, ": ");
+
+ /*
+ * If AIX says the file is not executable, the error can be further
+ * described by querying the loader about the last error.
+ */
+
+ if (errno == ENOEXEC) {
+ char *tmp[BUFSIZ/sizeof(char *)], **p;
+
+ if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1) {
+ strcpy(errbuf, strerror(errno));
+ } else {
+ for (p=tmp ; *p ; p++) {
+ caterr(*p);
+ }
+ }
+ } else {
+ strcat(errbuf, strerror(errno));
+ }
+ return NULL;
+ }
+
+ mp->refCnt = 1;
+ mp->next = modList;
+ modList = mp;
+
+ if (loadbind(0, mainModule, mp->entry) == -1) {
+ loadbindFailure:
+ dlclose(mp);
+ errvalid++;
+ strcpy(errbuf, "loadbind: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+ }
+
+ /*
+ * If the user wants global binding, loadbind against all other loaded
+ * modules.
+ */
+
+ if (mode & RTLD_GLOBAL) {
+ register ModulePtr mp1;
+
+ for (mp1 = mp->next; mp1; mp1 = mp1->next) {
+ if (loadbind(0, mp1->entry, mp->entry) == -1) {
+ goto loadbindFailure;
+ }
+ }
+ }
+
+ if (readExports(mp) == -1) {
+ dlclose(mp);
+ return NULL;
+ }
+
+ /*
+ * If there is a dl_info structure, call the init function.
+ */
+
+ if (mp->info = (struct dl_info *)dlsym(mp, "dl_info")) {
+ if (mp->info->init) {
+ mp->info->init();
+ }
+ } else {
+ errvalid = 0;
+ }
+
+ /*
+ * If the shared object was compiled using xlC we will need to call static
+ * constructors (and later on dlclose destructors).
+ */
+
+ if (mp->cdtors = (CdtorPtr) dlsym(mp, "__cdtors")) {
+ while (mp->cdtors->init) {
+ mp->cdtors->init();
+ mp->cdtors++;
+ }
+ } else {
+ errvalid = 0;
+ }
+
+ return (void *) mp;
+}
+
+/*
+ * Attempt to decipher an AIX loader error message and append it to our static
+ * error message buffer.
+ */
+
+static void
+caterr(
+ char *s)
+{
+ register char *p = s;
+
+ while (*p >= '0' && *p <= '9') {
+ p++;
+ }
+ switch (atoi(s)) { /* INTL: "C", UTF safe. */
+ case L_ERROR_TOOMANY:
+ strcat(errbuf, "to many errors");
+ break;
+ case L_ERROR_NOLIB:
+ strcat(errbuf, "can't load library");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_UNDEF:
+ strcat(errbuf, "can't find symbol");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_RLDBAD:
+ strcat(errbuf, "bad RLD");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_FORMAT:
+ strcat(errbuf, "bad exec format in");
+ strcat(errbuf, p);
+ break;
+ case L_ERROR_ERRNO:
+ strcat(errbuf, strerror(atoi(++p))); /* INTL: "C", UTF safe. */
+ break;
+ default:
+ strcat(errbuf, s);
+ break;
+ }
+}
+
+void *
+dlsym(
+ void *handle,
+ const char *symbol)
+{
+ register ModulePtr mp = (ModulePtr)handle;
+ register ExportPtr ep;
+ register int i;
+
+ /*
+ * Could speed up the search, but I assume that one assigns the result to
+ * function pointers anyways.
+ */
+
+ for (ep = mp->exports, i = mp->nExports; i; i--, ep++) {
+ if (strcmp(ep->name, symbol) == 0) {
+ return ep->addr;
+ }
+ }
+
+ errvalid++;
+ strcpy(errbuf, "dlsym: undefined symbol ");
+ strcat(errbuf, symbol);
+ return NULL;
+}
+
+char *
+dlerror(void)
+{
+ if (errvalid) {
+ errvalid = 0;
+ return errbuf;
+ }
+ return NULL;
+}
+
+int
+dlclose(
+ void *handle)
+{
+ register ModulePtr mp = (ModulePtr)handle;
+ int result;
+ register ModulePtr mp1;
+
+ if (--mp->refCnt > 0) {
+ return 0;
+ }
+
+ if (mp->info && mp->info->fini) {
+ mp->info->fini();
+ }
+
+ if (mp->cdtors) {
+ while (mp->cdtors->term) {
+ mp->cdtors->term();
+ mp->cdtors++;
+ }
+ }
+
+ result = unload(mp->entry);
+ if (result == -1) {
+ errvalid++;
+ strcpy(errbuf, strerror(errno));
+ }
+
+ if (mp->exports) {
+ register ExportPtr ep;
+ register int i;
+ for (ep = mp->exports, i = mp->nExports; i; i--, ep++) {
+ if (ep->name) {
+ free(ep->name);
+ }
+ }
+ free(mp->exports);
+ }
+
+ if (mp == modList) {
+ modList = mp->next;
+ } else {
+ for (mp1 = modList; mp1; mp1 = mp1->next) {
+ if (mp1->next == mp) {
+ mp1->next = mp->next;
+ break;
+ }
+ }
+ }
+
+ free(mp->name);
+ free(mp);
+ return result;
+}
+
+static void
+terminate(void)
+{
+ while (modList) {
+ dlclose(modList);
+ }
+}
+
+/*
+ * Build the export table from the XCOFF .loader section.
+ */
+
+static int
+readExports(
+ ModulePtr mp)
+{
+ LDFILE *ldp = NULL;
+ SCNHDR sh, shdata;
+ LDHDR *lhp;
+ char *ldbuf;
+ LDSYM *ls;
+ int i;
+ ExportPtr ep;
+ const char *errMsg;
+
+#define Error(msg) do{errMsg=(msg);goto error;}while(0)
+#define SysErr() Error(strerror(errno))
+
+ ldp = ldopen(mp->name, ldp);
+ if (ldp == NULL) {
+ struct ld_info *lp;
+ char *buf;
+ int size = 0;
+
+ if (errno != ENOENT) {
+ SysErr();
+ }
+
+ /*
+ * The module might be loaded due to the LIBPATH environment variable.
+ * Search for the loaded module using L_GETINFO.
+ */
+
+ while (1) {
+ size += 4 * 1024;
+ buf = malloc(size);
+ if (buf == NULL) {
+ SysErr();
+ }
+
+ i = loadquery(L_GETINFO, buf, size);
+
+ if (i != -1) {
+ break;
+ }
+ free(buf);
+ if (errno != ENOMEM) {
+ SysErr();
+ }
+ }
+
+ /*
+ * Traverse the list of loaded modules. The entry point returned by
+ * load() does actually point to the data segment origin.
+ */
+
+ lp = (struct ld_info *) buf;
+ while (lp) {
+ if (lp->ldinfo_dataorg == mp->entry) {
+ ldp = ldopen(lp->ldinfo_filename, ldp);
+ break;
+ }
+ if (lp->ldinfo_next == 0) {
+ lp = NULL;
+ } else {
+ lp = (struct ld_info *)((char *)lp + lp->ldinfo_next);
+ }
+ }
+
+ free(buf);
+
+ if (!ldp) {
+ SysErr();
+ }
+ }
+
+ if (TYPE(ldp) != U802TOCMAGIC) {
+ Error("bad magic");
+ }
+
+ /*
+ * Get the padding for the data section. This is needed for AIX 4.1
+ * compilers. This is used when building the final function pointer to the
+ * exported symbol.
+ */
+
+ if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) {
+ Error("cannot read data section header");
+ }
+
+ if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) {
+ Error("cannot read loader section header");
+ }
+
+ /*
+ * We read the complete loader section in one chunk, this makes finding
+ * long symbol names residing in the string table easier.
+ */
+
+ ldbuf = (char *) malloc(sh.s_size);
+ if (ldbuf == NULL) {
+ SysErr();
+ }
+
+ if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) {
+ free(ldbuf);
+ Error("cannot seek to loader section");
+ }
+
+ if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) {
+ free(ldbuf);
+ Error("cannot read loader section");
+ }
+
+ lhp = (LDHDR *) ldbuf;
+ ls = (LDSYM *)(ldbuf + LDHDRSZ);
+
+ /*
+ * Count the number of exports to include in our export table.
+ */
+
+ for (i = lhp->l_nsyms; i; i--, ls++) {
+ if (!LDR_EXPORT(*ls)) {
+ continue;
+ }
+ mp->nExports++;
+ }
+
+ mp->exports = (ExportPtr) calloc(mp->nExports, sizeof(*mp->exports));
+ if (mp->exports == NULL) {
+ free(ldbuf);
+ SysErr();
+ }
+
+ /*
+ * Fill in the export table. All entries are relative to the entry point
+ * we got from load.
+ */
+
+ ep = mp->exports;
+ ls = (LDSYM *)(ldbuf + LDHDRSZ);
+ for (i=lhp->l_nsyms ; i!=0 ; i--,ls++) {
+ char *symname;
+ char tmpsym[SYMNMLEN+1];
+
+ if (!LDR_EXPORT(*ls)) {
+ continue;
+ }
+
+ if (ls->l_zeroes == 0) {
+ symname = ls->l_offset + lhp->l_stoff + ldbuf;
+ } else {
+ /*
+ * The l_name member is not zero terminated, we must copy the
+ * first SYMNMLEN chars and make sure we have a zero byte at the
+ * end.
+ */
+
+ strncpy(tmpsym, ls->l_name, SYMNMLEN);
+ tmpsym[SYMNMLEN] = '\0';
+ symname = tmpsym;
+ }
+ ep->name = malloc((unsigned) (strlen(symname) + 1));
+ strcpy(ep->name, symname);
+ ep->addr = (void *)((unsigned long)
+ mp->entry + ls->l_value - shdata.s_vaddr);
+ ep++;
+ }
+ free(ldbuf);
+ while (ldclose(ldp) == FAILURE) {
+ /* Empty body */
+ }
+ return 0;
+
+ /*
+ * This is a factoring out of the error-handling code to make the rest of
+ * the function much simpler to read.
+ */
+
+ error:
+ errvalid++;
+ strcpy(errbuf, "readExports: ");
+ strcat(errbuf, errMsg);
+
+ if (ldp != NULL) {
+ while (ldclose(ldp) == FAILURE) {
+ /* Empty body */
+ }
+ }
+ return -1;
+}
+
+/*
+ * Find the main modules entry point. This is used as export pointer for
+ * loadbind() to be able to resolve references to the main part.
+ */
+
+static void *
+findMain(void)
+{
+ struct ld_info *lp;
+ char *buf;
+ int size = 4*1024;
+ int i;
+ void *ret;
+
+ buf = malloc(size);
+ if (buf == NULL) {
+ goto error;
+ }
+
+ while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
+ free(buf);
+ size += 4*1024;
+ buf = malloc(size);
+ if (buf == NULL) {
+ goto error;
+ }
+ }
+
+ if (i == -1) {
+ free(buf);
+ goto error;
+ }
+
+ /*
+ * The first entry is the main module. The entry point returned by load()
+ * does actually point to the data segment origin.
+ */
+
+ lp = (struct ld_info *) buf;
+ ret = lp->ldinfo_dataorg;
+ free(buf);
+ return ret;
+
+ error:
+ errvalid++;
+ strcpy(errbuf, "findMain: ");
+ strcat(errbuf, strerror(errno));
+ return NULL;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclLoadDl.c b/unix/tclLoadDl.c
new file mode 100644
index 0000000..aec071c
--- /dev/null
+++ b/unix/tclLoadDl.c
@@ -0,0 +1,274 @@
+/*
+ * tclLoadDl.c --
+ *
+ * This procedure provides a version of the TclLoadFile that works with
+ * the "dlopen" and "dlsym" library procedures for dynamic loading.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+#ifdef NO_DLFCN_H
+# include "../compat/dlfcn.h"
+#else
+# include <dlfcn.h>
+#endif
+
+/*
+ * In some systems, like SunOS 4.1.3, the RTLD_NOW flag isn't defined and this
+ * argument to dlopen must always be 1. The RTLD_LOCAL flag doesn't exist on
+ * some platforms; if it doesn't exist, set it to 0 so it has no effect.
+ * See [Bug #3216070]
+ */
+
+#ifndef RTLD_NOW
+# define RTLD_NOW 1
+#endif
+
+#ifndef RTLD_LOCAL
+# define RTLD_LOCAL 0
+#endif
+
+/*
+ * Static procedures defined within this file.
+ */
+
+static void * FindSymbol(Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle, const char *symbol);
+static void UnloadFile(Tcl_LoadHandle loadHandle);
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpDlopen --
+ *
+ * Dynamically loads a binary code file into memory and returns a handle
+ * to the new code.
+ *
+ * Results:
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * New code suddenly appears in memory.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpDlopen(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
+ * code (UTF-8). */
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
+ * (*unloadProcPtr)() to unload the file. */
+ Tcl_FSUnloadFileProc **unloadProcPtr,
+ /* Filled with address of Tcl_FSUnloadFileProc
+ * function which should be used for this
+ * file. */
+ int flags)
+{
+ void *handle;
+ Tcl_LoadHandle newHandle;
+ const char *native;
+ int dlopenflags = 0;
+
+ /*
+ * First try the full path the user gave us. This is particularly
+ * important if the cwd is inside a vfs, and we are trying to load using a
+ * relative path.
+ */
+
+ native = Tcl_FSGetNativePath(pathPtr);
+ /*
+ * Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
+ */
+ if (flags & TCL_LOAD_GLOBAL) {
+ dlopenflags |= RTLD_GLOBAL;
+ } else {
+ dlopenflags |= RTLD_LOCAL;
+ }
+ if (flags & TCL_LOAD_LAZY) {
+ dlopenflags |= RTLD_LAZY;
+ } else {
+ dlopenflags |= RTLD_NOW;
+ }
+ handle = dlopen(native, dlopenflags);
+ if (handle == NULL) {
+ /*
+ * Let the OS loader examine the binary search path for whatever
+ * string the user gave us which hopefully refers to a file on the
+ * binary path.
+ */
+
+ Tcl_DString ds;
+ const char *fileName = Tcl_GetString(pathPtr);
+
+ native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
+ /*
+ * Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
+ */
+ handle = dlopen(native, dlopenflags);
+ Tcl_DStringFree(&ds);
+ }
+
+ if (handle == NULL) {
+ /*
+ * Write the string to a variable first to work around a compiler bug
+ * in the Sun Forte 6 compiler. [Bug 1503729]
+ */
+
+ const char *errorStr = dlerror();
+
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't load file \"%s\": %s",
+ Tcl_GetString(pathPtr), errorStr));
+ }
+ return TCL_ERROR;
+ }
+ newHandle = ckalloc(sizeof(*newHandle));
+ newHandle->clientData = handle;
+ newHandle->findSymbolProcPtr = &FindSymbol;
+ newHandle->unloadFileProcPtr = &UnloadFile;
+ *unloadProcPtr = &UnloadFile;
+ *loadHandle = newHandle;
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindSymbol --
+ *
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library).
+ *
+ * Results:
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void *
+FindSymbol(
+ Tcl_Interp *interp, /* Place to put error messages. */
+ Tcl_LoadHandle loadHandle, /* Value from TcpDlopen(). */
+ const char *symbol) /* Symbol to look up. */
+{
+ const char *native; /* Name of the library to be loaded, in
+ * system encoding */
+ Tcl_DString newName, ds; /* Buffers for converting the name to
+ * system encoding and prepending an
+ * underscore*/
+ void *handle = (void *) loadHandle->clientData;
+ /* Native handle to the loaded library */
+ void *proc; /* Address corresponding to the resolved
+ * symbol */
+
+ /*
+ * Some platforms still add an underscore to the beginning of symbol
+ * names. If we can't find a name without an underscore, try again with
+ * the underscore.
+ */
+
+ native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
+ proc = dlsym(handle, native); /* INTL: Native. */
+ if (proc == NULL) {
+ Tcl_DStringInit(&newName);
+ TclDStringAppendLiteral(&newName, "_");
+ native = Tcl_DStringAppend(&newName, native, -1);
+ proc = dlsym(handle, native); /* INTL: Native. */
+ Tcl_DStringFree(&newName);
+ }
+ Tcl_DStringFree(&ds);
+ if (proc == NULL) {
+ const char *errorStr = dlerror();
+
+ if (interp) {
+ if (!errorStr) {
+ errorStr = "unknown";
+ }
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "cannot find symbol \"%s\": %s", symbol, errorStr));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol,
+ NULL);
+ }
+ }
+ return proc;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UnloadFile --
+ *
+ * Unloads a dynamically loaded binary code file from memory. Code
+ * pointers in the formerly loaded file are no longer valid after calling
+ * this function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Code removed from memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UnloadFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
+{
+ void *handle = loadHandle->clientData;
+
+ dlclose(handle);
+ ckfree(loadHandle);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGuessPackageName --
+ *
+ * If the "load" command is invoked without providing a package name,
+ * this procedure is invoked to try to figure it out.
+ *
+ * Results:
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGuessPackageName(
+ const char *fileName, /* Name of file containing package (already
+ * translated to local form if needed). */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
+ * name to this if possible. */
+{
+ return 0;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclLoadDyld.c b/unix/tclLoadDyld.c
new file mode 100644
index 0000000..e998bf9
--- /dev/null
+++ b/unix/tclLoadDyld.c
@@ -0,0 +1,719 @@
+/*
+ * tclLoadDyld.c --
+ *
+ * This procedure provides a version of the TclLoadFile that works with
+ * Apple's dyld dynamic loading.
+ * Original version of his file (superseded long ago) provided by
+ * Wilfredo Sanchez (wsanchez@apple.com).
+ *
+ * Copyright (c) 1995 Apple Computer, Inc.
+ * Copyright (c) 2001-2007 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+
+#ifndef MODULE_SCOPE
+# define MODULE_SCOPE extern
+#endif
+
+/*
+ * Use preferred dlfcn API on 10.4 and later
+ */
+
+#ifndef TCL_DYLD_USE_DLFCN
+# ifdef NO_DLFCN_H
+# define TCL_DYLD_USE_DLFCN 0
+# else
+# define TCL_DYLD_USE_DLFCN 1
+# endif
+#endif
+
+/*
+ * Use deprecated NSModule API only to support 10.3 and earlier:
+ */
+
+#ifndef TCL_DYLD_USE_NSMODULE
+# define TCL_DYLD_USE_NSMODULE 0
+#endif
+
+/*
+ * Use includes for the API we're using.
+ */
+
+#if TCL_DYLD_USE_DLFCN
+# include <dlfcn.h>
+#endif /* TCL_DYLD_USE_DLFCN */
+
+#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
+#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+#include <mach-o/dyld.h>
+#include <mach-o/fat.h>
+#include <mach-o/swap.h>
+#include <mach-o/arch.h>
+#include <libkern/OSByteOrder.h>
+#include <mach/mach.h>
+
+typedef struct Tcl_DyldModuleHandle {
+ struct Tcl_DyldModuleHandle *nextPtr;
+ NSModule module;
+} Tcl_DyldModuleHandle;
+#endif /* TCL_DYLD_USE_NSMODULE || TCL_LOAD_FROM_MEMORY */
+
+typedef struct {
+ void *dlHandle;
+#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
+ const struct mach_header *dyldLibHeader;
+ Tcl_DyldModuleHandle *modulePtr;
+#endif
+} Tcl_DyldLoadHandle;
+
+#if TCL_DYLD_USE_DLFCN || defined(TCL_LOAD_FROM_MEMORY)
+MODULE_SCOPE long tclMacOSXDarwinRelease;
+#endif
+
+/*
+ * Static functions defined in this file.
+ */
+
+static void * FindSymbol(Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle, const char *symbol);
+static void UnloadFile(Tcl_LoadHandle handle);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DyldOFIErrorMsg --
+ *
+ * Converts a numerical NSObjectFileImage error into an error message
+ * string.
+ *
+ * Results:
+ * Error message string.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
+static const char *
+DyldOFIErrorMsg(
+ int err)
+{
+ switch(err) {
+ case NSObjectFileImageSuccess:
+ return NULL;
+ case NSObjectFileImageFailure:
+ return "object file setup failure";
+ case NSObjectFileImageInappropriateFile:
+ return "not a Mach-O MH_BUNDLE file";
+ case NSObjectFileImageArch:
+ return "no object for this architecture";
+ case NSObjectFileImageFormat:
+ return "bad object file format";
+ case NSObjectFileImageAccess:
+ return "can't read object file";
+ default:
+ return "unknown error";
+ }
+}
+#endif /* TCL_DYLD_USE_NSMODULE || TCL_LOAD_FROM_MEMORY */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpDlopen --
+ *
+ * Dynamically loads a binary code file into memory and returns a handle
+ * to the new code.
+ *
+ * Results:
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interpreter's result.
+ *
+ * Side effects:
+ * New code suddenly appears in memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE int
+TclpDlopen(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
+ * code (UTF-8). */
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
+ * (*unloadProcPtr)() to unload the file. */
+ Tcl_FSUnloadFileProc **unloadProcPtr,
+ /* Filled with address of Tcl_FSUnloadFileProc
+ * function which should be used for this
+ * file. */
+ int flags)
+{
+ Tcl_DyldLoadHandle *dyldLoadHandle;
+ Tcl_LoadHandle newHandle;
+ void *dlHandle = NULL;
+#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
+ const struct mach_header *dyldLibHeader = NULL;
+ Tcl_DyldModuleHandle *modulePtr = NULL;
+#endif
+#if TCL_DYLD_USE_NSMODULE
+ NSLinkEditErrors editError;
+ int errorNumber;
+ const char *errorName, *objFileImageErrMsg = NULL;
+#endif /* TCL_DYLD_USE_NSMODULE */
+ const char *errMsg = NULL;
+ int result;
+ Tcl_DString ds;
+ const char *nativePath, *nativeFileName = NULL;
+#if TCL_DYLD_USE_DLFCN
+ int dlopenflags = 0;
+#endif /* TCL_DYLD_USE_DLFCN */
+
+ /*
+ * First try the full path the user gave us. This is particularly
+ * important if the cwd is inside a vfs, and we are trying to load using a
+ * relative path.
+ */
+
+ nativePath = Tcl_FSGetNativePath(pathPtr);
+ nativeFileName = Tcl_UtfToExternalDString(NULL, Tcl_GetString(pathPtr),
+ -1, &ds);
+
+#if TCL_DYLD_USE_DLFCN
+ /*
+ * Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
+ */
+
+ if (flags & TCL_LOAD_GLOBAL) {
+ dlopenflags |= RTLD_GLOBAL;
+ } else {
+ dlopenflags |= RTLD_LOCAL;
+ }
+ if (flags & TCL_LOAD_LAZY) {
+ dlopenflags |= RTLD_LAZY;
+ } else {
+ dlopenflags |= RTLD_NOW;
+ }
+ dlHandle = dlopen(nativePath, dlopenflags);
+ if (!dlHandle) {
+ /*
+ * Let the OS loader examine the binary search path for whatever string
+ * the user gave us which hopefully refers to a file on the binary
+ * path.
+ */
+
+ dlHandle = dlopen(nativeFileName, dlopenflags);
+ if (!dlHandle) {
+ errMsg = dlerror();
+ }
+ }
+#endif /* TCL_DYLD_USE_DLFCN */
+
+ if (!dlHandle) {
+#if TCL_DYLD_USE_NSMODULE
+ dyldLibHeader = NSAddImage(nativePath,
+ NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+ if (!dyldLibHeader) {
+ NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
+ if (editError == NSLinkEditFileAccessError) {
+ /*
+ * The requested file was not found. Let the OS loader examine
+ * the binary search path for whatever string the user gave us
+ * which hopefully refers to a file on the binary path.
+ */
+
+ dyldLibHeader = NSAddImage(nativeFileName,
+ NSADDIMAGE_OPTION_WITH_SEARCHING |
+ NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+ if (!dyldLibHeader) {
+ NSLinkEditError(&editError, &errorNumber, &errorName,
+ &errMsg);
+ }
+ } else if ((editError == NSLinkEditFileFormatError
+ && errorNumber == EBADMACHO)
+ || editError == NSLinkEditOtherError){
+ NSObjectFileImageReturnCode err;
+ NSObjectFileImage dyldObjFileImage;
+ NSModule module;
+
+ /*
+ * The requested file was found but was not of type MH_DYLIB,
+ * attempt to load it as a MH_BUNDLE.
+ */
+
+ err = NSCreateObjectFileImageFromFile(nativePath,
+ &dyldObjFileImage);
+ if (err == NSObjectFileImageSuccess && dyldObjFileImage) {
+ int nsflags = NSLINKMODULE_OPTION_RETURN_ON_ERROR;
+ if (!(flags & 1)) nsflags |= NSLINKMODULE_OPTION_PRIVATE;
+ if (!(flags & 2)) nsflags |= NSLINKMODULE_OPTION_BINDNOW;
+ module = NSLinkModule(dyldObjFileImage, nativePath, nsflags);
+ NSDestroyObjectFileImage(dyldObjFileImage);
+ if (module) {
+ modulePtr = ckalloc(sizeof(Tcl_DyldModuleHandle));
+ modulePtr->module = module;
+ modulePtr->nextPtr = NULL;
+ } else {
+ NSLinkEditError(&editError, &errorNumber, &errorName,
+ &errMsg);
+ }
+ } else {
+ objFileImageErrMsg = DyldOFIErrorMsg(err);
+ }
+ }
+ }
+#endif /* TCL_DYLD_USE_NSMODULE */
+ }
+
+ if (dlHandle
+#if TCL_DYLD_USE_NSMODULE
+ || dyldLibHeader || modulePtr
+#endif /* TCL_DYLD_USE_NSMODULE */
+ ) {
+ dyldLoadHandle = ckalloc(sizeof(Tcl_DyldLoadHandle));
+ dyldLoadHandle->dlHandle = dlHandle;
+#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
+ dyldLoadHandle->dyldLibHeader = dyldLibHeader;
+ dyldLoadHandle->modulePtr = modulePtr;
+#endif /* TCL_DYLD_USE_NSMODULE || TCL_LOAD_FROM_MEMORY */
+ newHandle = ckalloc(sizeof(*newHandle));
+ newHandle->clientData = dyldLoadHandle;
+ newHandle->findSymbolProcPtr = &FindSymbol;
+ newHandle->unloadFileProcPtr = &UnloadFile;
+ *unloadProcPtr = &UnloadFile;
+ *loadHandle = newHandle;
+ result = TCL_OK;
+ } else {
+ Tcl_Obj *errObj = Tcl_NewObj();
+
+ if (errMsg != NULL) {
+ Tcl_AppendToObj(errObj, errMsg, -1);
+ }
+#if TCL_DYLD_USE_NSMODULE
+ if (objFileImageErrMsg) {
+ Tcl_AppendPrintfToObj(errObj,
+ "\nNSCreateObjectFileImageFromFile() error: %s",
+ objFileImageErrMsg);
+ }
+#endif /* TCL_DYLD_USE_NSMODULE */
+ Tcl_SetObjResult(interp, errObj);
+ result = TCL_ERROR;
+ }
+
+ Tcl_DStringFree(&ds);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindSymbol --
+ *
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library).
+ *
+ * Results:
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void *
+FindSymbol(
+ Tcl_Interp *interp, /* For error reporting. */
+ Tcl_LoadHandle loadHandle, /* Handle from TclpDlopen. */
+ const char *symbol) /* Symbol name to look up. */
+{
+ Tcl_DyldLoadHandle *dyldLoadHandle = loadHandle->clientData;
+ Tcl_PackageInitProc *proc = NULL;
+ const char *errMsg = NULL;
+ Tcl_DString ds;
+ const char *native;
+
+ native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
+ if (dyldLoadHandle->dlHandle) {
+#if TCL_DYLD_USE_DLFCN
+ proc = dlsym(dyldLoadHandle->dlHandle, native);
+ if (!proc) {
+ errMsg = dlerror();
+ }
+#endif /* TCL_DYLD_USE_DLFCN */
+ } else {
+#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
+ NSSymbol nsSymbol = NULL;
+ Tcl_DString newName;
+
+ /*
+ * dyld adds an underscore to the beginning of symbol names.
+ */
+
+ Tcl_DStringInit(&newName);
+ TclDStringAppendLiteral(&newName, "_");
+ native = Tcl_DStringAppend(&newName, native, -1);
+ if (dyldLoadHandle->dyldLibHeader) {
+ nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyldLibHeader,
+ native, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW |
+ NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
+ if (nsSymbol) {
+ /*
+ * Until dyld supports unloading of MY_DYLIB binaries, the
+ * following is not needed.
+ */
+
+#ifdef DYLD_SUPPORTS_DYLIB_UNLOADING
+ NSModule module = NSModuleForSymbol(nsSymbol);
+ Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr;
+
+ while (modulePtr != NULL) {
+ if (module == modulePtr->module) {
+ break;
+ }
+ modulePtr = modulePtr->nextPtr;
+ }
+ if (modulePtr == NULL) {
+ modulePtr = ckalloc(sizeof(Tcl_DyldModuleHandle));
+ modulePtr->module = module;
+ modulePtr->nextPtr = dyldLoadHandle->modulePtr;
+ dyldLoadHandle->modulePtr = modulePtr;
+ }
+#endif /* DYLD_SUPPORTS_DYLIB_UNLOADING */
+ } else {
+ NSLinkEditErrors editError;
+ int errorNumber;
+ const char *errorName;
+
+ NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
+ }
+ } else if (dyldLoadHandle->modulePtr) {
+ nsSymbol = NSLookupSymbolInModule(
+ dyldLoadHandle->modulePtr->module, native);
+ }
+ if (nsSymbol) {
+ proc = NSAddressOfSymbol(nsSymbol);
+ }
+ Tcl_DStringFree(&newName);
+#endif /* TCL_DYLD_USE_NSMODULE */
+ }
+ Tcl_DStringFree(&ds);
+ if (errMsg && (interp != NULL)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "cannot find symbol \"%s\": %s", symbol, errMsg));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol,
+ NULL);
+ }
+ return proc;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UnloadFile --
+ *
+ * Unloads a dynamically loaded binary code file from memory. Code
+ * pointers in the formerly loaded file are no longer valid after calling
+ * this function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Code dissapears from memory. Note that dyld currently only supports
+ * unloading of binaries of type MH_BUNDLE loaded with NSLinkModule() in
+ * TclpDlopen() above.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UnloadFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
+{
+ Tcl_DyldLoadHandle *dyldLoadHandle = loadHandle->clientData;
+
+ if (dyldLoadHandle->dlHandle) {
+#if TCL_DYLD_USE_DLFCN
+ (void) dlclose(dyldLoadHandle->dlHandle);
+#endif /* TCL_DYLD_USE_DLFCN */
+ } else {
+#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
+ Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr;
+
+ while (modulePtr != NULL) {
+ void *ptr = modulePtr;
+
+ (void) NSUnLinkModule(modulePtr->module,
+ NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
+ modulePtr = modulePtr->nextPtr;
+ ckfree(ptr);
+ }
+#endif /* TCL_DYLD_USE_NSMODULE */
+ }
+ ckfree(dyldLoadHandle);
+ ckfree(loadHandle);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGuessPackageName --
+ *
+ * If the "load" command is invoked without providing a package name,
+ * this procedure is invoked to try to figure it out.
+ *
+ * Results:
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGuessPackageName(
+ const char *fileName, /* Name of file containing package (already
+ * translated to local form if needed). */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
+ * name to this if possible. */
+{
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpLoadMemoryGetBuffer --
+ *
+ * Allocate a buffer that can be used with TclpLoadMemory() below.
+ *
+ * Results:
+ * Pointer to allocated buffer or NULL if an error occurs.
+ *
+ * Side effects:
+ * Buffer is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_LOAD_FROM_MEMORY
+MODULE_SCOPE void *
+TclpLoadMemoryGetBuffer(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ int size) /* Size of desired buffer. */
+{
+ void *buffer = NULL;
+
+ /*
+ * NSCreateObjectFileImageFromMemory is available but always fails
+ * prior to Darwin 7.
+ */
+ if (tclMacOSXDarwinRelease >= 7) {
+ /*
+ * We must allocate the buffer using vm_allocate, because
+ * NSCreateObjectFileImageFromMemory will dispose of it using
+ * vm_deallocate.
+ */
+
+ if (vm_allocate(mach_task_self(), (vm_address_t *) &buffer, size, 1)) {
+ buffer = NULL;
+ }
+ }
+ return buffer;
+}
+#endif /* TCL_LOAD_FROM_MEMORY */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpLoadMemory --
+ *
+ * Dynamically loads binary code file from memory and returns a handle to
+ * the new code.
+ *
+ * Results:
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interpreter's result.
+ *
+ * Side effects:
+ * New code is loaded from memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef TCL_LOAD_FROM_MEMORY
+MODULE_SCOPE int
+TclpLoadMemory(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ void *buffer, /* Buffer containing the desired code
+ * (allocated with TclpLoadMemoryGetBuffer). */
+ int size, /* Allocation size of buffer. */
+ int codeSize, /* Size of code data read into buffer or -1 if
+ * an error occurred and the buffer should
+ * just be freed. */
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
+ * (*unloadProcPtr)() to unload the file. */
+ Tcl_FSUnloadFileProc **unloadProcPtr,
+ /* Filled with address of Tcl_FSUnloadFileProc
+ * function which should be used for this
+ * file. */
+ int flags)
+{
+ Tcl_LoadHandle newHandle;
+ Tcl_DyldLoadHandle *dyldLoadHandle;
+ NSObjectFileImage dyldObjFileImage = NULL;
+ Tcl_DyldModuleHandle *modulePtr;
+ NSModule module;
+ const char *objFileImageErrMsg = NULL;
+ int nsflags = NSLINKMODULE_OPTION_RETURN_ON_ERROR;
+
+ /*
+ * Try to create an object file image that we can load from.
+ */
+
+ if (codeSize >= 0) {
+ NSObjectFileImageReturnCode err = NSObjectFileImageSuccess;
+ const struct fat_header *fh = buffer;
+ uint32_t ms = 0;
+#ifndef __LP64__
+ const struct mach_header *mh = NULL;
+# define mh_size sizeof(struct mach_header)
+# define mh_magic MH_MAGIC
+# define arch_abi 0
+#else
+ const struct mach_header_64 *mh = NULL;
+# define mh_size sizeof(struct mach_header_64)
+# define mh_magic MH_MAGIC_64
+# define arch_abi CPU_ARCH_ABI64
+#endif /* __LP64__ */
+
+ if ((size_t) codeSize >= sizeof(struct fat_header)
+ && fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) {
+ uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);
+
+ /*
+ * Fat binary, try to find mach_header for our architecture
+ */
+
+ if ((size_t) codeSize >= sizeof(struct fat_header) +
+ fh_nfat_arch * sizeof(struct fat_arch)) {
+ void *fatarchs = (char*)buffer + sizeof(struct fat_header);
+ const NXArchInfo *arch = NXGetLocalArchInfo();
+ struct fat_arch *fa;
+
+ if (fh->magic != FAT_MAGIC) {
+ swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
+ }
+ fa = NXFindBestFatArch(arch->cputype | arch_abi,
+ arch->cpusubtype, fatarchs, fh_nfat_arch);
+ if (fa) {
+ mh = (void *)((char *) buffer + fa->offset);
+ ms = fa->size;
+ } else {
+ err = NSObjectFileImageInappropriateFile;
+ }
+ if (fh->magic != FAT_MAGIC) {
+ swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
+ }
+ } else {
+ err = NSObjectFileImageInappropriateFile;
+ }
+ } else {
+ /*
+ * Thin binary
+ */
+
+ mh = buffer;
+ ms = codeSize;
+ }
+ if (ms && !(ms >= mh_size && mh->magic == mh_magic &&
+ mh->filetype == MH_BUNDLE)) {
+ err = NSObjectFileImageInappropriateFile;
+ }
+ if (err == NSObjectFileImageSuccess) {
+ err = NSCreateObjectFileImageFromMemory(buffer, codeSize,
+ &dyldObjFileImage);
+ if (err != NSObjectFileImageSuccess) {
+ objFileImageErrMsg = DyldOFIErrorMsg(err);
+ }
+ } else {
+ objFileImageErrMsg = DyldOFIErrorMsg(err);
+ }
+ }
+
+ /*
+ * If it went wrong (or we were asked to just deallocate), get rid of the
+ * memory block and create an error message.
+ */
+
+ if (dyldObjFileImage == NULL) {
+ vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
+ if (objFileImageErrMsg != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "NSCreateObjectFileImageFromMemory() error: %s",
+ objFileImageErrMsg));
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * Extract the module we want from the image of the object file.
+ */
+
+ if (!(flags & 1)) nsflags |= NSLINKMODULE_OPTION_PRIVATE;
+ if (!(flags & 2)) nsflags |= NSLINKMODULE_OPTION_BINDNOW;
+ module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]", nsflags);
+ NSDestroyObjectFileImage(dyldObjFileImage);
+ if (!module) {
+ NSLinkEditErrors editError;
+ int errorNumber;
+ const char *errorName, *errMsg;
+
+ NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
+ return TCL_ERROR;
+ }
+
+ /*
+ * Stash the module reference within the load handle we create and return.
+ */
+
+ modulePtr = ckalloc(sizeof(Tcl_DyldModuleHandle));
+ modulePtr->module = module;
+ modulePtr->nextPtr = NULL;
+ dyldLoadHandle = ckalloc(sizeof(Tcl_DyldLoadHandle));
+ dyldLoadHandle->dlHandle = NULL;
+ dyldLoadHandle->dyldLibHeader = NULL;
+ dyldLoadHandle->modulePtr = modulePtr;
+ newHandle = ckalloc(sizeof(*newHandle));
+ newHandle->clientData = dyldLoadHandle;
+ newHandle->findSymbolProcPtr = &FindSymbol;
+ newHandle->unloadFileProcPtr = &UnloadFile;
+ *loadHandle = newHandle;
+ *unloadProcPtr = &UnloadFile;
+ return TCL_OK;
+}
+#endif /* TCL_LOAD_FROM_MEMORY */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 79
+ * End:
+ */
diff --git a/unix/tclLoadNext.c b/unix/tclLoadNext.c
new file mode 100644
index 0000000..eb0affa
--- /dev/null
+++ b/unix/tclLoadNext.c
@@ -0,0 +1,217 @@
+/*
+ * tclLoadNext.c --
+ *
+ * This procedure provides a version of the TclLoadFile that works with
+ * NeXTs rld_* dynamic loading. This file provided by Pedja Bogdanovich.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+#include <mach-o/rld.h>
+#include <streams/streams.h>
+
+/* Static procedures defined within this file */
+
+static void * FindSymbol(Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle, const char* symbol);
+static void UnloadFile(Tcl_LoadHandle loadHandle);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpDlopen --
+ *
+ * Dynamically loads a binary code file into memory and returns a handle
+ * to the new code.
+ *
+ * Results:
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * New code suddenly appears in memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpDlopen(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
+ * code (UTF-8). */
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
+ * (*unloadProcPtr)() to unload the file. */
+ Tcl_FSUnloadFileProc **unloadProcPtr,
+ /* Filled with address of Tcl_FSUnloadFileProc
+ * function which should be used for this
+ * file. */
+ int flags)
+{
+ Tcl_LoadHandle newHandle;
+ struct mach_header *header;
+ char *fileName;
+ char *files[2];
+ const char *native;
+ int result = 1;
+
+ NXStream *errorStream = NXOpenMemory(0,0,NX_READWRITE);
+
+ fileName = Tcl_GetString(pathPtr);
+
+ /*
+ * First try the full path the user gave us. This is particularly
+ * important if the cwd is inside a vfs, and we are trying to load using a
+ * relative path.
+ */
+
+ native = Tcl_FSGetNativePath(pathPtr);
+ files = {native,NULL};
+
+ result = rld_load(errorStream, &header, files, NULL);
+
+ if (!result) {
+ /*
+ * Let the OS loader examine the binary search path for whatever
+ * string the user gave us which hopefully refers to a file on the
+ * binary path
+ */
+
+ Tcl_DString ds;
+
+ native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
+ files = {native,NULL};
+ result = rld_load(errorStream, &header, files, NULL);
+ Tcl_DStringFree(&ds);
+ }
+
+ if (!result) {
+ char *data;
+ int len, maxlen;
+
+ NXGetMemoryBuffer(errorStream, &data, &len, &maxlen);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't load file \"%s\": %s", fileName, data));
+ NXCloseMemory(errorStream, NX_FREEBUFFER);
+ return TCL_ERROR;
+ }
+ NXCloseMemory(errorStream, NX_FREEBUFFER);
+
+ newHandle = ckalloc(sizeof(Tcl_LoadHandle));
+ newHandle->clientData = INT2PTR(1);
+ newHandle->findSymbolProcPtr = &FindSymbol;
+ newHandle->unloadFileProcPtr = &UnloadFile;
+ *loadHandle = newHandle;
+ *unloadProcPtr = &UnloadFile;
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindSymbol --
+ *
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library).
+ *
+ * Results:
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void *
+FindSymbol(
+ Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle,
+ const char *symbol)
+{
+ Tcl_PackageInitProc *proc = NULL;
+
+ if (symbol) {
+ char sym[strlen(symbol) + 2];
+
+ sym[0] = '_';
+ sym[1] = 0;
+ strcat(sym, symbol);
+ rld_lookup(NULL, sym, (unsigned long *) &proc);
+ }
+ if (proc == NULL && interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "cannot find symbol \"%s\"", symbol));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL);
+ }
+ return proc;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UnloadFile --
+ *
+ * Unloads a dynamically loaded binary code file from memory. Code
+ * pointers in the formerly loaded file are no longer valid after calling
+ * this function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Does nothing. Can anything be done?
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+UnloadFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
+{
+ ckfree(loadHandle);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGuessPackageName --
+ *
+ * If the "load" command is invoked without providing a package name,
+ * this procedure is invoked to try to figure it out.
+ *
+ * Results:
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGuessPackageName(
+ const char *fileName, /* Name of file containing package (already
+ * translated to local form if needed). */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
+ * name to this if possible. */
+{
+ return 0;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclLoadOSF.c b/unix/tclLoadOSF.c
new file mode 100644
index 0000000..377ed28
--- /dev/null
+++ b/unix/tclLoadOSF.c
@@ -0,0 +1,235 @@
+/*
+ * tclLoadOSF.c --
+ *
+ * This function provides a version of the TclLoadFile that works under
+ * OSF/1 1.0/1.1/1.2 and related systems, utilizing the old OSF/1
+ * /sbin/loader and /usr/include/loader.h. OSF/1 versions from 1.3 and on
+ * use ELF, rtld, and dlopen()[/usr/include/ldfcn.h].
+ *
+ * This is useful for:
+ * OSF/1 1.0, 1.1, 1.2 (from OSF)
+ * includes: MK4 and AD1 (from OSF RI)
+ * OSF/1 1.3 (from OSF) using ROSE
+ * HP OSF/1 1.0 ("Acorn") using COFF
+ *
+ * This is likely to be useful for:
+ * Paragon OSF/1 (from Intel)
+ * HI-OSF/1 (from Hitachi)
+ *
+ * This is NOT to be used on:
+ * Digitial Alpha OSF/1 systems
+ * OSF/1 1.3 or later (from OSF) using ELF
+ * includes: MK6, MK7, AD2, AD3 (from OSF RI)
+ *
+ * This approach to things was utter @&^#; thankfully, OSF/1 eventually
+ * supported dlopen().
+ *
+ * John Robert LoVerso <loverso@freebsd.osf.org>
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+#include <sys/types.h>
+#include <loader.h>
+
+/*
+ * Static functions defined within this file.
+ */
+
+static void * FindSymbol(Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle, const char* symbol);
+static void UnloadFile(Tcl_LoadHandle handle);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpDlopen --
+ *
+ * Dynamically loads a binary code file into memory and returns a handle
+ * to the new code.
+ *
+ * Results:
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * New code suddenly appears in memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpDlopen(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
+ * code (UTF-8). */
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
+ * (*unloadProcPtr)() to unload the file. */
+ Tcl_FSUnloadFileProc **unloadProcPtr,
+ /* Filled with address of Tcl_FSUnloadFileProc
+ * function which should be used for this
+ * file. */
+ int flags)
+{
+ Tcl_LoadHandle newHandle;
+ ldr_module_t lm;
+ char *pkg;
+ char *fileName = Tcl_GetString(pathPtr);
+ const char *native;
+
+ /*
+ * First try the full path the user gave us. This is particularly
+ * important if the cwd is inside a vfs, and we are trying to load using a
+ * relative path.
+ */
+
+ native = Tcl_FSGetNativePath(pathPtr);
+ lm = (Tcl_PackageInitProc *) load(native, LDR_NOFLAGS);
+
+ if (lm == LDR_NULL_MODULE) {
+ /*
+ * Let the OS loader examine the binary search path for whatever
+ * string the user gave us which hopefully refers to a file on the
+ * binary path
+ */
+
+ Tcl_DString ds;
+
+ native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
+ lm = (Tcl_PackageInitProc *) load(native, LDR_NOFLAGS);
+ Tcl_DStringFree(&ds);
+ }
+
+ if (lm == LDR_NULL_MODULE) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't load file \"%s\": %s",
+ fileName, Tcl_PosixError(interp)));
+ return TCL_ERROR;
+ }
+
+ *clientDataPtr = NULL;
+
+ /*
+ * My convention is to use a [OSF loader] package name the same as shlib,
+ * since the idiots never implemented ldr_lookup() and it is otherwise
+ * impossible to get a package name given a module.
+ *
+ * I build loadable modules with a makefile rule like
+ * ld ... -export $@: -o $@ $(OBJS)
+ */
+
+ if ((pkg = strrchr(fileName, '/')) == NULL) {
+ pkg = fileName;
+ } else {
+ pkg++;
+ }
+ newHandle = ckalloc(sizeof(*newHandle));
+ newHandle->clientData = pkg;
+ newHandle->findSymbolProcPtr = &FindSymbol;
+ newHandle->unloadFileProcPtr = &UnloadFile;
+ *loadHandle = newHandle;
+ *unloadProcPtr = &UnloadFile;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindSymbol --
+ *
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library).
+ *
+ * Results:
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void *
+FindSymbol(
+ Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle,
+ const char *symbol)
+{
+ void *retval = ldr_lookup_package((char *) loadHandle, symbol);
+
+ if (retval == NULL && interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "cannot find symbol \"%s\"", symbol));
+ Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL);
+ }
+ return retval;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UnloadFile --
+ *
+ * Unloads a dynamically loaded binary code file from memory. Code
+ * pointers in the formerly loaded file are no longer valid after calling
+ * this function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Does nothing. Can anything be done?
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UnloadFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
+{
+ ckfree(loadHandle);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGuessPackageName --
+ *
+ * If the "load" command is invoked without providing a package name,
+ * this function is invoked to try to figure it out.
+ *
+ * Results:
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGuessPackageName(
+ const char *fileName, /* Name of file containing package (already
+ * translated to local form if needed). */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
+ * name to this if possible. */
+{
+ return 0;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclLoadShl.c b/unix/tclLoadShl.c
new file mode 100644
index 0000000..4be3d7b
--- /dev/null
+++ b/unix/tclLoadShl.c
@@ -0,0 +1,224 @@
+/*
+ * tclLoadShl.c --
+ *
+ * This procedure provides a version of the TclLoadFile that works with
+ * the "shl_load" and "shl_findsym" library procedures for dynamic
+ * loading (e.g. for HP machines).
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include <dl.h>
+#include "tclInt.h"
+
+/*
+ * Static functions defined within this file.
+ */
+
+static void * FindSymbol(Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle, const char *symbol);
+static void UnloadFile(Tcl_LoadHandle handle);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpDlopen --
+ *
+ * Dynamically loads a binary code file into memory and returns a handle
+ * to the new code.
+ *
+ * Results:
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interp's result.
+ *
+ * Side effects:
+ * New code suddenly appears in memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpDlopen(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *pathPtr, /* Name of the file containing the desired
+ * code (UTF-8). */
+ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
+ * file which will be passed back to
+ * (*unloadProcPtr)() to unload the file. */
+ Tcl_FSUnloadFileProc **unloadProcPtr,
+ /* Filled with address of Tcl_FSUnloadFileProc
+ * function which should be used for this
+ * file. */
+ int flags)
+{
+ shl_t handle;
+ Tcl_LoadHandle newHandle;
+ const char *native;
+ char *fileName = Tcl_GetString(pathPtr);
+
+ /*
+ * The flags below used to be BIND_IMMEDIATE; they were changed at the
+ * suggestion of Wolfgang Kechel (wolfgang@prs.de): "This enables
+ * verbosity for missing symbols when loading a shared lib and allows to
+ * load libtk8.0.sl into tclsh8.0 without problems. In general, this
+ * delays resolving symbols until they are actually needed. Shared libs
+ * do no longer need all libraries linked in when they are build."
+ */
+
+ /*
+ * First try the full path the user gave us. This is particularly
+ * important if the cwd is inside a vfs, and we are trying to load using a
+ * relative path.
+ */
+
+ native = Tcl_FSGetNativePath(pathPtr);
+ handle = shl_load(native, BIND_DEFERRED|BIND_VERBOSE, 0L);
+
+ if (handle == NULL) {
+ /*
+ * Let the OS loader examine the binary search path for whatever
+ * string the user gave us which hopefully refers to a file on the
+ * binary path.
+ */
+
+ Tcl_DString ds;
+
+ native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
+ handle = shl_load(native, BIND_DEFERRED|BIND_VERBOSE|DYNAMIC_PATH, 0L);
+ Tcl_DStringFree(&ds);
+ }
+
+ if (handle == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't load file \"%s\": %s",
+ fileName, Tcl_PosixError(interp)));
+ return TCL_ERROR;
+ }
+ newHandle = ckalloc(sizeof(*newHandle));
+ newHandle->clientData = handle;
+ newHandle->findSymbolProcPtr = &FindSymbol;
+ newHandle->unloadFileProcPtr = *unloadProcPtr = &UnloadFile;
+ *loadHandle = newHandle;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FindSymbol --
+ *
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library).
+ *
+ * Results:
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void*
+FindSymbol(
+ Tcl_Interp *interp,
+ Tcl_LoadHandle loadHandle,
+ const char *symbol)
+{
+ Tcl_DString newName;
+ Tcl_PackageInitProc *proc = NULL;
+ shl_t handle = (shl_t) loadHandle->clientData;
+
+ /*
+ * Some versions of the HP system software still use "_" at the beginning
+ * of exported symbols while others don't; try both forms of each name.
+ */
+
+ if (shl_findsym(&handle, symbol, (short) TYPE_PROCEDURE,
+ (void *) &proc) != 0) {
+ Tcl_DStringInit(&newName);
+ TclDStringAppendLiteral(&newName, "_");
+ Tcl_DStringAppend(&newName, symbol, -1);
+ if (shl_findsym(&handle, Tcl_DStringValue(&newName),
+ (short) TYPE_PROCEDURE, (void *) &proc) != 0) {
+ proc = NULL;
+ }
+ Tcl_DStringFree(&newName);
+ }
+ if (proc == NULL && interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "cannot find symbol \"%s\": %s",
+ symbol, Tcl_PosixError(interp)));
+ }
+ return proc;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UnloadFile --
+ *
+ * Unloads a dynamically loaded binary code file from memory. Code
+ * pointers in the formerly loaded file are no longer valid after calling
+ * this function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Code removed from memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UnloadFile(
+ Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
+{
+ shl_t handle = (shl_t) loadHandle->clientData;
+
+ shl_unload(handle);
+ ckfree(loadHandle);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGuessPackageName --
+ *
+ * If the "load" command is invoked without providing a package name,
+ * this procedure is invoked to try to figure it out.
+ *
+ * Results:
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclGuessPackageName(
+ const char *fileName, /* Name of file containing package (already
+ * translated to local form if needed). */
+ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
+ * name to this if possible. */
+{
+ return 0;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclSelectNotfy.c b/unix/tclSelectNotfy.c
new file mode 100644
index 0000000..cf21b85
--- /dev/null
+++ b/unix/tclSelectNotfy.c
@@ -0,0 +1,1117 @@
+/*
+ * tclSelectNotfy.c --
+ *
+ * This file contains the implementation of the select()-based
+ * generic Unix notifier, which is the lowest-level part of the
+ * Tcl event loop. This file works together with generic/tclNotify.c.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#if !defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)
+
+#include "tclInt.h"
+#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
+ * in tclMacOSXNotify.c */
+#include <signal.h>
+
+/*
+ * This structure is used to keep track of the notifier info for a registered
+ * file.
+ */
+
+typedef struct FileHandler {
+ int fd;
+ int mask; /* Mask of desired events: TCL_READABLE,
+ * etc. */
+ int readyMask; /* Mask of events that have been seen since
+ * the last time file handlers were invoked
+ * for this file. */
+ Tcl_FileProc *proc; /* Function to call, in the style of
+ * Tcl_CreateFileHandler. */
+ ClientData clientData; /* Argument to pass to proc. */
+ struct FileHandler *nextPtr;/* Next in list of all files we care about. */
+} FileHandler;
+
+/*
+ * The following structure contains a set of select() masks to track readable,
+ * writable, and exception conditions.
+ */
+
+typedef struct {
+ fd_set readable;
+ fd_set writable;
+ fd_set exception;
+} SelectMasks;
+
+/*
+ * The following structure is what is added to the Tcl event queue when file
+ * handlers are ready to fire.
+ */
+
+typedef struct {
+ Tcl_Event header; /* Information that is standard for all
+ * events. */
+ int fd; /* File descriptor that is ready. Used to find
+ * the FileHandler structure for the file
+ * (can't point directly to the FileHandler
+ * structure because it could go away while
+ * the event is queued). */
+} FileHandlerEvent;
+
+/*
+ * The following static structure contains the state information for the
+ * select based implementation of the Tcl notifier. One of these structures is
+ * created for each thread that is using the notifier.
+ */
+
+typedef struct ThreadSpecificData {
+ FileHandler *firstFileHandlerPtr;
+ /* Pointer to head of file handler list. */
+ SelectMasks checkMasks; /* This structure is used to build up the
+ * masks to be used in the next call to
+ * select. Bits are set in response to calls
+ * to Tcl_CreateFileHandler. */
+ SelectMasks readyMasks; /* This array reflects the readable/writable
+ * conditions that were found to exist by the
+ * last call to select. */
+ int numFdBits; /* Number of valid bits in checkMasks (one
+ * more than highest fd for which
+ * Tcl_WatchFile has been called). */
+#ifdef TCL_THREADS
+ int onList; /* True if it is in this list */
+ unsigned int pollState; /* pollState is used to implement a polling
+ * handshake between each thread and the
+ * notifier thread. Bits defined below. */
+ struct ThreadSpecificData *nextPtr, *prevPtr;
+ /* All threads that are currently waiting on
+ * an event have their ThreadSpecificData
+ * structure on a doubly-linked listed formed
+ * from these pointers. You must hold the
+ * notifierMutex lock before accessing these
+ * fields. */
+#ifdef __CYGWIN__
+ void *event; /* Any other thread alerts a notifier
+ * that an event is ready to be processed
+ * by sending this event. */
+ void *hwnd; /* Messaging window. */
+#else /* !__CYGWIN__ */
+ pthread_cond_t waitCV; /* Any other thread alerts a notifier that an
+ * event is ready to be processed by signaling
+ * this condition variable. */
+#endif /* __CYGWIN__ */
+ int waitCVinitialized; /* Variable to flag initialization of the structure */
+ int eventReady; /* True if an event is ready to be processed.
+ * Used as condition flag together with waitCV
+ * above. */
+#endif /* TCL_THREADS */
+} ThreadSpecificData;
+
+static Tcl_ThreadDataKey dataKey;
+
+#ifdef TCL_THREADS
+/*
+ * The following static indicates the number of threads that have initialized
+ * notifiers.
+ *
+ * You must hold the notifierMutex lock before accessing this variable.
+ */
+
+static int notifierCount = 0;
+
+/*
+ * The following variable points to the head of a doubly-linked list of
+ * ThreadSpecificData structures for all threads that are currently waiting on
+ * an event.
+ *
+ * You must hold the notifierMutex lock before accessing this list.
+ */
+
+static ThreadSpecificData *waitingListPtr = NULL;
+
+/*
+ * The notifier thread spends all its time in select() waiting for a file
+ * descriptor associated with one of the threads on the waitingListPtr list to
+ * do something interesting. But if the contents of the waitingListPtr list
+ * ever changes, we need to wake up and restart the select() system call. You
+ * can wake up the notifier thread by writing a single byte to the file
+ * descriptor defined below. This file descriptor is the input-end of a pipe
+ * and the notifier thread is listening for data on the output-end of the same
+ * pipe. Hence writing to this file descriptor will cause the select() system
+ * call to return and wake up the notifier thread.
+ *
+ * You must hold the notifierMutex lock before writing to the pipe.
+ */
+
+static int triggerPipe = -1;
+
+/*
+ * The notifierMutex locks access to all of the global notifier state.
+ */
+
+static pthread_mutex_t notifierInitMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t notifierMutex = PTHREAD_MUTEX_INITIALIZER;
+/*
+ * The following static indicates if the notifier thread is running.
+ *
+ * You must hold the notifierInitMutex before accessing this variable.
+ */
+
+static int notifierThreadRunning = 0;
+
+/*
+ * The notifier thread signals the notifierCV when it has finished
+ * initializing the triggerPipe and right before the notifier thread
+ * terminates.
+ */
+
+static pthread_cond_t notifierCV = PTHREAD_COND_INITIALIZER;
+
+/*
+ * The pollState bits
+ * POLL_WANT is set by each thread before it waits on its condition
+ * variable. It is checked by the notifier before it does select.
+ * POLL_DONE is set by the notifier if it goes into select after seeing
+ * POLL_WANT. The idea is to ensure it tries a select with the
+ * same bits the initial thread had set.
+ */
+
+#define POLL_WANT 0x1
+#define POLL_DONE 0x2
+
+/*
+ * This is the thread ID of the notifier thread that does select.
+ */
+
+static Tcl_ThreadId notifierThread;
+#endif /* TCL_THREADS */
+
+/*
+ * Static routines defined in this file.
+ */
+
+#ifdef TCL_THREADS
+static TCL_NORETURN void NotifierThreadProc(ClientData clientData);
+#if defined(HAVE_PTHREAD_ATFORK)
+static int atForkInit = 0;
+static void AtForkChild(void);
+#endif /* HAVE_PTHREAD_ATFORK */
+#endif /* TCL_THREADS */
+static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
+
+/*
+ * Import of Windows API when building threaded with Cygwin.
+ */
+
+#if defined(TCL_THREADS) && defined(__CYGWIN__)
+typedef struct {
+ void *hwnd;
+ unsigned int *message;
+ int wParam;
+ int lParam;
+ int time;
+ int x;
+ int y;
+} MSG;
+
+typedef struct {
+ unsigned int style;
+ void *lpfnWndProc;
+ int cbClsExtra;
+ int cbWndExtra;
+ void *hInstance;
+ void *hIcon;
+ void *hCursor;
+ void *hbrBackground;
+ void *lpszMenuName;
+ const void *lpszClassName;
+} WNDCLASS;
+
+extern void __stdcall CloseHandle(void *);
+extern void *__stdcall CreateEventW(void *, unsigned char, unsigned char,
+ void *);
+extern void * __stdcall CreateWindowExW(void *, const void *, const void *,
+ DWORD, int, int, int, int, void *, void *, void *, void *);
+extern DWORD __stdcall DefWindowProcW(void *, int, void *, void *);
+extern unsigned char __stdcall DestroyWindow(void *);
+extern int __stdcall DispatchMessageW(const MSG *);
+extern unsigned char __stdcall GetMessageW(MSG *, void *, int, int);
+extern void __stdcall MsgWaitForMultipleObjects(DWORD, void *,
+ unsigned char, DWORD, DWORD);
+extern unsigned char __stdcall PeekMessageW(MSG *, void *, int, int, int);
+extern unsigned char __stdcall PostMessageW(void *, unsigned int, void *,
+ void *);
+extern void __stdcall PostQuitMessage(int);
+extern void *__stdcall RegisterClassW(const WNDCLASS *);
+extern unsigned char __stdcall ResetEvent(void *);
+extern unsigned char __stdcall TranslateMessage(const MSG *);
+
+/*
+ * Threaded-cygwin specific constants and functions in this file:
+ */
+
+static const WCHAR className[] = L"TclNotifier";
+static DWORD __stdcall NotifierProc(void *hwnd, unsigned int message,
+ void *wParam, void *lParam);
+#endif /* TCL_THREADS && __CYGWIN__ */
+
+
+#include "tclUnixNotfy.c"
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InitNotifier --
+ *
+ * Initializes the platform specific notifier state.
+ *
+ * Results:
+ * Returns a handle to the notifier state for this thread.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+Tcl_InitNotifier(void)
+{
+ if (tclNotifierHooks.initNotifierProc) {
+ return tclNotifierHooks.initNotifierProc();
+ } else {
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+#ifdef TCL_THREADS
+ tsdPtr->eventReady = 0;
+
+ /*
+ * Initialize thread specific condition variable for this thread.
+ */
+ if (tsdPtr->waitCVinitialized == 0) {
+#ifdef __CYGWIN__
+ WNDCLASS class;
+
+ class.style = 0;
+ class.cbClsExtra = 0;
+ class.cbWndExtra = 0;
+ class.hInstance = TclWinGetTclInstance();
+ class.hbrBackground = NULL;
+ class.lpszMenuName = NULL;
+ class.lpszClassName = className;
+ class.lpfnWndProc = NotifierProc;
+ class.hIcon = NULL;
+ class.hCursor = NULL;
+
+ RegisterClassW(&class);
+ tsdPtr->hwnd = CreateWindowExW(NULL, class.lpszClassName,
+ class.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL,
+ TclWinGetTclInstance(), NULL);
+ tsdPtr->event = CreateEventW(NULL, 1 /* manual */,
+ 0 /* !signaled */, NULL);
+#else
+ pthread_cond_init(&tsdPtr->waitCV, NULL);
+#endif /* __CYGWIN__ */
+ tsdPtr->waitCVinitialized = 1;
+ }
+
+ pthread_mutex_lock(&notifierInitMutex);
+#if defined(HAVE_PTHREAD_ATFORK)
+ /*
+ * Install pthread_atfork handlers to clean up the notifier in the
+ * child of a fork.
+ */
+
+ if (!atForkInit) {
+ int result = pthread_atfork(NULL, NULL, AtForkChild);
+
+ if (result) {
+ Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
+ }
+ atForkInit = 1;
+ }
+#endif /* HAVE_PTHREAD_ATFORK */
+
+ notifierCount++;
+
+ pthread_mutex_unlock(&notifierInitMutex);
+
+#endif /* TCL_THREADS */
+ return tsdPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_FinalizeNotifier --
+ *
+ * This function is called to cleanup the notifier state before a thread
+ * is terminated.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May terminate the background notifier thread if this is the last
+ * notifier instance.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_FinalizeNotifier(
+ ClientData clientData) /* Not used. */
+{
+ if (tclNotifierHooks.finalizeNotifierProc) {
+ tclNotifierHooks.finalizeNotifierProc(clientData);
+ return;
+ } else {
+#ifdef TCL_THREADS
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ pthread_mutex_lock(&notifierInitMutex);
+ notifierCount--;
+
+ /*
+ * If this is the last thread to use the notifier, close the notifier
+ * pipe and wait for the background thread to terminate.
+ */
+
+ if (notifierCount == 0) {
+
+ if (triggerPipe != -1) {
+ if (write(triggerPipe, "q", 1) != 1) {
+ Tcl_Panic("Tcl_FinalizeNotifier: %s",
+ "unable to write q to triggerPipe");
+ }
+ close(triggerPipe);
+ pthread_mutex_lock(&notifierMutex);
+ while(triggerPipe != -1) {
+ pthread_cond_wait(&notifierCV, &notifierMutex);
+ }
+ pthread_mutex_unlock(&notifierMutex);
+ if (notifierThreadRunning) {
+ int result = pthread_join((pthread_t) notifierThread, NULL);
+
+ if (result) {
+ Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier "
+ "thread");
+ }
+ notifierThreadRunning = 0;
+ }
+ }
+ }
+
+ /*
+ * Clean up any synchronization objects in the thread local storage.
+ */
+
+#ifdef __CYGWIN__
+ DestroyWindow(tsdPtr->hwnd);
+ CloseHandle(tsdPtr->event);
+#else /* __CYGWIN__ */
+ pthread_cond_destroy(&tsdPtr->waitCV);
+#endif /* __CYGWIN__ */
+ tsdPtr->waitCVinitialized = 0;
+
+ pthread_mutex_unlock(&notifierInitMutex);
+#endif /* TCL_THREADS */
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreateFileHandler --
+ *
+ * This function registers a file handler with the select notifier.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates a new file handler structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_CreateFileHandler(
+ int fd, /* Handle of stream to watch. */
+ int mask, /* OR'ed combination of TCL_READABLE,
+ * TCL_WRITABLE, and TCL_EXCEPTION: indicates
+ * conditions under which proc should be
+ * called. */
+ Tcl_FileProc *proc, /* Function to call for each selected
+ * event. */
+ ClientData clientData) /* Arbitrary data to pass to proc. */
+{
+ if (tclNotifierHooks.createFileHandlerProc) {
+ tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
+ return;
+ } else {
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr;
+
+ for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
+ filePtr = filePtr->nextPtr) {
+ if (filePtr->fd == fd) {
+ break;
+ }
+ }
+ if (filePtr == NULL) {
+ filePtr = ckalloc(sizeof(FileHandler));
+ filePtr->fd = fd;
+ filePtr->readyMask = 0;
+ filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
+ tsdPtr->firstFileHandlerPtr = filePtr;
+ }
+ filePtr->proc = proc;
+ filePtr->clientData = clientData;
+ filePtr->mask = mask;
+
+ /*
+ * Update the check masks for this file.
+ */
+
+ if (mask & TCL_READABLE) {
+ FD_SET(fd, &tsdPtr->checkMasks.readable);
+ } else {
+ FD_CLR(fd, &tsdPtr->checkMasks.readable);
+ }
+ if (mask & TCL_WRITABLE) {
+ FD_SET(fd, &tsdPtr->checkMasks.writable);
+ } else {
+ FD_CLR(fd, &tsdPtr->checkMasks.writable);
+ }
+ if (mask & TCL_EXCEPTION) {
+ FD_SET(fd, &tsdPtr->checkMasks.exception);
+ } else {
+ FD_CLR(fd, &tsdPtr->checkMasks.exception);
+ }
+ if (tsdPtr->numFdBits <= fd) {
+ tsdPtr->numFdBits = fd+1;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_DeleteFileHandler --
+ *
+ * Cancel a previously-arranged callback arrangement for a file.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If a callback was previously registered on file, remove it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_DeleteFileHandler(
+ int fd) /* Stream id for which to remove callback
+ * function. */
+{
+ if (tclNotifierHooks.deleteFileHandlerProc) {
+ tclNotifierHooks.deleteFileHandlerProc(fd);
+ return;
+ } else {
+ FileHandler *filePtr, *prevPtr;
+ int i;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ /*
+ * Find the entry for the given file (and return if there isn't one).
+ */
+
+ for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
+ prevPtr = filePtr, filePtr = filePtr->nextPtr) {
+ if (filePtr == NULL) {
+ return;
+ }
+ if (filePtr->fd == fd) {
+ break;
+ }
+ }
+
+ /*
+ * Update the check masks for this file.
+ */
+
+ if (filePtr->mask & TCL_READABLE) {
+ FD_CLR(fd, &tsdPtr->checkMasks.readable);
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ FD_CLR(fd, &tsdPtr->checkMasks.writable);
+ }
+ if (filePtr->mask & TCL_EXCEPTION) {
+ FD_CLR(fd, &tsdPtr->checkMasks.exception);
+ }
+
+ /*
+ * Find current max fd.
+ */
+
+ if (fd+1 == tsdPtr->numFdBits) {
+ int numFdBits = 0;
+
+ for (i = fd-1; i >= 0; i--) {
+ if (FD_ISSET(i, &tsdPtr->checkMasks.readable)
+ || FD_ISSET(i, &tsdPtr->checkMasks.writable)
+ || FD_ISSET(i, &tsdPtr->checkMasks.exception)) {
+ numFdBits = i+1;
+ break;
+ }
+ }
+ tsdPtr->numFdBits = numFdBits;
+ }
+
+ /*
+ * Clean up information in the callback record.
+ */
+
+ if (prevPtr == NULL) {
+ tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = filePtr->nextPtr;
+ }
+ ckfree(filePtr);
+ }
+}
+
+#if defined(TCL_THREADS) && defined(__CYGWIN__)
+
+static DWORD __stdcall
+NotifierProc(
+ void *hwnd,
+ unsigned int message,
+ void *wParam,
+ void *lParam)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ if (message != 1024) {
+ return DefWindowProcW(hwnd, message, wParam, lParam);
+ }
+
+ /*
+ * Process all of the runnable events.
+ */
+
+ tsdPtr->eventReady = 1;
+ Tcl_ServiceAll();
+ return 0;
+}
+#endif /* TCL_THREADS && __CYGWIN__ */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_WaitForEvent --
+ *
+ * This function is called by Tcl_DoOneEvent to wait for new events on
+ * the message queue. If the block time is 0, then Tcl_WaitForEvent just
+ * polls without blocking.
+ *
+ * Results:
+ * Returns -1 if the select would block forever, otherwise returns 0.
+ *
+ * Side effects:
+ * Queues file events that are detected by the select.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_WaitForEvent(
+ const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
+{
+ if (tclNotifierHooks.waitForEventProc) {
+ return tclNotifierHooks.waitForEventProc(timePtr);
+ } else {
+ FileHandler *filePtr;
+ int mask;
+ Tcl_Time vTime;
+#ifdef TCL_THREADS
+ int waitForFiles;
+# ifdef __CYGWIN__
+ MSG msg;
+# endif /* __CYGWIN__ */
+#else
+ /*
+ * Impl. notes: timeout & timeoutPtr are used if, and only if threads
+ * are not enabled. They are the arguments for the regular select()
+ * used when the core is not thread-enabled.
+ */
+
+ struct timeval timeout, *timeoutPtr;
+ int numFound;
+#endif /* TCL_THREADS */
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ /*
+ * Set up the timeout structure. Note that if there are no events to
+ * check for, we return with a negative result rather than blocking
+ * forever.
+ */
+
+ if (timePtr != NULL) {
+ /*
+ * TIP #233 (Virtualized Time). Is virtual time in effect? And do
+ * we actually have something to scale? If yes to both then we
+ * call the handler to do this scaling.
+ */
+
+ if (timePtr->sec != 0 || timePtr->usec != 0) {
+ vTime = *timePtr;
+ tclScaleTimeProcPtr(&vTime, tclTimeClientData);
+ timePtr = &vTime;
+ }
+#ifndef TCL_THREADS
+ timeout.tv_sec = timePtr->sec;
+ timeout.tv_usec = timePtr->usec;
+ timeoutPtr = &timeout;
+ } else if (tsdPtr->numFdBits == 0) {
+ /*
+ * If there are no threads, no timeout, and no fds registered,
+ * then there are no events possible and we must avoid deadlock.
+ * Note that this is not entirely correct because there might be a
+ * signal that could interrupt the select call, but we don't
+ * handle that case if we aren't using threads.
+ */
+
+ return -1;
+ } else {
+ timeoutPtr = NULL;
+#endif /* !TCL_THREADS */
+ }
+
+#ifdef TCL_THREADS
+ /*
+ * Start notifier thread and place this thread on the list of
+ * interested threads, signal the notifier thread, and wait for a
+ * response or a timeout.
+ */
+ StartNotifierThread("Tcl_WaitForEvent");
+
+ pthread_mutex_lock(&notifierMutex);
+
+ if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0
+#if defined(__APPLE__) && defined(__LP64__)
+ /*
+ * On 64-bit Darwin, pthread_cond_timedwait() appears to have
+ * a bug that causes it to wait forever when passed an
+ * absolute time which has already been exceeded by the system
+ * time; as a workaround, when given a very brief timeout,
+ * just do a poll. [Bug 1457797]
+ */
+ || timePtr->usec < 10
+#endif /* __APPLE__ && __LP64__ */
+ )) {
+ /*
+ * Cannot emulate a polling select with a polling condition
+ * variable. Instead, pretend to wait for files and tell the
+ * notifier thread what we are doing. The notifier thread makes
+ * sure it goes through select with its select mask in the same
+ * state as ours currently is. We block until that happens.
+ */
+
+ waitForFiles = 1;
+ tsdPtr->pollState = POLL_WANT;
+ timePtr = NULL;
+ } else {
+ waitForFiles = (tsdPtr->numFdBits > 0);
+ tsdPtr->pollState = 0;
+ }
+
+ if (waitForFiles) {
+ /*
+ * Add the ThreadSpecificData structure of this thread to the list
+ * of ThreadSpecificData structures of all threads that are
+ * waiting on file events.
+ */
+
+ tsdPtr->nextPtr = waitingListPtr;
+ if (waitingListPtr) {
+ waitingListPtr->prevPtr = tsdPtr;
+ }
+ tsdPtr->prevPtr = 0;
+ waitingListPtr = tsdPtr;
+ tsdPtr->onList = 1;
+
+ if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) {
+ Tcl_Panic("Tcl_WaitForEvent: %s",
+ "unable to write to triggerPipe");
+ }
+ }
+
+ FD_ZERO(&tsdPtr->readyMasks.readable);
+ FD_ZERO(&tsdPtr->readyMasks.writable);
+ FD_ZERO(&tsdPtr->readyMasks.exception);
+
+ if (!tsdPtr->eventReady) {
+#ifdef __CYGWIN__
+ if (!PeekMessageW(&msg, NULL, 0, 0, 0)) {
+ DWORD timeout;
+
+ if (timePtr) {
+ timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
+ } else {
+ timeout = 0xFFFFFFFF;
+ }
+ pthread_mutex_unlock(&notifierMutex);
+ MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279);
+ pthread_mutex_lock(&notifierMutex);
+ }
+#else
+ if (timePtr != NULL) {
+ Tcl_Time now;
+ struct timespec ptime;
+
+ Tcl_GetTime(&now);
+ ptime.tv_sec = timePtr->sec + now.sec + (timePtr->usec + now.usec) / 1000000;
+ ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);
+
+ pthread_cond_timedwait(&tsdPtr->waitCV, &notifierMutex, &ptime);
+ } else {
+ pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
+ }
+#endif /* __CYGWIN__ */
+ }
+ tsdPtr->eventReady = 0;
+
+#ifdef __CYGWIN__
+ while (PeekMessageW(&msg, NULL, 0, 0, 0)) {
+ /*
+ * Retrieve and dispatch the message.
+ */
+
+ DWORD result = GetMessageW(&msg, NULL, 0, 0);
+
+ if (result == 0) {
+ PostQuitMessage(msg.wParam);
+ /* What to do here? */
+ } else if (result != (DWORD) -1) {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+ }
+ ResetEvent(tsdPtr->event);
+#endif /* __CYGWIN__ */
+
+ if (waitForFiles && tsdPtr->onList) {
+ /*
+ * Remove the ThreadSpecificData structure of this thread from the
+ * waiting list. Alert the notifier thread to recompute its select
+ * masks - skipping this caused a hang when trying to close a pipe
+ * which the notifier thread was still doing a select on.
+ */
+
+ if (tsdPtr->prevPtr) {
+ tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
+ } else {
+ waitingListPtr = tsdPtr->nextPtr;
+ }
+ if (tsdPtr->nextPtr) {
+ tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
+ }
+ tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
+ tsdPtr->onList = 0;
+ if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) {
+ Tcl_Panic("Tcl_WaitForEvent: %s",
+ "unable to write to triggerPipe");
+ }
+ }
+
+#else
+ tsdPtr->readyMasks = tsdPtr->checkMasks;
+ numFound = select(tsdPtr->numFdBits, &tsdPtr->readyMasks.readable,
+ &tsdPtr->readyMasks.writable, &tsdPtr->readyMasks.exception,
+ timeoutPtr);
+
+ /*
+ * Some systems don't clear the masks after an error, so we have to do
+ * it here.
+ */
+
+ if (numFound == -1) {
+ FD_ZERO(&tsdPtr->readyMasks.readable);
+ FD_ZERO(&tsdPtr->readyMasks.writable);
+ FD_ZERO(&tsdPtr->readyMasks.exception);
+ }
+#endif /* TCL_THREADS */
+
+ /*
+ * Queue all detected file events before returning.
+ */
+
+ for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
+ filePtr = filePtr->nextPtr) {
+ mask = 0;
+ if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.readable)) {
+ mask |= TCL_READABLE;
+ }
+ if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.writable)) {
+ mask |= TCL_WRITABLE;
+ }
+ if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.exception)) {
+ mask |= TCL_EXCEPTION;
+ }
+
+ if (!mask) {
+ continue;
+ }
+
+ /*
+ * Don't bother to queue an event if the mask was previously
+ * non-zero since an event must still be on the queue.
+ */
+
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr =
+ ckalloc(sizeof(FileHandlerEvent));
+
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
+ }
+ filePtr->readyMask = mask;
+ }
+#ifdef TCL_THREADS
+ pthread_mutex_unlock(&notifierMutex);
+#endif /* TCL_THREADS */
+ return 0;
+ }
+}
+
+#ifdef TCL_THREADS
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NotifierThreadProc --
+ *
+ * This routine is the initial (and only) function executed by the
+ * special notifier thread. Its job is to wait for file descriptors to
+ * become readable or writable or to have an exception condition and then
+ * to notify other threads who are interested in this information by
+ * signalling a condition variable. Other threads can signal this
+ * notifier thread of a change in their interests by writing a single
+ * byte to a special pipe that the notifier thread is monitoring.
+ *
+ * Result:
+ * None. Once started, this routine never exits. It dies with the overall
+ * process.
+ *
+ * Side effects:
+ * The trigger pipe used to signal the notifier thread is created when
+ * the notifier thread first starts.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TCL_NORETURN void
+NotifierThreadProc(
+ ClientData clientData) /* Not used. */
+{
+ ThreadSpecificData *tsdPtr;
+ fd_set readableMask;
+ fd_set writableMask;
+ fd_set exceptionMask;
+ int i;
+ int fds[2], receivePipe;
+ long found;
+ struct timeval poll = {0., 0.}, *timePtr;
+ char buf[2];
+ int numFdBits = 0;
+
+ if (pipe(fds) != 0) {
+ Tcl_Panic("NotifierThreadProc: %s", "could not create trigger pipe");
+ }
+
+ receivePipe = fds[0];
+
+ if (TclUnixSetBlockingMode(receivePipe, TCL_MODE_NONBLOCKING) < 0) {
+ Tcl_Panic("NotifierThreadProc: %s",
+ "could not make receive pipe non blocking");
+ }
+ if (TclUnixSetBlockingMode(fds[1], TCL_MODE_NONBLOCKING) < 0) {
+ Tcl_Panic("NotifierThreadProc: %s",
+ "could not make trigger pipe non blocking");
+ }
+ if (fcntl(receivePipe, F_SETFD, FD_CLOEXEC) < 0) {
+ Tcl_Panic("NotifierThreadProc: %s",
+ "could not make receive pipe close-on-exec");
+ }
+ if (fcntl(fds[1], F_SETFD, FD_CLOEXEC) < 0) {
+ Tcl_Panic("NotifierThreadProc: %s",
+ "could not make trigger pipe close-on-exec");
+ }
+
+ /*
+ * Install the write end of the pipe into the global variable.
+ */
+
+ pthread_mutex_lock(&notifierMutex);
+ triggerPipe = fds[1];
+
+ /*
+ * Signal any threads that are waiting.
+ */
+
+ pthread_cond_broadcast(&notifierCV);
+ pthread_mutex_unlock(&notifierMutex);
+
+ /*
+ * Look for file events and report them to interested threads.
+ */
+
+ while (1) {
+ FD_ZERO(&readableMask);
+ FD_ZERO(&writableMask);
+ FD_ZERO(&exceptionMask);
+
+ /*
+ * Compute the logical OR of the masks from all the waiting
+ * notifiers.
+ */
+
+ pthread_mutex_lock(&notifierMutex);
+ timePtr = NULL;
+ for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
+ for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
+ if (FD_ISSET(i, &tsdPtr->checkMasks.readable)) {
+ FD_SET(i, &readableMask);
+ }
+ if (FD_ISSET(i, &tsdPtr->checkMasks.writable)) {
+ FD_SET(i, &writableMask);
+ }
+ if (FD_ISSET(i, &tsdPtr->checkMasks.exception)) {
+ FD_SET(i, &exceptionMask);
+ }
+ }
+ if (tsdPtr->numFdBits > numFdBits) {
+ numFdBits = tsdPtr->numFdBits;
+ }
+ if (tsdPtr->pollState & POLL_WANT) {
+ /*
+ * Here we make sure we go through select() with the same mask
+ * bits that were present when the thread tried to poll.
+ */
+
+ tsdPtr->pollState |= POLL_DONE;
+ timePtr = &poll;
+ }
+ }
+ pthread_mutex_unlock(&notifierMutex);
+
+ /*
+ * Set up the mask to include the receive pipe.
+ */
+
+ if (receivePipe >= numFdBits) {
+ numFdBits = receivePipe + 1;
+ }
+ FD_SET(receivePipe, &readableMask);
+
+ if (select(numFdBits, &readableMask, &writableMask, &exceptionMask,
+ timePtr) == -1) {
+ /*
+ * Try again immediately on an error.
+ */
+
+ continue;
+ }
+
+ /*
+ * Alert any threads that are waiting on a ready file descriptor.
+ */
+
+ pthread_mutex_lock(&notifierMutex);
+ for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
+ found = 0;
+
+ for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
+ if (FD_ISSET(i, &tsdPtr->checkMasks.readable)
+ && FD_ISSET(i, &readableMask)) {
+ FD_SET(i, &tsdPtr->readyMasks.readable);
+ found = 1;
+ }
+ if (FD_ISSET(i, &tsdPtr->checkMasks.writable)
+ && FD_ISSET(i, &writableMask)) {
+ FD_SET(i, &tsdPtr->readyMasks.writable);
+ found = 1;
+ }
+ if (FD_ISSET(i, &tsdPtr->checkMasks.exception)
+ && FD_ISSET(i, &exceptionMask)) {
+ FD_SET(i, &tsdPtr->readyMasks.exception);
+ found = 1;
+ }
+ }
+
+ if (found || (tsdPtr->pollState & POLL_DONE)) {
+ AlertSingleThread(tsdPtr);
+ }
+ }
+ pthread_mutex_unlock(&notifierMutex);
+
+ /*
+ * Consume the next byte from the notifier pipe if the pipe was
+ * readable. Note that there may be multiple bytes pending, but to
+ * avoid a race condition we only read one at a time.
+ */
+
+ do {
+ i = read(receivePipe, buf, 1);
+ if (i <= 0) {
+ break;
+ } else if ((i == 0) || ((i == 1) && (buf[0] == 'q'))) {
+ /*
+ * Someone closed the write end of the pipe or sent us a Quit
+ * message [Bug: 4139] and then closed the write end of the
+ * pipe so we need to shut down the notifier thread.
+ */
+
+ break;
+ }
+ } while (1);
+ if ((i == 0) || (buf[0] == 'q')) {
+ break;
+ }
+ }
+
+ /*
+ * Clean up the read end of the pipe and signal any threads waiting on
+ * termination of the notifier thread.
+ */
+
+ close(receivePipe);
+ pthread_mutex_lock(&notifierMutex);
+ triggerPipe = -1;
+ pthread_cond_broadcast(&notifierCV);
+ pthread_mutex_unlock(&notifierMutex);
+
+ TclpThreadExit(0);
+}
+
+#endif /* TCL_THREADS */
+
+#endif /* !HAVE_COREFOUNDATION */
+
+#endif /* !NOTIFIER_EPOLL && !NOTIFIER_KQUEUE */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c
new file mode 100644
index 0000000..ced684a
--- /dev/null
+++ b/unix/tclUnixChan.c
@@ -0,0 +1,1776 @@
+/*
+ * tclUnixChan.c
+ *
+ * Common channel driver for Unix channels based on files, command pipes
+ * and TCP sockets.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * 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.
+ */
+
+#include "tclInt.h" /* Internal definitions for Tcl. */
+#include "tclIO.h" /* To get Channel type declaration. */
+
+#undef SUPPORTS_TTY
+#if defined(HAVE_TERMIOS_H)
+# define SUPPORTS_TTY 1
+# include <termios.h>
+# ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+# endif /* HAVE_SYS_IOCTL_H */
+# ifdef HAVE_SYS_MODEM_H
+# include <sys/modem.h>
+# endif /* HAVE_SYS_MODEM_H */
+
+# ifdef FIONREAD
+# define GETREADQUEUE(fd, int) ioctl((fd), FIONREAD, &(int))
+# elif defined(FIORDCHK)
+# define GETREADQUEUE(fd, int) int = ioctl((fd), FIORDCHK, NULL)
+# else
+# define GETREADQUEUE(fd, int) int = 0
+# endif
+
+# ifdef TIOCOUTQ
+# define GETWRITEQUEUE(fd, int) ioctl((fd), TIOCOUTQ, &(int))
+# else
+# define GETWRITEQUEUE(fd, int) int = 0
+# endif
+
+# if !defined(CRTSCTS) && defined(CNEW_RTSCTS)
+# define CRTSCTS CNEW_RTSCTS
+# endif /* !CRTSCTS&CNEW_RTSCTS */
+# if !defined(PAREXT) && defined(CMSPAR)
+# define PAREXT CMSPAR
+# endif /* !PAREXT&&CMSPAR */
+
+#endif /* HAVE_TERMIOS_H */
+
+/*
+ * Helper macros to make parts of this file clearer. The macros do exactly
+ * what they say on the tin. :-) They also only ever refer to their arguments
+ * once, and so can be used without regard to side effects.
+ */
+
+#define SET_BITS(var, bits) ((var) |= (bits))
+#define CLEAR_BITS(var, bits) ((var) &= ~(bits))
+
+/*
+ * This structure describes per-instance state of a file based channel.
+ */
+
+typedef struct {
+ Tcl_Channel channel; /* Channel associated with this file. */
+ int fd; /* File handle. */
+ int validMask; /* OR'ed combination of TCL_READABLE,
+ * TCL_WRITABLE, or TCL_EXCEPTION: indicates
+ * which operations are valid on the file. */
+} FileState;
+
+#ifdef SUPPORTS_TTY
+
+/*
+ * The following structure is used to set or get the serial port attributes in
+ * a platform-independant manner.
+ */
+
+typedef struct {
+ int baud;
+ int parity;
+ int data;
+ int stop;
+} TtyAttrs;
+
+#endif /* !SUPPORTS_TTY */
+
+#define UNSUPPORTED_OPTION(detail) \
+ if (interp) { \
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf( \
+ "%s not supported for this platform", (detail))); \
+ Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL); \
+ }
+
+/*
+ * Static routines for this file:
+ */
+
+static int FileBlockModeProc(ClientData instanceData, int mode);
+static int FileCloseProc(ClientData instanceData,
+ Tcl_Interp *interp);
+static int FileGetHandleProc(ClientData instanceData,
+ int direction, ClientData *handlePtr);
+static int FileInputProc(ClientData instanceData, char *buf,
+ int toRead, int *errorCode);
+static int FileOutputProc(ClientData instanceData,
+ const char *buf, int toWrite, int *errorCode);
+static int FileSeekProc(ClientData instanceData, long offset,
+ int mode, int *errorCode);
+static int FileTruncateProc(ClientData instanceData,
+ Tcl_WideInt length);
+static Tcl_WideInt FileWideSeekProc(ClientData instanceData,
+ Tcl_WideInt offset, int mode, int *errorCode);
+static void FileWatchProc(ClientData instanceData, int mask);
+#ifdef SUPPORTS_TTY
+static void TtyGetAttributes(int fd, TtyAttrs *ttyPtr);
+static int TtyGetOptionProc(ClientData instanceData,
+ Tcl_Interp *interp, const char *optionName,
+ Tcl_DString *dsPtr);
+static int TtyGetBaud(speed_t speed);
+static speed_t TtyGetSpeed(int baud);
+static void TtyInit(int fd);
+static void TtyModemStatusStr(int status, Tcl_DString *dsPtr);
+static int TtyParseMode(Tcl_Interp *interp, const char *mode,
+ TtyAttrs *ttyPtr);
+static void TtySetAttributes(int fd, TtyAttrs *ttyPtr);
+static int TtySetOptionProc(ClientData instanceData,
+ Tcl_Interp *interp, const char *optionName,
+ const char *value);
+#endif /* SUPPORTS_TTY */
+
+/*
+ * This structure describes the channel type structure for file based IO:
+ */
+
+static const Tcl_ChannelType fileChannelType = {
+ "file", /* Type name. */
+ TCL_CHANNEL_VERSION_5, /* v5 channel */
+ FileCloseProc, /* Close proc. */
+ FileInputProc, /* Input proc. */
+ FileOutputProc, /* Output proc. */
+ FileSeekProc, /* Seek proc. */
+ NULL, /* Set option proc. */
+ NULL, /* Get option proc. */
+ FileWatchProc, /* Initialize notifier. */
+ FileGetHandleProc, /* Get OS handles out of channel. */
+ NULL, /* close2proc. */
+ FileBlockModeProc, /* Set blocking or non-blocking mode.*/
+ NULL, /* flush proc. */
+ NULL, /* handler proc. */
+ FileWideSeekProc, /* wide seek proc. */
+ NULL,
+ FileTruncateProc /* truncate proc. */
+};
+
+#ifdef SUPPORTS_TTY
+/*
+ * This structure describes the channel type structure for serial IO.
+ * Note that this type is a subclass of the "file" type.
+ */
+
+static const Tcl_ChannelType ttyChannelType = {
+ "tty", /* Type name. */
+ TCL_CHANNEL_VERSION_5, /* v5 channel */
+ FileCloseProc, /* Close proc. */
+ FileInputProc, /* Input proc. */
+ FileOutputProc, /* Output proc. */
+ NULL, /* Seek proc. */
+ TtySetOptionProc, /* Set option proc. */
+ TtyGetOptionProc, /* Get option proc. */
+ FileWatchProc, /* Initialize notifier. */
+ FileGetHandleProc, /* Get OS handles out of channel. */
+ NULL, /* close2proc. */
+ FileBlockModeProc, /* Set blocking or non-blocking mode.*/
+ NULL, /* flush proc. */
+ NULL, /* handler proc. */
+ NULL, /* wide seek proc. */
+ NULL, /* thread action proc. */
+ NULL /* truncate proc. */
+};
+#endif /* SUPPORTS_TTY */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileBlockModeProc --
+ *
+ * Helper function to set blocking and nonblocking modes on a file based
+ * channel. Invoked by generic IO level code.
+ *
+ * Results:
+ * 0 if successful, errno when failed.
+ *
+ * Side effects:
+ * Sets the device into blocking or non-blocking mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+FileBlockModeProc(
+ ClientData instanceData, /* File state. */
+ int mode) /* The mode to set. Can be TCL_MODE_BLOCKING
+ * or TCL_MODE_NONBLOCKING. */
+{
+ FileState *fsPtr = instanceData;
+
+ if (TclUnixSetBlockingMode(fsPtr->fd, mode) < 0) {
+ return errno;
+ }
+
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileInputProc --
+ *
+ * This function is invoked from the generic IO level to read input from
+ * a file based channel.
+ *
+ * Results:
+ * The number of bytes read is returned or -1 on error. An output
+ * argument contains a POSIX error code if an error occurs, or zero.
+ *
+ * Side effects:
+ * Reads input from the input device of the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileInputProc(
+ ClientData instanceData, /* File state. */
+ char *buf, /* Where to store data read. */
+ int toRead, /* How much space is available in the
+ * buffer? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ FileState *fsPtr = instanceData;
+ int bytesRead; /* How many bytes were actually read from the
+ * input device? */
+
+ *errorCodePtr = 0;
+
+ /*
+ * Assume there is always enough input available. This will block
+ * appropriately, and read will unblock as soon as a short read is
+ * possible, if the channel is in blocking mode. If the channel is
+ * nonblocking, the read will never block.
+ */
+
+ bytesRead = read(fsPtr->fd, buf, (size_t) toRead);
+ if (bytesRead > -1) {
+ return bytesRead;
+ }
+ *errorCodePtr = errno;
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileOutputProc--
+ *
+ * This function is invoked from the generic IO level to write output to
+ * a file channel.
+ *
+ * Results:
+ * The number of bytes written is returned or -1 on error. An output
+ * argument contains a POSIX error code if an error occurred, or zero.
+ *
+ * Side effects:
+ * Writes output on the output device of the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileOutputProc(
+ ClientData instanceData, /* File state. */
+ const char *buf, /* The data buffer. */
+ int toWrite, /* How many bytes to write? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ FileState *fsPtr = instanceData;
+ int written;
+
+ *errorCodePtr = 0;
+
+ if (toWrite == 0) {
+ /*
+ * SF Tcl Bug 465765. Do not try to write nothing into a file. STREAM
+ * based implementations will considers this as EOF (if there is a
+ * pipe behind the file).
+ */
+
+ return 0;
+ }
+ written = write(fsPtr->fd, buf, (size_t) toWrite);
+ if (written > -1) {
+ return written;
+ }
+ *errorCodePtr = errno;
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileCloseProc --
+ *
+ * This function is called from the generic IO level to perform
+ * channel-type-specific cleanup when a file based channel is closed.
+ *
+ * Results:
+ * 0 if successful, errno if failed.
+ *
+ * Side effects:
+ * Closes the device of the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileCloseProc(
+ ClientData instanceData, /* File state. */
+ Tcl_Interp *interp) /* For error reporting - unused. */
+{
+ FileState *fsPtr = instanceData;
+ int errorCode = 0;
+
+ Tcl_DeleteFileHandler(fsPtr->fd);
+
+ /*
+ * Do not close standard channels while in thread-exit.
+ */
+
+ if (!TclInThreadExit()
+ || ((fsPtr->fd != 0) && (fsPtr->fd != 1) && (fsPtr->fd != 2))) {
+ if (close(fsPtr->fd) < 0) {
+ errorCode = errno;
+ }
+ }
+ ckfree(fsPtr);
+ return errorCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileSeekProc --
+ *
+ * This function is called by the generic IO level to move the access
+ * point in a file based channel.
+ *
+ * Results:
+ * -1 if failed, the new position if successful. An output argument
+ * contains the POSIX error code if an error occurred, or zero.
+ *
+ * Side effects:
+ * Moves the location at which the channel will be accessed in future
+ * operations.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileSeekProc(
+ ClientData instanceData, /* File state. */
+ long offset, /* Offset to seek to. */
+ int mode, /* Relative to where should we seek? Can be
+ * one of SEEK_START, SEEK_SET or SEEK_END. */
+ int *errorCodePtr) /* To store error code. */
+{
+ FileState *fsPtr = instanceData;
+ Tcl_WideInt oldLoc, newLoc;
+
+ /*
+ * Save our current place in case we need to roll-back the seek.
+ */
+
+ oldLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) 0, SEEK_CUR);
+ if (oldLoc == Tcl_LongAsWide(-1)) {
+ /*
+ * Bad things are happening. Error out...
+ */
+
+ *errorCodePtr = errno;
+ return -1;
+ }
+
+ newLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) offset, mode);
+
+ /*
+ * Check for expressability in our return type, and roll-back otherwise.
+ */
+
+ if (newLoc > Tcl_LongAsWide(INT_MAX)) {
+ *errorCodePtr = EOVERFLOW;
+ TclOSseek(fsPtr->fd, (Tcl_SeekOffset) oldLoc, SEEK_SET);
+ return -1;
+ } else {
+ *errorCodePtr = (newLoc == Tcl_LongAsWide(-1)) ? errno : 0;
+ }
+ return (int) Tcl_WideAsLong(newLoc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileWideSeekProc --
+ *
+ * This function is called by the generic IO level to move the access
+ * point in a file based channel, with offsets expressed as wide
+ * integers.
+ *
+ * Results:
+ * -1 if failed, the new position if successful. An output argument
+ * contains the POSIX error code if an error occurred, or zero.
+ *
+ * Side effects:
+ * Moves the location at which the channel will be accessed in future
+ * operations.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_WideInt
+FileWideSeekProc(
+ ClientData instanceData, /* File state. */
+ Tcl_WideInt offset, /* Offset to seek to. */
+ int mode, /* Relative to where should we seek? Can be
+ * one of SEEK_START, SEEK_CUR or SEEK_END. */
+ int *errorCodePtr) /* To store error code. */
+{
+ FileState *fsPtr = instanceData;
+ Tcl_WideInt newLoc;
+
+ newLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) offset, mode);
+
+ *errorCodePtr = (newLoc == -1) ? errno : 0;
+ return newLoc;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileWatchProc --
+ *
+ * Initialize the notifier to watch the fd from this channel.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets up the notifier so that a future event on the channel will
+ * be seen by Tcl.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FileWatchProc(
+ ClientData instanceData, /* The file state. */
+ int mask) /* Events of interest; an OR-ed combination of
+ * TCL_READABLE, TCL_WRITABLE and
+ * TCL_EXCEPTION. */
+{
+ FileState *fsPtr = instanceData;
+
+ /*
+ * Make sure we only register for events that are valid on this file. Note
+ * that we are passing Tcl_NotifyChannel directly to Tcl_CreateFileHandler
+ * with the channel pointer as the client data.
+ */
+
+ mask &= fsPtr->validMask;
+ if (mask) {
+ Tcl_CreateFileHandler(fsPtr->fd, mask,
+ (Tcl_FileProc *) Tcl_NotifyChannel, fsPtr->channel);
+ } else {
+ Tcl_DeleteFileHandler(fsPtr->fd);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileGetHandleProc --
+ *
+ * Called from Tcl_GetChannelHandle to retrieve OS handles from a file
+ * based channel.
+ *
+ * Results:
+ * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no
+ * handle for the specified direction.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileGetHandleProc(
+ ClientData instanceData, /* The file state. */
+ int direction, /* TCL_READABLE or TCL_WRITABLE */
+ ClientData *handlePtr) /* Where to store the handle. */
+{
+ FileState *fsPtr = instanceData;
+
+ if (direction & fsPtr->validMask) {
+ *handlePtr = INT2PTR(fsPtr->fd);
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+
+#ifdef SUPPORTS_TTY
+/*
+ *----------------------------------------------------------------------
+ *
+ * TtyModemStatusStr --
+ *
+ * Converts a RS232 modem status list of readable flags
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TtyModemStatusStr(
+ int status, /* RS232 modem status */
+ Tcl_DString *dsPtr) /* Where to store string */
+{
+#ifdef TIOCM_CTS
+ Tcl_DStringAppendElement(dsPtr, "CTS");
+ Tcl_DStringAppendElement(dsPtr, (status & TIOCM_CTS) ? "1" : "0");
+#endif /* TIOCM_CTS */
+#ifdef TIOCM_DSR
+ Tcl_DStringAppendElement(dsPtr, "DSR");
+ Tcl_DStringAppendElement(dsPtr, (status & TIOCM_DSR) ? "1" : "0");
+#endif /* TIOCM_DSR */
+#ifdef TIOCM_RNG
+ Tcl_DStringAppendElement(dsPtr, "RING");
+ Tcl_DStringAppendElement(dsPtr, (status & TIOCM_RNG) ? "1" : "0");
+#endif /* TIOCM_RNG */
+#ifdef TIOCM_CD
+ Tcl_DStringAppendElement(dsPtr, "DCD");
+ Tcl_DStringAppendElement(dsPtr, (status & TIOCM_CD) ? "1" : "0");
+#endif /* TIOCM_CD */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TtySetOptionProc --
+ *
+ * Sets an option on a channel.
+ *
+ * Results:
+ * A standard Tcl result. Also sets the interp's result on error if
+ * interp is not NULL.
+ *
+ * Side effects:
+ * May modify an option on a device. Sets Error message if needed (by
+ * calling Tcl_BadChannelOption).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TtySetOptionProc(
+ ClientData instanceData, /* File state. */
+ Tcl_Interp *interp, /* For error reporting - can be NULL. */
+ const char *optionName, /* Which option to set? */
+ const char *value) /* New value for option. */
+{
+ FileState *fsPtr = instanceData;
+ unsigned int len, vlen;
+ TtyAttrs tty;
+ int argc;
+ const char **argv;
+ struct termios iostate;
+
+ len = strlen(optionName);
+ vlen = strlen(value);
+
+ /*
+ * Option -mode baud,parity,databits,stopbits
+ */
+
+ if ((len > 2) && (strncmp(optionName, "-mode", len) == 0)) {
+ if (TtyParseMode(interp, value, &tty) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * system calls results should be checked there. - dl
+ */
+
+ TtySetAttributes(fsPtr->fd, &tty);
+ return TCL_OK;
+ }
+
+ /*
+ * Option -handshake none|xonxoff|rtscts|dtrdsr
+ */
+
+ if ((len > 1) && (strncmp(optionName, "-handshake", len) == 0)) {
+ /*
+ * Reset all handshake options. DTR and RTS are ON by default.
+ */
+
+ tcgetattr(fsPtr->fd, &iostate);
+ CLEAR_BITS(iostate.c_iflag, IXON | IXOFF | IXANY);
+#ifdef CRTSCTS
+ CLEAR_BITS(iostate.c_cflag, CRTSCTS);
+#endif /* CRTSCTS */
+ if (Tcl_UtfNcasecmp(value, "NONE", vlen) == 0) {
+ /*
+ * Leave all handshake options disabled.
+ */
+ } else if (Tcl_UtfNcasecmp(value, "XONXOFF", vlen) == 0) {
+ SET_BITS(iostate.c_iflag, IXON | IXOFF | IXANY);
+ } else if (Tcl_UtfNcasecmp(value, "RTSCTS", vlen) == 0) {
+#ifdef CRTSCTS
+ SET_BITS(iostate.c_cflag, CRTSCTS);
+#else /* !CRTSTS */
+ UNSUPPORTED_OPTION("-handshake RTSCTS");
+ return TCL_ERROR;
+#endif /* CRTSCTS */
+ } else if (Tcl_UtfNcasecmp(value, "DTRDSR", vlen) == 0) {
+ UNSUPPORTED_OPTION("-handshake DTRDSR");
+ return TCL_ERROR;
+ } else {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "bad value for -handshake: must be one of"
+ " xonxoff, rtscts, dtrdsr or none", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
+ "VALUE", NULL);
+ }
+ return TCL_ERROR;
+ }
+ tcsetattr(fsPtr->fd, TCSADRAIN, &iostate);
+ return TCL_OK;
+ }
+
+ /*
+ * Option -xchar {\x11 \x13}
+ */
+
+ if ((len > 1) && (strncmp(optionName, "-xchar", len) == 0)) {
+ Tcl_DString ds;
+
+ if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) {
+ return TCL_ERROR;
+ } else if (argc != 2) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "bad value for -xchar: should be a list of"
+ " two elements", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
+ "VALUE", NULL);
+ }
+ ckfree(argv);
+ return TCL_ERROR;
+ }
+
+ tcgetattr(fsPtr->fd, &iostate);
+
+ Tcl_UtfToExternalDString(NULL, argv[0], -1, &ds);
+ iostate.c_cc[VSTART] = *(const cc_t *) Tcl_DStringValue(&ds);
+ TclDStringClear(&ds);
+
+ Tcl_UtfToExternalDString(NULL, argv[1], -1, &ds);
+ iostate.c_cc[VSTOP] = *(const cc_t *) Tcl_DStringValue(&ds);
+ Tcl_DStringFree(&ds);
+ ckfree(argv);
+
+ tcsetattr(fsPtr->fd, TCSADRAIN, &iostate);
+ return TCL_OK;
+ }
+
+ /*
+ * Option -timeout msec
+ */
+
+ if ((len > 2) && (strncmp(optionName, "-timeout", len) == 0)) {
+ int msec;
+
+ tcgetattr(fsPtr->fd, &iostate);
+ if (Tcl_GetInt(interp, value, &msec) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ iostate.c_cc[VMIN] = 0;
+ iostate.c_cc[VTIME] = (msec==0) ? 0 : (msec<100) ? 1 : (msec+50)/100;
+ tcsetattr(fsPtr->fd, TCSADRAIN, &iostate);
+ return TCL_OK;
+ }
+
+ /*
+ * Option -ttycontrol {DTR 1 RTS 0 BREAK 0}
+ */
+
+ if ((len > 4) && (strncmp(optionName, "-ttycontrol", len) == 0)) {
+#if defined(TIOCMGET) && defined(TIOCMSET)
+ int i, control, flag;
+
+ if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if ((argc % 2) == 1) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "bad value for -ttycontrol: should be a list of"
+ " signal,value pairs", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
+ "VALUE", NULL);
+ }
+ ckfree(argv);
+ return TCL_ERROR;
+ }
+
+ ioctl(fsPtr->fd, TIOCMGET, &control);
+ for (i = 0; i < argc-1; i += 2) {
+ if (Tcl_GetBoolean(interp, argv[i+1], &flag) == TCL_ERROR) {
+ ckfree(argv);
+ return TCL_ERROR;
+ }
+ if (Tcl_UtfNcasecmp(argv[i], "DTR", strlen(argv[i])) == 0) {
+ if (flag) {
+ SET_BITS(control, TIOCM_DTR);
+ } else {
+ CLEAR_BITS(control, TIOCM_DTR);
+ }
+ } else if (Tcl_UtfNcasecmp(argv[i], "RTS", strlen(argv[i])) == 0) {
+ if (flag) {
+ SET_BITS(control, TIOCM_RTS);
+ } else {
+ CLEAR_BITS(control, TIOCM_RTS);
+ }
+ } else if (Tcl_UtfNcasecmp(argv[i], "BREAK", strlen(argv[i])) == 0) {
+#if defined(TIOCSBRK) && defined(TIOCCBRK)
+ if (flag) {
+ ioctl(fsPtr->fd, TIOCSBRK, NULL);
+ } else {
+ ioctl(fsPtr->fd, TIOCCBRK, NULL);
+ }
+#else /* TIOCSBRK & TIOCCBRK */
+ UNSUPPORTED_OPTION("-ttycontrol BREAK");
+ ckfree(argv);
+ return TCL_ERROR;
+#endif /* TIOCSBRK & TIOCCBRK */
+ } else {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "bad signal \"%s\" for -ttycontrol: must be"
+ " DTR, RTS or BREAK", argv[i]));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE",
+ "VALUE", NULL);
+ }
+ ckfree(argv);
+ return TCL_ERROR;
+ }
+ } /* -ttycontrol options loop */
+
+ ioctl(fsPtr->fd, TIOCMSET, &control);
+ ckfree(argv);
+ return TCL_OK;
+#else /* TIOCMGET&TIOCMSET */
+ UNSUPPORTED_OPTION("-ttycontrol");
+#endif /* TIOCMGET&TIOCMSET */
+ }
+
+ return Tcl_BadChannelOption(interp, optionName,
+ "mode handshake timeout ttycontrol xchar");
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TtyGetOptionProc --
+ *
+ * Gets a mode associated with an IO channel. If the optionName arg is
+ * non-NULL, retrieves the value of that option. If the optionName arg is
+ * NULL, retrieves a list of alternating option names and values for the
+ * given channel.
+ *
+ * Results:
+ * A standard Tcl result. Also sets the supplied DString to the string
+ * value of the option(s) returned. Sets error message if needed
+ * (by calling Tcl_BadChannelOption).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TtyGetOptionProc(
+ ClientData instanceData, /* File state. */
+ Tcl_Interp *interp, /* For error reporting - can be NULL. */
+ const char *optionName, /* Option to get. */
+ Tcl_DString *dsPtr) /* Where to store value(s). */
+{
+ FileState *fsPtr = instanceData;
+ unsigned int len;
+ char buf[3*TCL_INTEGER_SPACE + 16];
+ int valid = 0; /* Flag if valid option parsed. */
+
+ if (optionName == NULL) {
+ len = 0;
+ } else {
+ len = strlen(optionName);
+ }
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-mode");
+ }
+ if (len==0 || (len>2 && strncmp(optionName, "-mode", len)==0)) {
+ TtyAttrs tty;
+
+ valid = 1;
+ TtyGetAttributes(fsPtr->fd, &tty);
+ sprintf(buf, "%d,%c,%d,%d", tty.baud, tty.parity, tty.data, tty.stop);
+ Tcl_DStringAppendElement(dsPtr, buf);
+ }
+
+ /*
+ * Get option -xchar
+ */
+
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-xchar");
+ Tcl_DStringStartSublist(dsPtr);
+ }
+ if (len==0 || (len>1 && strncmp(optionName, "-xchar", len)==0)) {
+ struct termios iostate;
+ Tcl_DString ds;
+
+ valid = 1;
+ tcgetattr(fsPtr->fd, &iostate);
+ Tcl_DStringInit(&ds);
+
+ Tcl_ExternalToUtfDString(NULL, (char *) &iostate.c_cc[VSTART], 1, &ds);
+ Tcl_DStringAppendElement(dsPtr, Tcl_DStringValue(&ds));
+ TclDStringClear(&ds);
+
+ Tcl_ExternalToUtfDString(NULL, (char *) &iostate.c_cc[VSTOP], 1, &ds);
+ Tcl_DStringAppendElement(dsPtr, Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+ }
+ if (len == 0) {
+ Tcl_DStringEndSublist(dsPtr);
+ }
+
+ /*
+ * Get option -queue
+ * Option is readonly and returned by [fconfigure chan -queue] but not
+ * returned by unnamed [fconfigure chan].
+ */
+
+ if ((len > 1) && (strncmp(optionName, "-queue", len) == 0)) {
+ int inQueue=0, outQueue=0, inBuffered, outBuffered;
+
+ valid = 1;
+ GETREADQUEUE(fsPtr->fd, inQueue);
+ GETWRITEQUEUE(fsPtr->fd, outQueue);
+ inBuffered = Tcl_InputBuffered(fsPtr->channel);
+ outBuffered = Tcl_OutputBuffered(fsPtr->channel);
+
+ sprintf(buf, "%d", inBuffered+inQueue);
+ Tcl_DStringAppendElement(dsPtr, buf);
+ sprintf(buf, "%d", outBuffered+outQueue);
+ Tcl_DStringAppendElement(dsPtr, buf);
+ }
+
+#if defined(TIOCMGET)
+ /*
+ * Get option -ttystatus
+ * Option is readonly and returned by [fconfigure chan -ttystatus] but not
+ * returned by unnamed [fconfigure chan].
+ */
+
+ if ((len > 4) && (strncmp(optionName, "-ttystatus", len) == 0)) {
+ int status;
+
+ valid = 1;
+ ioctl(fsPtr->fd, TIOCMGET, &status);
+ TtyModemStatusStr(status, dsPtr);
+ }
+#endif /* TIOCMGET */
+
+ if (valid) {
+ return TCL_OK;
+ }
+ return Tcl_BadChannelOption(interp, optionName,
+ "mode queue ttystatus xchar");
+}
+
+static const struct {int baud; speed_t speed;} speeds[] = {
+#ifdef B0
+ {0, B0},
+#endif
+#ifdef B50
+ {50, B50},
+#endif
+#ifdef B75
+ {75, B75},
+#endif
+#ifdef B110
+ {110, B110},
+#endif
+#ifdef B134
+ {134, B134},
+#endif
+#ifdef B150
+ {150, B150},
+#endif
+#ifdef B200
+ {200, B200},
+#endif
+#ifdef B300
+ {300, B300},
+#endif
+#ifdef B600
+ {600, B600},
+#endif
+#ifdef B1200
+ {1200, B1200},
+#endif
+#ifdef B1800
+ {1800, B1800},
+#endif
+#ifdef B2400
+ {2400, B2400},
+#endif
+#ifdef B4800
+ {4800, B4800},
+#endif
+#ifdef B9600
+ {9600, B9600},
+#endif
+#ifdef B14400
+ {14400, B14400},
+#endif
+#ifdef B19200
+ {19200, B19200},
+#endif
+#ifdef EXTA
+ {19200, EXTA},
+#endif
+#ifdef B28800
+ {28800, B28800},
+#endif
+#ifdef B38400
+ {38400, B38400},
+#endif
+#ifdef EXTB
+ {38400, EXTB},
+#endif
+#ifdef B57600
+ {57600, B57600},
+#endif
+#ifdef _B57600
+ {57600, _B57600},
+#endif
+#ifdef B76800
+ {76800, B76800},
+#endif
+#ifdef B115200
+ {115200, B115200},
+#endif
+#ifdef _B115200
+ {115200, _B115200},
+#endif
+#ifdef B153600
+ {153600, B153600},
+#endif
+#ifdef B230400
+ {230400, B230400},
+#endif
+#ifdef B307200
+ {307200, B307200},
+#endif
+#ifdef B460800
+ {460800, B460800},
+#endif
+#ifdef B500000
+ {500000, B500000},
+#endif
+#ifdef B576000
+ {576000, B576000},
+#endif
+#ifdef B921600
+ {921600, B921600},
+#endif
+#ifdef B1000000
+ {1000000, B1000000},
+#endif
+#ifdef B1152000
+ {1152000, B1152000},
+#endif
+#ifdef B1500000
+ {1500000,B1500000},
+#endif
+#ifdef B2000000
+ {2000000, B2000000},
+#endif
+#ifdef B2500000
+ {2500000,B2500000},
+#endif
+#ifdef B3000000
+ {3000000,B3000000},
+#endif
+#ifdef B3500000
+ {3500000,B3500000},
+#endif
+#ifdef B4000000
+ {4000000,B4000000},
+#endif
+ {-1, 0}
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TtyGetSpeed --
+ *
+ * Given an integer baud rate, get the speed_t value that should be
+ * used to select that baud rate.
+ *
+ * Results:
+ * As above.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static speed_t
+TtyGetSpeed(
+ int baud) /* The baud rate to look up. */
+{
+ int bestIdx, bestDiff, i, diff;
+
+ bestIdx = 0;
+ bestDiff = 1000000;
+
+ /*
+ * If the baud rate does not correspond to one of the known mask values,
+ * choose the mask value whose baud rate is closest to the specified baud
+ * rate.
+ */
+
+ for (i = 0; speeds[i].baud >= 0; i++) {
+ diff = speeds[i].baud - baud;
+ if (diff < 0) {
+ diff = -diff;
+ }
+ if (diff < bestDiff) {
+ bestIdx = i;
+ bestDiff = diff;
+ }
+ }
+ return speeds[bestIdx].speed;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TtyGetBaud --
+ *
+ * Return the integer baud rate corresponding to a given speed_t value.
+ *
+ * Results:
+ * As above. If the mask value was not recognized, 0 is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+TtyGetBaud(
+ speed_t speed) /* Speed mask value to look up. */
+{
+ int i;
+
+ for (i = 0; speeds[i].baud >= 0; i++) {
+ if (speeds[i].speed == speed) {
+ return speeds[i].baud;
+ }
+ }
+ return 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TtyGetAttributes --
+ *
+ * Get the current attributes of the specified serial device.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+TtyGetAttributes(
+ int fd, /* Open file descriptor for serial port to be
+ * queried. */
+ TtyAttrs *ttyPtr) /* Buffer filled with serial port
+ * attributes. */
+{
+ struct termios iostate;
+ int baud, parity, data, stop;
+
+ tcgetattr(fd, &iostate);
+
+ baud = TtyGetBaud(cfgetospeed(&iostate));
+
+ parity = 'n';
+#ifdef PAREXT
+ switch ((int) (iostate.c_cflag & (PARENB | PARODD | PAREXT))) {
+ case PARENB : parity = 'e'; break;
+ case PARENB | PARODD : parity = 'o'; break;
+ case PARENB | PAREXT : parity = 's'; break;
+ case PARENB | PARODD | PAREXT : parity = 'm'; break;
+ }
+#else /* !PAREXT */
+ switch ((int) (iostate.c_cflag & (PARENB | PARODD))) {
+ case PARENB : parity = 'e'; break;
+ case PARENB | PARODD : parity = 'o'; break;
+ }
+#endif /* PAREXT */
+
+ data = iostate.c_cflag & CSIZE;
+ data = (data == CS5) ? 5 : (data == CS6) ? 6 : (data == CS7) ? 7 : 8;
+
+ stop = (iostate.c_cflag & CSTOPB) ? 2 : 1;
+
+ ttyPtr->baud = baud;
+ ttyPtr->parity = parity;
+ ttyPtr->data = data;
+ ttyPtr->stop = stop;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TtySetAttributes --
+ *
+ * Set the current attributes of the specified serial device.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+TtySetAttributes(
+ int fd, /* Open file descriptor for serial port to be
+ * modified. */
+ TtyAttrs *ttyPtr) /* Buffer containing new attributes for serial
+ * port. */
+{
+ struct termios iostate;
+ int parity, data, flag;
+
+ tcgetattr(fd, &iostate);
+ cfsetospeed(&iostate, TtyGetSpeed(ttyPtr->baud));
+ cfsetispeed(&iostate, TtyGetSpeed(ttyPtr->baud));
+
+ flag = 0;
+ parity = ttyPtr->parity;
+ if (parity != 'n') {
+ SET_BITS(flag, PARENB);
+#ifdef PAREXT
+ CLEAR_BITS(iostate.c_cflag, PAREXT);
+ if ((parity == 'm') || (parity == 's')) {
+ SET_BITS(flag, PAREXT);
+ }
+#endif /* PAREXT */
+ if ((parity == 'm') || (parity == 'o')) {
+ SET_BITS(flag, PARODD);
+ }
+ }
+ data = ttyPtr->data;
+ SET_BITS(flag,
+ (data == 5) ? CS5 :
+ (data == 6) ? CS6 :
+ (data == 7) ? CS7 : CS8);
+ if (ttyPtr->stop == 2) {
+ SET_BITS(flag, CSTOPB);
+ }
+
+ CLEAR_BITS(iostate.c_cflag, PARENB | PARODD | CSIZE | CSTOPB);
+ SET_BITS(iostate.c_cflag, flag);
+
+ tcsetattr(fd, TCSADRAIN, &iostate);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TtyParseMode --
+ *
+ * Parse the "-mode" argument to the fconfigure command. The argument is
+ * of the form baud,parity,data,stop.
+ *
+ * Results:
+ * The return value is TCL_OK if the argument was successfully parsed,
+ * TCL_ERROR otherwise. If TCL_ERROR is returned, an error message is
+ * left in the interp's result (if interp is non-NULL).
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+TtyParseMode(
+ Tcl_Interp *interp, /* If non-NULL, interp for error return. */
+ const char *mode, /* Mode string to be parsed. */
+ TtyAttrs *ttyPtr) /* Filled with data from mode string */
+{
+ int i, end;
+ char parity;
+ const char *bad = "bad value for -mode";
+
+ i = sscanf(mode, "%d,%c,%d,%d%n",
+ &ttyPtr->baud,
+ &parity,
+ &ttyPtr->data,
+ &ttyPtr->stop, &end);
+ if ((i != 4) || (mode[end] != '\0')) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s: should be baud,parity,data,stop", bad));
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * Only allow setting mark/space parity on platforms that support it Make
+ * sure to allow for the case where strchr is a macro. [Bug: 5089]
+ *
+ * We cannot if/else/endif the strchr arguments, it has to be the whole
+ * function. On AIX this function is apparently a macro, and macros do
+ * not allow pre-processor directives in their arguments.
+ */
+
+ if (
+#if defined(PAREXT)
+ strchr("noems", parity)
+#else
+ strchr("noe", parity)
+#endif /* PAREXT */
+ == NULL) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s parity: should be %s", bad,
+#if defined(PAREXT)
+ "n, o, e, m, or s"
+#else
+ "n, o, or e"
+#endif /* PAREXT */
+ ));
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL);
+ }
+ return TCL_ERROR;
+ }
+ ttyPtr->parity = parity;
+ if ((ttyPtr->data < 5) || (ttyPtr->data > 8)) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s data: should be 5, 6, 7, or 8", bad));
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL);
+ }
+ return TCL_ERROR;
+ }
+ if ((ttyPtr->stop < 0) || (ttyPtr->stop > 2)) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "%s stop: should be 1 or 2", bad));
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL);
+ }
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TtyInit --
+ *
+ * Given file descriptor that refers to a serial port, initialize the
+ * serial port to a set of sane values so that Tcl can talk to a device
+ * located on the serial port.
+ *
+ * Side effects:
+ * Serial device initialized to non-blocking raw mode, similar to sockets
+ * All other modes can be simulated on top of this in Tcl.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+TtyInit(
+ int fd) /* Open file descriptor for serial port to be
+ * initialized. */
+{
+ struct termios iostate;
+ tcgetattr(fd, &iostate);
+
+ if (iostate.c_iflag != IGNBRK
+ || iostate.c_oflag != 0
+ || iostate.c_lflag != 0
+ || iostate.c_cflag & CREAD
+ || iostate.c_cc[VMIN] != 1
+ || iostate.c_cc[VTIME] != 0) {
+ iostate.c_iflag = IGNBRK;
+ iostate.c_oflag = 0;
+ iostate.c_lflag = 0;
+ iostate.c_cflag |= CREAD;
+ iostate.c_cc[VMIN] = 1;
+ iostate.c_cc[VTIME] = 0;
+
+ tcsetattr(fd, TCSADRAIN, &iostate);
+ }
+}
+#endif /* SUPPORTS_TTY */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpOpenFileChannel --
+ *
+ * Open an file based channel on Unix systems.
+ *
+ * Results:
+ * The new channel or NULL. If NULL, the output argument errorCodePtr is
+ * set to a POSIX error and an error message is left in the interp's
+ * result if interp is not NULL.
+ *
+ * Side effects:
+ * May open the channel and may cause creation of a file on the file
+ * system.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+TclpOpenFileChannel(
+ Tcl_Interp *interp, /* Interpreter for error reporting; can be
+ * NULL. */
+ Tcl_Obj *pathPtr, /* Name of file to open. */
+ int mode, /* POSIX open mode. */
+ int permissions) /* If the open involves creating a file, with
+ * what modes to create it? */
+{
+ int fd, channelPermissions;
+ FileState *fsPtr;
+ const char *native, *translation;
+ char channelName[16 + TCL_INTEGER_SPACE];
+ const Tcl_ChannelType *channelTypePtr;
+
+ switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
+ case O_RDONLY:
+ channelPermissions = TCL_READABLE;
+ break;
+ case O_WRONLY:
+ channelPermissions = TCL_WRITABLE;
+ break;
+ case O_RDWR:
+ channelPermissions = (TCL_READABLE | TCL_WRITABLE);
+ break;
+ default:
+ /*
+ * This may occurr if modeString was "", for example.
+ */
+
+ Tcl_Panic("TclpOpenFileChannel: invalid mode value");
+ return NULL;
+ }
+
+ native = Tcl_FSGetNativePath(pathPtr);
+ if (native == NULL) {
+ if (interp != (Tcl_Interp *) NULL) {
+ Tcl_AppendResult(interp, "couldn't open \"",
+ TclGetString(pathPtr), "\": filename is invalid on this platform",
+ NULL);
+ }
+ return NULL;
+ }
+
+#ifdef DJGPP
+ SET_BITS(mode, O_BINARY);
+#endif
+
+ fd = TclOSopen(native, mode, permissions);
+
+ if (fd < 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't open \"%s\": %s",
+ TclGetString(pathPtr), Tcl_PosixError(interp)));
+ }
+ return NULL;
+ }
+
+ /*
+ * Set close-on-exec flag on the fd so that child processes will not
+ * inherit this fd.
+ */
+
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ sprintf(channelName, "file%d", fd);
+
+#ifdef SUPPORTS_TTY
+ if (strcmp(native, "/dev/tty") != 0 && isatty(fd)) {
+ /*
+ * Initialize the serial port to a set of sane parameters. Especially
+ * important if the remote device is set to echo and the serial port
+ * driver was also set to echo -- as soon as a char were sent to the
+ * serial port, the remote device would echo it, then the serial
+ * driver would echo it back to the device, etc.
+ *
+ * Note that we do not do this if we're dealing with /dev/tty itself,
+ * as that tends to cause Bad Things To Happen when you're working
+ * interactively. Strictly a better check would be to see if the FD
+ * being set up is a device and has the same major/minor as the
+ * initial std FDs (beware reopening!) but that's nearly as messy.
+ */
+
+ translation = "auto crlf";
+ channelTypePtr = &ttyChannelType;
+ TtyInit(fd);
+ } else
+#endif /* SUPPORTS_TTY */
+ {
+ translation = NULL;
+ channelTypePtr = &fileChannelType;
+ }
+
+ fsPtr = ckalloc(sizeof(FileState));
+ fsPtr->validMask = channelPermissions | TCL_EXCEPTION;
+ fsPtr->fd = fd;
+
+ fsPtr->channel = Tcl_CreateChannel(channelTypePtr, channelName,
+ fsPtr, channelPermissions);
+
+ if (translation != NULL) {
+ /*
+ * Gotcha. Most modems need a "\r" at the end of the command sequence.
+ * If you just send "at\n", the modem will not respond with "OK"
+ * because it never got a "\r" to actually invoke the command. So, by
+ * default, newlines are translated to "\r\n" on output to avoid "bug"
+ * reports that the serial port isn't working.
+ */
+
+ if (Tcl_SetChannelOption(interp, fsPtr->channel, "-translation",
+ translation) != TCL_OK) {
+ Tcl_Close(NULL, fsPtr->channel);
+ return NULL;
+ }
+ }
+
+ return fsPtr->channel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_MakeFileChannel --
+ *
+ * Makes a Tcl_Channel from an existing OS level file handle.
+ *
+ * Results:
+ * The Tcl_Channel created around the preexisting OS level file handle.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+Tcl_MakeFileChannel(
+ ClientData handle, /* OS level handle. */
+ int mode) /* ORed combination of TCL_READABLE and
+ * TCL_WRITABLE to indicate file mode. */
+{
+ FileState *fsPtr;
+ char channelName[16 + TCL_INTEGER_SPACE];
+ int fd = PTR2INT(handle);
+ const Tcl_ChannelType *channelTypePtr;
+ struct sockaddr sockaddr;
+ socklen_t sockaddrLen = sizeof(sockaddr);
+
+ if (mode == 0) {
+ return NULL;
+ }
+
+ sockaddr.sa_family = AF_UNSPEC;
+
+#ifdef SUPPORTS_TTY
+ if (isatty(fd)) {
+ channelTypePtr = &ttyChannelType;
+ sprintf(channelName, "serial%d", fd);
+ } else
+#endif /* SUPPORTS_TTY */
+ if ((getsockname(fd, (struct sockaddr *)&sockaddr, &sockaddrLen) == 0)
+ && (sockaddrLen > 0)
+ && (sockaddr.sa_family == AF_INET || sockaddr.sa_family == AF_INET6)) {
+ return TclpMakeTcpClientChannelMode(INT2PTR(fd), mode);
+ } else {
+ channelTypePtr = &fileChannelType;
+ sprintf(channelName, "file%d", fd);
+ }
+
+ fsPtr = ckalloc(sizeof(FileState));
+ fsPtr->fd = fd;
+ fsPtr->validMask = mode | TCL_EXCEPTION;
+ fsPtr->channel = Tcl_CreateChannel(channelTypePtr, channelName,
+ fsPtr, mode);
+
+ return fsPtr->channel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGetDefaultStdChannel --
+ *
+ * Creates channels for standard input, standard output or standard error
+ * output if they do not already exist.
+ *
+ * Results:
+ * Returns the specified default standard channel, or NULL.
+ *
+ * Side effects:
+ * May cause the creation of a standard channel and the underlying file.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+TclpGetDefaultStdChannel(
+ int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */
+{
+ Tcl_Channel channel = NULL;
+ int fd = 0; /* Initializations needed to prevent */
+ int mode = 0; /* compiler warning (used before set). */
+ const char *bufMode = NULL;
+
+ /*
+ * Some #def's to make the code a little clearer!
+ */
+
+#define ZERO_OFFSET ((Tcl_SeekOffset) 0)
+#define ERROR_OFFSET ((Tcl_SeekOffset) -1)
+
+ switch (type) {
+ case TCL_STDIN:
+ if ((TclOSseek(0, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
+ && (errno == EBADF)) {
+ return NULL;
+ }
+ fd = 0;
+ mode = TCL_READABLE;
+ bufMode = "line";
+ break;
+ case TCL_STDOUT:
+ if ((TclOSseek(1, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
+ && (errno == EBADF)) {
+ return NULL;
+ }
+ fd = 1;
+ mode = TCL_WRITABLE;
+ bufMode = "line";
+ break;
+ case TCL_STDERR:
+ if ((TclOSseek(2, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET)
+ && (errno == EBADF)) {
+ return NULL;
+ }
+ fd = 2;
+ mode = TCL_WRITABLE;
+ bufMode = "none";
+ break;
+ default:
+ Tcl_Panic("TclGetDefaultStdChannel: Unexpected channel type");
+ break;
+ }
+
+#undef ZERO_OFFSET
+#undef ERROR_OFFSET
+
+ channel = Tcl_MakeFileChannel(INT2PTR(fd), mode);
+ if (channel == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Set up the normal channel options for stdio handles.
+ */
+
+ if (Tcl_GetChannelType(channel) == &fileChannelType) {
+ Tcl_SetChannelOption(NULL, channel, "-translation", "auto");
+ } else {
+ Tcl_SetChannelOption(NULL, channel, "-translation", "auto crlf");
+ }
+ Tcl_SetChannelOption(NULL, channel, "-buffering", bufMode);
+ return channel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetOpenFile --
+ *
+ * Given a name of a channel registered in the given interpreter, returns
+ * a FILE * for it.
+ *
+ * Results:
+ * A standard Tcl result. If the channel is registered in the given
+ * interpreter and it is managed by the "file" channel driver, and it is
+ * open for the requested mode, then the output parameter filePtr is set
+ * to a FILE * for the underlying file. On error, the filePtr is not set,
+ * TCL_ERROR is returned and an error message is left in the interp's
+ * result.
+ *
+ * Side effects:
+ * May invoke fdopen to create the FILE * for the requested file.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetOpenFile(
+ Tcl_Interp *interp, /* Interpreter in which to find file. */
+ const char *chanID, /* String that identifies file. */
+ int forWriting, /* 1 means the file is going to be used for
+ * writing, 0 means for reading. */
+ int checkUsage, /* 1 means verify that the file was opened in
+ * a mode that allows the access specified by
+ * "forWriting". Ignored, we always check that
+ * the channel is open for the requested
+ * mode. */
+ ClientData *filePtr) /* Store pointer to FILE structure here. */
+{
+ Tcl_Channel chan;
+ int chanMode, fd;
+ const Tcl_ChannelType *chanTypePtr;
+ ClientData data;
+ FILE *f;
+
+ chan = Tcl_GetChannel(interp, chanID, &chanMode);
+ if (chan == NULL) {
+ return TCL_ERROR;
+ }
+ if (forWriting && !(chanMode & TCL_WRITABLE)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "\"%s\" wasn't opened for writing", chanID));
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "CHANNEL", "NOT_WRITABLE",
+ NULL);
+ return TCL_ERROR;
+ } else if (!forWriting && !(chanMode & TCL_READABLE)) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "\"%s\" wasn't opened for reading", chanID));
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "CHANNEL", "NOT_READABLE",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * We allow creating a FILE * out of file based, pipe based and socket
+ * based channels. We currently do not allow any other channel types,
+ * because it is likely that stdio will not know what to do with them.
+ */
+
+ chanTypePtr = Tcl_GetChannelType(chan);
+ if ((chanTypePtr == &fileChannelType)
+#ifdef SUPPORTS_TTY
+ || (chanTypePtr == &ttyChannelType)
+#endif /* SUPPORTS_TTY */
+ || (strcmp(chanTypePtr->typeName, "tcp") == 0)
+ || (strcmp(chanTypePtr->typeName, "pipe") == 0)) {
+ if (Tcl_GetChannelHandle(chan,
+ (forWriting ? TCL_WRITABLE : TCL_READABLE), &data) == TCL_OK) {
+ fd = PTR2INT(data);
+
+ /*
+ * The call to fdopen below is probably dangerous, since it will
+ * truncate an existing file if the file is being opened for
+ * writing....
+ */
+
+ f = fdopen(fd, (forWriting ? "w" : "r"));
+ if (f == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "cannot get a FILE * for \"%s\"", chanID));
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "CHANNEL",
+ "FILE_FAILURE", NULL);
+ return TCL_ERROR;
+ }
+ *filePtr = f;
+ return TCL_OK;
+ }
+ }
+
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "\"%s\" cannot be used to get a FILE *", chanID));
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "CHANNEL", "NO_DESCRIPTOR",
+ NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileTruncateProc --
+ *
+ * Truncates a file to a given length.
+ *
+ * Results:
+ * 0 if the operation succeeded, and -1 if it failed (in which case
+ * *errorCodePtr will be set to errno).
+ *
+ * Side effects:
+ * The underlying file is potentially truncated. This can have a wide
+ * variety of side effects, including moving file pointers that point at
+ * places later in the file than the truncate point.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileTruncateProc(
+ ClientData instanceData,
+ Tcl_WideInt length)
+{
+ FileState *fsPtr = instanceData;
+ int result;
+
+#ifdef HAVE_TYPE_OFF64_T
+ /*
+ * We assume this goes with the type for now...
+ */
+
+ result = ftruncate64(fsPtr->fd, (off64_t) length);
+#else
+ result = ftruncate(fsPtr->fd, (off_t) length);
+#endif
+ if (result) {
+ return errno;
+ }
+ return 0;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixCompat.c b/unix/tclUnixCompat.c
new file mode 100644
index 0000000..ea6067e
--- /dev/null
+++ b/unix/tclUnixCompat.c
@@ -0,0 +1,1022 @@
+/*
+ * tclUnixCompat.c
+ *
+ * Written by: Zoran Vasiljevic (vasiljevic@users.sourceforge.net).
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <string.h>
+
+/*
+ * See also: SC_BLOCKING_STYLE in unix/tcl.m4
+ */
+
+#ifdef USE_FIONBIO
+# ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h> /* For FIONBIO. */
+# endif
+# ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+# endif
+#endif /* USE_FIONBIO */
+
+/*
+ * Used to pad structures at size'd boundaries
+ *
+ * This macro assumes that the pointer 'buffer' was created from an aligned
+ * pointer by adding the 'length'. If this 'length' was not a multiple of the
+ * 'size' the result is unaligned and PadBuffer corrects both the pointer,
+ * _and_ the 'length'. The latter means that future increments of 'buffer' by
+ * 'length' stay aligned.
+ */
+
+#define PadBuffer(buffer, length, size) \
+ if (((length) % (size))) { \
+ (buffer) += ((size) - ((length) % (size))); \
+ (length) += ((size) - ((length) % (size))); \
+ }
+
+/*
+ * Per-thread private storage used to store values returned from MT-unsafe
+ * library calls.
+ */
+
+#ifdef TCL_THREADS
+
+typedef struct {
+ struct passwd pwd;
+#if defined(HAVE_GETPWNAM_R_5) || defined(HAVE_GETPWUID_R_5)
+#define NEED_PW_CLEANER 1
+ char *pbuf;
+ int pbuflen;
+#else
+ char pbuf[2048];
+#endif
+
+ struct group grp;
+#if defined(HAVE_GETGRNAM_R_5) || defined(HAVE_GETGRGID_R_5)
+#define NEED_GR_CLEANER 1
+ char *gbuf;
+ int gbuflen;
+#else
+ char gbuf[2048];
+#endif
+
+#if !defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR)
+ struct hostent hent;
+ char hbuf[2048];
+#endif
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+#if ((!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \
+ (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || \
+ !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \
+ !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || \
+ !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R)
+/*
+ * Mutex to lock access to MT-unsafe calls. This is just to protect our own
+ * usage. It does not protect us from others calling the same functions
+ * without (or using some different) lock.
+ */
+
+static Tcl_Mutex compatLock;
+
+/*
+ * Helper function declarations. Note that these are only used if needed and
+ * only defined if used (via the NEED_* macros).
+ */
+
+#undef NEED_COPYARRAY
+#undef NEED_COPYGRP
+#undef NEED_COPYHOSTENT
+#undef NEED_COPYPWD
+#undef NEED_COPYSTRING
+
+#if !defined(HAVE_GETGRNAM_R_5) && !defined(HAVE_GETGRNAM_R_4)
+#define NEED_COPYGRP 1
+static int CopyGrp(struct group *tgtPtr, char *buf, int buflen);
+#endif
+
+#if !defined(HAVE_GETPWNAM_R_5) && !defined(HAVE_GETPWNAM_R_4)
+#define NEED_COPYPWD 1
+static int CopyPwd(struct passwd *tgtPtr, char *buf, int buflen);
+#endif
+
+static int CopyArray(char **src, int elsize, char *buf,
+ int buflen);
+static int CopyHostent(struct hostent *tgtPtr, char *buf,
+ int buflen);
+static int CopyString(const char *src, char *buf, int buflen);
+
+#endif
+
+#ifdef NEED_PW_CLEANER
+static void FreePwBuf(ClientData ignored);
+#endif
+#ifdef NEED_GR_CLEANER
+static void FreeGrBuf(ClientData ignored);
+#endif
+#endif /* TCL_THREADS */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclUnixSetBlockingMode --
+ *
+ * Set the blocking mode of a file descriptor.
+ *
+ * Results:
+ *
+ * 0 on success, -1 (with errno set) on error.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclUnixSetBlockingMode(
+ int fd, /* File descriptor */
+ int mode) /* Either TCL_MODE_BLOCKING or
+ * TCL_MODE_NONBLOCKING. */
+{
+#ifndef USE_FIONBIO
+ int flags = fcntl(fd, F_GETFL);
+
+ if (mode == TCL_MODE_BLOCKING) {
+ flags &= ~O_NONBLOCK;
+ } else {
+ flags |= O_NONBLOCK;
+ }
+ return fcntl(fd, F_SETFL, flags);
+#else /* USE_FIONBIO */
+ int state = (mode == TCL_MODE_NONBLOCKING);
+
+ return ioctl(fd, FIONBIO, &state);
+#endif /* !USE_FIONBIO */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpGetPwNam --
+ *
+ * Thread-safe wrappers for getpwnam(). See "man getpwnam" for more
+ * details.
+ *
+ * Results:
+ * Pointer to struct passwd on success or NULL on error.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+struct passwd *
+TclpGetPwNam(
+ const char *name)
+{
+#if !defined(TCL_THREADS)
+ return getpwnam(name);
+#else
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+#if defined(HAVE_GETPWNAM_R_5)
+ struct passwd *pwPtr = NULL;
+
+ /*
+ * How to allocate a buffer of the right initial size. If you want the
+ * gory detail, see http://www.opengroup.org/austin/docs/austin_328.txt
+ * and weep.
+ */
+
+ if (tsdPtr->pbuf == NULL) {
+ tsdPtr->pbuflen = (int) sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (tsdPtr->pbuflen < 1) {
+ tsdPtr->pbuflen = 1024;
+ }
+ tsdPtr->pbuf = ckalloc(tsdPtr->pbuflen);
+ Tcl_CreateThreadExitHandler(FreePwBuf, NULL);
+ }
+ while (1) {
+ int e = getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, tsdPtr->pbuflen,
+ &pwPtr);
+
+ if (e == 0) {
+ break;
+ } else if (e != ERANGE) {
+ return NULL;
+ }
+ tsdPtr->pbuflen *= 2;
+ tsdPtr->pbuf = ckrealloc(tsdPtr->pbuf, tsdPtr->pbuflen);
+ }
+ return (pwPtr != NULL ? &tsdPtr->pwd : NULL);
+
+#elif defined(HAVE_GETPWNAM_R_4)
+ return getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf));
+
+#else
+ struct passwd *pwPtr;
+
+ Tcl_MutexLock(&compatLock);
+ pwPtr = getpwnam(name);
+ if (pwPtr != NULL) {
+ tsdPtr->pwd = *pwPtr;
+ pwPtr = &tsdPtr->pwd;
+ if (CopyPwd(&tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)) == -1) {
+ pwPtr = NULL;
+ }
+ }
+ Tcl_MutexUnlock(&compatLock);
+ return pwPtr;
+#endif
+
+ return NULL; /* Not reached. */
+#endif /* TCL_THREADS */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpGetPwUid --
+ *
+ * Thread-safe wrappers for getpwuid(). See "man getpwuid" for more
+ * details.
+ *
+ * Results:
+ * Pointer to struct passwd on success or NULL on error.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+struct passwd *
+TclpGetPwUid(
+ uid_t uid)
+{
+#if !defined(TCL_THREADS)
+ return getpwuid(uid);
+#else
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+#if defined(HAVE_GETPWUID_R_5)
+ struct passwd *pwPtr = NULL;
+
+ /*
+ * How to allocate a buffer of the right initial size. If you want the
+ * gory detail, see http://www.opengroup.org/austin/docs/austin_328.txt
+ * and weep.
+ */
+
+ if (tsdPtr->pbuf == NULL) {
+ tsdPtr->pbuflen = (int) sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (tsdPtr->pbuflen < 1) {
+ tsdPtr->pbuflen = 1024;
+ }
+ tsdPtr->pbuf = ckalloc(tsdPtr->pbuflen);
+ Tcl_CreateThreadExitHandler(FreePwBuf, NULL);
+ }
+ while (1) {
+ int e = getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, tsdPtr->pbuflen,
+ &pwPtr);
+
+ if (e == 0) {
+ break;
+ } else if (e != ERANGE) {
+ return NULL;
+ }
+ tsdPtr->pbuflen *= 2;
+ tsdPtr->pbuf = ckrealloc(tsdPtr->pbuf, tsdPtr->pbuflen);
+ }
+ return (pwPtr != NULL ? &tsdPtr->pwd : NULL);
+
+#elif defined(HAVE_GETPWUID_R_4)
+ return getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf));
+
+#else
+ struct passwd *pwPtr;
+
+ Tcl_MutexLock(&compatLock);
+ pwPtr = getpwuid(uid);
+ if (pwPtr != NULL) {
+ tsdPtr->pwd = *pwPtr;
+ pwPtr = &tsdPtr->pwd;
+ if (CopyPwd(&tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)) == -1) {
+ pwPtr = NULL;
+ }
+ }
+ Tcl_MutexUnlock(&compatLock);
+ return pwPtr;
+#endif
+
+ return NULL; /* Not reached. */
+#endif /* TCL_THREADS */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreePwBuf --
+ *
+ * Helper that is used to dispose of space allocated and referenced from
+ * the ThreadSpecificData for user entries. (Darn that baroque POSIX
+ * reentrant interface.)
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_PW_CLEANER
+static void
+FreePwBuf(
+ ClientData ignored)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ ckfree(tsdPtr->pbuf);
+}
+#endif /* NEED_PW_CLEANER */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpGetGrNam --
+ *
+ * Thread-safe wrappers for getgrnam(). See "man getgrnam" for more
+ * details.
+ *
+ * Results:
+ * Pointer to struct group on success or NULL on error.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+struct group *
+TclpGetGrNam(
+ const char *name)
+{
+#if !defined(TCL_THREADS)
+ return getgrnam(name);
+#else
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+#if defined(HAVE_GETGRNAM_R_5)
+ struct group *grPtr = NULL;
+
+ /*
+ * How to allocate a buffer of the right initial size. If you want the
+ * gory detail, see http://www.opengroup.org/austin/docs/austin_328.txt
+ * and weep.
+ */
+
+ if (tsdPtr->gbuf == NULL) {
+ tsdPtr->gbuflen = (int) sysconf(_SC_GETGR_R_SIZE_MAX);
+ if (tsdPtr->gbuflen < 1) {
+ tsdPtr->gbuflen = 1024;
+ }
+ tsdPtr->gbuf = ckalloc(tsdPtr->gbuflen);
+ Tcl_CreateThreadExitHandler(FreeGrBuf, NULL);
+ }
+ while (1) {
+ int e = getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, tsdPtr->gbuflen,
+ &grPtr);
+
+ if (e == 0) {
+ break;
+ } else if (e != ERANGE) {
+ return NULL;
+ }
+ tsdPtr->gbuflen *= 2;
+ tsdPtr->gbuf = ckrealloc(tsdPtr->gbuf, tsdPtr->gbuflen);
+ }
+ return (grPtr != NULL ? &tsdPtr->grp : NULL);
+
+#elif defined(HAVE_GETGRNAM_R_4)
+ return getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf));
+
+#else
+ struct group *grPtr;
+
+ Tcl_MutexLock(&compatLock);
+ grPtr = getgrnam(name);
+ if (grPtr != NULL) {
+ tsdPtr->grp = *grPtr;
+ grPtr = &tsdPtr->grp;
+ if (CopyGrp(&tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)) == -1) {
+ grPtr = NULL;
+ }
+ }
+ Tcl_MutexUnlock(&compatLock);
+ return grPtr;
+#endif
+
+ return NULL; /* Not reached. */
+#endif /* TCL_THREADS */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpGetGrGid --
+ *
+ * Thread-safe wrappers for getgrgid(). See "man getgrgid" for more
+ * details.
+ *
+ * Results:
+ * Pointer to struct group on success or NULL on error.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+struct group *
+TclpGetGrGid(
+ gid_t gid)
+{
+#if !defined(TCL_THREADS)
+ return getgrgid(gid);
+#else
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+#if defined(HAVE_GETGRGID_R_5)
+ struct group *grPtr = NULL;
+
+ /*
+ * How to allocate a buffer of the right initial size. If you want the
+ * gory detail, see http://www.opengroup.org/austin/docs/austin_328.txt
+ * and weep.
+ */
+
+ if (tsdPtr->gbuf == NULL) {
+ tsdPtr->gbuflen = (int) sysconf(_SC_GETGR_R_SIZE_MAX);
+ if (tsdPtr->gbuflen < 1) {
+ tsdPtr->gbuflen = 1024;
+ }
+ tsdPtr->gbuf = ckalloc(tsdPtr->gbuflen);
+ Tcl_CreateThreadExitHandler(FreeGrBuf, NULL);
+ }
+ while (1) {
+ int e = getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, tsdPtr->gbuflen,
+ &grPtr);
+
+ if (e == 0) {
+ break;
+ } else if (e != ERANGE) {
+ return NULL;
+ }
+ tsdPtr->gbuflen *= 2;
+ tsdPtr->gbuf = ckrealloc(tsdPtr->gbuf, tsdPtr->gbuflen);
+ }
+ return (grPtr != NULL ? &tsdPtr->grp : NULL);
+
+#elif defined(HAVE_GETGRGID_R_4)
+ return getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf));
+
+#else
+ struct group *grPtr;
+
+ Tcl_MutexLock(&compatLock);
+ grPtr = getgrgid(gid);
+ if (grPtr != NULL) {
+ tsdPtr->grp = *grPtr;
+ grPtr = &tsdPtr->grp;
+ if (CopyGrp(&tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)) == -1) {
+ grPtr = NULL;
+ }
+ }
+ Tcl_MutexUnlock(&compatLock);
+ return grPtr;
+#endif
+
+ return NULL; /* Not reached. */
+#endif /* TCL_THREADS */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeGrBuf --
+ *
+ * Helper that is used to dispose of space allocated and referenced from
+ * the ThreadSpecificData for group entries. (Darn that baroque POSIX
+ * reentrant interface.)
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_GR_CLEANER
+static void
+FreeGrBuf(
+ ClientData ignored)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ ckfree(tsdPtr->gbuf);
+}
+#endif /* NEED_GR_CLEANER */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpGetHostByName --
+ *
+ * Thread-safe wrappers for gethostbyname(). See "man gethostbyname" for
+ * more details.
+ *
+ * Results:
+ * Pointer to struct hostent on success or NULL on error.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+struct hostent *
+TclpGetHostByName(
+ const char *name)
+{
+#if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYNAME)
+ return gethostbyname(name);
+#else
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+#if defined(HAVE_GETHOSTBYNAME_R_5)
+ int h_errno;
+
+ return gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
+ sizeof(tsdPtr->hbuf), &h_errno);
+
+#elif defined(HAVE_GETHOSTBYNAME_R_6)
+ struct hostent *hePtr = NULL;
+ int h_errno, result;
+
+ result = gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
+ sizeof(tsdPtr->hbuf), &hePtr, &h_errno);
+ return (result == 0) ? hePtr : NULL;
+
+#elif defined(HAVE_GETHOSTBYNAME_R_3)
+ struct hostent_data data;
+
+ return (gethostbyname_r(name, &tsdPtr->hent, &data) == 0)
+ ? &tsdPtr->hent : NULL;
+
+#else
+#define NEED_COPYHOSTENT 1
+ struct hostent *hePtr;
+
+ Tcl_MutexLock(&compatLock);
+ hePtr = gethostbyname(name);
+ if (hePtr != NULL) {
+ tsdPtr->hent = *hePtr;
+ hePtr = &tsdPtr->hent;
+ if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf,
+ sizeof(tsdPtr->hbuf)) == -1) {
+ hePtr = NULL;
+ }
+ }
+ Tcl_MutexUnlock(&compatLock);
+ return hePtr;
+#endif
+
+ return NULL; /* Not reached. */
+#endif /* TCL_THREADS */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpGetHostByAddr --
+ *
+ * Thread-safe wrappers for gethostbyaddr(). See "man gethostbyaddr" for
+ * more details.
+ *
+ * Results:
+ * Pointer to struct hostent on success or NULL on error.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+struct hostent *
+TclpGetHostByAddr(
+ const char *addr,
+ int length,
+ int type)
+{
+#if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYADDR)
+ return gethostbyaddr(addr, length, type);
+#else
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+#if defined(HAVE_GETHOSTBYADDR_R_7)
+ int h_errno;
+
+ return gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
+ sizeof(tsdPtr->hbuf), &h_errno);
+
+#elif defined(HAVE_GETHOSTBYADDR_R_8)
+ struct hostent *hePtr;
+ int h_errno;
+
+ return (gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
+ sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0)
+ ? &tsdPtr->hent : NULL;
+#else
+#define NEED_COPYHOSTENT 1
+ struct hostent *hePtr;
+
+ Tcl_MutexLock(&compatLock);
+ hePtr = gethostbyaddr(addr, length, type);
+ if (hePtr != NULL) {
+ tsdPtr->hent = *hePtr;
+ hePtr = &tsdPtr->hent;
+ if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf,
+ sizeof(tsdPtr->hbuf)) == -1) {
+ hePtr = NULL;
+ }
+ }
+ Tcl_MutexUnlock(&compatLock);
+ return hePtr;
+#endif
+
+ return NULL; /* Not reached. */
+#endif /* TCL_THREADS */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyGrp --
+ *
+ * Copies string fields of the group structure to the private buffer,
+ * honouring the size of the buffer.
+ *
+ * Results:
+ * 0 on success or -1 on error (errno = ERANGE).
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYGRP
+#define NEED_COPYARRAY 1
+#define NEED_COPYSTRING 1
+
+static int
+CopyGrp(
+ struct group *tgtPtr,
+ char *buf,
+ int buflen)
+{
+ register char *p = buf;
+ register int copied, len = 0;
+
+ /*
+ * Copy username.
+ */
+
+ copied = CopyString(tgtPtr->gr_name, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->gr_name = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ /*
+ * Copy password.
+ */
+
+ copied = CopyString(tgtPtr->gr_passwd, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->gr_passwd = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ /*
+ * Copy group members.
+ */
+
+ PadBuffer(p, len, sizeof(char *));
+ copied = CopyArray((char **)tgtPtr->gr_mem, -1, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->gr_mem = (copied > 0) ? (char **)p : NULL;
+
+ return 0;
+
+ range:
+ errno = ERANGE;
+ return -1;
+}
+#endif /* NEED_COPYGRP */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyHostent --
+ *
+ * Copies string fields of the hostnent structure to the private buffer,
+ * honouring the size of the buffer.
+ *
+ * Results:
+ * Number of bytes copied on success or -1 on error (errno = ERANGE)
+ *
+ * Side effects:
+ * None
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYHOSTENT
+#define NEED_COPYSTRING 1
+#define NEED_COPYARRAY 1
+
+static int
+CopyHostent(
+ struct hostent *tgtPtr,
+ char *buf,
+ int buflen)
+{
+ char *p = buf;
+ int copied, len = 0;
+
+ copied = CopyString(tgtPtr->h_name, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->h_name = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ PadBuffer(p, len, sizeof(char *));
+ copied = CopyArray(tgtPtr->h_aliases, -1, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->h_aliases = (copied > 0) ? (char **)p : NULL;
+ len += copied;
+ p += len;
+
+ PadBuffer(p, len, sizeof(char *));
+ copied = CopyArray(tgtPtr->h_addr_list, tgtPtr->h_length, p, buflen-len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->h_addr_list = (copied > 0) ? (char **)p : NULL;
+
+ return 0;
+
+ range:
+ errno = ERANGE;
+ return -1;
+}
+#endif /* NEED_COPYHOSTENT */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyPwd --
+ *
+ * Copies string fields of the passwd structure to the private buffer,
+ * honouring the size of the buffer.
+ *
+ * Results:
+ * 0 on success or -1 on error (errno = ERANGE).
+ *
+ * Side effects:
+ * We are not copying the gecos field as it may not be supported on all
+ * platforms.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYPWD
+#define NEED_COPYSTRING 1
+
+static int
+CopyPwd(
+ struct passwd *tgtPtr,
+ char *buf,
+ int buflen)
+{
+ char *p = buf;
+ int copied, len = 0;
+
+ copied = CopyString(tgtPtr->pw_name, p, buflen - len);
+ if (copied == -1) {
+ range:
+ errno = ERANGE;
+ return -1;
+ }
+ tgtPtr->pw_name = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ copied = CopyString(tgtPtr->pw_passwd, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->pw_passwd = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ copied = CopyString(tgtPtr->pw_dir, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->pw_dir = (copied > 0) ? p : NULL;
+ len += copied;
+ p = buf + len;
+
+ copied = CopyString(tgtPtr->pw_shell, p, buflen - len);
+ if (copied == -1) {
+ goto range;
+ }
+ tgtPtr->pw_shell = (copied > 0) ? p : NULL;
+
+ return 0;
+}
+#endif /* NEED_COPYPWD */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyArray --
+ *
+ * Copies array of NULL-terminated or fixed-length strings to the private
+ * buffer, honouring the size of the buffer.
+ *
+ * Results:
+ * Number of bytes copied on success or -1 on error (errno = ERANGE)
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYARRAY
+static int
+CopyArray(
+ char **src, /* Array of elements to copy. */
+ int elsize, /* Size of each element, or -1 to indicate
+ * that they are C strings of dynamic
+ * length. */
+ char *buf, /* Buffer to copy into. */
+ int buflen) /* Size of buffer. */
+{
+ int i, j, len = 0;
+ char *p, **new;
+
+ if (src == NULL) {
+ return 0;
+ }
+
+ for (i = 0; src[i] != NULL; i++) {
+ /*
+ * Empty loop to count how many.
+ */
+ }
+ len = sizeof(char *) * (i + 1); /* Leave place for the array. */
+ if (len > buflen) {
+ return -1;
+ }
+
+ new = (char **) buf;
+ p = buf + len;
+
+ for (j = 0; j < i; j++) {
+ int sz = (elsize<0 ? (int) strlen(src[j]) + 1 : elsize);
+
+ len += sz;
+ if (len > buflen) {
+ return -1;
+ }
+ memcpy(p, src[j], sz);
+ new[j] = p;
+ p = buf + len;
+ }
+ new[j] = NULL;
+
+ return len;
+}
+#endif /* NEED_COPYARRAY */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyString --
+ *
+ * Copies a NULL-terminated string to the private buffer, honouring the
+ * size of the buffer
+ *
+ * Results:
+ * 0 success or -1 on error (errno = ERANGE)
+ *
+ * Side effects:
+ * None
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NEED_COPYSTRING
+static int
+CopyString(
+ const char *src, /* String to copy. */
+ char *buf, /* Buffer to copy into. */
+ int buflen) /* Size of buffer. */
+{
+ int len = 0;
+
+ if (src != NULL) {
+ len = strlen(src) + 1;
+ if (len > buflen) {
+ return -1;
+ }
+ memcpy(buf, src, len);
+ }
+
+ return len;
+}
+#endif /* NEED_COPYSTRING */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * TclWinCPUID --
+ *
+ * Get CPU ID information on an Intel box under UNIX (either Linux or Cygwin)
+ *
+ * Results:
+ * Returns TCL_OK if successful, TCL_ERROR if CPUID is not supported.
+ *
+ * Side effects:
+ * If successful, stores EAX, EBX, ECX and EDX registers after the CPUID
+ * instruction in the four integers designated by 'regsPtr'
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclWinCPUID(
+ int index, /* Which CPUID value to retrieve. */
+ int *regsPtr) /* Registers after the CPUID. */
+{
+ int status = TCL_ERROR;
+
+ /* See: <http://en.wikipedia.org/wiki/CPUID> */
+#if defined(HAVE_CPUID)
+#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
+ __asm__ __volatile__("movq %%rbx, %%rsi \n\t" /* save %rbx */
+ "cpuid \n\t"
+ "xchgq %%rsi, %%rbx \n\t" /* restore the old %rbx */
+ : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
+ : "a"(index));
+#else
+ __asm__ __volatile__("mov %%ebx, %%esi \n\t" /* save %ebx */
+ "cpuid \n\t"
+ "xchg %%esi, %%ebx \n\t" /* restore the old %ebx */
+ : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
+ : "a"(index));
+#endif
+ status = TCL_OK;
+#endif
+ return status;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixEvent.c b/unix/tclUnixEvent.c
new file mode 100644
index 0000000..40aac6f
--- /dev/null
+++ b/unix/tclUnixEvent.c
@@ -0,0 +1,95 @@
+/*
+ * tclUnixEvent.c --
+ *
+ * This file implements Unix specific event related routines.
+ *
+ * Copyright (c) 1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
+ * in tclMacOSXNotify.c */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_Sleep --
+ *
+ * Delay execution for the specified number of milliseconds.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Time passes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_Sleep(
+ int ms) /* Number of milliseconds to sleep. */
+{
+ struct timeval delay;
+ Tcl_Time before, after, vdelay;
+
+ /*
+ * The only trick here is that select appears to return early under some
+ * conditions, so we have to check to make sure that the right amount of
+ * time really has elapsed. If it's too early, go back to sleep again.
+ */
+
+ Tcl_GetTime(&before);
+ after = before;
+ after.sec += ms/1000;
+ after.usec += (ms%1000)*1000;
+ if (after.usec > 1000000) {
+ after.usec -= 1000000;
+ after.sec += 1;
+ }
+ while (1) {
+ /*
+ * TIP #233: Scale from virtual time to real-time for select.
+ */
+
+ vdelay.sec = after.sec - before.sec;
+ vdelay.usec = after.usec - before.usec;
+
+ if (vdelay.usec < 0) {
+ vdelay.usec += 1000000;
+ vdelay.sec -= 1;
+ }
+
+ if ((vdelay.sec != 0) || (vdelay.usec != 0)) {
+ tclScaleTimeProcPtr(&vdelay, tclTimeClientData);
+ }
+
+ delay.tv_sec = vdelay.sec;
+ delay.tv_usec = vdelay.usec;
+
+ /*
+ * Special note: must convert delay.tv_sec to int before comparing to
+ * zero, since delay.tv_usec is unsigned on some platforms.
+ */
+
+ if ((((int) delay.tv_sec) < 0)
+ || ((delay.tv_usec == 0) && (delay.tv_sec == 0))) {
+ break;
+ }
+ (void) select(0, (SELECT_MASK *) 0, (SELECT_MASK *) 0,
+ (SELECT_MASK *) 0, &delay);
+ Tcl_GetTime(&before);
+ }
+}
+
+#endif /* HAVE_COREFOUNDATION */
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c
new file mode 100644
index 0000000..e156f77
--- /dev/null
+++ b/unix/tclUnixFCmd.c
@@ -0,0 +1,2515 @@
+/*
+ * tclUnixFCmd.c
+ *
+ * This file implements the unix specific portion of file manipulation
+ * subcommands of the "file" command. All filename arguments should
+ * already be translated to native format.
+ *
+ * Copyright (c) 1996-1998 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Portions of this code were derived from NetBSD source code which has the
+ * following copyright notice:
+ *
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include "tclInt.h"
+#include <utime.h>
+#include <grp.h>
+#ifndef HAVE_STRUCT_STAT_ST_BLKSIZE
+#ifndef NO_FSTATFS
+#include <sys/statfs.h>
+#endif
+#endif /* !HAVE_STRUCT_STAT_ST_BLKSIZE */
+#ifdef HAVE_FTS
+#include <fts.h>
+#endif
+
+/*
+ * The following constants specify the type of callback when
+ * TraverseUnixTree() calls the traverseProc()
+ */
+
+#define DOTREE_PRED 1 /* pre-order directory */
+#define DOTREE_POSTD 2 /* post-order directory */
+#define DOTREE_F 3 /* regular file */
+
+/*
+ * Fallback temporary file location the temporary file generation code. Can be
+ * overridden at compile time for when it is known that temp files can't be
+ * written to /tmp (hello, iOS!).
+ */
+
+#ifndef TCL_TEMPORARY_FILE_DIRECTORY
+#define TCL_TEMPORARY_FILE_DIRECTORY "/tmp"
+#endif
+
+/*
+ * Callbacks for file attributes code.
+ */
+
+static int GetGroupAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr);
+static int GetOwnerAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr);
+static int GetPermissionsAttribute(Tcl_Interp *interp,
+ int objIndex, Tcl_Obj *fileName,
+ Tcl_Obj **attributePtrPtr);
+static int SetGroupAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj *attributePtr);
+static int SetOwnerAttribute(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj *attributePtr);
+static int SetPermissionsAttribute(Tcl_Interp *interp,
+ int objIndex, Tcl_Obj *fileName,
+ Tcl_Obj *attributePtr);
+static int GetModeFromPermString(Tcl_Interp *interp,
+ const char *modeStringPtr, mode_t *modePtr);
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) || defined(__CYGWIN__)
+static int GetUnixFileAttributes(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr);
+static int SetUnixFileAttributes(Tcl_Interp *interp, int objIndex,
+ Tcl_Obj *fileName, Tcl_Obj *attributePtr);
+#endif
+
+/*
+ * Prototype for the TraverseUnixTree callback function.
+ */
+
+typedef int (TraversalProc)(Tcl_DString *srcPtr, Tcl_DString *dstPtr,
+ const Tcl_StatBuf *statBufPtr, int type, Tcl_DString *errorPtr);
+
+/*
+ * Constants and variables necessary for file attributes subcommand.
+ *
+ * IMPORTANT: The permissions attribute is assumed to be the third item (i.e.
+ * to be indexed with '2' in arrays) in code in tclIOUtil.c and possibly
+ * elsewhere in Tcl's core.
+ */
+
+#ifdef DJGPP
+
+/*
+ * See contrib/djgpp/tclDjgppFCmd.c for definition.
+ */
+
+extern TclFileAttrProcs tclpFileAttrProcs[];
+extern const char *const tclpFileAttrStrings[];
+
+#else /* !DJGPP */
+enum {
+#if defined(__CYGWIN__)
+ UNIX_ARCHIVE_ATTRIBUTE,
+#endif
+ UNIX_GROUP_ATTRIBUTE,
+#if defined(__CYGWIN__)
+ UNIX_HIDDEN_ATTRIBUTE,
+#endif
+ UNIX_OWNER_ATTRIBUTE, UNIX_PERMISSIONS_ATTRIBUTE,
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) || defined(__CYGWIN__)
+ UNIX_READONLY_ATTRIBUTE,
+#endif
+#if defined(__CYGWIN__)
+ UNIX_SYSTEM_ATTRIBUTE,
+#endif
+#ifdef MAC_OSX_TCL
+ MACOSX_CREATOR_ATTRIBUTE, MACOSX_TYPE_ATTRIBUTE, MACOSX_HIDDEN_ATTRIBUTE,
+ MACOSX_RSRCLENGTH_ATTRIBUTE,
+#endif
+ UNIX_INVALID_ATTRIBUTE /* lint - last enum value needs no trailing , */
+};
+
+MODULE_SCOPE const char *const tclpFileAttrStrings[];
+const char *const tclpFileAttrStrings[] = {
+#if defined(__CYGWIN__)
+ "-archive",
+#endif
+ "-group",
+#if defined(__CYGWIN__)
+ "-hidden",
+#endif
+ "-owner", "-permissions",
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) || defined(__CYGWIN__)
+ "-readonly",
+#endif
+#if defined(__CYGWIN__)
+ "-system",
+#endif
+#ifdef MAC_OSX_TCL
+ "-creator", "-type", "-hidden", "-rsrclength",
+#endif
+ NULL
+};
+
+MODULE_SCOPE const TclFileAttrProcs tclpFileAttrProcs[];
+const TclFileAttrProcs tclpFileAttrProcs[] = {
+#if defined(__CYGWIN__)
+ {GetUnixFileAttributes, SetUnixFileAttributes},
+#endif
+ {GetGroupAttribute, SetGroupAttribute},
+#if defined(__CYGWIN__)
+ {GetUnixFileAttributes, SetUnixFileAttributes},
+#endif
+ {GetOwnerAttribute, SetOwnerAttribute},
+ {GetPermissionsAttribute, SetPermissionsAttribute},
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) || defined(__CYGWIN__)
+ {GetUnixFileAttributes, SetUnixFileAttributes},
+#endif
+#if defined(__CYGWIN__)
+ {GetUnixFileAttributes, SetUnixFileAttributes},
+#endif
+#ifdef MAC_OSX_TCL
+ {TclMacOSXGetFileAttribute, TclMacOSXSetFileAttribute},
+ {TclMacOSXGetFileAttribute, TclMacOSXSetFileAttribute},
+ {TclMacOSXGetFileAttribute, TclMacOSXSetFileAttribute},
+ {TclMacOSXGetFileAttribute, TclMacOSXSetFileAttribute},
+#endif
+};
+#endif /* DJGPP */
+
+/*
+ * This is the maximum number of consecutive readdir/unlink calls that can be
+ * made (with no intervening rewinddir or closedir/opendir) before triggering
+ * a bug that makes readdir return NULL even though some directory entries
+ * have not been processed. The bug afflicts SunOS's readdir when applied to
+ * ufs file systems and Darwin 6.5's (and OSX v.10.3.8's) HFS+. JH found the
+ * Darwin readdir to reset at 147, so 130 is chosen to be conservative. We
+ * can't do a general rewind on failure as NFS can create special files that
+ * recreate themselves when you try and delete them. 8.4.8 added a solution
+ * that was affected by a single such NFS file, this solution should not be
+ * affected by less than THRESHOLD such files. [Bug 1034337]
+ */
+
+#define MAX_READDIR_UNLINK_THRESHOLD 130
+
+/*
+ * Declarations for local procedures defined in this file:
+ */
+
+static int CopyFileAtts(const char *src,
+ const char *dst, const Tcl_StatBuf *statBufPtr);
+static const char * DefaultTempDir(void);
+static int DoCopyFile(const char *srcPtr, const char *dstPtr,
+ const Tcl_StatBuf *statBufPtr);
+static int DoCreateDirectory(const char *pathPtr);
+static int DoRemoveDirectory(Tcl_DString *pathPtr,
+ int recursive, Tcl_DString *errorPtr);
+static int DoRenameFile(const char *src, const char *dst);
+static int TraversalCopy(Tcl_DString *srcPtr,
+ Tcl_DString *dstPtr,
+ const Tcl_StatBuf *statBufPtr, int type,
+ Tcl_DString *errorPtr);
+static int TraversalDelete(Tcl_DString *srcPtr,
+ Tcl_DString *dstPtr,
+ const Tcl_StatBuf *statBufPtr, int type,
+ Tcl_DString *errorPtr);
+static int TraverseUnixTree(TraversalProc *traversalProc,
+ Tcl_DString *sourcePtr, Tcl_DString *destPtr,
+ Tcl_DString *errorPtr, int doRewind);
+
+#ifdef PURIFY
+/*
+ * realpath and purify don't mix happily. It has been noted that realpath
+ * should not be used with purify because of bogus warnings, but just
+ * memset'ing the resolved path will squelch those. This assumes we are
+ * passing the standard MAXPATHLEN size resolved arg.
+ */
+
+static char * Realpath(const char *path, char *resolved);
+
+char *
+Realpath(
+ const char *path,
+ char *resolved)
+{
+ memset(resolved, 0, MAXPATHLEN);
+ return realpath(path, resolved);
+}
+#else
+# define Realpath realpath
+#endif /* PURIFY */
+
+#ifndef NO_REALPATH
+#if defined(__APPLE__) && defined(TCL_THREADS) && \
+ defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
+ MAC_OS_X_VERSION_MIN_REQUIRED < 1030
+/*
+ * Prior to Darwin 7, realpath is not thread-safe, c.f. Bug 711232; if we
+ * might potentially be running on pre-10.3 OSX, check Darwin release at
+ * runtime before using realpath.
+ */
+
+MODULE_SCOPE long tclMacOSXDarwinRelease;
+# define haveRealpath (tclMacOSXDarwinRelease >= 7)
+#else
+# define haveRealpath 1
+#endif
+#endif /* NO_REALPATH */
+
+#ifdef HAVE_FTS
+#if defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__)
+/* fts doesn't do stat64 */
+# define noFtsStat 1
+#elif defined(__APPLE__) && defined(__LP64__) && \
+ defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
+ MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+/*
+ * Prior to Darwin 9, 64bit fts_open() without FTS_NOSTAT may crash (due to a
+ * 64bit-unsafe ALIGN macro); if we could be running on pre-10.5 OSX, check
+ * Darwin release at runtime and do a separate stat() if necessary.
+ */
+
+MODULE_SCOPE long tclMacOSXDarwinRelease;
+# define noFtsStat (tclMacOSXDarwinRelease < 9)
+#else
+# define noFtsStat 0
+#endif
+#endif /* HAVE_FTS */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpObjRenameFile, DoRenameFile --
+ *
+ * Changes the name of an existing file or directory, from src to dst. If
+ * src and dst refer to the same file or directory, does nothing and
+ * returns success. Otherwise if dst already exists, it will be deleted
+ * and replaced by src subject to the following conditions:
+ * If src is a directory, dst may be an empty directory.
+ * If src is a file, dst may be a file.
+ * In any other situation where dst already exists, the rename will fail.
+ *
+ * Results:
+ * If the directory was successfully created, returns TCL_OK. Otherwise
+ * the return value is TCL_ERROR and errno is set to indicate the error.
+ * Some possible values for errno are:
+ *
+ * EACCES: src or dst parent directory can't be read and/or written.
+ * EEXIST: dst is a non-empty directory.
+ * EINVAL: src is a root directory or dst is a subdirectory of src.
+ * EISDIR: dst is a directory, but src is not.
+ * ENOENT: src doesn't exist, or src or dst is "".
+ * ENOTDIR: src is a directory, but dst is not.
+ * EXDEV: src and dst are on different filesystems.
+ *
+ * Side effects:
+ * The implementation of rename may allow cross-filesystem renames, but
+ * the caller should be prepared to emulate it with copy and delete if
+ * errno is EXDEV.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpObjRenameFile(
+ Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr)
+{
+ return DoRenameFile(Tcl_FSGetNativePath(srcPathPtr),
+ Tcl_FSGetNativePath(destPathPtr));
+}
+
+static int
+DoRenameFile(
+ const char *src, /* Pathname of file or dir to be renamed
+ * (native). */
+ const char *dst) /* New pathname of file or directory
+ * (native). */
+{
+ if (rename(src, dst) == 0) { /* INTL: Native. */
+ return TCL_OK;
+ }
+ if (errno == ENOTEMPTY) {
+ errno = EEXIST;
+ }
+
+ /*
+ * IRIX returns EIO when you attept to move a directory into itself. We
+ * just map EIO to EINVAL get the right message on SGI. Most platforms
+ * don't return EIO except in really strange cases.
+ */
+
+ if (errno == EIO) {
+ errno = EINVAL;
+ }
+
+#ifndef NO_REALPATH
+ /*
+ * SunOS 4.1.4 reports overwriting a non-empty directory with a directory
+ * as EINVAL instead of EEXIST (first rule out the correct EINVAL result
+ * code for moving a directory into itself). Must be conditionally
+ * compiled because realpath() not defined on all systems.
+ */
+
+ if (errno == EINVAL && haveRealpath) {
+ char srcPath[MAXPATHLEN], dstPath[MAXPATHLEN];
+ DIR *dirPtr;
+ Tcl_DirEntry *dirEntPtr;
+
+ if ((Realpath((char *) src, srcPath) != NULL) /* INTL: Native. */
+ && (Realpath((char *) dst, dstPath) != NULL) /* INTL: Native */
+ && (strncmp(srcPath, dstPath, strlen(srcPath)) != 0)) {
+ dirPtr = opendir(dst); /* INTL: Native. */
+ if (dirPtr != NULL) {
+ while (1) {
+ dirEntPtr = TclOSreaddir(dirPtr); /* INTL: Native. */
+ if (dirEntPtr == NULL) {
+ break;
+ }
+ if ((strcmp(dirEntPtr->d_name, ".") != 0) &&
+ (strcmp(dirEntPtr->d_name, "..") != 0)) {
+ errno = EEXIST;
+ closedir(dirPtr);
+ return TCL_ERROR;
+ }
+ }
+ closedir(dirPtr);
+ }
+ }
+ errno = EINVAL;
+ }
+#endif /* !NO_REALPATH */
+
+ if (strcmp(src, "/") == 0) {
+ /*
+ * Alpha reports renaming / as EBUSY and Linux reports it as EACCES,
+ * instead of EINVAL.
+ */
+
+ errno = EINVAL;
+ }
+
+ /*
+ * DEC Alpha OSF1 V3.0 returns EACCES when attempting to move a file
+ * across filesystems and the parent directory of that file is not
+ * writable. Most other systems return EXDEV. Does nothing to correct this
+ * behavior.
+ */
+
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpObjCopyFile, DoCopyFile --
+ *
+ * Copy a single file (not a directory). If dst already exists and is not
+ * a directory, it is removed.
+ *
+ * Results:
+ * If the file was successfully copied, returns TCL_OK. Otherwise the
+ * return value is TCL_ERROR and errno is set to indicate the error. Some
+ * possible values for errno are:
+ *
+ * EACCES: src or dst parent directory can't be read and/or written.
+ * EISDIR: src or dst is a directory.
+ * ENOENT: src doesn't exist. src or dst is "".
+ *
+ * Side effects:
+ * This procedure will also copy symbolic links, block, and character
+ * devices, and fifos. For symbolic links, the links themselves will be
+ * copied and not what they point to. For the other special file types,
+ * the directory entry will be copied and not the contents of the device
+ * that it refers to.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpObjCopyFile(
+ Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr)
+{
+ const char *src = Tcl_FSGetNativePath(srcPathPtr);
+ Tcl_StatBuf srcStatBuf;
+
+ if (TclOSlstat(src, &srcStatBuf) != 0) { /* INTL: Native. */
+ return TCL_ERROR;
+ }
+
+ return DoCopyFile(src, Tcl_FSGetNativePath(destPathPtr), &srcStatBuf);
+}
+
+static int
+DoCopyFile(
+ const char *src, /* Pathname of file to be copied (native). */
+ const char *dst, /* Pathname of file to copy to (native). */
+ const Tcl_StatBuf *statBufPtr)
+ /* Used to determine filetype. */
+{
+ Tcl_StatBuf dstStatBuf;
+
+ if (S_ISDIR(statBufPtr->st_mode)) {
+ errno = EISDIR;
+ return TCL_ERROR;
+ }
+
+ /*
+ * Symlink, and some of the other calls will fail if the target exists, so
+ * we remove it first.
+ */
+
+ if (TclOSlstat(dst, &dstStatBuf) == 0) { /* INTL: Native. */
+ if (S_ISDIR(dstStatBuf.st_mode)) {
+ errno = EISDIR;
+ return TCL_ERROR;
+ }
+ }
+ if (unlink(dst) != 0) { /* INTL: Native. */
+ if (errno != ENOENT) {
+ return TCL_ERROR;
+ }
+ }
+
+ switch ((int) (statBufPtr->st_mode & S_IFMT)) {
+#ifndef DJGPP
+ case S_IFLNK: {
+ char linkBuf[MAXPATHLEN+1];
+ int length;
+
+ length = readlink(src, linkBuf, MAXPATHLEN);
+ /* INTL: Native. */
+ if (length == -1) {
+ return TCL_ERROR;
+ }
+ linkBuf[length] = '\0';
+ if (symlink(linkBuf, dst) < 0) { /* INTL: Native. */
+ return TCL_ERROR;
+ }
+#ifdef MAC_OSX_TCL
+ TclMacOSXCopyFileAttributes(src, dst, statBufPtr);
+#endif
+ break;
+ }
+#endif /* !DJGPP */
+ case S_IFBLK:
+ case S_IFCHR:
+ if (mknod(dst, statBufPtr->st_mode, /* INTL: Native. */
+ statBufPtr->st_rdev) < 0) {
+ return TCL_ERROR;
+ }
+ return CopyFileAtts(src, dst, statBufPtr);
+ case S_IFIFO:
+ if (mkfifo(dst, statBufPtr->st_mode) < 0) { /* INTL: Native. */
+ return TCL_ERROR;
+ }
+ return CopyFileAtts(src, dst, statBufPtr);
+ default:
+ return TclUnixCopyFile(src, dst, statBufPtr, 0);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclUnixCopyFile -
+ *
+ * Helper function for TclpCopyFile. Copies one regular file, using
+ * read() and write().
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A file is copied. Dst will be overwritten if it exists.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclUnixCopyFile(
+ const char *src, /* Pathname of file to copy (native). */
+ const char *dst, /* Pathname of file to create/overwrite
+ * (native). */
+ const Tcl_StatBuf *statBufPtr,
+ /* Used to determine mode and blocksize. */
+ int dontCopyAtts) /* If flag set, don't copy attributes. */
+{
+ int srcFd, dstFd;
+ unsigned blockSize; /* Optimal I/O blocksize for filesystem */
+ char *buffer; /* Data buffer for copy */
+ size_t nread;
+
+#ifdef DJGPP
+#define BINMODE |O_BINARY
+#else
+#define BINMODE
+#endif /* DJGPP */
+
+#define DEFAULT_COPY_BLOCK_SIZE 4096
+
+ if ((srcFd = TclOSopen(src, O_RDONLY BINMODE, 0)) < 0) { /* INTL: Native */
+ return TCL_ERROR;
+ }
+
+ dstFd = TclOSopen(dst, O_CREAT|O_TRUNC|O_WRONLY BINMODE, /* INTL: Native */
+ statBufPtr->st_mode);
+ if (dstFd < 0) {
+ close(srcFd);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Try to work out the best size of buffer to use for copying. If we
+ * can't, it's no big deal as we can just use a (32-bit) page, since
+ * that's likely to be fairly efficient anyway.
+ */
+
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+ blockSize = statBufPtr->st_blksize;
+#elif !defined(NO_FSTATFS)
+ {
+ struct statfs fs;
+
+ if (fstatfs(srcFd, &fs) == 0) {
+ blockSize = fs.f_bsize;
+ } else {
+ blockSize = DEFAULT_COPY_BLOCK_SIZE;
+ }
+ }
+#else
+ blockSize = DEFAULT_COPY_BLOCK_SIZE;
+#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
+
+ /*
+ * [SF Tcl Bug 1586470] Even if we HAVE_STRUCT_STAT_ST_BLKSIZE, there are
+ * filesystems which report a bogus value for the blocksize. An example
+ * is the Andrew Filesystem (afs), reporting a blocksize of 0. When
+ * detecting such a situation we now simply fall back to a hardwired
+ * default size.
+ */
+
+ if (blockSize <= 0) {
+ blockSize = DEFAULT_COPY_BLOCK_SIZE;
+ }
+ buffer = ckalloc(blockSize);
+ while (1) {
+ nread = (size_t) read(srcFd, buffer, blockSize);
+ if ((nread == (size_t) -1) || (nread == 0)) {
+ break;
+ }
+ if ((size_t) write(dstFd, buffer, nread) != nread) {
+ nread = (size_t) -1;
+ break;
+ }
+ }
+
+ ckfree(buffer);
+ close(srcFd);
+ if ((close(dstFd) != 0) || (nread == (size_t) -1)) {
+ unlink(dst); /* INTL: Native. */
+ return TCL_ERROR;
+ }
+ if (!dontCopyAtts && CopyFileAtts(src, dst, statBufPtr) == TCL_ERROR) {
+ /*
+ * The copy succeeded, but setting the permissions failed, so be in a
+ * consistent state, we remove the file that was created by the copy.
+ */
+
+ unlink(dst); /* INTL: Native. */
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpObjDeleteFile, TclpDeleteFile --
+ *
+ * Removes a single file (not a directory).
+ *
+ * Results:
+ * If the file was successfully deleted, returns TCL_OK. Otherwise the
+ * return value is TCL_ERROR and errno is set to indicate the error. Some
+ * possible values for errno are:
+ *
+ * EACCES: a parent directory can't be read and/or written.
+ * EISDIR: path is a directory.
+ * ENOENT: path doesn't exist or is "".
+ *
+ * Side effects:
+ * The file is deleted, even if it is read-only.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpObjDeleteFile(
+ Tcl_Obj *pathPtr)
+{
+ return TclpDeleteFile(Tcl_FSGetNativePath(pathPtr));
+}
+
+int
+TclpDeleteFile(
+ const void *path) /* Pathname of file to be removed (native). */
+{
+ if (unlink((const char *)path) != 0) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpCreateDirectory, DoCreateDirectory --
+ *
+ * Creates the specified directory. All parent directories of the
+ * specified directory must already exist. The directory is automatically
+ * created with permissions so that user can access the new directory and
+ * create new files or subdirectories in it.
+ *
+ * Results:
+ * If the directory was successfully created, returns TCL_OK. Otherwise
+ * the return value is TCL_ERROR and errno is set to indicate the error.
+ * Some possible values for errno are:
+ *
+ * EACCES: a parent directory can't be read and/or written.
+ * EEXIST: path already exists.
+ * ENOENT: a parent directory doesn't exist.
+ *
+ * Side effects:
+ * A directory is created with the current umask, except that permission
+ * for u+rwx will always be added.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpObjCreateDirectory(
+ Tcl_Obj *pathPtr)
+{
+ return DoCreateDirectory(Tcl_FSGetNativePath(pathPtr));
+}
+
+static int
+DoCreateDirectory(
+ const char *path) /* Pathname of directory to create (native). */
+{
+ mode_t mode;
+
+ mode = umask(0);
+ umask(mode);
+
+ /*
+ * umask return value is actually the inverse of the permissions.
+ */
+
+ mode = (0777 & ~mode) | S_IRUSR | S_IWUSR | S_IXUSR;
+
+ if (mkdir(path, mode) != 0) { /* INTL: Native. */
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpObjCopyDirectory --
+ *
+ * Recursively copies a directory. The target directory dst must not
+ * already exist. Note that this function does not merge two directory
+ * hierarchies, even if the target directory is an an empty directory.
+ *
+ * Results:
+ * If the directory was successfully copied, returns TCL_OK. Otherwise
+ * the return value is TCL_ERROR, errno is set to indicate the error, and
+ * the pathname of the file that caused the error is stored in errorPtr.
+ * See TclpObjCreateDirectory and TclpObjCopyFile for a description of
+ * possible values for errno.
+ *
+ * Side effects:
+ * An exact copy of the directory hierarchy src will be created with the
+ * name dst. If an error occurs, the error will be returned immediately,
+ * and remaining files will not be processed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpObjCopyDirectory(
+ Tcl_Obj *srcPathPtr,
+ Tcl_Obj *destPathPtr,
+ Tcl_Obj **errorPtr)
+{
+ Tcl_DString ds;
+ Tcl_DString srcString, dstString;
+ int ret;
+ Tcl_Obj *transPtr;
+
+ transPtr = Tcl_FSGetTranslatedPath(NULL,srcPathPtr);
+ Tcl_UtfToExternalDString(NULL,
+ (transPtr != NULL ? TclGetString(transPtr) : NULL),
+ -1, &srcString);
+ if (transPtr != NULL) {
+ Tcl_DecrRefCount(transPtr);
+ }
+ transPtr = Tcl_FSGetTranslatedPath(NULL,destPathPtr);
+ Tcl_UtfToExternalDString(NULL,
+ (transPtr != NULL ? TclGetString(transPtr) : NULL),
+ -1, &dstString);
+ if (transPtr != NULL) {
+ Tcl_DecrRefCount(transPtr);
+ }
+
+ ret = TraverseUnixTree(TraversalCopy, &srcString, &dstString, &ds, 0);
+
+ Tcl_DStringFree(&srcString);
+ Tcl_DStringFree(&dstString);
+
+ if (ret != TCL_OK) {
+ *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
+ Tcl_DStringFree(&ds);
+ Tcl_IncrRefCount(*errorPtr);
+ }
+ return ret;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpRemoveDirectory, DoRemoveDirectory --
+ *
+ * Removes directory (and its contents, if the recursive flag is set).
+ *
+ * Results:
+ * If the directory was successfully removed, returns TCL_OK. Otherwise
+ * the return value is TCL_ERROR, errno is set to indicate the error, and
+ * the pathname of the file that caused the error is stored in errorPtr.
+ * Some possible values for errno are:
+ *
+ * EACCES: path directory can't be read and/or written.
+ * EEXIST: path is a non-empty directory.
+ * EINVAL: path is a root directory.
+ * ENOENT: path doesn't exist or is "".
+ * ENOTDIR: path is not a directory.
+ *
+ * Side effects:
+ * Directory removed. If an error occurs, the error will be returned
+ * immediately, and remaining files will not be deleted.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpObjRemoveDirectory(
+ Tcl_Obj *pathPtr,
+ int recursive,
+ Tcl_Obj **errorPtr)
+{
+ Tcl_DString ds;
+ Tcl_DString pathString;
+ int ret;
+ Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
+
+ Tcl_UtfToExternalDString(NULL,
+ (transPtr != NULL ? TclGetString(transPtr) : NULL),
+ -1, &pathString);
+ if (transPtr != NULL) {
+ Tcl_DecrRefCount(transPtr);
+ }
+ ret = DoRemoveDirectory(&pathString, recursive, &ds);
+ Tcl_DStringFree(&pathString);
+
+ if (ret != TCL_OK) {
+ *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
+ Tcl_DStringFree(&ds);
+ Tcl_IncrRefCount(*errorPtr);
+ }
+ return ret;
+}
+
+static int
+DoRemoveDirectory(
+ Tcl_DString *pathPtr, /* Pathname of directory to be removed
+ * (native). */
+ int recursive, /* If non-zero, removes directories that are
+ * nonempty. Otherwise, will only remove empty
+ * directories. */
+ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString
+ * filled with UTF-8 name of file causing
+ * error. */
+{
+ const char *path;
+ mode_t oldPerm = 0;
+ int result;
+
+ path = Tcl_DStringValue(pathPtr);
+
+ if (recursive != 0) {
+ /*
+ * We should try to change permissions so this can be deleted.
+ */
+
+ Tcl_StatBuf statBuf;
+ int newPerm;
+
+ if (TclOSstat(path, &statBuf) == 0) {
+ oldPerm = (mode_t) (statBuf.st_mode & 0x00007FFF);
+ }
+
+ newPerm = oldPerm | (64+128+256);
+ chmod(path, (mode_t) newPerm);
+ }
+
+ if (rmdir(path) == 0) { /* INTL: Native. */
+ return TCL_OK;
+ }
+ if (errno == ENOTEMPTY) {
+ errno = EEXIST;
+ }
+
+ result = TCL_OK;
+ if ((errno != EEXIST) || (recursive == 0)) {
+ if (errorPtr != NULL) {
+ Tcl_ExternalToUtfDString(NULL, path, -1, errorPtr);
+ }
+ result = TCL_ERROR;
+ }
+
+ /*
+ * The directory is nonempty, but the recursive flag has been specified,
+ * so we recursively remove all the files in the directory.
+ */
+
+ if (result == TCL_OK) {
+ result = TraverseUnixTree(TraversalDelete, pathPtr, NULL, errorPtr, 1);
+ }
+
+ if ((result != TCL_OK) && (recursive != 0)) {
+ /*
+ * Try to restore permissions.
+ */
+
+ chmod(path, oldPerm);
+ }
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TraverseUnixTree --
+ *
+ * Traverse directory tree specified by sourcePtr, calling the function
+ * traverseProc for each file and directory encountered. If destPtr is
+ * non-null, each of name in the sourcePtr directory is appended to the
+ * directory specified by destPtr and passed as the second argument to
+ * traverseProc().
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * None caused by TraverseUnixTree, however the user specified
+ * traverseProc() may change state. If an error occurs, the error will be
+ * returned immediately, and remaining files will not be processed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+TraverseUnixTree(
+ TraversalProc *traverseProc,/* Function to call for every file and
+ * directory in source hierarchy. */
+ Tcl_DString *sourcePtr, /* Pathname of source directory to be
+ * traversed (native). */
+ Tcl_DString *targetPtr, /* Pathname of directory to traverse in
+ * parallel with source directory (native). */
+ Tcl_DString *errorPtr, /* If non-NULL, uninitialized or free DString
+ * filled with UTF-8 name of file causing
+ * error. */
+ int doRewind) /* Flag indicating that to ensure complete
+ * traversal of source hierarchy, the readdir
+ * loop should be rewound whenever
+ * traverseProc has returned TCL_OK; this is
+ * required when traverseProc modifies the
+ * source hierarchy, e.g. by deleting
+ * files. */
+{
+ Tcl_StatBuf statBuf;
+ const char *source, *errfile;
+ int result, sourceLen;
+ int targetLen;
+#ifndef HAVE_FTS
+ int numProcessed = 0;
+ Tcl_DirEntry *dirEntPtr;
+ DIR *dirPtr;
+#else
+ const char *paths[2] = {NULL, NULL};
+ FTS *fts = NULL;
+ FTSENT *ent;
+#endif
+
+ errfile = NULL;
+ result = TCL_OK;
+ targetLen = 0; /* lint. */
+
+ source = Tcl_DStringValue(sourcePtr);
+ if (TclOSlstat(source, &statBuf) != 0) { /* INTL: Native. */
+ errfile = source;
+ goto end;
+ }
+ if (!S_ISDIR(statBuf.st_mode)) {
+ /*
+ * Process the regular file
+ */
+
+ return traverseProc(sourcePtr, targetPtr, &statBuf, DOTREE_F,
+ errorPtr);
+ }
+#ifndef HAVE_FTS
+ dirPtr = opendir(source); /* INTL: Native. */
+ if (dirPtr == NULL) {
+ /*
+ * Can't read directory
+ */
+
+ errfile = source;
+ goto end;
+ }
+ result = traverseProc(sourcePtr, targetPtr, &statBuf, DOTREE_PRED,
+ errorPtr);
+ if (result != TCL_OK) {
+ closedir(dirPtr);
+ return result;
+ }
+
+ TclDStringAppendLiteral(sourcePtr, "/");
+ sourceLen = Tcl_DStringLength(sourcePtr);
+
+ if (targetPtr != NULL) {
+ TclDStringAppendLiteral(targetPtr, "/");
+ targetLen = Tcl_DStringLength(targetPtr);
+ }
+
+ while ((dirEntPtr = TclOSreaddir(dirPtr)) != NULL) { /* INTL: Native. */
+ if ((dirEntPtr->d_name[0] == '.')
+ && ((dirEntPtr->d_name[1] == '\0')
+ || (strcmp(dirEntPtr->d_name, "..") == 0))) {
+ continue;
+ }
+
+ /*
+ * Append name after slash, and recurse on the file.
+ */
+
+ Tcl_DStringAppend(sourcePtr, dirEntPtr->d_name, -1);
+ if (targetPtr != NULL) {
+ Tcl_DStringAppend(targetPtr, dirEntPtr->d_name, -1);
+ }
+ result = TraverseUnixTree(traverseProc, sourcePtr, targetPtr,
+ errorPtr, doRewind);
+ if (result != TCL_OK) {
+ break;
+ } else {
+ numProcessed++;
+ }
+
+ /*
+ * Remove name after slash.
+ */
+
+ Tcl_DStringSetLength(sourcePtr, sourceLen);
+ if (targetPtr != NULL) {
+ Tcl_DStringSetLength(targetPtr, targetLen);
+ }
+ if (doRewind && (numProcessed > MAX_READDIR_UNLINK_THRESHOLD)) {
+ /*
+ * Call rewinddir if we've called unlink or rmdir so many times
+ * (since the opendir or the previous rewinddir), to avoid a
+ * NULL-return that may a symptom of a buggy readdir.
+ */
+
+ rewinddir(dirPtr);
+ numProcessed = 0;
+ }
+ }
+ closedir(dirPtr);
+
+ /*
+ * Strip off the trailing slash we added
+ */
+
+ Tcl_DStringSetLength(sourcePtr, sourceLen - 1);
+ if (targetPtr != NULL) {
+ Tcl_DStringSetLength(targetPtr, targetLen - 1);
+ }
+
+ if (result == TCL_OK) {
+ /*
+ * Call traverseProc() on a directory after visiting all the files in
+ * that directory.
+ */
+
+ result = traverseProc(sourcePtr, targetPtr, &statBuf, DOTREE_POSTD,
+ errorPtr);
+ }
+#else /* HAVE_FTS */
+ paths[0] = source;
+ fts = fts_open((char **) paths, FTS_PHYSICAL | FTS_NOCHDIR |
+ (noFtsStat || doRewind ? FTS_NOSTAT : 0), NULL);
+ if (fts == NULL) {
+ errfile = source;
+ goto end;
+ }
+
+ sourceLen = Tcl_DStringLength(sourcePtr);
+ if (targetPtr != NULL) {
+ targetLen = Tcl_DStringLength(targetPtr);
+ }
+
+ while ((ent = fts_read(fts)) != NULL) {
+ unsigned short info = ent->fts_info;
+ char *path = ent->fts_path + sourceLen;
+ unsigned short pathlen = ent->fts_pathlen - sourceLen;
+ int type;
+ Tcl_StatBuf *statBufPtr = NULL;
+
+ if (info == FTS_DNR || info == FTS_ERR || info == FTS_NS) {
+ errfile = ent->fts_path;
+ break;
+ }
+ Tcl_DStringAppend(sourcePtr, path, pathlen);
+ if (targetPtr != NULL) {
+ Tcl_DStringAppend(targetPtr, path, pathlen);
+ }
+ switch (info) {
+ case FTS_D:
+ type = DOTREE_PRED;
+ break;
+ case FTS_DP:
+ type = DOTREE_POSTD;
+ break;
+ default:
+ type = DOTREE_F;
+ break;
+ }
+ if (!doRewind) { /* no need to stat for delete */
+ if (noFtsStat) {
+ statBufPtr = &statBuf;
+ if (TclOSlstat(ent->fts_path, statBufPtr) != 0) {
+ errfile = ent->fts_path;
+ break;
+ }
+ } else {
+ statBufPtr = (Tcl_StatBuf *) ent->fts_statp;
+ }
+ }
+ result = traverseProc(sourcePtr, targetPtr, statBufPtr, type,
+ errorPtr);
+ if (result != TCL_OK) {
+ break;
+ }
+ Tcl_DStringSetLength(sourcePtr, sourceLen);
+ if (targetPtr != NULL) {
+ Tcl_DStringSetLength(targetPtr, targetLen);
+ }
+ }
+#endif /* !HAVE_FTS */
+
+ end:
+ if (errfile != NULL) {
+ if (errorPtr != NULL) {
+ Tcl_ExternalToUtfDString(NULL, errfile, -1, errorPtr);
+ }
+ result = TCL_ERROR;
+ }
+#ifdef HAVE_FTS
+ if (fts != NULL) {
+ fts_close(fts);
+ }
+#endif
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TraversalCopy
+ *
+ * Called from TraverseUnixTree in order to execute a recursive copy of a
+ * directory.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * The file or directory src may be copied to dst, depending on the value
+ * of type.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TraversalCopy(
+ Tcl_DString *srcPtr, /* Source pathname to copy (native). */
+ Tcl_DString *dstPtr, /* Destination pathname of copy (native). */
+ const Tcl_StatBuf *statBufPtr,
+ /* Stat info for file specified by srcPtr. */
+ int type, /* Reason for call - see TraverseUnixTree(). */
+ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString
+ * filled with UTF-8 name of file causing
+ * error. */
+{
+ switch (type) {
+ case DOTREE_F:
+ if (DoCopyFile(Tcl_DStringValue(srcPtr), Tcl_DStringValue(dstPtr),
+ statBufPtr) == TCL_OK) {
+ return TCL_OK;
+ }
+ break;
+
+ case DOTREE_PRED:
+ if (DoCreateDirectory(Tcl_DStringValue(dstPtr)) == TCL_OK) {
+ return TCL_OK;
+ }
+ break;
+
+ case DOTREE_POSTD:
+ if (CopyFileAtts(Tcl_DStringValue(srcPtr),
+ Tcl_DStringValue(dstPtr), statBufPtr) == TCL_OK) {
+ return TCL_OK;
+ }
+ break;
+ }
+
+ /*
+ * There shouldn't be a problem with src, because we already checked it to
+ * get here.
+ */
+
+ if (errorPtr != NULL) {
+ Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(dstPtr),
+ Tcl_DStringLength(dstPtr), errorPtr);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TraversalDelete --
+ *
+ * Called by procedure TraverseUnixTree for every file and directory that
+ * it encounters in a directory hierarchy. This procedure unlinks files,
+ * and removes directories after all the containing files have been
+ * processed.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Files or directory specified by src will be deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TraversalDelete(
+ Tcl_DString *srcPtr, /* Source pathname (native). */
+ Tcl_DString *ignore, /* Destination pathname (not used). */
+ const Tcl_StatBuf *statBufPtr,
+ /* Stat info for file specified by srcPtr. */
+ int type, /* Reason for call - see TraverseUnixTree(). */
+ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString
+ * filled with UTF-8 name of file causing
+ * error. */
+{
+ switch (type) {
+ case DOTREE_F:
+ if (TclpDeleteFile(Tcl_DStringValue(srcPtr)) == 0) {
+ return TCL_OK;
+ }
+ break;
+ case DOTREE_PRED:
+ return TCL_OK;
+ case DOTREE_POSTD:
+ if (DoRemoveDirectory(srcPtr, 0, NULL) == 0) {
+ return TCL_OK;
+ }
+ break;
+ }
+ if (errorPtr != NULL) {
+ Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(srcPtr),
+ Tcl_DStringLength(srcPtr), errorPtr);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CopyFileAtts --
+ *
+ * Copy the file attributes such as owner, group, permissions, and
+ * modification date from one file to another.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * User id, group id, permission bits, last modification time, and last
+ * access time are updated in the new file to reflect the old file.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+CopyFileAtts(
+ const char *src, /* Path name of source file (native). */
+ const char *dst, /* Path name of target file (native). */
+ const Tcl_StatBuf *statBufPtr)
+ /* Stat info for source file */
+{
+ struct utimbuf tval;
+ mode_t newMode;
+
+ newMode = statBufPtr->st_mode
+ & (S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO);
+
+ /*
+ * Note that if you copy a setuid file that is owned by someone else, and
+ * you are not root, then the copy will be setuid to you. The most correct
+ * implementation would probably be to have the copy not setuid to anyone
+ * if the original file was owned by someone else, but this corner case
+ * isn't currently handled. It would require another lstat(), or getuid().
+ */
+
+ if (chmod(dst, newMode)) { /* INTL: Native. */
+ newMode &= ~(S_ISUID | S_ISGID);
+ if (chmod(dst, newMode)) { /* INTL: Native. */
+ return TCL_ERROR;
+ }
+ }
+
+ tval.actime = statBufPtr->st_atime;
+ tval.modtime = statBufPtr->st_mtime;
+
+ if (utime(dst, &tval)) { /* INTL: Native. */
+ return TCL_ERROR;
+ }
+#ifdef MAC_OSX_TCL
+ TclMacOSXCopyFileAttributes(src, dst, statBufPtr);
+#endif
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetGroupAttribute
+ *
+ * Gets the group attribute of a file.
+ *
+ * Results:
+ * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
+ * is no error.
+ *
+ * Side effects:
+ * A new object is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetGroupAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
+{
+ Tcl_StatBuf statBuf;
+ struct group *groupPtr;
+ int result;
+
+ result = TclpObjStat(fileName, &statBuf);
+
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not read \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+
+ groupPtr = TclpGetGrGid(statBuf.st_gid);
+
+ if (groupPtr == NULL) {
+ *attributePtrPtr = Tcl_NewIntObj((int) statBuf.st_gid);
+ } else {
+ Tcl_DString ds;
+ const char *utf;
+
+ utf = Tcl_ExternalToUtfDString(NULL, groupPtr->gr_name, -1, &ds);
+ *attributePtrPtr = Tcl_NewStringObj(utf, -1);
+ Tcl_DStringFree(&ds);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetOwnerAttribute
+ *
+ * Gets the owner attribute of a file.
+ *
+ * Results:
+ * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
+ * is no error.
+ *
+ * Side effects:
+ * A new object is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetOwnerAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
+{
+ Tcl_StatBuf statBuf;
+ struct passwd *pwPtr;
+ int result;
+
+ result = TclpObjStat(fileName, &statBuf);
+
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not read \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+
+ pwPtr = TclpGetPwUid(statBuf.st_uid);
+
+ if (pwPtr == NULL) {
+ *attributePtrPtr = Tcl_NewIntObj((int) statBuf.st_uid);
+ } else {
+ Tcl_DString ds;
+
+ (void) Tcl_ExternalToUtfDString(NULL, pwPtr->pw_name, -1, &ds);
+ *attributePtrPtr = TclDStringToObj(&ds);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetPermissionsAttribute
+ *
+ * Gets the group attribute of a file.
+ *
+ * Results:
+ * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
+ * is no error. The object will have ref count 0.
+ *
+ * Side effects:
+ * A new object is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetPermissionsAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
+{
+ Tcl_StatBuf statBuf;
+ int result;
+
+ result = TclpObjStat(fileName, &statBuf);
+
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not read \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+
+ *attributePtrPtr = Tcl_ObjPrintf(
+ "%0#5lo", (long) (statBuf.st_mode & 0x00007FFF));
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SetGroupAttribute --
+ *
+ * Sets the group of the file to the specified group.
+ *
+ * Results:
+ * Standard TCL result.
+ *
+ * Side effects:
+ * As above.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+SetGroupAttribute(
+ Tcl_Interp *interp, /* The interp for error reporting. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj *attributePtr) /* New group for file. */
+{
+ long gid;
+ int result;
+ const char *native;
+
+ if (Tcl_GetLongFromObj(NULL, attributePtr, &gid) != TCL_OK) {
+ Tcl_DString ds;
+ struct group *groupPtr = NULL;
+ const char *string;
+
+ string = TclGetString(attributePtr);
+
+ native = Tcl_UtfToExternalDString(NULL, string, attributePtr->length, &ds);
+ groupPtr = TclpGetGrNam(native); /* INTL: Native. */
+ Tcl_DStringFree(&ds);
+
+ if (groupPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not set group for file \"%s\":"
+ " group \"%s\" does not exist",
+ TclGetString(fileName), string));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SETGRP",
+ "NO_GROUP", NULL);
+ }
+ return TCL_ERROR;
+ }
+ gid = groupPtr->gr_gid;
+ }
+
+ native = Tcl_FSGetNativePath(fileName);
+ result = chown(native, (uid_t) -1, (gid_t) gid); /* INTL: Native. */
+
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not set group for file \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SetOwnerAttribute --
+ *
+ * Sets the owner of the file to the specified owner.
+ *
+ * Results:
+ * Standard TCL result.
+ *
+ * Side effects:
+ * As above.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+SetOwnerAttribute(
+ Tcl_Interp *interp, /* The interp for error reporting. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj *attributePtr) /* New owner for file. */
+{
+ long uid;
+ int result;
+ const char *native;
+
+ if (Tcl_GetLongFromObj(NULL, attributePtr, &uid) != TCL_OK) {
+ Tcl_DString ds;
+ struct passwd *pwPtr = NULL;
+ const char *string;
+
+ string = TclGetString(attributePtr);
+
+ native = Tcl_UtfToExternalDString(NULL, string, attributePtr->length, &ds);
+ pwPtr = TclpGetPwNam(native); /* INTL: Native. */
+ Tcl_DStringFree(&ds);
+
+ if (pwPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not set owner for file \"%s\":"
+ " user \"%s\" does not exist",
+ TclGetString(fileName), string));
+ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SETOWN",
+ "NO_USER", NULL);
+ }
+ return TCL_ERROR;
+ }
+ uid = pwPtr->pw_uid;
+ }
+
+ native = Tcl_FSGetNativePath(fileName);
+ result = chown(native, (uid_t) uid, (gid_t) -1); /* INTL: Native. */
+
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not set owner for file \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SetPermissionsAttribute
+ *
+ * Sets the file to the given permission.
+ *
+ * Results:
+ * Standard TCL result.
+ *
+ * Side effects:
+ * The permission of the file is changed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+SetPermissionsAttribute(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj *attributePtr) /* The attribute to set. */
+{
+ long mode;
+ mode_t newMode;
+ int result = TCL_ERROR;
+ const char *native;
+ const char *modeStringPtr = TclGetString(attributePtr);
+ int scanned = TclParseAllWhiteSpace(modeStringPtr, -1);
+
+ /*
+ * First supply support for octal number format
+ */
+
+ if ((modeStringPtr[scanned] == '0')
+ && (modeStringPtr[scanned+1] >= '0')
+ && (modeStringPtr[scanned+1] <= '7')) {
+ /* Leading zero - attempt octal interpretation */
+ Tcl_Obj *modeObj;
+
+ TclNewLiteralStringObj(modeObj, "0o");
+ Tcl_AppendToObj(modeObj, modeStringPtr+scanned+1, -1);
+ result = Tcl_GetLongFromObj(NULL, modeObj, &mode);
+ Tcl_DecrRefCount(modeObj);
+ }
+ if (result == TCL_OK
+ || Tcl_GetLongFromObj(NULL, attributePtr, &mode) == TCL_OK) {
+ newMode = (mode_t) (mode & 0x00007FFF);
+ } else {
+ Tcl_StatBuf buf;
+
+ /*
+ * Try the forms "rwxrwxrwx" and "ugo=rwx"
+ *
+ * We get the current mode of the file, in order to allow for ug+-=rwx
+ * style chmod strings.
+ */
+
+ result = TclpObjStat(fileName, &buf);
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not read \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+ newMode = (mode_t) (buf.st_mode & 0x00007FFF);
+
+ if (GetModeFromPermString(NULL, modeStringPtr, &newMode) != TCL_OK) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "unknown permission string format \"%s\"",
+ modeStringPtr));
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "PERMISSION", NULL);
+ }
+ return TCL_ERROR;
+ }
+ }
+
+ native = Tcl_FSGetNativePath(fileName);
+ result = chmod(native, newMode); /* INTL: Native. */
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not set permissions for file \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+#ifndef DJGPP
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpObjListVolumes --
+ *
+ * Lists the currently mounted volumes, which on UNIX is just /.
+ *
+ * Results:
+ * The list of volumes.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclpObjListVolumes(void)
+{
+ Tcl_Obj *resultPtr;
+ TclNewLiteralStringObj(resultPtr, "/");
+
+ Tcl_IncrRefCount(resultPtr);
+ return resultPtr;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetModeFromPermString --
+ *
+ * This procedure is invoked to process the "file permissions" Tcl
+ * command, to check for a "rwxrwxrwx" or "ugoa+-=rwxst" string. See the
+ * user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetModeFromPermString(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ const char *modeStringPtr, /* Permissions string */
+ mode_t *modePtr) /* pointer to the mode value */
+{
+ mode_t newMode;
+ mode_t oldMode; /* Storage for the value of the old mode (that
+ * is passed in), to allow for the chmod style
+ * manipulation. */
+ int i,n, who, op, what, op_found, who_found;
+
+ /*
+ * We start off checking for an "rwxrwxrwx" style permissions string
+ */
+
+ if (strlen(modeStringPtr) != 9) {
+ goto chmodStyleCheck;
+ }
+
+ newMode = 0;
+ for (i = 0; i < 9; i++) {
+ switch (*(modeStringPtr+i)) {
+ case 'r':
+ if ((i%3) != 0) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(8-i));
+ break;
+ case 'w':
+ if ((i%3) != 1) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(8-i));
+ break;
+ case 'x':
+ if ((i%3) != 2) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(8-i));
+ break;
+ case 's':
+ if (((i%3) != 2) || (i > 5)) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(8-i));
+ newMode |= (1<<(11-(i/3)));
+ break;
+ case 'S':
+ if (((i%3) != 2) || (i > 5)) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(11-(i/3)));
+ break;
+ case 't':
+ if (i != 8) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<(8-i));
+ newMode |= (1<<9);
+ break;
+ case 'T':
+ if (i != 8) {
+ goto chmodStyleCheck;
+ }
+ newMode |= (1<<9);
+ break;
+ case '-':
+ break;
+ default:
+ /*
+ * Oops, not what we thought it was, so go on
+ */
+ goto chmodStyleCheck;
+ }
+ }
+ *modePtr = newMode;
+ return TCL_OK;
+
+ chmodStyleCheck:
+ /*
+ * We now check for an "ugoa+-=rwxst" style permissions string
+ */
+
+ for (n = 0 ; *(modeStringPtr+n) != '\0' ; n = n + i) {
+ oldMode = *modePtr;
+ who = op = what = op_found = who_found = 0;
+ for (i = 0 ; *(modeStringPtr+n+i) != '\0' ; i++ ) {
+ if (!who_found) {
+ /* who */
+ switch (*(modeStringPtr+n+i)) {
+ case 'u':
+ who |= 0x9c0;
+ continue;
+ case 'g':
+ who |= 0x438;
+ continue;
+ case 'o':
+ who |= 0x207;
+ continue;
+ case 'a':
+ who |= 0xfff;
+ continue;
+ }
+ }
+ who_found = 1;
+ if (who == 0) {
+ who = 0xfff;
+ }
+ if (!op_found) {
+ /* op */
+ switch (*(modeStringPtr+n+i)) {
+ case '+':
+ op = 1;
+ op_found = 1;
+ continue;
+ case '-':
+ op = 2;
+ op_found = 1;
+ continue;
+ case '=':
+ op = 3;
+ op_found = 1;
+ continue;
+ default:
+ return TCL_ERROR;
+ }
+ }
+ /* what */
+ switch (*(modeStringPtr+n+i)) {
+ case 'r':
+ what |= 0x124;
+ continue;
+ case 'w':
+ what |= 0x92;
+ continue;
+ case 'x':
+ what |= 0x49;
+ continue;
+ case 's':
+ what |= 0xc00;
+ continue;
+ case 't':
+ what |= 0x200;
+ continue;
+ case ',':
+ break;
+ default:
+ return TCL_ERROR;
+ }
+ if (*(modeStringPtr+n+i) == ',') {
+ i++;
+ break;
+ }
+ }
+ switch (op) {
+ case 1:
+ *modePtr = oldMode | (who & what);
+ continue;
+ case 2:
+ *modePtr = oldMode & ~(who & what);
+ continue;
+ case 3:
+ *modePtr = (oldMode & ~who) | (who & what);
+ continue;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpObjNormalizePath --
+ *
+ * This function scans through a path specification and replaces it, in
+ * place, with a normalized version. A normalized version is one in which
+ * all symlinks in the path are replaced with their expanded form (except
+ * a symlink at the very end of the path).
+ *
+ * Results:
+ * The new 'nextCheckpoint' value, giving as far as we could understand
+ * in the path.
+ *
+ * Side effects:
+ * The pathPtr string, is modified.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpObjNormalizePath(
+ Tcl_Interp *interp,
+ Tcl_Obj *pathPtr,
+ int nextCheckpoint)
+{
+ const char *currentPathEndPosition;
+ char cur;
+ const char *path = TclGetString(pathPtr);
+ size_t pathLen = pathPtr->length;
+ Tcl_DString ds;
+ const char *nativePath;
+#ifndef NO_REALPATH
+ char normPath[MAXPATHLEN];
+#endif
+
+ /*
+ * We add '1' here because if nextCheckpoint is zero we know that '/'
+ * exists, and if it isn't zero, it must point at a directory separator
+ * which we also know exists.
+ */
+
+ currentPathEndPosition = path + nextCheckpoint;
+ if (*currentPathEndPosition == '/') {
+ currentPathEndPosition++;
+ }
+
+#ifndef NO_REALPATH
+ /*
+ * For speed, try to get the entire path in one go.
+ */
+
+ if (nextCheckpoint == 0 && haveRealpath) {
+ char *lastDir = strrchr(currentPathEndPosition, '/');
+
+ if (lastDir != NULL) {
+ nativePath = Tcl_UtfToExternalDString(NULL, path,
+ lastDir-path, &ds);
+ if (Realpath(nativePath, normPath) != NULL) {
+ if (*nativePath != '/' && *normPath == '/') {
+ /*
+ * realpath has transformed a relative path into an
+ * absolute path, we do not know how to handle this.
+ */
+ } else {
+ nextCheckpoint = lastDir - path;
+ goto wholeStringOk;
+ }
+ }
+ Tcl_DStringFree(&ds);
+ }
+ }
+
+ /*
+ * Else do it the slow way.
+ */
+#endif
+
+ while (1) {
+ cur = *currentPathEndPosition;
+ if ((cur == '/') && (path != currentPathEndPosition)) {
+ /*
+ * Reached directory separator.
+ */
+
+ int accessOk;
+
+ nativePath = Tcl_UtfToExternalDString(NULL, path,
+ currentPathEndPosition - path, &ds);
+ accessOk = access(nativePath, F_OK);
+ Tcl_DStringFree(&ds);
+
+ if (accessOk != 0) {
+ /*
+ * File doesn't exist.
+ */
+
+ break;
+ }
+
+ /*
+ * Update the acceptable point.
+ */
+
+ nextCheckpoint = currentPathEndPosition - path;
+ } else if (cur == 0) {
+ /*
+ * Reached end of string.
+ */
+
+ break;
+ }
+ currentPathEndPosition++;
+ }
+
+ /*
+ * We should really now convert this to a canonical path. We do that with
+ * 'realpath' if we have it available. Otherwise we could step through
+ * every single path component, checking whether it is a symlink, but that
+ * would be a lot of work, and most modern OSes have 'realpath'.
+ */
+
+#ifndef NO_REALPATH
+ if (haveRealpath) {
+ /*
+ * If we only had '/foo' or '/' then we never increment nextCheckpoint
+ * and we don't need or want to go through 'Realpath'. Also, on some
+ * platforms, passing an empty string to 'Realpath' will give us the
+ * normalized pwd, which is not what we want at all!
+ */
+
+ if (nextCheckpoint == 0) {
+ return 0;
+ }
+
+ nativePath = Tcl_UtfToExternalDString(NULL, path,nextCheckpoint, &ds);
+ if (Realpath(nativePath, normPath) != NULL) {
+ int newNormLen;
+
+ wholeStringOk:
+ newNormLen = strlen(normPath);
+ if ((newNormLen == Tcl_DStringLength(&ds))
+ && (strcmp(normPath, nativePath) == 0)) {
+ /*
+ * String is unchanged.
+ */
+
+ Tcl_DStringFree(&ds);
+
+ /*
+ * Enable this to have the native FS claim normalization of
+ * the whole path for existing files. That would permit the
+ * caller to declare normalization complete without calls to
+ * additional filesystems. Saving lots of calls is probably
+ * worth the extra access() time here. When no other FS's are
+ * registered though, things are less clear.
+ *
+ if (0 == access(normPath, F_OK)) {
+ return pathLen;
+ }
+ */
+
+ return nextCheckpoint;
+ }
+
+ /*
+ * Free up the native path and put in its place the converted,
+ * normalized path.
+ */
+
+ Tcl_DStringFree(&ds);
+ Tcl_ExternalToUtfDString(NULL, normPath, (int) newNormLen, &ds);
+
+ if (path[nextCheckpoint] != '\0') {
+ /*
+ * Not at end, append remaining path.
+ */
+
+ int normLen = Tcl_DStringLength(&ds);
+
+ Tcl_DStringAppend(&ds, path + nextCheckpoint,
+ pathLen - nextCheckpoint);
+
+ /*
+ * We recognise up to and including the directory separator.
+ */
+
+ nextCheckpoint = normLen + 1;
+ } else {
+ /*
+ * We recognise the whole string.
+ */
+
+ nextCheckpoint = Tcl_DStringLength(&ds);
+ }
+
+ /*
+ * Overwrite with the normalized path.
+ */
+
+ Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds),
+ Tcl_DStringLength(&ds));
+ }
+ Tcl_DStringFree(&ds);
+ }
+#endif /* !NO_REALPATH */
+
+ return nextCheckpoint;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpOpenTemporaryFile, TclUnixOpenTemporaryFile --
+ *
+ * Creates a temporary file, possibly based on the supplied bits and
+ * pieces of template supplied in the first three arguments. If the
+ * fourth argument is non-NULL, it contains a Tcl_Obj to store the name
+ * of the temporary file in (and it is caller's responsibility to clean
+ * up). If the fourth argument is NULL, try to arrange for the temporary
+ * file to go away once it is no longer needed.
+ *
+ * Results:
+ * A read-write Tcl Channel open on the file for TclpOpenTemporaryFile,
+ * or a file descriptor (or -1 on failure) for TclUnixOpenTemporaryFile.
+ *
+ * Side effects:
+ * Accesses the filesystem. Will set the contents of the Tcl_Obj fourth
+ * argument (if that is non-NULL).
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+TclpOpenTemporaryFile(
+ Tcl_Obj *dirObj,
+ Tcl_Obj *basenameObj,
+ Tcl_Obj *extensionObj,
+ Tcl_Obj *resultingNameObj)
+{
+ int fd = TclUnixOpenTemporaryFile(dirObj, basenameObj, extensionObj,
+ resultingNameObj);
+
+ if (fd == -1) {
+ return NULL;
+ }
+ return Tcl_MakeFileChannel(INT2PTR(fd), TCL_READABLE|TCL_WRITABLE);
+}
+
+int
+TclUnixOpenTemporaryFile(
+ Tcl_Obj *dirObj,
+ Tcl_Obj *basenameObj,
+ Tcl_Obj *extensionObj,
+ Tcl_Obj *resultingNameObj)
+{
+ Tcl_DString template, tmp;
+ const char *string;
+ int fd;
+
+ /*
+ * We should also check against making more then TMP_MAX of these.
+ */
+
+ if (dirObj) {
+ string = TclGetString(dirObj);
+ Tcl_UtfToExternalDString(NULL, string, dirObj->length, &template);
+ } else {
+ Tcl_DStringInit(&template);
+ Tcl_DStringAppend(&template, DefaultTempDir(), -1); /* INTL: native */
+ }
+
+ TclDStringAppendLiteral(&template, "/");
+
+ if (basenameObj) {
+ string = TclGetString(basenameObj);
+ Tcl_UtfToExternalDString(NULL, string, basenameObj->length, &tmp);
+ TclDStringAppendDString(&template, &tmp);
+ Tcl_DStringFree(&tmp);
+ } else {
+ TclDStringAppendLiteral(&template, "tcl");
+ }
+
+ TclDStringAppendLiteral(&template, "_XXXXXX");
+
+#ifdef HAVE_MKSTEMPS
+ if (extensionObj) {
+ string = TclGetString(extensionObj);
+ Tcl_UtfToExternalDString(NULL, string, extensionObj->length, &tmp);
+ TclDStringAppendDString(&template, &tmp);
+ fd = mkstemps(Tcl_DStringValue(&template), Tcl_DStringLength(&tmp));
+ Tcl_DStringFree(&tmp);
+ } else
+#endif
+ {
+ fd = mkstemp(Tcl_DStringValue(&template));
+ }
+
+ if (fd == -1) {
+ Tcl_DStringFree(&template);
+ return -1;
+ }
+
+ if (resultingNameObj) {
+ Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&template),
+ Tcl_DStringLength(&template), &tmp);
+ Tcl_SetStringObj(resultingNameObj, Tcl_DStringValue(&tmp),
+ Tcl_DStringLength(&tmp));
+ Tcl_DStringFree(&tmp);
+ } else {
+ /*
+ * Try to delete the file immediately since we're not reporting the
+ * name to anyone. Note that we're *not* handling any errors from
+ * this!
+ */
+
+ unlink(Tcl_DStringValue(&template));
+ errno = 0;
+ }
+ Tcl_DStringFree(&template);
+
+ return fd;
+}
+
+/*
+ * Helper that does *part* of what tempnam() does.
+ */
+
+static const char *
+DefaultTempDir(void)
+{
+ const char *dir;
+ struct stat buf;
+
+ dir = getenv("TMPDIR");
+ if (dir && dir[0] && stat(dir, &buf) == 0 && S_ISDIR(buf.st_mode)
+ && access(dir, W_OK) == 0) {
+ return dir;
+ }
+
+#ifdef P_tmpdir
+ dir = P_tmpdir;
+ if (stat(dir, &buf)==0 && S_ISDIR(buf.st_mode) && access(dir, W_OK)==0) {
+ return dir;
+ }
+#endif
+
+ /*
+ * Assume that the default location ("/tmp" if not overridden) is always
+ * an existing writable directory; we've no recovery mechanism if it
+ * isn't.
+ */
+
+ return TCL_TEMPORARY_FILE_DIRECTORY;
+}
+
+#if defined(__CYGWIN__)
+
+static void
+StatError(
+ Tcl_Interp *interp, /* The interp that has the error */
+ Tcl_Obj *fileName) /* The name of the file which caused the
+ * error. */
+{
+ TclWinConvertError(GetLastError());
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("could not read \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+}
+
+static WCHAR *
+winPathFromObj(
+ Tcl_Obj *fileName)
+{
+ int size;
+ const char *native = Tcl_FSGetNativePath(fileName);
+ WCHAR *winPath;
+
+ size = cygwin_conv_path(1, native, NULL, 0);
+ winPath = ckalloc(size);
+ cygwin_conv_path(1, native, winPath, size);
+
+ return winPath;
+}
+
+static const int attributeArray[] = {
+ 0x20, 0, 2, 0, 0, 1, 4};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetUnixFileAttributes
+ *
+ * Gets the readonly attribute of a file.
+ *
+ * Results:
+ * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
+ * is no error. The object will have ref count 0.
+ *
+ * Side effects:
+ * A new object is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetUnixFileAttributes(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
+{
+ int fileAttributes;
+ WCHAR *winPath = winPathFromObj(fileName);
+
+ fileAttributes = GetFileAttributesW(winPath);
+ ckfree(winPath);
+
+ if (fileAttributes == -1) {
+ StatError(interp, fileName);
+ return TCL_ERROR;
+ }
+
+ *attributePtrPtr = Tcl_NewIntObj((fileAttributes&attributeArray[objIndex])!=0);
+
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SetUnixFileAttributes
+ *
+ * Sets the readonly attribute of a file.
+ *
+ * Results:
+ * Standard TCL result.
+ *
+ * Side effects:
+ * The readonly attribute of the file is changed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+SetUnixFileAttributes(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj *attributePtr) /* The attribute to set. */
+{
+ int yesNo, fileAttributes, old;
+ WCHAR *winPath;
+
+ if (Tcl_GetBooleanFromObj(interp, attributePtr, &yesNo) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ winPath = winPathFromObj(fileName);
+
+ fileAttributes = old = GetFileAttributesW(winPath);
+
+ if (fileAttributes == -1) {
+ ckfree(winPath);
+ StatError(interp, fileName);
+ return TCL_ERROR;
+ }
+
+ if (yesNo) {
+ fileAttributes |= attributeArray[objIndex];
+ } else {
+ fileAttributes &= ~attributeArray[objIndex];
+ }
+
+ if ((fileAttributes != old)
+ && !SetFileAttributesW(winPath, fileAttributes)) {
+ ckfree(winPath);
+ StatError(interp, fileName);
+ return TCL_ERROR;
+ }
+
+ ckfree(winPath);
+ return TCL_OK;
+}
+#elif defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetUnixFileAttributes
+ *
+ * Gets the readonly attribute (user immutable flag) of a file.
+ *
+ * Results:
+ * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there
+ * is no error. The object will have ref count 0.
+ *
+ * Side effects:
+ * A new object is allocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetUnixFileAttributes(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */
+{
+ Tcl_StatBuf statBuf;
+ int result;
+
+ result = TclpObjStat(fileName, &statBuf);
+
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not read \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+
+ *attributePtrPtr = Tcl_NewBooleanObj(statBuf.st_flags&UF_IMMUTABLE);
+
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SetUnixFileAttributes
+ *
+ * Sets the readonly attribute (user immutable flag) of a file.
+ *
+ * Results:
+ * Standard TCL result.
+ *
+ * Side effects:
+ * The readonly attribute of the file is changed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+SetUnixFileAttributes(
+ Tcl_Interp *interp, /* The interp we are using for errors. */
+ int objIndex, /* The index of the attribute. */
+ Tcl_Obj *fileName, /* The name of the file (UTF-8). */
+ Tcl_Obj *attributePtr) /* The attribute to set. */
+{
+ Tcl_StatBuf statBuf;
+ int result, readonly;
+ const char *native;
+
+ if (Tcl_GetBooleanFromObj(interp, attributePtr, &readonly) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ result = TclpObjStat(fileName, &statBuf);
+
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not read \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+
+ if (readonly) {
+ statBuf.st_flags |= UF_IMMUTABLE;
+ } else {
+ statBuf.st_flags &= ~UF_IMMUTABLE;
+ }
+
+ native = Tcl_FSGetNativePath(fileName);
+ result = chflags(native, statBuf.st_flags); /* INTL: Native. */
+ if (result != 0) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "could not set flags for file \"%s\": %s",
+ TclGetString(fileName), Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+#endif /* defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c
new file mode 100644
index 0000000..5f5bfe0
--- /dev/null
+++ b/unix/tclUnixFile.c
@@ -0,0 +1,1244 @@
+/*
+ * tclUnixFile.c --
+ *
+ * This file contains wrappers around UNIX file handling functions.
+ * These wrappers mask differences between Windows and UNIX.
+ *
+ * Copyright (c) 1995-1998 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+#include "tclFileSystem.h"
+
+static int NativeMatchType(Tcl_Interp *interp, const char* nativeEntry,
+ const char* nativeName, Tcl_GlobTypeData *types);
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpFindExecutable --
+ *
+ * This function computes the absolute path name of the current
+ * application, given its argv[0] value. For Cygwin, argv[0] is
+ * ignored and the path is determined the same as under win32.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The computed path name is stored as a ProcessGlobalValue.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TclpFindExecutable(
+ const char *argv0) /* The value of the application's argv[0]
+ * (native). */
+{
+ Tcl_Encoding encoding;
+#ifdef __CYGWIN__
+ int length;
+ char buf[PATH_MAX * 2];
+ char name[PATH_MAX * TCL_UTF_MAX + 1];
+ GetModuleFileNameW(NULL, buf, PATH_MAX);
+ cygwin_conv_path(3, buf, name, PATH_MAX);
+ length = strlen(name);
+ if ((length > 4) && !strcasecmp(name + length - 4, ".exe")) {
+ /* Strip '.exe' part. */
+ length -= 4;
+ }
+ encoding = Tcl_GetEncoding(NULL, NULL);
+ TclSetObjNameOfExecutable(
+ Tcl_NewStringObj(name, length), encoding);
+#else
+ const char *name, *p;
+ Tcl_StatBuf statBuf;
+ Tcl_DString buffer, nameString, cwd, utfName;
+
+ if (argv0 == NULL) {
+ return;
+ }
+ Tcl_DStringInit(&buffer);
+
+ name = argv0;
+ for (p = name; *p != '\0'; p++) {
+ if (*p == '/') {
+ /*
+ * The name contains a slash, so use the name directly without
+ * doing a path search.
+ */
+
+ goto gotName;
+ }
+ }
+
+ p = getenv("PATH"); /* INTL: Native. */
+ if (p == NULL) {
+ /*
+ * There's no PATH environment variable; use the default that is used
+ * by sh.
+ */
+
+ p = ":/bin:/usr/bin";
+ } else if (*p == '\0') {
+ /*
+ * An empty path is equivalent to ".".
+ */
+
+ p = "./";
+ }
+
+ /*
+ * Search through all the directories named in the PATH variable to see if
+ * argv[0] is in one of them. If so, use that file name.
+ */
+
+ while (1) {
+ while (TclIsSpaceProc(*p)) {
+ p++;
+ }
+ name = p;
+ while ((*p != ':') && (*p != 0)) {
+ p++;
+ }
+ TclDStringClear(&buffer);
+ if (p != name) {
+ Tcl_DStringAppend(&buffer, name, p - name);
+ if (p[-1] != '/') {
+ TclDStringAppendLiteral(&buffer, "/");
+ }
+ }
+ name = Tcl_DStringAppend(&buffer, argv0, -1);
+
+ /*
+ * INTL: The following calls to access() and stat() should not be
+ * converted to Tclp routines because they need to operate on native
+ * strings directly.
+ */
+
+ if ((access(name, X_OK) == 0) /* INTL: Native. */
+ && (TclOSstat(name, &statBuf) == 0) /* INTL: Native. */
+ && S_ISREG(statBuf.st_mode)) {
+ goto gotName;
+ }
+ if (*p == '\0') {
+ break;
+ } else if (*(p+1) == 0) {
+ p = "./";
+ } else {
+ p++;
+ }
+ }
+ TclSetObjNameOfExecutable(Tcl_NewObj(), NULL);
+ goto done;
+
+ /*
+ * If the name starts with "/" then just store it
+ */
+
+ gotName:
+#ifdef DJGPP
+ if (name[1] == ':')
+#else
+ if (name[0] == '/')
+#endif
+ {
+ encoding = Tcl_GetEncoding(NULL, NULL);
+ Tcl_ExternalToUtfDString(encoding, name, -1, &utfName);
+ TclSetObjNameOfExecutable(
+ Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
+ Tcl_DStringFree(&utfName);
+ goto done;
+ }
+
+ if (TclpGetCwd(NULL, &cwd) == NULL) {
+ TclSetObjNameOfExecutable(Tcl_NewObj(), NULL);
+ goto done;
+ }
+
+ /*
+ * The name is relative to the current working directory. First strip off
+ * a leading "./", if any, then add the full path name of the current
+ * working directory.
+ */
+
+ if ((name[0] == '.') && (name[1] == '/')) {
+ name += 2;
+ }
+
+ Tcl_DStringInit(&nameString);
+ Tcl_DStringAppend(&nameString, name, -1);
+
+ Tcl_DStringFree(&buffer);
+ Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&cwd),
+ Tcl_DStringLength(&cwd), &buffer);
+ if (Tcl_DStringValue(&cwd)[Tcl_DStringLength(&cwd) -1] != '/') {
+ TclDStringAppendLiteral(&buffer, "/");
+ }
+ Tcl_DStringFree(&cwd);
+ TclDStringAppendDString(&buffer, &nameString);
+ Tcl_DStringFree(&nameString);
+
+ encoding = Tcl_GetEncoding(NULL, NULL);
+ Tcl_ExternalToUtfDString(encoding, Tcl_DStringValue(&buffer), -1,
+ &utfName);
+ TclSetObjNameOfExecutable(
+ Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
+ Tcl_DStringFree(&utfName);
+
+ done:
+ Tcl_DStringFree(&buffer);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpMatchInDirectory --
+ *
+ * This routine is used by the globbing code to search a directory for
+ * all files which match a given pattern.
+ *
+ * Results:
+ * The return value is a standard Tcl result indicating whether an error
+ * occurred in globbing. Errors are left in interp, good results are
+ * [lappend]ed to resultPtr (which must be a valid object).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpMatchInDirectory(
+ Tcl_Interp *interp, /* Interpreter to receive errors. */
+ Tcl_Obj *resultPtr, /* List object to lappend results. */
+ Tcl_Obj *pathPtr, /* Contains path to directory to search. */
+ const char *pattern, /* Pattern to match against. */
+ Tcl_GlobTypeData *types) /* Object containing list of acceptable types.
+ * May be NULL. In particular the directory
+ * flag is very important. */
+{
+ const char *native;
+ Tcl_Obj *fileNamePtr;
+ int matchResult = 0;
+
+ if (types != NULL && types->type == TCL_GLOB_TYPE_MOUNT) {
+ /*
+ * The native filesystem never adds mounts.
+ */
+
+ return TCL_OK;
+ }
+
+ fileNamePtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
+ if (fileNamePtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ if (pattern == NULL || (*pattern == '\0')) {
+ /*
+ * Match a file directly.
+ */
+
+ Tcl_Obj *tailPtr;
+ const char *nativeTail;
+
+ native = Tcl_FSGetNativePath(pathPtr);
+ tailPtr = TclPathPart(interp, pathPtr, TCL_PATH_TAIL);
+ nativeTail = Tcl_FSGetNativePath(tailPtr);
+ matchResult = NativeMatchType(interp, native, nativeTail, types);
+ if (matchResult == 1) {
+ Tcl_ListObjAppendElement(interp, resultPtr, pathPtr);
+ }
+ Tcl_DecrRefCount(tailPtr);
+ Tcl_DecrRefCount(fileNamePtr);
+ } else {
+ DIR *d;
+ Tcl_DirEntry *entryPtr;
+ const char *dirName;
+ size_t dirLength, nativeDirLen;
+ int matchHidden, matchHiddenPat;
+ Tcl_StatBuf statBuf;
+ Tcl_DString ds; /* native encoding of dir */
+ Tcl_DString dsOrig; /* utf-8 encoding of dir */
+
+ Tcl_DStringInit(&dsOrig);
+ dirName = TclGetString(fileNamePtr);
+ dirLength = fileNamePtr->length;
+ Tcl_DStringAppend(&dsOrig, dirName, dirLength);
+
+ /*
+ * Make sure that the directory part of the name really is a
+ * directory. If the directory name is "", use the name "." instead,
+ * because some UNIX systems don't treat "" like "." automatically.
+ * Keep the "" for use in generating file names, otherwise "glob
+ * foo.c" would return "./foo.c".
+ */
+
+ if (dirLength == 0) {
+ dirName = ".";
+ } else {
+ dirName = Tcl_DStringValue(&dsOrig);
+
+ /*
+ * Make sure we have a trailing directory delimiter.
+ */
+
+ if (dirName[dirLength-1] != '/') {
+ dirName = TclDStringAppendLiteral(&dsOrig, "/");
+ dirLength++;
+ }
+ }
+
+ /*
+ * Now open the directory for reading and iterate over the contents.
+ */
+
+ native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds);
+
+ if ((TclOSstat(native, &statBuf) != 0) /* INTL: Native. */
+ || !S_ISDIR(statBuf.st_mode)) {
+ Tcl_DStringFree(&dsOrig);
+ Tcl_DStringFree(&ds);
+ Tcl_DecrRefCount(fileNamePtr);
+ return TCL_OK;
+ }
+
+ d = opendir(native); /* INTL: Native. */
+ if (d == NULL) {
+ Tcl_DStringFree(&ds);
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't read directory \"%s\": %s",
+ Tcl_DStringValue(&dsOrig), Tcl_PosixError(interp)));
+ }
+ Tcl_DStringFree(&dsOrig);
+ Tcl_DecrRefCount(fileNamePtr);
+ return TCL_ERROR;
+ }
+
+ nativeDirLen = Tcl_DStringLength(&ds);
+
+ /*
+ * Check to see if -type or the pattern requests hidden files.
+ */
+
+ matchHiddenPat = (pattern[0] == '.')
+ || ((pattern[0] == '\\') && (pattern[1] == '.'));
+ matchHidden = matchHiddenPat
+ || (types && (types->perm & TCL_GLOB_PERM_HIDDEN));
+ while ((entryPtr = TclOSreaddir(d)) != NULL) { /* INTL: Native. */
+ Tcl_DString utfDs;
+ const char *utfname;
+
+ /*
+ * Skip this file if it doesn't agree with the hidden parameters
+ * requested by the user (via -type or pattern).
+ */
+
+ if (*entryPtr->d_name == '.') {
+ if (!matchHidden) {
+ continue;
+ }
+ } else {
+#ifdef MAC_OSX_TCL
+ if (matchHiddenPat) {
+ continue;
+ }
+ /* Also need to check HFS hidden flag in TclMacOSXMatchType. */
+#else
+ if (matchHidden) {
+ continue;
+ }
+#endif
+ }
+
+ /*
+ * Now check to see if the file matches, according to both type
+ * and pattern. If so, add the file to the result.
+ */
+
+ utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name, -1,
+ &utfDs);
+ if (Tcl_StringCaseMatch(utfname, pattern, 0)) {
+ int typeOk = 1;
+
+ if (types != NULL) {
+ Tcl_DStringSetLength(&ds, nativeDirLen);
+ native = Tcl_DStringAppend(&ds, entryPtr->d_name, -1);
+ matchResult = NativeMatchType(interp, native,
+ entryPtr->d_name, types);
+ typeOk = (matchResult == 1);
+ }
+ if (typeOk) {
+ Tcl_ListObjAppendElement(interp, resultPtr,
+ TclNewFSPathObj(pathPtr, utfname,
+ Tcl_DStringLength(&utfDs)));
+ }
+ }
+ Tcl_DStringFree(&utfDs);
+ if (matchResult < 0) {
+ break;
+ }
+ }
+
+ closedir(d);
+ Tcl_DStringFree(&ds);
+ Tcl_DStringFree(&dsOrig);
+ Tcl_DecrRefCount(fileNamePtr);
+ }
+ if (matchResult < 0) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NativeMatchType --
+ *
+ * This routine is used by the globbing code to check if a file matches a
+ * given type description.
+ *
+ * Results:
+ * The return value is 1, 0 or -1 indicating whether the file matches the
+ * given criteria, does not match them, or an error occurred (in which
+ * case an error is left in interp).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+NativeMatchType(
+ Tcl_Interp *interp, /* Interpreter to receive errors. */
+ const char *nativeEntry, /* Native path to check. */
+ const char *nativeName, /* Native filename to check. */
+ Tcl_GlobTypeData *types) /* Type description to match against. */
+{
+ Tcl_StatBuf buf;
+
+ if (types == NULL) {
+ /*
+ * Simply check for the file's existence, but do it with lstat, in
+ * case it is a link to a file which doesn't exist (since that case
+ * would not show up if we used 'access' or 'stat')
+ */
+
+ if (TclOSlstat(nativeEntry, &buf) != 0) {
+ return 0;
+ }
+ return 1;
+ }
+
+ if (types->perm != 0) {
+ if (TclOSstat(nativeEntry, &buf) != 0) {
+ /*
+ * Either the file has disappeared between the 'readdir' call and
+ * the 'stat' call, or the file is a link to a file which doesn't
+ * exist (which we could ascertain with lstat), or there is some
+ * other strange problem. In all these cases, we define this to
+ * mean the file does not match any defined permission, and
+ * therefore it is not added to the list of files to return.
+ */
+
+ return 0;
+ }
+
+ /*
+ * readonly means that there are NO write permissions (even for user),
+ * but execute is OK for anybody OR that the user immutable flag is
+ * set (where supported).
+ */
+
+ if (((types->perm & TCL_GLOB_PERM_RONLY) &&
+#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
+ !(buf.st_flags & UF_IMMUTABLE) &&
+#endif
+ (buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) ||
+ ((types->perm & TCL_GLOB_PERM_R) &&
+ (access(nativeEntry, R_OK) != 0)) ||
+ ((types->perm & TCL_GLOB_PERM_W) &&
+ (access(nativeEntry, W_OK) != 0)) ||
+ ((types->perm & TCL_GLOB_PERM_X) &&
+ (access(nativeEntry, X_OK) != 0))
+#ifndef MAC_OSX_TCL
+ || ((types->perm & TCL_GLOB_PERM_HIDDEN) &&
+ (*nativeName != '.'))
+#endif /* MAC_OSX_TCL */
+ ) {
+ return 0;
+ }
+ }
+ if (types->type != 0) {
+ if (types->perm == 0) {
+ /*
+ * We haven't yet done a stat on the file.
+ */
+
+ if (TclOSstat(nativeEntry, &buf) != 0) {
+ /*
+ * Posix error occurred. The only ok case is if this is a link
+ * to a nonexistent file, and the user did 'glob -l'. So we
+ * check that here:
+ */
+
+ if ((types->type & TCL_GLOB_TYPE_LINK)
+ && (TclOSlstat(nativeEntry, &buf) == 0)
+ && S_ISLNK(buf.st_mode)) {
+ return 1;
+ }
+ return 0;
+ }
+ }
+
+ /*
+ * In order bcdpsfl as in 'find -t'
+ */
+
+ if ( ((types->type & TCL_GLOB_TYPE_BLOCK)&& S_ISBLK(buf.st_mode)) ||
+ ((types->type & TCL_GLOB_TYPE_CHAR) && S_ISCHR(buf.st_mode)) ||
+ ((types->type & TCL_GLOB_TYPE_DIR) && S_ISDIR(buf.st_mode)) ||
+ ((types->type & TCL_GLOB_TYPE_PIPE) && S_ISFIFO(buf.st_mode))||
+#ifdef S_ISSOCK
+ ((types->type & TCL_GLOB_TYPE_SOCK) && S_ISSOCK(buf.st_mode))||
+#endif /* S_ISSOCK */
+ ((types->type & TCL_GLOB_TYPE_FILE) && S_ISREG(buf.st_mode))) {
+ /*
+ * Do nothing - this file is ok.
+ */
+ } else {
+#ifdef S_ISLNK
+ if ((types->type & TCL_GLOB_TYPE_LINK)
+ && (TclOSlstat(nativeEntry, &buf) == 0)
+ && S_ISLNK(buf.st_mode)) {
+ goto filetypeOK;
+ }
+#endif /* S_ISLNK */
+ return 0;
+ }
+ }
+ filetypeOK:
+
+ /*
+ * If we're on OSX, we also have to worry about matching the file creator
+ * code (if specified). Do that now.
+ */
+
+#ifdef MAC_OSX_TCL
+ if (types->macType != NULL || types->macCreator != NULL ||
+ (types->perm & TCL_GLOB_PERM_HIDDEN)) {
+ int matchResult;
+
+ if (types->perm == 0 && types->type == 0) {
+ /*
+ * We haven't yet done a stat on the file.
+ */
+
+ if (TclOSstat(nativeEntry, &buf) != 0) {
+ return 0;
+ }
+ }
+
+ matchResult = TclMacOSXMatchType(interp, nativeEntry, nativeName,
+ &buf, types);
+ if (matchResult != 1) {
+ return matchResult;
+ }
+ }
+#endif /* MAC_OSX_TCL */
+
+ return 1;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpGetUserHome --
+ *
+ * This function takes the specified user name and finds their home
+ * directory.
+ *
+ * Results:
+ * The result is a pointer to a string specifying the user's home
+ * directory, or NULL if the user's home directory could not be
+ * determined. Storage for the result string is allocated in bufferPtr;
+ * the caller must call Tcl_DStringFree() when the result is no longer
+ * needed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const char *
+TclpGetUserHome(
+ const char *name, /* User name for desired home directory. */
+ Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with
+ * name of user's home directory. */
+{
+ struct passwd *pwPtr;
+ Tcl_DString ds;
+ const char *native = Tcl_UtfToExternalDString(NULL, name, -1, &ds);
+
+ pwPtr = TclpGetPwNam(native); /* INTL: Native. */
+ Tcl_DStringFree(&ds);
+
+ if (pwPtr == NULL) {
+ return NULL;
+ }
+ Tcl_ExternalToUtfDString(NULL, pwPtr->pw_dir, -1, bufferPtr);
+ return Tcl_DStringValue(bufferPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpObjAccess --
+ *
+ * This function replaces the library version of access().
+ *
+ * Results:
+ * See access() documentation.
+ *
+ * Side effects:
+ * See access() documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpObjAccess(
+ Tcl_Obj *pathPtr, /* Path of file to access */
+ int mode) /* Permission setting. */
+{
+ const char *path = Tcl_FSGetNativePath(pathPtr);
+
+ if (path == NULL) {
+ return -1;
+ }
+ return access(path, mode);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpObjChdir --
+ *
+ * This function replaces the library version of chdir().
+ *
+ * Results:
+ * See chdir() documentation.
+ *
+ * Side effects:
+ * See chdir() documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpObjChdir(
+ Tcl_Obj *pathPtr) /* Path to new working directory */
+{
+ const char *path = Tcl_FSGetNativePath(pathPtr);
+
+ if (path == NULL) {
+ return -1;
+ }
+ return chdir(path);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpObjLstat --
+ *
+ * This function replaces the library version of lstat().
+ *
+ * Results:
+ * See lstat() documentation.
+ *
+ * Side effects:
+ * See lstat() documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpObjLstat(
+ Tcl_Obj *pathPtr, /* Path of file to stat */
+ Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */
+{
+ return TclOSlstat(Tcl_FSGetNativePath(pathPtr), bufPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpGetNativeCwd --
+ *
+ * This function replaces the library version of getcwd().
+ *
+ * Results:
+ * The input and output are filesystem paths in native form. The result
+ * is either the given clientData, if the working directory hasn't
+ * changed, or a new clientData (owned by our caller), giving the new
+ * native path, or NULL if the current directory could not be determined.
+ * If NULL is returned, the caller can examine the standard posix error
+ * codes to determine the cause of the problem.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ClientData
+TclpGetNativeCwd(
+ ClientData clientData)
+{
+ char buffer[MAXPATHLEN+1];
+
+#ifdef USEGETWD
+ if (getwd(buffer) == NULL) { /* INTL: Native. */
+ return NULL;
+ }
+#else
+ if (getcwd(buffer, MAXPATHLEN+1) == NULL) { /* INTL: Native. */
+ return NULL;
+ }
+#endif /* USEGETWD */
+
+ if ((clientData == NULL) || strcmp(buffer, (const char *) clientData)) {
+ char *newCd = ckalloc(strlen(buffer) + 1);
+
+ strcpy(newCd, buffer);
+ return newCd;
+ }
+
+ /*
+ * No change to pwd.
+ */
+
+ return clientData;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpGetCwd --
+ *
+ * This function replaces the library version of getcwd(). (Obsolete
+ * function, only retained for old extensions which may call it
+ * directly).
+ *
+ * Results:
+ * The result is a pointer to a string specifying the current directory,
+ * or NULL if the current directory could not be determined. If NULL is
+ * returned, an error message is left in the interp's result. Storage for
+ * the result string is allocated in bufferPtr; the caller must call
+ * Tcl_DStringFree() when the result is no longer needed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+const char *
+TclpGetCwd(
+ Tcl_Interp *interp, /* If non-NULL, used for error reporting. */
+ Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with
+ * name of current directory. */
+{
+ char buffer[MAXPATHLEN+1];
+
+#ifdef USEGETWD
+ if (getwd(buffer) == NULL) /* INTL: Native. */
+#else
+ if (getcwd(buffer, MAXPATHLEN+1) == NULL) /* INTL: Native. */
+#endif /* USEGETWD */
+ {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "error getting working directory name: %s",
+ Tcl_PosixError(interp)));
+ }
+ return NULL;
+ }
+ return Tcl_ExternalToUtfDString(NULL, buffer, -1, bufferPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpReadlink --
+ *
+ * This function replaces the library version of readlink().
+ *
+ * Results:
+ * The result is a pointer to a string specifying the contents of the
+ * symbolic link given by 'path', or NULL if the symbolic link could not
+ * be read. Storage for the result string is allocated in bufferPtr; the
+ * caller must call Tcl_DStringFree() when the result is no longer
+ * needed.
+ *
+ * Side effects:
+ * See readlink() documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+char *
+TclpReadlink(
+ const char *path, /* Path of file to readlink (UTF-8). */
+ Tcl_DString *linkPtr) /* Uninitialized or free DString filled with
+ * contents of link (UTF-8). */
+{
+#ifndef DJGPP
+ char link[MAXPATHLEN];
+ int length;
+ const char *native;
+ Tcl_DString ds;
+
+ native = Tcl_UtfToExternalDString(NULL, path, -1, &ds);
+ length = readlink(native, link, sizeof(link)); /* INTL: Native. */
+ Tcl_DStringFree(&ds);
+
+ if (length < 0) {
+ return NULL;
+ }
+
+ Tcl_ExternalToUtfDString(NULL, link, length, linkPtr);
+ return Tcl_DStringValue(linkPtr);
+#else
+ return NULL;
+#endif /* !DJGPP */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpObjStat --
+ *
+ * This function replaces the library version of stat().
+ *
+ * Results:
+ * See stat() documentation.
+ *
+ * Side effects:
+ * See stat() documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpObjStat(
+ Tcl_Obj *pathPtr, /* Path of file to stat */
+ Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */
+{
+ const char *path = Tcl_FSGetNativePath(pathPtr);
+
+ if (path == NULL) {
+ return -1;
+ }
+ return TclOSstat(path, bufPtr);
+}
+
+#ifdef S_IFLNK
+
+Tcl_Obj *
+TclpObjLink(
+ Tcl_Obj *pathPtr,
+ Tcl_Obj *toPtr,
+ int linkAction)
+{
+ if (toPtr != NULL) {
+ const char *src = Tcl_FSGetNativePath(pathPtr);
+ const char *target = NULL;
+
+ if (src == NULL) {
+ return NULL;
+ }
+
+ /*
+ * If we're making a symbolic link and the path is relative, then we
+ * must check whether it exists _relative_ to the directory in which
+ * the src is found (not relative to the current cwd which is just not
+ * relevant in this case).
+ *
+ * If we're making a hard link, then a relative path is just converted
+ * to absolute relative to the cwd.
+ */
+
+ if ((linkAction & TCL_CREATE_SYMBOLIC_LINK)
+ && (Tcl_FSGetPathType(toPtr) == TCL_PATH_RELATIVE)) {
+ Tcl_Obj *dirPtr, *absPtr;
+
+ dirPtr = TclPathPart(NULL, pathPtr, TCL_PATH_DIRNAME);
+ if (dirPtr == NULL) {
+ return NULL;
+ }
+ absPtr = Tcl_FSJoinToPath(dirPtr, 1, &toPtr);
+ Tcl_IncrRefCount(absPtr);
+ if (Tcl_FSAccess(absPtr, F_OK) == -1) {
+ Tcl_DecrRefCount(absPtr);
+ Tcl_DecrRefCount(dirPtr);
+
+ /*
+ * Target doesn't exist.
+ */
+
+ errno = ENOENT;
+ return NULL;
+ }
+
+ /*
+ * Target exists; we'll construct the relative path we want below.
+ */
+
+ Tcl_DecrRefCount(absPtr);
+ Tcl_DecrRefCount(dirPtr);
+ } else {
+ target = Tcl_FSGetNativePath(toPtr);
+ if (target == NULL) {
+ return NULL;
+ }
+ if (access(target, F_OK) == -1) {
+ /*
+ * Target doesn't exist.
+ */
+
+ errno = ENOENT;
+ return NULL;
+ }
+ }
+
+ if (access(src, F_OK) != -1) {
+ /*
+ * Src exists.
+ */
+
+ errno = EEXIST;
+ return NULL;
+ }
+
+ /*
+ * Check symbolic link flag first, since we prefer to create these.
+ */
+
+ if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
+ Tcl_DString ds;
+ Tcl_Obj *transPtr;
+
+ /*
+ * Now we don't want to link to the absolute, normalized path.
+ * Relative links are quite acceptable (but links to ~user are not
+ * -- these must be expanded first).
+ */
+
+ transPtr = Tcl_FSGetTranslatedPath(NULL, toPtr);
+ if (transPtr == NULL) {
+ return NULL;
+ }
+ target = TclGetString(transPtr);
+ target = Tcl_UtfToExternalDString(NULL, target, transPtr->length, &ds);
+ Tcl_DecrRefCount(transPtr);
+
+ if (symlink(target, src) != 0) {
+ toPtr = NULL;
+ }
+ Tcl_DStringFree(&ds);
+ } else if (linkAction & TCL_CREATE_HARD_LINK) {
+ if (link(target, src) != 0) {
+ return NULL;
+ }
+ } else {
+ errno = ENODEV;
+ return NULL;
+ }
+ return toPtr;
+ } else {
+ Tcl_Obj *linkPtr = NULL;
+
+ char link[MAXPATHLEN];
+ int length;
+ Tcl_DString ds;
+ Tcl_Obj *transPtr;
+
+ transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
+ if (transPtr == NULL) {
+ return NULL;
+ }
+ Tcl_DecrRefCount(transPtr);
+
+ length = readlink(Tcl_FSGetNativePath(pathPtr), link, sizeof(link));
+ if (length < 0) {
+ return NULL;
+ }
+
+ Tcl_ExternalToUtfDString(NULL, link, length, &ds);
+ linkPtr = TclDStringToObj(&ds);
+ Tcl_IncrRefCount(linkPtr);
+ return linkPtr;
+ }
+}
+#endif /* S_IFLNK */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpFilesystemPathType --
+ *
+ * This function is part of the native filesystem support, and returns
+ * the path type of the given path. Right now it simply returns NULL. In
+ * the future it could return specific path types, like 'nfs', 'samba',
+ * 'FAT32', etc.
+ *
+ * Results:
+ * NULL at present.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclpFilesystemPathType(
+ Tcl_Obj *pathPtr)
+{
+ /*
+ * All native paths are of the same type.
+ */
+
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpNativeToNormalized --
+ *
+ * Convert native format to a normalized path object, with refCount of
+ * zero.
+ *
+ * Currently assumes all native paths are actually normalized already, so
+ * if the path given is not normalized this will actually just convert to
+ * a valid string path, but not necessarily a normalized one.
+ *
+ * Results:
+ * A valid normalized path.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclpNativeToNormalized(
+ ClientData clientData)
+{
+ Tcl_DString ds;
+
+ Tcl_ExternalToUtfDString(NULL, (const char *) clientData, -1, &ds);
+ return TclDStringToObj(&ds);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclNativeCreateNativeRep --
+ *
+ * Create a native representation for the given path.
+ *
+ * Results:
+ * The nativePath representation.
+ *
+ * Side effects:
+ * Memory will be allocated. The path may need to be normalized.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+ClientData
+TclNativeCreateNativeRep(
+ Tcl_Obj *pathPtr)
+{
+ char *nativePathPtr;
+ const char *str;
+ Tcl_DString ds;
+ Tcl_Obj *validPathPtr;
+ size_t len;
+
+ if (TclFSCwdIsNative()) {
+ /*
+ * The cwd is native, which means we can use the translated path
+ * without worrying about normalization (this will also usually be
+ * shorter so the utf-to-external conversion will be somewhat faster).
+ */
+
+ validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
+ if (validPathPtr == NULL) {
+ return NULL;
+ }
+ } else {
+ /*
+ * Make sure the normalized path is set.
+ */
+
+ validPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
+ if (validPathPtr == NULL) {
+ return NULL;
+ }
+ Tcl_IncrRefCount(validPathPtr);
+ }
+
+ str = TclGetString(validPathPtr);
+ len = validPathPtr->length;
+ Tcl_UtfToExternalDString(NULL, str, len, &ds);
+ len = Tcl_DStringLength(&ds) + sizeof(char);
+ if (strlen(Tcl_DStringValue(&ds)) < len - sizeof(char)) {
+ /* See bug [3118489]: NUL in filenames */
+ Tcl_DecrRefCount(validPathPtr);
+ Tcl_DStringFree(&ds);
+ return NULL;
+ }
+ Tcl_DecrRefCount(validPathPtr);
+ nativePathPtr = ckalloc(len);
+ memcpy(nativePathPtr, Tcl_DStringValue(&ds), (size_t) len);
+
+ Tcl_DStringFree(&ds);
+ return nativePathPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclNativeDupInternalRep --
+ *
+ * Duplicate the native representation.
+ *
+ * Results:
+ * The copied native representation, or NULL if it is not possible to
+ * copy the representation.
+ *
+ * Side effects:
+ * Memory will be allocated for the copy.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+ClientData
+TclNativeDupInternalRep(
+ ClientData clientData)
+{
+ char *copy;
+ size_t len;
+
+ if (clientData == NULL) {
+ return NULL;
+ }
+
+ /*
+ * ASCII representation when running on Unix.
+ */
+
+ len = (strlen((const char*) clientData) + 1) * sizeof(char);
+
+ copy = ckalloc(len);
+ memcpy(copy, clientData, len);
+ return copy;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpUtime --
+ *
+ * Set the modification date for a file.
+ *
+ * Results:
+ * 0 on success, -1 on error.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TclpUtime(
+ Tcl_Obj *pathPtr, /* File to modify */
+ struct utimbuf *tval) /* New modification date structure */
+{
+ return utime(Tcl_FSGetNativePath(pathPtr), tval);
+}
+
+#ifdef __CYGWIN__
+
+int
+TclOSstat(
+ const char *name,
+ void *cygstat)
+{
+ struct stat buf;
+ Tcl_StatBuf *statBuf = cygstat;
+ int result = stat(name, &buf);
+
+ statBuf->st_mode = buf.st_mode;
+ statBuf->st_ino = buf.st_ino;
+ statBuf->st_dev = buf.st_dev;
+ statBuf->st_rdev = buf.st_rdev;
+ statBuf->st_nlink = buf.st_nlink;
+ statBuf->st_uid = buf.st_uid;
+ statBuf->st_gid = buf.st_gid;
+ statBuf->st_size = buf.st_size;
+ statBuf->st_atime = buf.st_atime;
+ statBuf->st_mtime = buf.st_mtime;
+ statBuf->st_ctime = buf.st_ctime;
+ return result;
+}
+
+int
+TclOSlstat(
+ const char *name,
+ void *cygstat)
+{
+ struct stat buf;
+ Tcl_StatBuf *statBuf = cygstat;
+ int result = lstat(name, &buf);
+
+ statBuf->st_mode = buf.st_mode;
+ statBuf->st_ino = buf.st_ino;
+ statBuf->st_dev = buf.st_dev;
+ statBuf->st_rdev = buf.st_rdev;
+ statBuf->st_nlink = buf.st_nlink;
+ statBuf->st_uid = buf.st_uid;
+ statBuf->st_gid = buf.st_gid;
+ statBuf->st_size = buf.st_size;
+ statBuf->st_atime = buf.st_atime;
+ statBuf->st_mtime = buf.st_mtime;
+ statBuf->st_ctime = buf.st_ctime;
+ return result;
+}
+#endif /* CYGWIN */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c
new file mode 100644
index 0000000..feeffa6
--- /dev/null
+++ b/unix/tclUnixInit.c
@@ -0,0 +1,1087 @@
+/*
+ * tclUnixInit.c --
+ *
+ * Contains the Unix-specific interpreter initialization functions.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1999 by Scriptics Corporation.
+ * All rights reserved.
+ */
+
+#include "tclInt.h"
+#include <stddef.h>
+#include <locale.h>
+#ifdef HAVE_LANGINFO
+# include <langinfo.h>
+# ifdef __APPLE__
+# if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1030
+ /* Support for weakly importing nl_langinfo on Darwin. */
+# define WEAK_IMPORT_NL_LANGINFO
+ extern char *nl_langinfo(nl_item) WEAK_IMPORT_ATTRIBUTE;
+# endif
+# endif
+#endif
+#include <sys/resource.h>
+#if defined(__FreeBSD__) && defined(__GNUC__)
+# include <floatingpoint.h>
+#endif
+#if defined(__bsdi__)
+# include <sys/param.h>
+# if _BSDI_VERSION > 199501
+# include <dlfcn.h>
+# endif
+#endif
+
+#ifdef __CYGWIN__
+DLLIMPORT extern __stdcall unsigned char GetVersionExW(void *);
+DLLIMPORT extern __stdcall void *GetModuleHandleW(const void *);
+DLLIMPORT extern __stdcall void FreeLibrary(void *);
+DLLIMPORT extern __stdcall void *GetProcAddress(void *, const char *);
+DLLIMPORT extern __stdcall void GetSystemInfo(void *);
+
+#define NUMPLATFORMS 4
+static const char *const platforms[NUMPLATFORMS] = {
+ "Win32s", "Windows 95", "Windows NT", "Windows CE"
+};
+
+#define NUMPROCESSORS 11
+static const char *const processors[NUMPROCESSORS] = {
+ "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
+ "amd64", "ia32_on_win64"
+};
+
+typedef struct {
+ union {
+ DWORD dwOemId;
+ struct {
+ int wProcessorArchitecture;
+ int wReserved;
+ };
+ };
+ DWORD dwPageSize;
+ void *lpMinimumApplicationAddress;
+ void *lpMaximumApplicationAddress;
+ void *dwActiveProcessorMask;
+ DWORD dwNumberOfProcessors;
+ DWORD dwProcessorType;
+ DWORD dwAllocationGranularity;
+ int wProcessorLevel;
+ int wProcessorRevision;
+} SYSTEM_INFO;
+
+typedef struct {
+ DWORD dwOSVersionInfoSize;
+ DWORD dwMajorVersion;
+ DWORD dwMinorVersion;
+ DWORD dwBuildNumber;
+ DWORD dwPlatformId;
+ wchar_t szCSDVersion[128];
+} OSVERSIONINFOW;
+#endif
+
+#ifdef HAVE_COREFOUNDATION
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+/*
+ * Tcl tries to use standard and homebrew methods to guess the right encoding
+ * on the platform. However, there is always a final fallback, and this value
+ * is it. Make sure it is a real Tcl encoding.
+ */
+
+#ifndef TCL_DEFAULT_ENCODING
+#define TCL_DEFAULT_ENCODING "iso8859-1"
+#endif
+
+/*
+ * Default directory in which to look for Tcl library scripts. The symbol is
+ * defined by Makefile.
+ */
+
+static char defaultLibraryDir[sizeof(TCL_LIBRARY)+200] = TCL_LIBRARY;
+
+/*
+ * Directory in which to look for packages (each package is typically
+ * installed as a subdirectory of this directory). The symbol is defined by
+ * Makefile.
+ */
+
+static char pkgPath[sizeof(TCL_PACKAGE_PATH)+200] = TCL_PACKAGE_PATH;
+
+/*
+ * The following table is used to map from Unix locale strings to encoding
+ * files. If HAVE_LANGINFO is defined, then this is a fallback table when the
+ * result from nl_langinfo isn't a recognized encoding. Otherwise this is the
+ * first list checked for a mapping from env encoding to Tcl encoding name.
+ */
+
+typedef struct {
+ const char *lang;
+ const char *encoding;
+} LocaleTable;
+
+/*
+ * The table below is sorted for the sake of doing binary searches on it. The
+ * indenting reflects different categories of data. The leftmost data
+ * represent the encoding names directly implemented by data files in Tcl's
+ * default encoding directory. Indented by one TAB are the encoding names that
+ * are common alternative spellings. Indented by two TABs are the accumulated
+ * "bug fixes" that have been added to deal with the wide variability seen
+ * among existing platforms.
+ */
+
+static const LocaleTable localeTable[] = {
+ {"", "iso8859-1"},
+ {"ansi-1251", "cp1251"},
+ {"ansi_x3.4-1968", "iso8859-1"},
+ {"ascii", "ascii"},
+ {"big5", "big5"},
+ {"cp1250", "cp1250"},
+ {"cp1251", "cp1251"},
+ {"cp1252", "cp1252"},
+ {"cp1253", "cp1253"},
+ {"cp1254", "cp1254"},
+ {"cp1255", "cp1255"},
+ {"cp1256", "cp1256"},
+ {"cp1257", "cp1257"},
+ {"cp1258", "cp1258"},
+ {"cp437", "cp437"},
+ {"cp737", "cp737"},
+ {"cp775", "cp775"},
+ {"cp850", "cp850"},
+ {"cp852", "cp852"},
+ {"cp855", "cp855"},
+ {"cp857", "cp857"},
+ {"cp860", "cp860"},
+ {"cp861", "cp861"},
+ {"cp862", "cp862"},
+ {"cp863", "cp863"},
+ {"cp864", "cp864"},
+ {"cp865", "cp865"},
+ {"cp866", "cp866"},
+ {"cp869", "cp869"},
+ {"cp874", "cp874"},
+ {"cp932", "cp932"},
+ {"cp936", "cp936"},
+ {"cp949", "cp949"},
+ {"cp950", "cp950"},
+ {"dingbats", "dingbats"},
+ {"ebcdic", "ebcdic"},
+ {"euc-cn", "euc-cn"},
+ {"euc-jp", "euc-jp"},
+ {"euc-kr", "euc-kr"},
+ {"eucjp", "euc-jp"},
+ {"euckr", "euc-kr"},
+ {"euctw", "euc-cn"},
+ {"gb12345", "gb12345"},
+ {"gb1988", "gb1988"},
+ {"gb2312", "gb2312"},
+ {"gb2312-1980", "gb2312"},
+ {"gb2312-raw", "gb2312-raw"},
+ {"greek8", "cp869"},
+ {"ibm1250", "cp1250"},
+ {"ibm1251", "cp1251"},
+ {"ibm1252", "cp1252"},
+ {"ibm1253", "cp1253"},
+ {"ibm1254", "cp1254"},
+ {"ibm1255", "cp1255"},
+ {"ibm1256", "cp1256"},
+ {"ibm1257", "cp1257"},
+ {"ibm1258", "cp1258"},
+ {"ibm437", "cp437"},
+ {"ibm737", "cp737"},
+ {"ibm775", "cp775"},
+ {"ibm850", "cp850"},
+ {"ibm852", "cp852"},
+ {"ibm855", "cp855"},
+ {"ibm857", "cp857"},
+ {"ibm860", "cp860"},
+ {"ibm861", "cp861"},
+ {"ibm862", "cp862"},
+ {"ibm863", "cp863"},
+ {"ibm864", "cp864"},
+ {"ibm865", "cp865"},
+ {"ibm866", "cp866"},
+ {"ibm869", "cp869"},
+ {"ibm874", "cp874"},
+ {"ibm932", "cp932"},
+ {"ibm936", "cp936"},
+ {"ibm949", "cp949"},
+ {"ibm950", "cp950"},
+ {"iso-2022", "iso2022"},
+ {"iso-2022-jp", "iso2022-jp"},
+ {"iso-2022-kr", "iso2022-kr"},
+ {"iso-8859-1", "iso8859-1"},
+ {"iso-8859-10", "iso8859-10"},
+ {"iso-8859-13", "iso8859-13"},
+ {"iso-8859-14", "iso8859-14"},
+ {"iso-8859-15", "iso8859-15"},
+ {"iso-8859-16", "iso8859-16"},
+ {"iso-8859-2", "iso8859-2"},
+ {"iso-8859-3", "iso8859-3"},
+ {"iso-8859-4", "iso8859-4"},
+ {"iso-8859-5", "iso8859-5"},
+ {"iso-8859-6", "iso8859-6"},
+ {"iso-8859-7", "iso8859-7"},
+ {"iso-8859-8", "iso8859-8"},
+ {"iso-8859-9", "iso8859-9"},
+ {"iso2022", "iso2022"},
+ {"iso2022-jp", "iso2022-jp"},
+ {"iso2022-kr", "iso2022-kr"},
+ {"iso8859-1", "iso8859-1"},
+ {"iso8859-10", "iso8859-10"},
+ {"iso8859-13", "iso8859-13"},
+ {"iso8859-14", "iso8859-14"},
+ {"iso8859-15", "iso8859-15"},
+ {"iso8859-16", "iso8859-16"},
+ {"iso8859-2", "iso8859-2"},
+ {"iso8859-3", "iso8859-3"},
+ {"iso8859-4", "iso8859-4"},
+ {"iso8859-5", "iso8859-5"},
+ {"iso8859-6", "iso8859-6"},
+ {"iso8859-7", "iso8859-7"},
+ {"iso8859-8", "iso8859-8"},
+ {"iso8859-9", "iso8859-9"},
+ {"iso88591", "iso8859-1"},
+ {"iso885915", "iso8859-15"},
+ {"iso88592", "iso8859-2"},
+ {"iso88595", "iso8859-5"},
+ {"iso88596", "iso8859-6"},
+ {"iso88597", "iso8859-7"},
+ {"iso88598", "iso8859-8"},
+ {"iso88599", "iso8859-9"},
+#ifdef hpux
+ {"ja", "shiftjis"},
+#else
+ {"ja", "euc-jp"},
+#endif
+ {"ja_jp", "euc-jp"},
+ {"ja_jp.euc", "euc-jp"},
+ {"ja_jp.eucjp", "euc-jp"},
+ {"ja_jp.jis", "iso2022-jp"},
+ {"ja_jp.mscode", "shiftjis"},
+ {"ja_jp.sjis", "shiftjis"},
+ {"ja_jp.ujis", "euc-jp"},
+ {"japan", "euc-jp"},
+#ifdef hpux
+ {"japanese", "shiftjis"},
+#else
+ {"japanese", "euc-jp"},
+#endif
+ {"japanese-sjis", "shiftjis"},
+ {"japanese-ujis", "euc-jp"},
+ {"japanese.euc", "euc-jp"},
+ {"japanese.sjis", "shiftjis"},
+ {"jis0201", "jis0201"},
+ {"jis0208", "jis0208"},
+ {"jis0212", "jis0212"},
+ {"jp_jp", "shiftjis"},
+ {"ko", "euc-kr"},
+ {"ko_kr", "euc-kr"},
+ {"ko_kr.euc", "euc-kr"},
+ {"ko_kw.euckw", "euc-kr"},
+ {"koi8-r", "koi8-r"},
+ {"koi8-u", "koi8-u"},
+ {"korean", "euc-kr"},
+ {"ksc5601", "ksc5601"},
+ {"maccenteuro", "macCentEuro"},
+ {"maccroatian", "macCroatian"},
+ {"maccyrillic", "macCyrillic"},
+ {"macdingbats", "macDingbats"},
+ {"macgreek", "macGreek"},
+ {"maciceland", "macIceland"},
+ {"macjapan", "macJapan"},
+ {"macroman", "macRoman"},
+ {"macromania", "macRomania"},
+ {"macthai", "macThai"},
+ {"macturkish", "macTurkish"},
+ {"macukraine", "macUkraine"},
+ {"roman8", "iso8859-1"},
+ {"ru", "iso8859-5"},
+ {"ru_ru", "iso8859-5"},
+ {"ru_su", "iso8859-5"},
+ {"shiftjis", "shiftjis"},
+ {"sjis", "shiftjis"},
+ {"symbol", "symbol"},
+ {"tis-620", "tis-620"},
+ {"tis620", "tis-620"},
+ {"turkish8", "cp857"},
+ {"utf8", "utf-8"},
+ {"zh", "cp936"},
+ {"zh_cn.gb2312", "euc-cn"},
+ {"zh_cn.gbk", "euc-cn"},
+ {"zh_cz.gb2312", "euc-cn"},
+ {"zh_tw", "euc-tw"},
+ {"zh_tw.big5", "big5"},
+};
+
+#ifdef HAVE_COREFOUNDATION
+static int MacOSXGetLibraryPath(Tcl_Interp *interp,
+ int maxPathLen, char *tclLibPath);
+#endif /* HAVE_COREFOUNDATION */
+#if defined(__APPLE__) && (defined(TCL_LOAD_FROM_MEMORY) || ( \
+ defined(MAC_OS_X_VERSION_MIN_REQUIRED) && ( \
+ (defined(TCL_THREADS) && MAC_OS_X_VERSION_MIN_REQUIRED < 1030) || \
+ (defined(__LP64__) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050) || \
+ (defined(HAVE_COREFOUNDATION) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050)\
+ )))
+/*
+ * Need to check Darwin release at runtime in tclUnixFCmd.c and tclLoadDyld.c:
+ * initialize release global at startup from uname().
+ */
+#define GET_DARWIN_RELEASE 1
+MODULE_SCOPE long tclMacOSXDarwinRelease;
+long tclMacOSXDarwinRelease = 0;
+#endif
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpInitPlatform --
+ *
+ * Initialize all the platform-dependant things like signals and
+ * floating-point error handling.
+ *
+ * Called at process initialization time.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TclpInitPlatform(void)
+{
+#ifdef DJGPP
+ tclPlatform = TCL_PLATFORM_WINDOWS;
+#else
+ tclPlatform = TCL_PLATFORM_UNIX;
+#endif
+
+ /*
+ * Make sure, that the standard FDs exist. [Bug 772288]
+ */
+
+ if (TclOSseek(0, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
+ open("/dev/null", O_RDONLY);
+ }
+ if (TclOSseek(1, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
+ open("/dev/null", O_WRONLY);
+ }
+ if (TclOSseek(2, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
+ open("/dev/null", O_WRONLY);
+ }
+
+ /*
+ * The code below causes SIGPIPE (broken pipe) errors to be ignored. This
+ * is needed so that Tcl processes don't die if they create child
+ * processes (e.g. using "exec" or "open") that terminate prematurely.
+ * The signal handler is only set up when the first interpreter is
+ * created; after this the application can override the handler with a
+ * different one of its own, if it wants.
+ */
+
+#ifdef SIGPIPE
+ (void) signal(SIGPIPE, SIG_IGN);
+#endif /* SIGPIPE */
+
+#if defined(__FreeBSD__) && defined(__GNUC__)
+ (void) fpsetmask(0L);
+#endif
+
+#if defined(__bsdi__) && (_BSDI_VERSION > 199501)
+ /*
+ * Find local symbols. Don't report an error if we fail.
+ */
+
+ (void) dlopen(NULL, RTLD_NOW); /* INTL: Native. */
+#endif
+
+ /*
+ * Initialize the C library's locale subsystem. This is required for input
+ * methods to work properly on X11. We only do this for LC_CTYPE because
+ * that's the necessary one, and we don't want to affect LC_TIME here.
+ * The side effect of setting the default locale should be to load any
+ * locale specific modules that are needed by X. [BUG: 5422 3345 4236 2522
+ * 2521].
+ */
+
+ setlocale(LC_CTYPE, "");
+
+ /*
+ * In case the initial locale is not "C", ensure that the numeric
+ * processing is done in "C" locale regardless. This is needed because Tcl
+ * relies on routines like strtod, but should not have locale dependent
+ * behavior.
+ */
+
+ setlocale(LC_NUMERIC, "C");
+
+#ifdef GET_DARWIN_RELEASE
+ {
+ struct utsname name;
+
+ if (!uname(&name)) {
+ tclMacOSXDarwinRelease = strtol(name.release, NULL, 10);
+ }
+ }
+#endif
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpInitLibraryPath --
+ *
+ * This is the fallback routine that sets the library path if the
+ * application has not set one by the first time it is needed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the library path to an initial value.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+void
+TclpInitLibraryPath(
+ char **valuePtr,
+ size_t *lengthPtr,
+ Tcl_Encoding *encodingPtr)
+{
+#define LIBRARY_SIZE 32
+ Tcl_Obj *pathPtr, *objPtr;
+ const char *str;
+ Tcl_DString buffer;
+
+ pathPtr = Tcl_NewObj();
+
+ /*
+ * Look for the library relative to the TCL_LIBRARY env variable. If the
+ * last dirname in the TCL_LIBRARY path does not match the last dirname in
+ * the installLib variable, use the last dir name of installLib in
+ * addition to the orginal TCL_LIBRARY path.
+ */
+
+ str = getenv("TCL_LIBRARY"); /* INTL: Native. */
+ Tcl_ExternalToUtfDString(NULL, str, -1, &buffer);
+ str = Tcl_DStringValue(&buffer);
+
+ if ((str != NULL) && (str[0] != '\0')) {
+ Tcl_DString ds;
+ int pathc;
+ const char **pathv;
+ char installLib[LIBRARY_SIZE];
+
+ Tcl_DStringInit(&ds);
+
+ /*
+ * Initialize the substrings used when locating an executable. The
+ * installLib variable computes the path as though the executable is
+ * installed.
+ */
+
+ sprintf(installLib, "lib/tcl%s", TCL_VERSION);
+
+ /*
+ * If TCL_LIBRARY is set, search there.
+ */
+
+ Tcl_ListObjAppendElement(NULL, pathPtr, Tcl_NewStringObj(str, -1));
+
+ Tcl_SplitPath(str, &pathc, &pathv);
+ if ((pathc > 0) && (strcasecmp(installLib + 4, pathv[pathc-1]) != 0)) {
+ /*
+ * If TCL_LIBRARY is set but refers to a different tcl
+ * installation than the current version, try fiddling with the
+ * specified directory to make it refer to this installation by
+ * removing the old "tclX.Y" and substituting the current version
+ * string.
+ */
+
+ pathv[pathc - 1] = installLib + 4;
+ str = Tcl_JoinPath(pathc, pathv, &ds);
+ Tcl_ListObjAppendElement(NULL, pathPtr, TclDStringToObj(&ds));
+ }
+ ckfree(pathv);
+ }
+
+ /*
+ * Finally, look for the library relative to the compiled-in path. This is
+ * needed when users install Tcl with an exec-prefix that is different
+ * from the prefix.
+ */
+
+ {
+#ifdef HAVE_COREFOUNDATION
+ char tclLibPath[MAXPATHLEN + 1];
+
+ if (MacOSXGetLibraryPath(NULL, MAXPATHLEN, tclLibPath) == TCL_OK) {
+ str = tclLibPath;
+ } else
+#endif /* HAVE_COREFOUNDATION */
+ {
+ /*
+ * TODO: Pull this value from the TIP 59 table.
+ */
+
+ str = defaultLibraryDir;
+ }
+ if (str[0] != '\0') {
+ objPtr = Tcl_NewStringObj(str, -1);
+ Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
+ }
+ }
+ Tcl_DStringFree(&buffer);
+
+ *encodingPtr = Tcl_GetEncoding(NULL, NULL);
+ str = TclGetString(pathPtr);
+ *lengthPtr = pathPtr->length;
+ *valuePtr = ckalloc(*lengthPtr + 1);
+ memcpy(*valuePtr, str, *lengthPtr + 1);
+ Tcl_DecrRefCount(pathPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpSetInitialEncodings --
+ *
+ * Based on the locale, determine the encoding of the operating system
+ * and the default encoding for newly opened files.
+ *
+ * Called at process initialization time, and part way through startup,
+ * we verify that the initial encodings were correctly setup. Depending
+ * on Tcl's environment, there may not have been enough information first
+ * time through (above).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The Tcl library path is converted from native encoding to UTF-8, on
+ * the first call, and the encodings may be changed on first or second
+ * call.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TclpSetInitialEncodings(void)
+{
+ Tcl_DString encodingName;
+ Tcl_SetSystemEncoding(NULL,
+ Tcl_GetEncodingNameFromEnvironment(&encodingName));
+ Tcl_DStringFree(&encodingName);
+}
+
+void
+TclpSetInterfaces(void)
+{
+ /* do nothing */
+}
+
+static const char *
+SearchKnownEncodings(
+ const char *encoding)
+{
+ int left = 0;
+ int right = sizeof(localeTable)/sizeof(LocaleTable);
+
+ while (left < right) {
+ int test = (left + right)/2;
+ int code = strcmp(localeTable[test].lang, encoding);
+
+ if (code == 0) {
+ return localeTable[test].encoding;
+ }
+ if (code < 0) {
+ left = test+1;
+ } else {
+ right = test-1;
+ }
+ }
+ return NULL;
+}
+
+const char *
+Tcl_GetEncodingNameFromEnvironment(
+ Tcl_DString *bufPtr)
+{
+ const char *encoding;
+ const char *knownEncoding;
+
+ Tcl_DStringInit(bufPtr);
+
+ /*
+ * Determine the current encoding from the LC_* or LANG environment
+ * variables. We previously used setlocale() to determine the locale, but
+ * this does not work on some systems (e.g. Linux/i386 RH 5.0).
+ */
+
+#ifdef HAVE_LANGINFO
+ if (
+#ifdef WEAK_IMPORT_NL_LANGINFO
+ nl_langinfo != NULL &&
+#endif
+ setlocale(LC_CTYPE, "") != NULL) {
+ Tcl_DString ds;
+
+ /*
+ * Use a DString so we can modify case.
+ */
+
+ Tcl_DStringInit(&ds);
+ encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
+ Tcl_UtfToLower(Tcl_DStringValue(&ds));
+ knownEncoding = SearchKnownEncodings(encoding);
+ if (knownEncoding != NULL) {
+ Tcl_DStringAppend(bufPtr, knownEncoding, -1);
+ } else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
+ Tcl_DStringAppend(bufPtr, encoding, -1);
+ }
+ Tcl_DStringFree(&ds);
+ if (Tcl_DStringLength(bufPtr)) {
+ return Tcl_DStringValue(bufPtr);
+ }
+ }
+#endif /* HAVE_LANGINFO */
+
+ /*
+ * Classic fallback check. This tries a homebrew algorithm to determine
+ * what encoding should be used based on env vars.
+ */
+
+ encoding = getenv("LC_ALL");
+
+ if (encoding == NULL || encoding[0] == '\0') {
+ encoding = getenv("LC_CTYPE");
+ }
+ if (encoding == NULL || encoding[0] == '\0') {
+ encoding = getenv("LANG");
+ }
+ if (encoding == NULL || encoding[0] == '\0') {
+ encoding = NULL;
+ }
+
+ if (encoding != NULL) {
+ const char *p;
+ Tcl_DString ds;
+
+ Tcl_DStringInit(&ds);
+ p = encoding;
+ encoding = Tcl_DStringAppend(&ds, p, -1);
+ Tcl_UtfToLower(Tcl_DStringValue(&ds));
+
+ knownEncoding = SearchKnownEncodings(encoding);
+ if (knownEncoding != NULL) {
+ Tcl_DStringAppend(bufPtr, knownEncoding, -1);
+ } else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
+ Tcl_DStringAppend(bufPtr, encoding, -1);
+ }
+ if (Tcl_DStringLength(bufPtr)) {
+ Tcl_DStringFree(&ds);
+ return Tcl_DStringValue(bufPtr);
+ }
+
+ /*
+ * We didn't recognize the full value as an encoding name. If there is
+ * an encoding subfield, we can try to guess from that.
+ */
+
+ for (p = encoding; *p != '\0'; p++) {
+ if (*p == '.') {
+ p++;
+ break;
+ }
+ }
+ if (*p != '\0') {
+ knownEncoding = SearchKnownEncodings(p);
+ if (knownEncoding != NULL) {
+ Tcl_DStringAppend(bufPtr, knownEncoding, -1);
+ } else if (NULL != Tcl_GetEncoding(NULL, p)) {
+ Tcl_DStringAppend(bufPtr, p, -1);
+ }
+ }
+ Tcl_DStringFree(&ds);
+ if (Tcl_DStringLength(bufPtr)) {
+ return Tcl_DStringValue(bufPtr);
+ }
+ }
+ return Tcl_DStringAppend(bufPtr, TCL_DEFAULT_ENCODING, -1);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpSetVariables --
+ *
+ * Performs platform-specific interpreter initialization related to the
+ * tcl_library and tcl_platform variables, and other platform-specific
+ * things.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets "tclDefaultLibrary", "tcl_pkgPath", and "tcl_platform" Tcl
+ * variables.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#if defined(HAVE_COREFOUNDATION) && MAC_OS_X_VERSION_MAX_ALLOWED > 1020
+/*
+ * Helper because whether CFLocaleCopyCurrent and CFLocaleGetIdentifier are
+ * strongly or weakly bound varies by version of OSX, triggering warnings.
+ */
+
+static inline void
+InitMacLocaleInfoVar(
+ CFLocaleRef (*localeCopyCurrent)(void),
+ CFStringRef (*localeGetIdentifier)(CFLocaleRef),
+ Tcl_Interp *interp)
+{
+ CFLocaleRef localeRef;
+ CFStringRef locale;
+ char loc[256];
+
+ if (localeCopyCurrent == NULL || localeGetIdentifier == NULL) {
+ return;
+ }
+
+ localeRef = localeCopyCurrent();
+ if (!localeRef) {
+ return;
+ }
+
+ locale = localeGetIdentifier(localeRef);
+ if (locale && CFStringGetCString(locale, loc, 256,
+ kCFStringEncodingUTF8)) {
+ if (!Tcl_CreateNamespace(interp, "::tcl::mac", NULL, NULL)) {
+ Tcl_ResetResult(interp);
+ }
+ Tcl_SetVar2(interp, "::tcl::mac::locale", NULL, loc, TCL_GLOBAL_ONLY);
+ }
+ CFRelease(localeRef);
+}
+#endif /*defined(HAVE_COREFOUNDATION) && MAC_OS_X_VERSION_MAX_ALLOWED > 1020*/
+
+void
+TclpSetVariables(
+ Tcl_Interp *interp)
+{
+#ifdef __CYGWIN__
+ SYSTEM_INFO sysInfo;
+ static OSVERSIONINFOW osInfo;
+ static int osInfoInitialized = 0;
+ char buffer[TCL_INTEGER_SPACE * 2];
+#elif !defined(NO_UNAME)
+ struct utsname name;
+#endif
+ int unameOK;
+ Tcl_DString ds;
+
+#ifdef HAVE_COREFOUNDATION
+ char tclLibPath[MAXPATHLEN + 1];
+
+ /*
+ * Set msgcat fallback locale to current CFLocale identifier.
+ */
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED > 1020
+ InitMacLocaleInfoVar(CFLocaleCopyCurrent, CFLocaleGetIdentifier, interp);
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED > 1020 */
+
+ if (MacOSXGetLibraryPath(interp, MAXPATHLEN, tclLibPath) == TCL_OK) {
+ const char *str;
+ CFBundleRef bundleRef;
+
+ Tcl_SetVar2(interp, "tclDefaultLibrary", NULL, tclLibPath, TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "tcl_pkgPath", NULL, tclLibPath, TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "tcl_pkgPath", NULL, " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+
+ str = TclGetEnv("DYLD_FRAMEWORK_PATH", &ds);
+ if ((str != NULL) && (str[0] != '\0')) {
+ char *p = Tcl_DStringValue(&ds);
+
+ /*
+ * Convert DYLD_FRAMEWORK_PATH from colon to space separated.
+ */
+
+ do {
+ if (*p == ':') {
+ *p = ' ';
+ }
+ } while (*p++);
+ Tcl_SetVar2(interp, "tcl_pkgPath", NULL, Tcl_DStringValue(&ds),
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_SetVar2(interp, "tcl_pkgPath", NULL, " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_DStringFree(&ds);
+ }
+ bundleRef = CFBundleGetMainBundle();
+ if (bundleRef) {
+ CFURLRef frameworksURL;
+ Tcl_StatBuf statBuf;
+
+ frameworksURL = CFBundleCopyPrivateFrameworksURL(bundleRef);
+ if (frameworksURL) {
+ if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
+ (unsigned char*) tclLibPath, MAXPATHLEN) &&
+ ! TclOSstat(tclLibPath, &statBuf) &&
+ S_ISDIR(statBuf.st_mode)) {
+ Tcl_SetVar2(interp, "tcl_pkgPath", NULL, tclLibPath,
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_SetVar2(interp, "tcl_pkgPath", NULL, " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ }
+ CFRelease(frameworksURL);
+ }
+ frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef);
+ if (frameworksURL) {
+ if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
+ (unsigned char*) tclLibPath, MAXPATHLEN) &&
+ ! TclOSstat(tclLibPath, &statBuf) &&
+ S_ISDIR(statBuf.st_mode)) {
+ Tcl_SetVar2(interp, "tcl_pkgPath", NULL, tclLibPath,
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ Tcl_SetVar2(interp, "tcl_pkgPath", NULL, " ",
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ }
+ CFRelease(frameworksURL);
+ }
+ }
+ Tcl_SetVar2(interp, "tcl_pkgPath", NULL, pkgPath,
+ TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
+ } else
+#endif /* HAVE_COREFOUNDATION */
+ {
+ Tcl_SetVar2(interp, "tcl_pkgPath", NULL, pkgPath, TCL_GLOBAL_ONLY);
+ }
+
+#ifdef DJGPP
+ Tcl_SetVar2(interp, "tcl_platform", "platform", "dos", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "tcl_platform", "platform", "unix", TCL_GLOBAL_ONLY);
+#endif
+
+ unameOK = 0;
+#ifdef __CYGWIN__
+ unameOK = 1;
+ if (!osInfoInitialized) {
+ HANDLE handle = GetModuleHandleW(L"NTDLL");
+ int(__stdcall *getversion)(void *) =
+ (int(__stdcall *)(void *))GetProcAddress(handle, "RtlGetVersion");
+ osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
+ if (!getversion || getversion(&osInfo)) {
+ GetVersionExW(&osInfo);
+ }
+ osInfoInitialized = 1;
+ }
+
+ GetSystemInfo(&sysInfo);
+
+ if (osInfo.dwPlatformId < NUMPLATFORMS) {
+ Tcl_SetVar2(interp, "tcl_platform", "os",
+ platforms[osInfo.dwPlatformId], TCL_GLOBAL_ONLY);
+ }
+ sprintf(buffer, "%d.%d", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", buffer, TCL_GLOBAL_ONLY);
+ if (sysInfo.wProcessorArchitecture < NUMPROCESSORS) {
+ Tcl_SetVar2(interp, "tcl_platform", "machine",
+ processors[sysInfo.wProcessorArchitecture],
+ TCL_GLOBAL_ONLY);
+ }
+
+#elif !defined NO_UNAME
+ if (uname(&name) >= 0) {
+ const char *native;
+
+ unameOK = 1;
+
+ native = Tcl_ExternalToUtfDString(NULL, name.sysname, -1, &ds);
+ Tcl_SetVar2(interp, "tcl_platform", "os", native, TCL_GLOBAL_ONLY);
+ Tcl_DStringFree(&ds);
+
+ /*
+ * The following code is a special hack to handle differences in the
+ * way version information is returned by uname. On most systems the
+ * full version number is available in name.release. However, under
+ * AIX the major version number is in name.version and the minor
+ * version number is in name.release.
+ */
+
+ if ((strchr(name.release, '.') != NULL)
+ || !isdigit(UCHAR(name.version[0]))) { /* INTL: digit */
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
+ TCL_GLOBAL_ONLY);
+ } else {
+#ifdef DJGPP
+ /*
+ * For some obscure reason DJGPP puts major version into
+ * name.release and minor into name.version. As of DJGPP 2.04 this
+ * is documented in djgpp libc.info file.
+ */
+
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
+ TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", ".",
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.version,
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
+#else
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.version,
+ TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", ".",
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", name.release,
+ TCL_GLOBAL_ONLY|TCL_APPEND_VALUE);
+
+#endif /* DJGPP */
+ }
+ Tcl_SetVar2(interp, "tcl_platform", "machine", name.machine,
+ TCL_GLOBAL_ONLY);
+ }
+#endif /* !NO_UNAME */
+ if (!unameOK) {
+ Tcl_SetVar2(interp, "tcl_platform", "os", "", TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "tcl_platform", "osVersion", "", TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "tcl_platform", "machine", "", TCL_GLOBAL_ONLY);
+ }
+
+ /*
+ * Copy the username of the real user (according to getuid()) into
+ * tcl_platform(user).
+ */
+
+ {
+ struct passwd *pwEnt = TclpGetPwUid(getuid());
+ const char *user;
+
+ if (pwEnt == NULL) {
+ user = "";
+ Tcl_DStringInit(&ds); /* ensure cleanliness */
+ } else {
+ user = Tcl_ExternalToUtfDString(NULL, pwEnt->pw_name, -1, &ds);
+ }
+
+ Tcl_SetVar2(interp, "tcl_platform", "user", user, TCL_GLOBAL_ONLY);
+ Tcl_DStringFree(&ds);
+ }
+
+ /*
+ * Define what the platform PATH separator is. [TIP #315]
+ */
+
+ Tcl_SetVar2(interp, "tcl_platform","pathSeparator", ":", TCL_GLOBAL_ONLY);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFindVariable --
+ *
+ * Locate the entry in environ for a given name. On Unix this routine is
+ * case sensetive, on Windows this matches mixed case.
+ *
+ * Results:
+ * The return value is the index in environ of an entry with the name
+ * "name", or -1 if there is no such entry. The integer at *lengthPtr is
+ * filled in with the length of name (if a matching entry is found) or
+ * the length of the environ array (if no matching entry is found).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpFindVariable(
+ const char *name, /* Name of desired environment variable
+ * (native). */
+ int *lengthPtr) /* Used to return length of name (for
+ * successful searches) or number of non-NULL
+ * entries in environ (for unsuccessful
+ * searches). */
+{
+ int i, result = -1;
+ register const char *env, *p1, *p2;
+ Tcl_DString envString;
+
+ Tcl_DStringInit(&envString);
+ for (i = 0, env = environ[i]; env != NULL; i++, env = environ[i]) {
+ p1 = Tcl_ExternalToUtfDString(NULL, env, -1, &envString);
+ p2 = name;
+
+ for (; *p2 == *p1; p1++, p2++) {
+ /* NULL loop body. */
+ }
+ if ((*p1 == '=') && (*p2 == '\0')) {
+ *lengthPtr = p2 - name;
+ result = i;
+ goto done;
+ }
+
+ Tcl_DStringFree(&envString);
+ }
+
+ *lengthPtr = i;
+
+ done:
+ Tcl_DStringFree(&envString);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MacOSXGetLibraryPath --
+ *
+ * If we have a bundle structure for the Tcl installation, then check
+ * there first to see if we can find the libraries there.
+ *
+ * Results:
+ * TCL_OK if we have found the tcl library; TCL_ERROR otherwise.
+ *
+ * Side effects:
+ * Same as for Tcl_MacOSXOpenVersionedBundleResources.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef HAVE_COREFOUNDATION
+static int
+MacOSXGetLibraryPath(
+ Tcl_Interp *interp,
+ int maxPathLen,
+ char *tclLibPath)
+{
+ int foundInFramework = TCL_ERROR;
+
+#ifdef TCL_FRAMEWORK
+ foundInFramework = Tcl_MacOSXOpenVersionedBundleResources(interp,
+ "com.tcltk.tcllibrary", TCL_FRAMEWORK_VERSION, 0, maxPathLen,
+ tclLibPath);
+#endif
+
+ return foundInFramework;
+}
+#endif /* HAVE_COREFOUNDATION */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c
new file mode 100644
index 0000000..5bc753a
--- /dev/null
+++ b/unix/tclUnixNotfy.c
@@ -0,0 +1,575 @@
+/*
+ * tclUnixNotfy.c --
+ *
+ * This file contains subroutines shared by all notifier backend
+ * implementations on *nix platforms.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include <poll.h>
+
+/*
+ * Static routines defined in this file.
+ */
+
+#ifdef NOTIFIER_SELECT
+#ifdef TCL_THREADS
+static TCL_NORETURN void NotifierThreadProc(ClientData clientData);
+#if defined(HAVE_PTHREAD_ATFORK)
+static void AtForkChild(void);
+#endif /* HAVE_PTHREAD_ATFORK */
+#endif /* TCL_THREADS */
+#endif /* NOTIFIER_SELECT */
+static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
+
+#ifdef NOTIFIER_SELECT
+#if TCL_THREADS
+/*
+ *----------------------------------------------------------------------
+ *
+ * StartNotifierThread --
+ *
+ * Start a notfier thread and wait for the notifier pipe to be created.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Running Thread.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+StartNotifierThread(const char *proc)
+{
+ if (!notifierThreadRunning) {
+ pthread_mutex_lock(&notifierInitMutex);
+ if (!notifierThreadRunning) {
+ if (TclpThreadCreate(&notifierThread, NotifierThreadProc, NULL,
+ TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) {
+ Tcl_Panic("%s: unable to start notifier thread", proc);
+ }
+
+ pthread_mutex_lock(&notifierMutex);
+ /*
+ * Wait for the notifier pipe to be created.
+ */
+
+ while (triggerPipe < 0) {
+ pthread_cond_wait(&notifierCV, &notifierMutex);
+ }
+ pthread_mutex_unlock(&notifierMutex);
+
+ notifierThreadRunning = 1;
+ }
+ pthread_mutex_unlock(&notifierInitMutex);
+ }
+}
+#endif /* TCL_THREADS */
+#endif /* NOTIFIER_SELECT */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AlertNotifier --
+ *
+ * Wake up the specified notifier from any thread. This routine is called
+ * by the platform independent notifier code whenever the Tcl_ThreadAlert
+ * routine is called. This routine is guaranteed not to be called on a
+ * given notifier after Tcl_FinalizeNotifier is called for that notifier.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * select(2) notifier:
+ * signals the notifier condition variable for the specified
+ * notifier.
+ * epoll(7) notifier:
+ * write(2)s to the eventfd(2) of the specified thread.
+ * kqueue(2) notifier:
+ * write(2)s to the trigger pipe(2) of the specified thread.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_AlertNotifier(
+ ClientData clientData)
+{
+ if (tclNotifierHooks.alertNotifierProc) {
+ tclNotifierHooks.alertNotifierProc(clientData);
+ return;
+ } else {
+#ifdef NOTIFIER_SELECT
+#ifdef TCL_THREADS
+ ThreadSpecificData *tsdPtr = clientData;
+
+ pthread_mutex_lock(&notifierMutex);
+ tsdPtr->eventReady = 1;
+
+# ifdef __CYGWIN__
+ PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
+# else
+ pthread_cond_broadcast(&tsdPtr->waitCV);
+# endif /* __CYGWIN__ */
+ pthread_mutex_unlock(&notifierMutex);
+#endif /* TCL_THREADS */
+#else
+ ThreadSpecificData *tsdPtr = clientData;
+#if defined(NOTIFIER_EPOLL) && defined(HAVE_EVENTFD)
+ uint64_t eventFdVal = 1;
+ if (write(tsdPtr->triggerEventFd, &eventFdVal,
+ sizeof(eventFdVal)) != sizeof(eventFdVal)) {
+ Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerEventFd",
+ (void *)tsdPtr);
+#else
+ if (write(tsdPtr->triggerPipe[1], "", 1) != 1) {
+ Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerPipe",
+ (void *)tsdPtr);
+#endif /* NOTIFIER_EPOLL && HAVE_EVENTFD */
+ }
+#endif /* NOTIFIER_SELECT */
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetTimer --
+ *
+ * This function sets the current notifier timer value. This interface is
+ * not implemented in this notifier because we are always running inside
+ * of Tcl_DoOneEvent.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetTimer(
+ const Tcl_Time *timePtr) /* Timeout value, may be NULL. */
+{
+ if (tclNotifierHooks.setTimerProc) {
+ tclNotifierHooks.setTimerProc(timePtr);
+ return;
+ } else {
+ /*
+ * The interval timer doesn't do anything in this implementation,
+ * because the only event loop is via Tcl_DoOneEvent, which passes
+ * timeout values to Tcl_WaitForEvent.
+ */
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ServiceModeHook --
+ *
+ * This function is invoked whenever the service mode changes.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_ServiceModeHook(
+ int mode) /* Either TCL_SERVICE_ALL, or
+ * TCL_SERVICE_NONE. */
+{
+ if (tclNotifierHooks.serviceModeHookProc) {
+ tclNotifierHooks.serviceModeHookProc(mode);
+ return;
+ } else if (mode == TCL_SERVICE_ALL) {
+#ifdef NOTIFIER_SELECT
+#if TCL_THREADS
+ StartNotifierThread("Tcl_ServiceModeHook");
+#endif
+#endif /* NOTIFIER_SELECT */
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileHandlerEventProc --
+ *
+ * This function is called by Tcl_ServiceEvent when a file event reaches
+ * the front of the event queue. This function is responsible for
+ * actually handling the event by invoking the callback for the file
+ * handler.
+ *
+ * Results:
+ * Returns 1 if the event was handled, meaning it should be removed from
+ * the queue. Returns 0 if the event was not handled, meaning it should
+ * stay on the queue. The only time the event isn't handled is if the
+ * TCL_FILE_EVENTS flag bit isn't set.
+ *
+ * Side effects:
+ * Whatever the file handler's callback function does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileHandlerEventProc(
+ Tcl_Event *evPtr, /* Event to service. */
+ int flags) /* Flags that indicate what events to handle,
+ * such as TCL_FILE_EVENTS. */
+{
+ int mask;
+ FileHandler *filePtr;
+ FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr;
+ ThreadSpecificData *tsdPtr;
+
+ if (!(flags & TCL_FILE_EVENTS)) {
+ return 0;
+ }
+
+ /*
+ * Search through the file handlers to find the one whose handle matches
+ * the event. We do this rather than keeping a pointer to the file handler
+ * directly in the event, so that the handler can be deleted while the
+ * event is queued without leaving a dangling pointer.
+ */
+
+ tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
+ filePtr = filePtr->nextPtr) {
+ if (filePtr->fd != fileEvPtr->fd) {
+ continue;
+ }
+
+ /*
+ * The code is tricky for two reasons:
+ * 1. The file handler's desired events could have changed since the
+ * time when the event was queued, so AND the ready mask with the
+ * desired mask.
+ * 2. The file could have been closed and re-opened since the time
+ * when the event was queued. This is why the ready mask is stored
+ * in the file handler rather than the queued event: it will be
+ * zeroed when a new file handler is created for the newly opened
+ * file.
+ */
+
+ mask = filePtr->readyMask & filePtr->mask;
+ filePtr->readyMask = 0;
+ if (mask != 0) {
+ filePtr->proc(filePtr->clientData, mask);
+ }
+ break;
+ }
+ return 1;
+}
+
+#ifdef NOTIFIER_SELECT
+#ifdef TCL_THREADS
+/*
+ *----------------------------------------------------------------------
+ *
+ * AlertSingleThread --
+ *
+ * Notify a single thread that is waiting on a file descriptor to become
+ * readable or writable or to have an exception condition.
+ * notifierMutex must be held.
+ *
+ * Result:
+ * None.
+ *
+ * Side effects:
+ * The condition variable associated with the thread is broadcasted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AlertSingleThread(
+ ThreadSpecificData *tsdPtr)
+{
+ tsdPtr->eventReady = 1;
+ if (tsdPtr->onList) {
+ /*
+ * Remove the ThreadSpecificData structure of this thread
+ * from the waiting list. This prevents us from
+ * continuously spinning on epoll_wait until the other
+ * threads runs and services the file event.
+ */
+
+ if (tsdPtr->prevPtr) {
+ tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
+ } else {
+ waitingListPtr = tsdPtr->nextPtr;
+ }
+ if (tsdPtr->nextPtr) {
+ tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
+ }
+ tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
+ tsdPtr->onList = 0;
+ tsdPtr->pollState = 0;
+ }
+#ifdef __CYGWIN__
+ PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
+#else /* __CYGWIN__ */
+ pthread_cond_broadcast(&tsdPtr->waitCV);
+#endif /* __CYGWIN__ */
+}
+
+#if defined(HAVE_PTHREAD_ATFORK)
+/*
+ *----------------------------------------------------------------------
+ *
+ * AtForkChild --
+ *
+ * Unlock and reinstall the notifier in the child after a fork.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AtForkChild(void)
+{
+ if (notifierThreadRunning == 1) {
+ pthread_cond_destroy(&notifierCV);
+ }
+ pthread_mutex_init(&notifierInitMutex, NULL);
+ pthread_mutex_init(&notifierMutex, NULL);
+ pthread_cond_init(&notifierCV, NULL);
+
+ /*
+ * notifierThreadRunning == 1: thread is running, (there might be data in notifier lists)
+ * atForkInit == 0: InitNotifier was never called
+ * notifierCount != 0: unbalanced InitNotifier() / FinalizeNotifier calls
+ * waitingListPtr != 0: there are threads currently waiting for events.
+ */
+
+ if (atForkInit == 1) {
+
+ notifierCount = 0;
+ if (notifierThreadRunning == 1) {
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ notifierThreadRunning = 0;
+
+ close(triggerPipe);
+ triggerPipe = -1;
+ /*
+ * The waitingListPtr might contain event info from multiple
+ * threads, which are invalid here, so setting it to NULL is not
+ * unreasonable.
+ */
+ waitingListPtr = NULL;
+
+ /*
+ * The tsdPtr from before the fork is copied as well. But since
+ * we are paranoic, we don't trust its condvar and reset it.
+ */
+#ifdef __CYGWIN__
+ DestroyWindow(tsdPtr->hwnd);
+ tsdPtr->hwnd = CreateWindowExW(NULL, className,
+ className, 0, 0, 0, 0, 0, NULL, NULL,
+ TclWinGetTclInstance(), NULL);
+ ResetEvent(tsdPtr->event);
+#else
+ pthread_cond_destroy(&tsdPtr->waitCV);
+ pthread_cond_init(&tsdPtr->waitCV, NULL);
+#endif
+
+ /*
+ * In case, we had multiple threads running before the fork,
+ * make sure, we don't try to reach out to their thread local data.
+ */
+ tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
+
+ /*
+ * The list of registered event handlers at fork time is in
+ * tsdPtr->firstFileHandlerPtr;
+ */
+ }
+ }
+
+ Tcl_InitNotifier();
+}
+#endif /* HAVE_PTHREAD_ATFORK */
+
+#endif /* TCL_THREADS */
+
+#endif /* NOTIFIER_SELECT */
+#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
+ * in tclMacOSXNotify.c */
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclUnixWaitForFile --
+ *
+ * This function waits synchronously for a file to become readable or
+ * writable, with an optional timeout.
+ *
+ * Results:
+ * The return value is an OR'ed combination of TCL_READABLE,
+ * TCL_WRITABLE, and TCL_EXCEPTION, indicating the conditions that are
+ * present on file at the time of the return. This function will not
+ * return until either "timeout" milliseconds have elapsed or at least
+ * one of the conditions given by mask has occurred for file (a return
+ * value of 0 means that a timeout occurred). No normal events will be
+ * serviced during the execution of this function.
+ *
+ * Side effects:
+ * Time passes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclUnixWaitForFile(
+ int fd, /* Handle for file on which to wait. */
+ int mask, /* What to wait for: OR'ed combination of
+ * TCL_READABLE, TCL_WRITABLE, and
+ * TCL_EXCEPTION. */
+ int timeout) /* Maximum amount of time to wait for one of
+ * the conditions in mask to occur, in
+ * milliseconds. A value of 0 means don't wait
+ * at all, and a value of -1 means wait
+ * forever. */
+{
+ Tcl_Time abortTime = {0, 0}, now; /* silence gcc 4 warning */
+ struct timeval blockTime, *timeoutPtr;
+ struct pollfd pollFds[1];
+ int numFound, result = 0, pollTimeout;
+
+ /*
+ * If there is a non-zero finite timeout, compute the time when we give
+ * up.
+ */
+
+ if (timeout > 0) {
+ Tcl_GetTime(&now);
+ abortTime.sec = now.sec + timeout/1000;
+ abortTime.usec = now.usec + (timeout%1000)*1000;
+ if (abortTime.usec >= 1000000) {
+ abortTime.usec -= 1000000;
+ abortTime.sec += 1;
+ }
+ timeoutPtr = &blockTime;
+ } else if (timeout == 0) {
+ timeoutPtr = &blockTime;
+ blockTime.tv_sec = 0;
+ blockTime.tv_usec = 0;
+ } else {
+ timeoutPtr = NULL;
+ }
+
+ /*
+ * Setup the pollfd structure for the fd.
+ */
+
+ pollFds[0].fd = fd;
+ pollFds[0].events = pollFds[0].revents = 0;
+ if (mask & TCL_READABLE) {
+ pollFds[0].events |= (POLLIN | POLLHUP);
+ }
+ if (mask & TCL_WRITABLE) {
+ pollFds[0].events |= POLLOUT;
+ }
+ if (mask & TCL_EXCEPTION) {
+ pollFds[0].events |= POLLERR;
+ }
+
+ /*
+ * Loop in a mini-event loop of our own, waiting for either the file to
+ * become ready or a timeout to occur.
+ */
+
+ while (1) {
+ if (timeout > 0) {
+ blockTime.tv_sec = abortTime.sec - now.sec;
+ blockTime.tv_usec = abortTime.usec - now.usec;
+ if (blockTime.tv_usec < 0) {
+ blockTime.tv_sec -= 1;
+ blockTime.tv_usec += 1000000;
+ }
+ if (blockTime.tv_sec < 0) {
+ blockTime.tv_sec = 0;
+ blockTime.tv_usec = 0;
+ }
+ }
+
+ /*
+ * Wait for the event or a timeout.
+ */
+
+ if (!timeoutPtr) {
+ pollTimeout = -1;
+ } else if (!timeoutPtr->tv_sec && !timeoutPtr->tv_usec) {
+ pollTimeout = 0;
+ } else {
+ pollTimeout = (int)timeoutPtr->tv_sec * 1000;
+ if (timeoutPtr->tv_usec) {
+ pollTimeout += ((int)timeoutPtr->tv_usec / 1000);
+ }
+ }
+ numFound = poll(pollFds, 1, pollTimeout);
+ if (numFound == 1) {
+ result = 0;
+ if (pollFds[0].events & (POLLIN | POLLHUP)) {
+ result |= TCL_READABLE;
+ }
+ if (pollFds[0].events & POLLOUT) {
+ result |= TCL_WRITABLE;
+ }
+ if (pollFds[0].events & POLLERR) {
+ result |= TCL_EXCEPTION;
+ }
+ if (result) {
+ break;
+ }
+ }
+ if (timeout == 0) {
+ break;
+ }
+ if (timeout < 0) {
+ continue;
+ }
+
+ /*
+ * The select returned early, so we need to recompute the timeout.
+ */
+
+ Tcl_GetTime(&now);
+ if ((abortTime.sec < now.sec)
+ || (abortTime.sec==now.sec && abortTime.usec<=now.usec)) {
+ break;
+ }
+ }
+ return result;
+}
+#endif /* !HAVE_COREFOUNDATION */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c
new file mode 100644
index 0000000..be7b4eb
--- /dev/null
+++ b/unix/tclUnixPipe.c
@@ -0,0 +1,1327 @@
+/*
+ * tclUnixPipe.c --
+ *
+ * This file implements the UNIX-specific exec pipeline functions, the
+ * "pipe" channel driver, and the "pid" Tcl command.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+
+#ifdef USE_VFORK
+#define fork vfork
+#endif
+
+/*
+ * The following macros convert between TclFile's and fd's. The conversion
+ * simple involves shifting fd's up by one to ensure that no valid fd is ever
+ * the same as NULL.
+ */
+
+#define MakeFile(fd) ((TclFile) INT2PTR(((int) (fd)) + 1))
+#define GetFd(file) (PTR2INT(file) - 1)
+
+/*
+ * This structure describes per-instance state of a pipe based channel.
+ */
+
+typedef struct {
+ Tcl_Channel channel; /* Channel associated with this file. */
+ TclFile inFile; /* Output from pipe. */
+ TclFile outFile; /* Input to pipe. */
+ TclFile errorFile; /* Error output from pipe. */
+ int numPids; /* How many processes are attached to this
+ * pipe? */
+ Tcl_Pid *pidPtr; /* The process IDs themselves. Allocated by
+ * the creator of the pipe. */
+ int isNonBlocking; /* Nonzero when the pipe is in nonblocking
+ * mode. Used to decide whether to wait for
+ * the children at close time. */
+} PipeState;
+
+/*
+ * Declarations for local functions defined in this file:
+ */
+
+static int PipeBlockModeProc(ClientData instanceData, int mode);
+static int PipeClose2Proc(ClientData instanceData,
+ Tcl_Interp *interp, int flags);
+static int PipeGetHandleProc(ClientData instanceData,
+ int direction, ClientData *handlePtr);
+static int PipeInputProc(ClientData instanceData, char *buf,
+ int toRead, int *errorCode);
+static int PipeOutputProc(ClientData instanceData,
+ const char *buf, int toWrite, int *errorCode);
+static void PipeWatchProc(ClientData instanceData, int mask);
+static void RestoreSignals(void);
+static int SetupStdFile(TclFile file, int type);
+
+/*
+ * This structure describes the channel type structure for command pipe based
+ * I/O:
+ */
+
+static const Tcl_ChannelType pipeChannelType = {
+ "pipe", /* Type name. */
+ TCL_CHANNEL_VERSION_5, /* v5 channel */
+ TCL_CLOSE2PROC, /* Close proc. */
+ PipeInputProc, /* Input proc. */
+ PipeOutputProc, /* Output proc. */
+ NULL, /* Seek proc. */
+ NULL, /* Set option proc. */
+ NULL, /* Get option proc. */
+ PipeWatchProc, /* Initialize notifier. */
+ PipeGetHandleProc, /* Get OS handles out of channel. */
+ PipeClose2Proc, /* close2proc. */
+ PipeBlockModeProc, /* Set blocking or non-blocking mode.*/
+ NULL, /* flush proc. */
+ NULL, /* handler proc. */
+ NULL, /* wide seek proc */
+ NULL, /* thread action proc */
+ NULL /* truncation */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpMakeFile --
+ *
+ * Make a TclFile from a channel.
+ *
+ * Results:
+ * Returns a new TclFile or NULL on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TclFile
+TclpMakeFile(
+ Tcl_Channel channel, /* Channel to get file from. */
+ int direction) /* Either TCL_READABLE or TCL_WRITABLE. */
+{
+ ClientData data;
+
+ if (Tcl_GetChannelHandle(channel, direction, &data) != TCL_OK) {
+ return NULL;
+ }
+
+ return MakeFile(PTR2INT(data));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpOpenFile --
+ *
+ * Open a file for use in a pipeline.
+ *
+ * Results:
+ * Returns a new TclFile handle or NULL on failure.
+ *
+ * Side effects:
+ * May cause a file to be created on the file system.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TclFile
+TclpOpenFile(
+ const char *fname, /* The name of the file to open. */
+ int mode) /* In what mode to open the file? */
+{
+ int fd;
+ const char *native;
+ Tcl_DString ds;
+
+ native = Tcl_UtfToExternalDString(NULL, fname, -1, &ds);
+ fd = TclOSopen(native, mode, 0666); /* INTL: Native. */
+ Tcl_DStringFree(&ds);
+ if (fd != -1) {
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ /*
+ * If the file is being opened for writing, seek to the end so we can
+ * append to any data already in the file.
+ */
+
+ if ((mode & O_WRONLY) && !(mode & O_APPEND)) {
+ TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_END);
+ }
+
+ /*
+ * Increment the fd so it can't be 0, which would conflict with the
+ * NULL return for errors.
+ */
+
+ return MakeFile(fd);
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpCreateTempFile --
+ *
+ * This function creates a temporary file initialized with an optional
+ * string, and returns a file handle with the file pointer at the
+ * beginning of the file.
+ *
+ * Results:
+ * A handle to a file.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TclFile
+TclpCreateTempFile(
+ const char *contents) /* String to write into temp file, or NULL. */
+{
+ int fd = TclUnixOpenTemporaryFile(NULL, NULL, NULL, NULL);
+
+ if (fd == -1) {
+ return NULL;
+ }
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (contents != NULL) {
+ Tcl_DString dstring;
+ char *native;
+
+ native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring);
+ if (write(fd, native, Tcl_DStringLength(&dstring)) == -1) {
+ close(fd);
+ Tcl_DStringFree(&dstring);
+ return NULL;
+ }
+ Tcl_DStringFree(&dstring);
+ TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_SET);
+ }
+ return MakeFile(fd);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpTempFileName --
+ *
+ * This function returns unique filename.
+ *
+ * Results:
+ * Returns a valid Tcl_Obj* with refCount 0, or NULL on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclpTempFileName(void)
+{
+ Tcl_Obj *retVal, *nameObj = Tcl_NewObj();
+ int fd;
+
+ Tcl_IncrRefCount(nameObj);
+ fd = TclUnixOpenTemporaryFile(NULL, NULL, NULL, nameObj);
+ if (fd == -1) {
+ Tcl_DecrRefCount(nameObj);
+ return NULL;
+ }
+
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ TclpObjDeleteFile(nameObj);
+ close(fd);
+ retVal = Tcl_DuplicateObj(nameObj);
+ Tcl_DecrRefCount(nameObj);
+ return retVal;
+}
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * TclpTempFileNameForLibrary --
+ *
+ * Constructs a file name in the native file system where a dynamically
+ * loaded library may be placed.
+ *
+ * Results:
+ * Returns the constructed file name. If an error occurs, returns NULL
+ * and leaves an error message in the interpreter result.
+ *
+ * On Unix, it works to load a shared object from a file of any name, so this
+ * function is merely a thin wrapper around TclpTempFileName().
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+TclpTempFileNameForLibrary(
+ Tcl_Interp *interp, /* Tcl interpreter. */
+ Tcl_Obj *path) /* Path name of the library in the VFS. */
+{
+ Tcl_Obj *retval = TclpTempFileName();
+
+ if (retval == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't create temporary file: %s",
+ Tcl_PosixError(interp)));
+ }
+ return retval;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpCreatePipe --
+ *
+ * Creates a pipe - simply calls the pipe() function.
+ *
+ * Results:
+ * Returns 1 on success, 0 on failure.
+ *
+ * Side effects:
+ * Creates a pipe.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpCreatePipe(
+ TclFile *readPipe, /* Location to store file handle for read side
+ * of pipe. */
+ TclFile *writePipe) /* Location to store file handle for write
+ * side of pipe. */
+{
+ int pipeIds[2];
+
+ if (pipe(pipeIds) != 0) {
+ return 0;
+ }
+
+ fcntl(pipeIds[0], F_SETFD, FD_CLOEXEC);
+ fcntl(pipeIds[1], F_SETFD, FD_CLOEXEC);
+
+ *readPipe = MakeFile(pipeIds[0]);
+ *writePipe = MakeFile(pipeIds[1]);
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpCloseFile --
+ *
+ * Implements a mechanism to close a UNIX file.
+ *
+ * Results:
+ * Returns 0 on success, or -1 on error, setting errno.
+ *
+ * Side effects:
+ * The file is closed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpCloseFile(
+ TclFile file) /* The file to close. */
+{
+ int fd = GetFd(file);
+
+ /*
+ * Refuse to close the fds for stdin, stdout and stderr.
+ */
+
+ if ((fd == 0) || (fd == 1) || (fd == 2)) {
+ return 0;
+ }
+
+ Tcl_DeleteFileHandler(fd);
+ return close(fd);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TclpCreateProcess --
+ *
+ * Create a child process that has the specified files as its standard
+ * input, output, and error. The child process runs asynchronously and
+ * runs with the same environment variables as the creating process.
+ *
+ * The path is searched to find the specified executable.
+ *
+ * Results:
+ * The return value is TCL_ERROR and an error message is left in the
+ * interp's result if there was a problem creating the child process.
+ * Otherwise, the return value is TCL_OK and *pidPtr is filled with the
+ * process id of the child process.
+ *
+ * Side effects:
+ * A process is created.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+TclpCreateProcess(
+ Tcl_Interp *interp, /* Interpreter in which to leave errors that
+ * occurred when creating the child process.
+ * Error messages from the child process
+ * itself are sent to errorFile. */
+ int argc, /* Number of arguments in following array. */
+ const char **argv, /* Array of argument strings in UTF-8.
+ * argv[0] contains the name of the executable
+ * translated using Tcl_TranslateFileName
+ * call). Additional arguments have not been
+ * converted. */
+ TclFile inputFile, /* If non-NULL, gives the file to use as input
+ * for the child process. If inputFile file is
+ * not readable or is NULL, the child will
+ * receive no standard input. */
+ TclFile outputFile, /* If non-NULL, gives the file that receives
+ * output from the child process. If
+ * outputFile file is not writeable or is
+ * NULL, output from the child will be
+ * discarded. */
+ TclFile errorFile, /* If non-NULL, gives the file that receives
+ * errors from the child process. If errorFile
+ * file is not writeable or is NULL, errors
+ * from the child will be discarded. errorFile
+ * may be the same as outputFile. */
+ Tcl_Pid *pidPtr) /* If this function is successful, pidPtr is
+ * filled with the process id of the child
+ * process. */
+{
+ TclFile errPipeIn, errPipeOut;
+ int count, status, fd;
+ char errSpace[200 + TCL_INTEGER_SPACE];
+ Tcl_DString *dsArray;
+ char **newArgv;
+ int pid, i;
+
+ errPipeIn = NULL;
+ errPipeOut = NULL;
+ pid = -1;
+
+ /*
+ * Create a pipe that the child can use to return error information if
+ * anything goes wrong.
+ */
+
+ if (TclpCreatePipe(&errPipeIn, &errPipeOut) == 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't create pipe: %s", Tcl_PosixError(interp)));
+ goto error;
+ }
+
+ /*
+ * We need to allocate and convert this before the fork so it is properly
+ * deallocated later
+ */
+
+ dsArray = TclStackAlloc(interp, argc * sizeof(Tcl_DString));
+ newArgv = TclStackAlloc(interp, (argc+1) * sizeof(char *));
+ newArgv[argc] = NULL;
+ for (i = 0; i < argc; i++) {
+ newArgv[i] = Tcl_UtfToExternalDString(NULL, argv[i], -1, &dsArray[i]);
+ }
+
+#ifdef USE_VFORK
+ /*
+ * After vfork(), do not call code in the child that changes global state,
+ * because it is using the parent's memory space at that point and writes
+ * might corrupt the parent: so ensure standard channels are initialized
+ * in the parent, otherwise SetupStdFile() might initialize them in the
+ * child.
+ */
+
+ if (!inputFile) {
+ Tcl_GetStdChannel(TCL_STDIN);
+ }
+ if (!outputFile) {
+ Tcl_GetStdChannel(TCL_STDOUT);
+ }
+ if (!errorFile) {
+ Tcl_GetStdChannel(TCL_STDERR);
+ }
+#endif
+
+ pid = fork();
+ if (pid == 0) {
+ size_t len;
+ int joinThisError = errorFile && (errorFile == outputFile);
+
+ fd = GetFd(errPipeOut);
+
+ /*
+ * Set up stdio file handles for the child process.
+ */
+
+ if (!SetupStdFile(inputFile, TCL_STDIN)
+ || !SetupStdFile(outputFile, TCL_STDOUT)
+ || (!joinThisError && !SetupStdFile(errorFile, TCL_STDERR))
+ || (joinThisError &&
+ ((dup2(1,2) == -1) || (fcntl(2, F_SETFD, 0) != 0)))) {
+ sprintf(errSpace,
+ "%dforked process couldn't set up input/output", errno);
+ len = strlen(errSpace);
+ if (len != (size_t) write(fd, errSpace, len)) {
+ Tcl_Panic("TclpCreateProcess: unable to write to errPipeOut");
+ }
+ _exit(1);
+ }
+
+ /*
+ * Close the input side of the error pipe.
+ */
+
+ RestoreSignals();
+ execvp(newArgv[0], newArgv); /* INTL: Native. */
+ sprintf(errSpace, "%dcouldn't execute \"%.150s\"", errno, argv[0]);
+ len = strlen(errSpace);
+ if (len != (size_t) write(fd, errSpace, len)) {
+ Tcl_Panic("TclpCreateProcess: unable to write to errPipeOut");
+ }
+ _exit(1);
+ }
+
+ /*
+ * Free the mem we used for the fork
+ */
+
+ for (i = 0; i < argc; i++) {
+ Tcl_DStringFree(&dsArray[i]);
+ }
+ TclStackFree(interp, newArgv);
+ TclStackFree(interp, dsArray);
+
+ if (pid == -1) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't fork child process: %s", Tcl_PosixError(interp)));
+ goto error;
+ }
+
+ /*
+ * Read back from the error pipe to see if the child started up OK. The
+ * info in the pipe (if any) consists of a decimal errno value followed by
+ * an error message.
+ */
+
+ TclpCloseFile(errPipeOut);
+ errPipeOut = NULL;
+
+ fd = GetFd(errPipeIn);
+ count = read(fd, errSpace, (size_t) (sizeof(errSpace) - 1));
+ if (count > 0) {
+ char *end;
+
+ errSpace[count] = 0;
+ errno = strtol(errSpace, &end, 10);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s: %s",
+ end, Tcl_PosixError(interp)));
+ goto error;
+ }
+
+ TclpCloseFile(errPipeIn);
+ *pidPtr = (Tcl_Pid) INT2PTR(pid);
+ return TCL_OK;
+
+ error:
+ if (pid != -1) {
+ /*
+ * Reap the child process now if an error occurred during its startup.
+ * We don't call this with WNOHANG because that can lead to defunct
+ * processes on an MP system. We shouldn't have to worry about hanging
+ * here, since this is the error case. [Bug: 6148]
+ */
+
+ Tcl_WaitPid((Tcl_Pid) INT2PTR(pid), &status, 0);
+ }
+
+ if (errPipeIn) {
+ TclpCloseFile(errPipeIn);
+ }
+ if (errPipeOut) {
+ TclpCloseFile(errPipeOut);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RestoreSignals --
+ *
+ * This function is invoked in a forked child process just before
+ * exec-ing a new program to restore all signals to their default
+ * settings.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Signal settings get changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RestoreSignals(void)
+{
+#ifdef SIGABRT
+ signal(SIGABRT, SIG_DFL);
+#endif
+#ifdef SIGALRM
+ signal(SIGALRM, SIG_DFL);
+#endif
+#ifdef SIGFPE
+ signal(SIGFPE, SIG_DFL);
+#endif
+#ifdef SIGHUP
+ signal(SIGHUP, SIG_DFL);
+#endif
+#ifdef SIGILL
+ signal(SIGILL, SIG_DFL);
+#endif
+#ifdef SIGINT
+ signal(SIGINT, SIG_DFL);
+#endif
+#ifdef SIGPIPE
+ signal(SIGPIPE, SIG_DFL);
+#endif
+#ifdef SIGQUIT
+ signal(SIGQUIT, SIG_DFL);
+#endif
+#ifdef SIGSEGV
+ signal(SIGSEGV, SIG_DFL);
+#endif
+#ifdef SIGTERM
+ signal(SIGTERM, SIG_DFL);
+#endif
+#ifdef SIGUSR1
+ signal(SIGUSR1, SIG_DFL);
+#endif
+#ifdef SIGUSR2
+ signal(SIGUSR2, SIG_DFL);
+#endif
+#ifdef SIGCHLD
+ signal(SIGCHLD, SIG_DFL);
+#endif
+#ifdef SIGCONT
+ signal(SIGCONT, SIG_DFL);
+#endif
+#ifdef SIGTSTP
+ signal(SIGTSTP, SIG_DFL);
+#endif
+#ifdef SIGTTIN
+ signal(SIGTTIN, SIG_DFL);
+#endif
+#ifdef SIGTTOU
+ signal(SIGTTOU, SIG_DFL);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetupStdFile --
+ *
+ * Set up stdio file handles for the child process, using the current
+ * standard channels if no other files are specified. If no standard
+ * channel is defined, or if no file is associated with the channel, then
+ * the corresponding standard fd is closed.
+ *
+ * Results:
+ * Returns 1 on success, or 0 on failure.
+ *
+ * Side effects:
+ * Replaces stdio fds.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetupStdFile(
+ TclFile file, /* File to dup, or NULL. */
+ int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR */
+{
+ Tcl_Channel channel;
+ int fd;
+ int targetFd = 0; /* Initializations here needed only to */
+ int direction = 0; /* prevent warnings about using uninitialized
+ * variables. */
+
+ switch (type) {
+ case TCL_STDIN:
+ targetFd = 0;
+ direction = TCL_READABLE;
+ break;
+ case TCL_STDOUT:
+ targetFd = 1;
+ direction = TCL_WRITABLE;
+ break;
+ case TCL_STDERR:
+ targetFd = 2;
+ direction = TCL_WRITABLE;
+ break;
+ }
+
+ if (!file) {
+ channel = Tcl_GetStdChannel(type);
+ if (channel) {
+ file = TclpMakeFile(channel, direction);
+ }
+ }
+ if (file) {
+ fd = GetFd(file);
+ if (fd != targetFd) {
+ if (dup2(fd, targetFd) == -1) {
+ return 0;
+ }
+
+ /*
+ * Must clear the close-on-exec flag for the target FD, since some
+ * systems (e.g. Ultrix) do not clear the CLOEXEC flag on the
+ * target FD.
+ */
+
+ fcntl(targetFd, F_SETFD, 0);
+ } else {
+ /*
+ * Since we aren't dup'ing the file, we need to explicitly clear
+ * the close-on-exec flag.
+ */
+
+ fcntl(fd, F_SETFD, 0);
+ }
+ } else {
+ close(targetFd);
+ }
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpCreateCommandChannel --
+ *
+ * This function is called by the generic IO level to perform the
+ * platform specific channel initialization for a command channel.
+ *
+ * Results:
+ * Returns a new channel or NULL on failure.
+ *
+ * Side effects:
+ * Allocates a new channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+TclpCreateCommandChannel(
+ TclFile readFile, /* If non-null, gives the file for reading. */
+ TclFile writeFile, /* If non-null, gives the file for writing. */
+ TclFile errorFile, /* If non-null, gives the file where errors
+ * can be read. */
+ int numPids, /* The number of pids in the pid array. */
+ Tcl_Pid *pidPtr) /* An array of process identifiers. Allocated
+ * by the caller, freed when the channel is
+ * closed or the processes are detached (in a
+ * background exec). */
+{
+ char channelName[16 + TCL_INTEGER_SPACE];
+ int channelId;
+ PipeState *statePtr = ckalloc(sizeof(PipeState));
+ int mode;
+
+ statePtr->inFile = readFile;
+ statePtr->outFile = writeFile;
+ statePtr->errorFile = errorFile;
+ statePtr->numPids = numPids;
+ statePtr->pidPtr = pidPtr;
+ statePtr->isNonBlocking = 0;
+
+ mode = 0;
+ if (readFile) {
+ mode |= TCL_READABLE;
+ }
+ if (writeFile) {
+ mode |= TCL_WRITABLE;
+ }
+
+ /*
+ * Use one of the fds associated with the channel as the channel id.
+ */
+
+ if (readFile) {
+ channelId = GetFd(readFile);
+ } else if (writeFile) {
+ channelId = GetFd(writeFile);
+ } else if (errorFile) {
+ channelId = GetFd(errorFile);
+ } else {
+ channelId = 0;
+ }
+
+ /*
+ * For backward compatibility with previous versions of Tcl, we use
+ * "file%d" as the base name for pipes even though it would be more
+ * natural to use "pipe%d".
+ */
+
+ sprintf(channelName, "file%d", channelId);
+ statePtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,
+ statePtr, mode);
+ return statePtr->channel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_CreatePipe --
+ *
+ * System dependent interface to create a pipe for the [chan pipe]
+ * command. Stolen from TclX.
+ *
+ * Results:
+ * TCL_OK or TCL_ERROR.
+ *
+ * Side effects:
+ * Registers two channels.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_CreatePipe(
+ Tcl_Interp *interp, /* Errors returned in result. */
+ Tcl_Channel *rchan, /* Returned read side. */
+ Tcl_Channel *wchan, /* Returned write side. */
+ int flags) /* Reserved for future use. */
+{
+ int fileNums[2];
+
+ if (pipe(fileNums) < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf("pipe creation failed: %s",
+ Tcl_PosixError(interp)));
+ return TCL_ERROR;
+ }
+
+ fcntl(fileNums[0], F_SETFD, FD_CLOEXEC);
+ fcntl(fileNums[1], F_SETFD, FD_CLOEXEC);
+
+ *rchan = Tcl_MakeFileChannel(INT2PTR(fileNums[0]), TCL_READABLE);
+ Tcl_RegisterChannel(interp, *rchan);
+ *wchan = Tcl_MakeFileChannel(INT2PTR(fileNums[1]), TCL_WRITABLE);
+ Tcl_RegisterChannel(interp, *wchan);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclGetAndDetachPids --
+ *
+ * This function is invoked in the generic implementation of a
+ * background "exec" (an exec when invoked with a terminating "&") to
+ * store a list of the PIDs for processes in a command pipeline in the
+ * interp's result and to detach the processes.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Modifies the interp's result. Detaches processes.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclGetAndDetachPids(
+ Tcl_Interp *interp, /* Interpreter to append the PIDs to. */
+ Tcl_Channel chan) /* Handle for the pipeline. */
+{
+ PipeState *pipePtr;
+ const Tcl_ChannelType *chanTypePtr;
+ Tcl_Obj *pidsObj;
+ int i;
+
+ /*
+ * Punt if the channel is not a command channel.
+ */
+
+ chanTypePtr = Tcl_GetChannelType(chan);
+ if (chanTypePtr != &pipeChannelType) {
+ return;
+ }
+
+ pipePtr = Tcl_GetChannelInstanceData(chan);
+ TclNewObj(pidsObj);
+ for (i = 0; i < pipePtr->numPids; i++) {
+ Tcl_ListObjAppendElement(NULL, pidsObj, Tcl_NewIntObj(
+ PTR2INT(pipePtr->pidPtr[i])));
+ Tcl_DetachPids(1, &pipePtr->pidPtr[i]);
+ }
+ Tcl_SetObjResult(interp, pidsObj);
+ if (pipePtr->numPids > 0) {
+ ckfree(pipePtr->pidPtr);
+ pipePtr->numPids = 0;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PipeBlockModeProc --
+ *
+ * Helper function to set blocking and nonblocking modes on a pipe based
+ * channel. Invoked by generic IO level code.
+ *
+ * Results:
+ * 0 if successful, errno when failed.
+ *
+ * Side effects:
+ * Sets the device into blocking or non-blocking mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+PipeBlockModeProc(
+ ClientData instanceData, /* Pipe state. */
+ int mode) /* The mode to set. Can be one of
+ * TCL_MODE_BLOCKING or
+ * TCL_MODE_NONBLOCKING. */
+{
+ PipeState *psPtr = instanceData;
+
+ if (psPtr->inFile
+ && TclUnixSetBlockingMode(GetFd(psPtr->inFile), mode) < 0) {
+ return errno;
+ }
+ if (psPtr->outFile
+ && TclUnixSetBlockingMode(GetFd(psPtr->outFile), mode) < 0) {
+ return errno;
+ }
+
+ psPtr->isNonBlocking = (mode == TCL_MODE_NONBLOCKING);
+
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PipeClose2Proc
+ *
+ * This function is invoked by the generic IO level to perform
+ * pipeline-type-specific half or full-close.
+ *
+ * Results:
+ * 0 on success, errno otherwise.
+ *
+ * Side effects:
+ * Closes the command pipeline channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PipeClose2Proc(
+ ClientData instanceData, /* The pipe to close. */
+ Tcl_Interp *interp, /* For error reporting. */
+ int flags) /* Flags that indicate which side to close. */
+{
+ PipeState *pipePtr = instanceData;
+ Tcl_Channel errChan;
+ int errorCode, result;
+
+ errorCode = 0;
+ result = 0;
+
+ if (((!flags) || (flags & TCL_CLOSE_READ)) && (pipePtr->inFile != NULL)) {
+ if (TclpCloseFile(pipePtr->inFile) < 0) {
+ errorCode = errno;
+ } else {
+ pipePtr->inFile = NULL;
+ }
+ }
+ if (((!flags) || (flags & TCL_CLOSE_WRITE)) && (pipePtr->outFile != NULL)
+ && (errorCode == 0)) {
+ if (TclpCloseFile(pipePtr->outFile) < 0) {
+ errorCode = errno;
+ } else {
+ pipePtr->outFile = NULL;
+ }
+ }
+
+ /*
+ * If half-closing, stop here.
+ */
+
+ if (flags) {
+ return errorCode;
+ }
+
+ if (pipePtr->isNonBlocking || TclInExit()) {
+ /*
+ * If the channel is non-blocking or Tcl is being cleaned up, just
+ * detach the children PIDs, reap them (important if we are in a
+ * dynamic load module), and discard the errorFile.
+ */
+
+ Tcl_DetachPids(pipePtr->numPids, pipePtr->pidPtr);
+ Tcl_ReapDetachedProcs();
+
+ if (pipePtr->errorFile) {
+ TclpCloseFile(pipePtr->errorFile);
+ }
+ } else {
+ /*
+ * Wrap the error file into a channel and give it to the cleanup
+ * routine.
+ */
+
+ if (pipePtr->errorFile) {
+ errChan = Tcl_MakeFileChannel(
+ INT2PTR(GetFd(pipePtr->errorFile)),
+ TCL_READABLE);
+ } else {
+ errChan = NULL;
+ }
+ result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr,
+ errChan);
+ }
+
+ if (pipePtr->numPids != 0) {
+ ckfree(pipePtr->pidPtr);
+ }
+ ckfree(pipePtr);
+ if (errorCode == 0) {
+ return result;
+ }
+ return errorCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PipeInputProc --
+ *
+ * This function is invoked from the generic IO level to read input from
+ * a command pipeline based channel.
+ *
+ * Results:
+ * The number of bytes read is returned or -1 on error. An output
+ * argument contains a POSIX error code if an error occurs, or zero.
+ *
+ * Side effects:
+ * Reads input from the input device of the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PipeInputProc(
+ ClientData instanceData, /* Pipe state. */
+ char *buf, /* Where to store data read. */
+ int toRead, /* How much space is available in the
+ * buffer? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ PipeState *psPtr = instanceData;
+ int bytesRead; /* How many bytes were actually read from the
+ * input device? */
+
+ *errorCodePtr = 0;
+
+ /*
+ * Assume there is always enough input available. This will block
+ * appropriately, and read will unblock as soon as a short read is
+ * possible, if the channel is in blocking mode. If the channel is
+ * nonblocking, the read will never block. Some OSes can throw an
+ * interrupt error, for which we should immediately retry. [Bug #415131]
+ */
+
+ do {
+ bytesRead = read(GetFd(psPtr->inFile), buf, (size_t) toRead);
+ } while ((bytesRead < 0) && (errno == EINTR));
+
+ if (bytesRead < 0) {
+ *errorCodePtr = errno;
+ return -1;
+ }
+ return bytesRead;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PipeOutputProc--
+ *
+ * This function is invoked from the generic IO level to write output to
+ * a command pipeline based channel.
+ *
+ * Results:
+ * The number of bytes written is returned or -1 on error. An output
+ * argument contains a POSIX error code if an error occurred, or zero.
+ *
+ * Side effects:
+ * Writes output on the output device of the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PipeOutputProc(
+ ClientData instanceData, /* Pipe state. */
+ const char *buf, /* The data buffer. */
+ int toWrite, /* How many bytes to write? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ PipeState *psPtr = instanceData;
+ int written;
+
+ *errorCodePtr = 0;
+
+ /*
+ * Some OSes can throw an interrupt error, for which we should immediately
+ * retry. [Bug #415131]
+ */
+
+ do {
+ written = write(GetFd(psPtr->outFile), buf, (size_t) toWrite);
+ } while ((written < 0) && (errno == EINTR));
+
+ if (written < 0) {
+ *errorCodePtr = errno;
+ return -1;
+ }
+ return written;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PipeWatchProc --
+ *
+ * Initialize the notifier to watch the fds from this channel.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets up the notifier so that a future event on the channel will be
+ * seen by Tcl.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+PipeWatchProc(
+ ClientData instanceData, /* The pipe state. */
+ int mask) /* Events of interest; an OR-ed combination of
+ * TCL_READABLE, TCL_WRITABLE and
+ * TCL_EXCEPTION. */
+{
+ PipeState *psPtr = instanceData;
+ int newmask;
+
+ if (psPtr->inFile) {
+ newmask = mask & (TCL_READABLE | TCL_EXCEPTION);
+ if (newmask) {
+ Tcl_CreateFileHandler(GetFd(psPtr->inFile), newmask,
+ (Tcl_FileProc *) Tcl_NotifyChannel, psPtr->channel);
+ } else {
+ Tcl_DeleteFileHandler(GetFd(psPtr->inFile));
+ }
+ }
+ if (psPtr->outFile) {
+ newmask = mask & (TCL_WRITABLE | TCL_EXCEPTION);
+ if (newmask) {
+ Tcl_CreateFileHandler(GetFd(psPtr->outFile), newmask,
+ (Tcl_FileProc *) Tcl_NotifyChannel, psPtr->channel);
+ } else {
+ Tcl_DeleteFileHandler(GetFd(psPtr->outFile));
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PipeGetHandleProc --
+ *
+ * Called from Tcl_GetChannelHandle to retrieve OS handles from inside a
+ * command pipeline based channel.
+ *
+ * Results:
+ * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no
+ * handle for the specified direction.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PipeGetHandleProc(
+ ClientData instanceData, /* The pipe state. */
+ int direction, /* TCL_READABLE or TCL_WRITABLE */
+ ClientData *handlePtr) /* Where to store the handle. */
+{
+ PipeState *psPtr = instanceData;
+
+ if (direction == TCL_READABLE && psPtr->inFile) {
+ *handlePtr = INT2PTR(GetFd(psPtr->inFile));
+ return TCL_OK;
+ }
+ if (direction == TCL_WRITABLE && psPtr->outFile) {
+ *handlePtr = INT2PTR(GetFd(psPtr->outFile));
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_WaitPid --
+ *
+ * Implements the waitpid system call on Unix systems.
+ *
+ * Results:
+ * Result of calling waitpid.
+ *
+ * Side effects:
+ * Waits for a process to terminate.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Pid
+Tcl_WaitPid(
+ Tcl_Pid pid,
+ int *statPtr,
+ int options)
+{
+ int result;
+ pid_t real_pid = (pid_t) PTR2INT(pid);
+
+ while (1) {
+ result = (int) waitpid(real_pid, statPtr, options);
+ if ((result != -1) || (errno != EINTR)) {
+ return (Tcl_Pid) INT2PTR(result);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_PidObjCmd --
+ *
+ * This function is invoked to process the "pid" Tcl command. See the
+ * user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+Tcl_PidObjCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Argument strings. */
+{
+ Tcl_Channel chan;
+ PipeState *pipePtr;
+ int i;
+ Tcl_Obj *resultPtr;
+
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 1) {
+ Tcl_SetObjResult(interp, Tcl_NewLongObj((long) getpid()));
+ } else {
+ /*
+ * Get the channel and make sure that it refers to a pipe.
+ */
+
+ chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL);
+ if (chan == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetChannelType(chan) != &pipeChannelType) {
+ return TCL_OK;
+ }
+
+ /*
+ * Extract the process IDs from the pipe structure.
+ */
+
+ pipePtr = Tcl_GetChannelInstanceData(chan);
+ resultPtr = Tcl_NewObj();
+ for (i = 0; i < pipePtr->numPids; i++) {
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewIntObj(PTR2INT(TclpGetPid(pipePtr->pidPtr[i]))));
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFinalizePipes --
+ *
+ * Cleans up the pipe subsystem from Tcl_FinalizeThread
+ *
+ * Results:
+ * None.
+ *
+ * Notes:
+ * This function carries out no operation on Unix.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpFinalizePipes(void)
+{
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixPort.h b/unix/tclUnixPort.h
new file mode 100644
index 0000000..ba56089
--- /dev/null
+++ b/unix/tclUnixPort.h
@@ -0,0 +1,725 @@
+/*
+ * tclUnixPort.h --
+ *
+ * This header file handles porting issues that occur because of
+ * differences between systems. It reads in UNIX-related header files and
+ * sets up UNIX-related macros for Tcl's UNIX core. It should be the only
+ * file that contains #ifdefs to handle different flavors of UNIX. This
+ * file sets up the union of all UNIX-related things needed by any of the
+ * Tcl core files. This file depends on configuration #defines such as
+ * NO_DIRENT_H that are set up by the "configure" script.
+ *
+ * Much of the material in this file was originally contributed by Karl
+ * Lehenbauer, Mark Diekhans and Peter da Silva.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TCLUNIXPORT
+#define _TCLUNIXPORT
+
+/*
+ *---------------------------------------------------------------------------
+ * The following sets of #includes and #ifdefs are required to get Tcl to
+ * compile under the various flavors of unix.
+ *---------------------------------------------------------------------------
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_NET_ERRNO_H
+# include <net/errno.h>
+#endif
+#include <pwd.h>
+#include <signal.h>
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+#include <sys/types.h>
+#ifdef USE_DIRENT2_H
+# include "../compat/dirent2.h"
+#else
+#ifdef NO_DIRENT_H
+# include "../compat/dirent.h"
+#else
+# include <dirent.h>
+#endif
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Parameterize for 64-bit filesystem support.
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef HAVE_STRUCT_DIRENT64
+typedef struct dirent64 Tcl_DirEntry;
+# define TclOSreaddir readdir64
+#else
+typedef struct dirent Tcl_DirEntry;
+# define TclOSreaddir readdir
+#endif
+
+#ifdef HAVE_TYPE_OFF64_T
+typedef off64_t Tcl_SeekOffset;
+# define TclOSseek lseek64
+# define TclOSopen open64
+#else
+typedef off_t Tcl_SeekOffset;
+# define TclOSseek lseek
+# define TclOSopen open
+#endif
+
+#ifdef __CYGWIN__
+
+ /* Make some symbols available without including <windows.h> */
+# define DWORD unsigned int
+# define CP_UTF8 65001
+# define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004
+# define HANDLE void *
+# define HINSTANCE void *
+# define SOCKET unsigned int
+# define WSAEWOULDBLOCK 10035
+ typedef unsigned short WCHAR;
+ __declspec(dllimport) extern __stdcall int GetModuleHandleExW(unsigned int, const char *, void *);
+ __declspec(dllimport) extern __stdcall int GetModuleFileNameW(void *, const char *, int);
+ __declspec(dllimport) extern __stdcall int WideCharToMultiByte(int, int, const char *, int,
+ const char *, int, const char *, const char *);
+ __declspec(dllimport) extern __stdcall int MultiByteToWideChar(int, int, const char *, int,
+ WCHAR *, int);
+ __declspec(dllimport) extern __stdcall void OutputDebugStringW(const WCHAR *);
+ __declspec(dllimport) extern __stdcall int IsDebuggerPresent();
+ __declspec(dllimport) extern __stdcall int GetLastError();
+ __declspec(dllimport) extern __stdcall int GetFileAttributesW(const WCHAR *);
+ __declspec(dllimport) extern __stdcall int SetFileAttributesW(const WCHAR *, int);
+
+ __declspec(dllimport) extern int cygwin_conv_path(int, const void *, void *, int);
+/* On Cygwin, the environment is imported from the Cygwin DLL. */
+#ifndef __x86_64__
+# define environ __cygwin_environ
+ extern char **__cygwin_environ;
+#endif
+# define timezone _timezone
+ extern int TclOSstat(const char *name, void *statBuf);
+ extern int TclOSlstat(const char *name, void *statBuf);
+#elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__)
+# define TclOSstat stat64
+# define TclOSlstat lstat64
+#else
+# define TclOSstat stat
+# define TclOSlstat lstat
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Miscellaneous includes that might be missing.
+ *---------------------------------------------------------------------------
+ */
+
+#include <sys/file.h>
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#include <sys/stat.h>
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+# include <time.h>
+#endif
+#endif
+#ifndef NO_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#include <limits.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#else
+# include "../compat/unistd.h"
+#endif
+
+extern int TclUnixSetBlockingMode(int fd, int mode);
+
+#include <utime.h>
+
+/*
+ *---------------------------------------------------------------------------
+ * Socket support stuff: This likely needs more work to parameterize for each
+ * system.
+ *---------------------------------------------------------------------------
+ */
+
+#include <sys/socket.h> /* struct sockaddr, SOCK_STREAM, ... */
+#ifndef NO_UNAME
+# include <sys/utsname.h> /* uname system call. */
+#endif
+#include <netinet/in.h> /* struct in_addr, struct sockaddr_in */
+#include <arpa/inet.h> /* inet_ntoa() */
+#include <netdb.h> /* getaddrinfo() */
+#ifdef NEED_FAKE_RFC2553
+# include "../compat/fake-rfc2553.h"
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Some platforms (e.g. SunOS) don't define FLT_MAX and FLT_MIN, so we look
+ * for an alternative definition. If no other alternative is available we use
+ * a reasonable guess.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef NO_FLOAT_H
+# include <float.h>
+#else
+#ifndef NO_VALUES_H
+# include <values.h>
+#endif
+#endif
+
+#ifndef FLT_MAX
+# ifdef MAXFLOAT
+# define FLT_MAX MAXFLOAT
+# else
+# define FLT_MAX 3.402823466E+38F
+# endif
+#endif
+#ifndef FLT_MIN
+# ifdef MINFLOAT
+# define FLT_MIN MINFLOAT
+# else
+# define FLT_MIN 1.175494351E-38F
+# endif
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * NeXT doesn't define O_NONBLOCK, so #define it here if necessary.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 0x80
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * The type of the status returned by wait varies from UNIX system to UNIX
+ * system. The macro below defines it:
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef _AIX
+# define WAIT_STATUS_TYPE pid_t
+#else
+#ifndef NO_UNION_WAIT
+# define WAIT_STATUS_TYPE union wait
+#else
+# define WAIT_STATUS_TYPE int
+#endif
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Supply definitions for macros to query wait status, if not already defined
+ * in header files above.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef WIFEXITED
+# define WIFEXITED(stat) (((*((int *) &(stat))) & 0xff) == 0)
+#endif
+
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff)
+#endif
+
+#ifndef WIFSIGNALED
+# define WIFSIGNALED(stat) \
+ (((*((int *) &(stat)))) && ((*((int *) &(stat))) \
+ == ((*((int *) &(stat))) & 0x00ff)))
+#endif
+
+#ifndef WTERMSIG
+# define WTERMSIG(stat) ((*((int *) &(stat))) & 0x7f)
+#endif
+
+#ifndef WIFSTOPPED
+# define WIFSTOPPED(stat) (((*((int *) &(stat))) & 0xff) == 0177)
+#endif
+
+#ifndef WSTOPSIG
+# define WSTOPSIG(stat) (((*((int *) &(stat))) >> 8) & 0xff)
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Define constants for waitpid() system call if they aren't defined by a
+ * system header file.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef WNOHANG
+# define WNOHANG 1
+#endif
+#ifndef WUNTRACED
+# define WUNTRACED 2
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Supply macros for seek offsets, if they're not already provided by an
+ * include file.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef SEEK_SET
+# define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+# define SEEK_CUR 1
+#endif
+#ifndef SEEK_END
+# define SEEK_END 2
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * The stuff below is needed by the "time" command. If this system has no
+ * gettimeofday call, then must use times() instead.
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NO_GETTOD
+# include <sys/times.h>
+#else
+# ifdef HAVE_BSDGETTIMEOFDAY
+# define gettimeofday BSDgettimeofday
+# endif
+#endif
+
+#ifdef GETTOD_NOT_DECLARED
+extern int gettimeofday(struct timeval *tp,
+ struct timezone *tzp);
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Define access mode constants if they aren't already defined.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef F_OK
+# define F_OK 00
+#endif
+#ifndef X_OK
+# define X_OK 01
+#endif
+#ifndef W_OK
+# define W_OK 02
+#endif
+#ifndef R_OK
+# define R_OK 04
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Define FD_CLOEEXEC (the close-on-exec flag bit) if it isn't already
+ * defined.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef FD_CLOEXEC
+# define FD_CLOEXEC 1
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * On systems without symbolic links (i.e. S_IFLNK isn't defined) define
+ * "lstat" to use "stat" instead.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef S_IFLNK
+# undef TclOSlstat
+# define lstat stat
+# define lstat64 stat64
+# define TclOSlstat TclOSstat
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Define macros to query file type bits, if they're not already defined.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef S_ISREG
+# ifdef S_IFREG
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+# else
+# define S_ISREG(m) 0
+# endif
+#endif /* !S_ISREG */
+#ifndef S_ISDIR
+# ifdef S_IFDIR
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# else
+# define S_ISDIR(m) 0
+# endif
+#endif /* !S_ISDIR */
+#ifndef S_ISCHR
+# ifdef S_IFCHR
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+# else
+# define S_ISCHR(m) 0
+# endif
+#endif /* !S_ISCHR */
+
+#ifndef S_ISBLK
+# ifdef S_IFBLK
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+# else
+# define S_ISBLK(m) 0
+# endif
+#endif /* !S_ISBLK */
+
+#ifndef S_ISFIFO
+# ifdef S_IFIFO
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# else
+# define S_ISFIFO(m) 0
+# endif
+#endif /* !S_ISFIFO */
+
+#ifndef S_ISLNK
+# ifdef S_IFLNK
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+# else
+# define S_ISLNK(m) 0
+# endif
+#endif /* !S_ISLNK */
+
+#ifndef S_ISSOCK
+# ifdef S_IFSOCK
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# else
+# define S_ISSOCK(m) 0
+# endif
+#endif /* !S_ISSOCK */
+
+/*
+ *---------------------------------------------------------------------------
+ * Make sure that MAXPATHLEN and MAXNAMLEN are defined.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef MAXPATHLEN
+# ifdef PATH_MAX
+# define MAXPATHLEN PATH_MAX
+# else
+# define MAXPATHLEN 2048
+# endif
+#endif
+
+#ifndef MAXNAMLEN
+# ifdef NAME_MAX
+# define MAXNAMLEN NAME_MAX
+# else
+# define MAXNAMLEN 255
+# endif
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * The following macro defines the type of the mask arguments to select:
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef NO_FD_SET
+# define SELECT_MASK fd_set
+#else /* NO_FD_SET */
+# ifndef _AIX
+ typedef long fd_mask;
+# endif /* !AIX */
+# if defined(_IBMR2)
+# define SELECT_MASK void
+# else /* !defined(_IBMR2) */
+# define SELECT_MASK int
+# endif /* defined(_IBMR2) */
+#endif /* !NO_FD_SET */
+
+/*
+ *---------------------------------------------------------------------------
+ * Define "NBBY" (number of bits per byte) if it's not already defined.
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef NBBY
+# define NBBY 8
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * The following macro defines the number of fd_masks in an fd_set:
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef FD_SETSIZE
+# ifdef OPEN_MAX
+# define FD_SETSIZE OPEN_MAX
+# else
+# define FD_SETSIZE 256
+# endif
+#endif /* FD_SETSIZE */
+
+#ifndef howmany
+# define howmany(x, y) (((x)+((y)-1))/(y))
+#endif /* !defined(howmany) */
+
+#ifndef NFDBITS
+# define NFDBITS NBBY*sizeof(fd_mask)
+#endif /* NFDBITS */
+
+#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS)
+
+/*
+ *---------------------------------------------------------------------------
+ * Not all systems declare the errno variable in errno.h. so this file does it
+ * explicitly. The list of system error messages also isn't generally declared
+ * in a header file anywhere.
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef NO_ERRNO
+extern int errno;
+#endif /* NO_ERRNO */
+
+/*
+ *---------------------------------------------------------------------------
+ * Not all systems declare all the errors that Tcl uses! Provide some
+ * work-arounds...
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef EOVERFLOW
+# ifdef EFBIG
+# define EOVERFLOW EFBIG
+# else /* !EFBIG */
+# define EOVERFLOW EINVAL
+# endif /* EFBIG */
+#endif /* EOVERFLOW */
+
+/*
+ *---------------------------------------------------------------------------
+ * Variables provided by the C library:
+ *---------------------------------------------------------------------------
+ */
+
+#if defined(__APPLE__) && defined(__DYNAMIC__)
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+# define USE_PUTENV 1
+#else
+# if defined(_sgi) || defined(__sgi)
+# define environ _environ
+# endif
+extern char ** environ;
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Darwin specifc configure overrides.
+ *---------------------------------------------------------------------------
+ */
+
+#ifdef __APPLE__
+
+/*
+ *---------------------------------------------------------------------------
+ * Support for fat compiles: configure runs only once for multiple architectures
+ *---------------------------------------------------------------------------
+ */
+
+# if defined(__LP64__) && defined (NO_COREFOUNDATION_64)
+# undef HAVE_COREFOUNDATION
+# endif /* __LP64__ && NO_COREFOUNDATION_64 */
+# include <sys/cdefs.h>
+# ifdef __DARWIN_UNIX03
+# if __DARWIN_UNIX03
+# undef HAVE_PUTENV_THAT_COPIES
+# else
+# define HAVE_PUTENV_THAT_COPIES 1
+# endif
+# endif /* __DARWIN_UNIX03 */
+
+/*
+ *---------------------------------------------------------------------------
+ * Include AvailabilityMacros.h here (when available) to ensure any symbolic
+ * MAC_OS_X_VERSION_* constants passed on the command line are translated.
+ *---------------------------------------------------------------------------
+ */
+
+# ifdef HAVE_AVAILABILITYMACROS_H
+# include <AvailabilityMacros.h>
+# endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Support for weak import.
+ *---------------------------------------------------------------------------
+ */
+
+# ifdef HAVE_WEAK_IMPORT
+# if !defined(HAVE_AVAILABILITYMACROS_H) || !defined(MAC_OS_X_VERSION_MIN_REQUIRED)
+# undef HAVE_WEAK_IMPORT
+# else
+# ifndef WEAK_IMPORT_ATTRIBUTE
+# define WEAK_IMPORT_ATTRIBUTE __attribute__((weak_import))
+# endif
+# endif
+# endif /* HAVE_WEAK_IMPORT */
+
+/*
+ *---------------------------------------------------------------------------
+ * Support for MAC_OS_X_VERSION_MAX_ALLOWED define from AvailabilityMacros.h:
+ * only use API available in the indicated OS version or earlier.
+ *---------------------------------------------------------------------------
+ */
+
+# ifdef MAC_OS_X_VERSION_MAX_ALLOWED
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 && defined(__LP64__)
+# undef HAVE_COREFOUNDATION
+# endif
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1040
+# undef HAVE_OSSPINLOCKLOCK
+# undef HAVE_PTHREAD_ATFORK
+# undef HAVE_COPYFILE
+# endif
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
+# ifdef TCL_THREADS
+ /* prior to 10.3, realpath is not threadsafe, c.f. bug 711232 */
+# define NO_REALPATH 1
+# endif
+# undef HAVE_LANGINFO
+# endif
+# endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
+# if defined(HAVE_COREFOUNDATION) && defined(__LP64__) && \
+ defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+# warning "Weak import of 64-bit CoreFoundation is not supported, will not run on Mac OS X < 10.5."
+# endif
+
+/*
+ *---------------------------------------------------------------------------
+ * At present, using vfork() instead of fork() causes execve() to fail
+ * intermittently on Darwin x86_64. rdar://4685553
+ *---------------------------------------------------------------------------
+ */
+
+# if defined(__x86_64__) && !defined(FIXED_RDAR_4685553)
+# undef USE_VFORK
+# endif /* __x86_64__ */
+/* Workaround problems with vfork() when building with llvm-gcc-4.2 */
+# if defined (__llvm__) && \
+ (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 2 || \
+ (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ > 0))))
+# undef USE_VFORK
+# endif /* __llvm__ */
+#endif /* __APPLE__ */
+
+/*
+ *---------------------------------------------------------------------------
+ * The following macros and declarations represent the interface between
+ * generic and unix-specific parts of Tcl. Some of the macros may override
+ * functions declared in tclInt.h.
+ *---------------------------------------------------------------------------
+ */
+
+/*
+ * The default platform eol translation on Unix is TCL_TRANSLATE_LF.
+ */
+
+#ifdef DJGPP
+#define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_CRLF
+typedef int socklen_t;
+#else
+#define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_LF
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * The following macros have trivial definitions, allowing generic code to
+ * address platform-specific issues.
+ *---------------------------------------------------------------------------
+ */
+
+#define TclpReleaseFile(file) /* Nothing. */
+
+/*
+ *---------------------------------------------------------------------------
+ * The following defines wrap the system memory allocation routines.
+ *---------------------------------------------------------------------------
+ */
+
+#define TclpSysAlloc(size, isBin) malloc((size_t)(size))
+#define TclpSysFree(ptr) free((char *)(ptr))
+#define TclpSysRealloc(ptr, size) realloc((char *)(ptr), (size_t)(size))
+
+/*
+ *---------------------------------------------------------------------------
+ * The following macros and declaration wrap the C runtime library functions.
+ *---------------------------------------------------------------------------
+ */
+
+#define TclpExit exit
+
+#ifdef TCL_THREADS
+# include <pthread.h>
+#endif /* TCL_THREADS */
+
+/* FIXME - Hyper-enormous platform assumption! */
+#ifndef AF_INET6
+# define AF_INET6 10
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ * Set of MT-safe implementations of some known-to-be-MT-unsafe library calls.
+ * Instead of returning pointers to the static storage, those return pointers
+ * to the TSD data.
+ *---------------------------------------------------------------------------
+ */
+
+#include <pwd.h>
+#include <grp.h>
+
+extern struct passwd * TclpGetPwNam(const char *name);
+extern struct group * TclpGetGrNam(const char *name);
+extern struct passwd * TclpGetPwUid(uid_t uid);
+extern struct group * TclpGetGrGid(gid_t gid);
+extern struct hostent * TclpGetHostByName(const char *name);
+extern struct hostent * TclpGetHostByAddr(const char *addr,
+ int length, int type);
+extern void *TclpMakeTcpClientChannelMode(
+ void *tcpSocket, int mode);
+
+#endif /* _TCLUNIXPORT */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
new file mode 100644
index 0000000..45abc01
--- /dev/null
+++ b/unix/tclUnixSock.c
@@ -0,0 +1,1821 @@
+/*
+ * tclUnixSock.c --
+ *
+ * This file contains Unix-specific socket related code.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+
+/*
+ * Helper macros to make parts of this file clearer. The macros do exactly
+ * what they say on the tin. :-) They also only ever refer to their arguments
+ * once, and so can be used without regard to side effects.
+ */
+
+#define SET_BITS(var, bits) ((var) |= (bits))
+#define CLEAR_BITS(var, bits) ((var) &= ~(bits))
+#define GOT_BITS(var, bits) (((var) & (bits)) != 0)
+
+/* "sock" + a pointer in hex + \0 */
+#define SOCK_CHAN_LENGTH (4 + sizeof(void *) * 2 + 1)
+#define SOCK_TEMPLATE "sock%lx"
+
+#undef SOCKET /* Possible conflict with win32 SOCKET */
+
+/*
+ * This is needed to comply with the strict aliasing rules of GCC, but it also
+ * simplifies casting between the different sockaddr types.
+ */
+
+typedef union {
+ struct sockaddr sa;
+ struct sockaddr_in sa4;
+ struct sockaddr_in6 sa6;
+ struct sockaddr_storage sas;
+} address;
+
+/*
+ * This structure describes per-instance state of a tcp based channel.
+ */
+
+typedef struct TcpState TcpState;
+
+typedef struct TcpFdList {
+ TcpState *statePtr;
+ int fd;
+ struct TcpFdList *next;
+} TcpFdList;
+
+struct TcpState {
+ Tcl_Channel channel; /* Channel associated with this file. */
+ int testFlags; /* bit field for tests. Is set by testsocket
+ * test procedure */
+ TcpFdList fds; /* The file descriptors of the sockets. */
+ int flags; /* ORed combination of the bitfields defined
+ * below. */
+ int interest; /* Event types of interest */
+
+ /*
+ * Only needed for server sockets
+ */
+
+ Tcl_TcpAcceptProc *acceptProc;
+ /* Proc to call on accept. */
+ ClientData acceptProcData; /* The data for the accept proc. */
+
+ /*
+ * Only needed for client sockets
+ */
+
+ struct addrinfo *addrlist; /* Addresses to connect to. */
+ struct addrinfo *addr; /* Iterator over addrlist. */
+ struct addrinfo *myaddrlist;/* Local address. */
+ struct addrinfo *myaddr; /* Iterator over myaddrlist. */
+ int filehandlers; /* Caches FileHandlers that get set up while
+ * an async socket is not yet connected. */
+ int connectError; /* Cache SO_ERROR of async socket. */
+ int cachedBlocking; /* Cache blocking mode of async socket. */
+};
+
+/*
+ * These bits may be ORed together into the "flags" field of a TcpState
+ * structure.
+ */
+
+#define TCP_NONBLOCKING (1<<0) /* Socket with non-blocking I/O */
+#define TCP_ASYNC_CONNECT (1<<1) /* Async connect in progress. */
+#define TCP_ASYNC_PENDING (1<<4) /* TcpConnect was called to
+ * process an async connect. This
+ * flag indicates that reentry is
+ * still pending */
+#define TCP_ASYNC_FAILED (1<<5) /* An async connect finally failed */
+
+/*
+ * These bits may be ORed together into the "testFlags" field of a TcpState
+ * structure.
+ */
+
+#define TCP_ASYNC_TEST_MODE (1<<0) /* Async testing activated. Do not
+ * automatically continue connection
+ * process. */
+
+/*
+ * The following defines the maximum length of the listen queue. This is the
+ * number of outstanding yet-to-be-serviced requests for a connection on a
+ * server socket, more than this number of outstanding requests and the
+ * connection request will fail.
+ */
+
+#ifndef SOMAXCONN
+# define SOMAXCONN 100
+#elif (SOMAXCONN < 100)
+# undef SOMAXCONN
+# define SOMAXCONN 100
+#endif /* SOMAXCONN < 100 */
+
+/*
+ * The following defines how much buffer space the kernel should maintain for
+ * a socket.
+ */
+
+#define SOCKET_BUFSIZE 4096
+
+/*
+ * Static routines for this file:
+ */
+
+static int TcpConnect(Tcl_Interp *interp, TcpState *state);
+static void TcpAccept(ClientData data, int mask);
+static int TcpBlockModeProc(ClientData data, int mode);
+static int TcpCloseProc(ClientData instanceData,
+ Tcl_Interp *interp);
+static int TcpClose2Proc(ClientData instanceData,
+ Tcl_Interp *interp, int flags);
+static int TcpGetHandleProc(ClientData instanceData,
+ int direction, ClientData *handlePtr);
+static int TcpGetOptionProc(ClientData instanceData,
+ Tcl_Interp *interp, const char *optionName,
+ Tcl_DString *dsPtr);
+static int TcpInputProc(ClientData instanceData, char *buf,
+ int toRead, int *errorCode);
+static int TcpOutputProc(ClientData instanceData,
+ const char *buf, int toWrite, int *errorCode);
+static void TcpWatchProc(ClientData instanceData, int mask);
+static int WaitForConnect(TcpState *statePtr, int *errorCodePtr);
+static void WrapNotify(ClientData clientData, int mask);
+
+/*
+ * This structure describes the channel type structure for TCP socket
+ * based IO:
+ */
+
+static const Tcl_ChannelType tcpChannelType = {
+ "tcp", /* Type name. */
+ TCL_CHANNEL_VERSION_5, /* v5 channel */
+ TcpCloseProc, /* Close proc. */
+ TcpInputProc, /* Input proc. */
+ TcpOutputProc, /* Output proc. */
+ NULL, /* Seek proc. */
+ NULL, /* Set option proc. */
+ TcpGetOptionProc, /* Get option proc. */
+ TcpWatchProc, /* Initialize notifier. */
+ TcpGetHandleProc, /* Get OS handles out of channel. */
+ TcpClose2Proc, /* Close2 proc. */
+ TcpBlockModeProc, /* Set blocking or non-blocking mode.*/
+ NULL, /* flush proc. */
+ NULL, /* handler proc. */
+ NULL, /* wide seek proc. */
+ NULL, /* thread action proc. */
+ NULL /* truncate proc. */
+};
+
+/*
+ * The following variable holds the network name of this host.
+ */
+
+static TclInitProcessGlobalValueProc InitializeHostName;
+static ProcessGlobalValue hostName =
+ {0, 0, NULL, NULL, InitializeHostName, NULL, NULL};
+
+#if 0
+/* printf debugging */
+void
+printaddrinfo(
+ struct addrinfo *addrlist,
+ char *prefix)
+{
+ char host[NI_MAXHOST], port[NI_MAXSERV];
+ struct addrinfo *ai;
+
+ for (ai = addrlist; ai != NULL; ai = ai->ai_next) {
+ getnameinfo(ai->ai_addr, ai->ai_addrlen,
+ host, sizeof(host), port, sizeof(port),
+ NI_NUMERICHOST|NI_NUMERICSERV);
+ fprintf(stderr,"%s: %s:%s\n", prefix, host, port);
+ }
+}
+#endif
+/*
+ * ----------------------------------------------------------------------
+ *
+ * InitializeHostName --
+ *
+ * This routine sets the process global value of the name of the local
+ * host on which the process is running.
+ *
+ * Results:
+ * None.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static void
+InitializeHostName(
+ char **valuePtr,
+ size_t *lengthPtr,
+ Tcl_Encoding *encodingPtr)
+{
+ const char *native = NULL;
+
+#ifndef NO_UNAME
+ struct utsname u;
+ struct hostent *hp;
+
+ memset(&u, (int) 0, sizeof(struct utsname));
+ if (uname(&u) > -1) { /* INTL: Native. */
+ hp = TclpGetHostByName(u.nodename); /* INTL: Native. */
+ if (hp == NULL) {
+ /*
+ * Sometimes the nodename is fully qualified, but gets truncated
+ * as it exceeds SYS_NMLN. See if we can just get the immediate
+ * nodename and get a proper answer that way.
+ */
+
+ char *dot = strchr(u.nodename, '.');
+
+ if (dot != NULL) {
+ char *node = ckalloc(dot - u.nodename + 1);
+
+ memcpy(node, u.nodename, (size_t) (dot - u.nodename));
+ node[dot - u.nodename] = '\0';
+ hp = TclpGetHostByName(node);
+ ckfree(node);
+ }
+ }
+ if (hp != NULL) {
+ native = hp->h_name;
+ } else {
+ native = u.nodename;
+ }
+ }
+ if (native == NULL) {
+ native = &tclEmptyString;
+ }
+#else /* !NO_UNAME */
+ /*
+ * Uname doesn't exist; try gethostname instead.
+ *
+ * There is no portable macro for the maximum length of host names
+ * returned by gethostbyname(). We should only trust SYS_NMLN if it is at
+ * least 255 + 1 bytes to comply with DNS host name limits.
+ *
+ * Note: SYS_NMLN is a restriction on "uname" not on gethostbyname!
+ *
+ * For example HP-UX 10.20 has SYS_NMLN == 9, while gethostbyname() can
+ * return a fully qualified name from DNS of up to 255 bytes.
+ *
+ * Fix suggested by Viktor Dukhovni (viktor@esm.com)
+ */
+
+# if defined(SYS_NMLN) && (SYS_NMLEN >= 256)
+ char buffer[SYS_NMLEN];
+# else
+ char buffer[256];
+# endif
+
+ if (gethostname(buffer, sizeof(buffer)) > -1) { /* INTL: Native. */
+ native = buffer;
+ }
+#endif /* NO_UNAME */
+
+ *encodingPtr = Tcl_GetEncoding(NULL, NULL);
+ *lengthPtr = strlen(native);
+ *valuePtr = ckalloc(*lengthPtr + 1);
+ memcpy(*valuePtr, native, *lengthPtr + 1);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Tcl_GetHostName --
+ *
+ * Returns the name of the local host.
+ *
+ * Results:
+ * A string containing the network name for this machine, or an empty
+ * string if we can't figure out the name. The caller must not modify or
+ * free this string.
+ *
+ * Side effects:
+ * Caches the name to return for future calls.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+const char *
+Tcl_GetHostName(void)
+{
+ return Tcl_GetString(TclGetProcessGlobalValue(&hostName));
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * TclpHasSockets --
+ *
+ * Detect if sockets are available on this platform.
+ *
+ * Results:
+ * Returns TCL_OK.
+ *
+ * Side effects:
+ * None.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+int
+TclpHasSockets(
+ Tcl_Interp *interp) /* Not used. */
+{
+ return TCL_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * TclpFinalizeSockets --
+ *
+ * Performs per-thread socket subsystem finalization.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+void
+TclpFinalizeSockets(void)
+{
+ return;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * TcpBlockModeProc --
+ *
+ * This function is invoked by the generic IO level to set blocking and
+ * nonblocking mode on a TCP socket based channel.
+ *
+ * Results:
+ * 0 if successful, errno when failed.
+ *
+ * Side effects:
+ * Sets the device into blocking or nonblocking mode.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TcpBlockModeProc(
+ ClientData instanceData, /* Socket state. */
+ int mode) /* The mode to set. Can be one of
+ * TCL_MODE_BLOCKING or
+ * TCL_MODE_NONBLOCKING. */
+{
+ TcpState *statePtr = instanceData;
+
+ if (mode == TCL_MODE_BLOCKING) {
+ CLEAR_BITS(statePtr->flags, TCP_NONBLOCKING);
+ } else {
+ SET_BITS(statePtr->flags, TCP_NONBLOCKING);
+ }
+ if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
+ statePtr->cachedBlocking = mode;
+ return 0;
+ }
+ if (TclUnixSetBlockingMode(statePtr->fds.fd, mode) < 0) {
+ return errno;
+ }
+ return 0;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * WaitForConnect --
+ *
+ * Check the state of an async connect process. If a connection attempt
+ * terminated, process it, which may finalize it or may start the next
+ * attempt. If a connect error occures, it is saved in
+ * statePtr->connectError to be reported by 'fconfigure -error'.
+ *
+ * There are two modes of operation, defined by errorCodePtr:
+ * * non-NULL: Called by explicite read/write command. Blocks if the
+ * socket is blocking.
+ * May return two error codes:
+ * * EWOULDBLOCK: if connect is still in progress
+ * * ENOTCONN: if connect failed. This would be the error message
+ * of a rect or sendto syscall so this is emulated here.
+ * * NULL: Called by a backround operation. Do not block and do not
+ * return any error code.
+ *
+ * Results:
+ * 0 if the connection has completed, -1 if still in progress or there is
+ * an error.
+ *
+ * Side effects:
+ * Processes socket events off the system queue. May process
+ * asynchroneous connects.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WaitForConnect(
+ TcpState *statePtr, /* State of the socket. */
+ int *errorCodePtr)
+{
+ int timeout;
+
+ /*
+ * Check if an async connect failed already and error reporting is
+ * demanded, return the error ENOTCONN
+ */
+
+ if (errorCodePtr != NULL && GOT_BITS(statePtr->flags, TCP_ASYNC_FAILED)) {
+ *errorCodePtr = ENOTCONN;
+ return -1;
+ }
+
+ /*
+ * Check if an async connect is running. If not return ok
+ */
+
+ if (!GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
+ return 0;
+ }
+
+ /*
+ * In socket test mode do not continue with the connect.
+ * Exceptions are:
+ * - Call by recv/send and blocking socket
+ * (errorCodePtr != NULL && !GOT_BITS(flags, TCP_NONBLOCKING))
+ */
+
+ if (GOT_BITS(statePtr->testFlags, TCP_ASYNC_TEST_MODE)
+ && !(errorCodePtr != NULL
+ && !GOT_BITS(statePtr->flags, TCP_NONBLOCKING))) {
+ *errorCodePtr = EWOULDBLOCK;
+ return -1;
+ }
+
+ if (errorCodePtr == NULL || GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
+ timeout = 0;
+ } else {
+ timeout = -1;
+ }
+ do {
+ if (TclUnixWaitForFile(statePtr->fds.fd,
+ TCL_WRITABLE | TCL_EXCEPTION, timeout) != 0) {
+ TcpConnect(NULL, statePtr);
+ }
+
+ /*
+ * Do this only once in the nonblocking case and repeat it until the
+ * socket is final when blocking.
+ */
+ } while (timeout == -1 && GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT));
+
+ if (errorCodePtr != NULL) {
+ if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
+ *errorCodePtr = EAGAIN;
+ return -1;
+ } else if (statePtr->connectError != 0) {
+ *errorCodePtr = ENOTCONN;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpInputProc --
+ *
+ * This function is invoked by the generic IO level to read input from a
+ * TCP socket based channel.
+ *
+ * NOTE: We cannot share code with FilePipeInputProc because here we must
+ * use recv to obtain the input from the channel, not read.
+ *
+ * Results:
+ * The number of bytes read is returned or -1 on error. An output
+ * argument contains the POSIX error code on error, or zero if no error
+ * occurred.
+ *
+ * Side effects:
+ * Reads input from the input device of the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TcpInputProc(
+ ClientData instanceData, /* Socket state. */
+ char *buf, /* Where to store data read. */
+ int bufSize, /* How much space is available in the
+ * buffer? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ TcpState *statePtr = instanceData;
+ int bytesRead;
+
+ *errorCodePtr = 0;
+ if (WaitForConnect(statePtr, errorCodePtr) != 0) {
+ return -1;
+ }
+ bytesRead = recv(statePtr->fds.fd, buf, (size_t) bufSize, 0);
+ if (bytesRead > -1) {
+ return bytesRead;
+ }
+ if (errno == ECONNRESET) {
+ /*
+ * Turn ECONNRESET into a soft EOF condition.
+ */
+
+ return 0;
+ }
+ *errorCodePtr = errno;
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpOutputProc --
+ *
+ * This function is invoked by the generic IO level to write output to a
+ * TCP socket based channel.
+ *
+ * NOTE: We cannot share code with FilePipeOutputProc because here we
+ * must use send, not write, to get reliable error reporting.
+ *
+ * Results:
+ * The number of bytes written is returned. An output argument is set to
+ * a POSIX error code if an error occurred, or zero.
+ *
+ * Side effects:
+ * Writes output on the output device of the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TcpOutputProc(
+ ClientData instanceData, /* Socket state. */
+ const char *buf, /* The data buffer. */
+ int toWrite, /* How many bytes to write? */
+ int *errorCodePtr) /* Where to store error code. */
+{
+ TcpState *statePtr = instanceData;
+ int written;
+
+ *errorCodePtr = 0;
+ if (WaitForConnect(statePtr, errorCodePtr) != 0) {
+ return -1;
+ }
+ written = send(statePtr->fds.fd, buf, (size_t) toWrite, 0);
+
+ if (written > -1) {
+ return written;
+ }
+ *errorCodePtr = errno;
+ return -1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpCloseProc --
+ *
+ * This function is invoked by the generic IO level to perform
+ * channel-type-specific cleanup when a TCP socket based channel is
+ * closed.
+ *
+ * Results:
+ * 0 if successful, the value of errno if failed.
+ *
+ * Side effects:
+ * Closes the socket of the channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TcpCloseProc(
+ ClientData instanceData, /* The socket to close. */
+ Tcl_Interp *interp) /* For error reporting - unused. */
+{
+ TcpState *statePtr = instanceData;
+ int errorCode = 0;
+ TcpFdList *fds;
+
+ /*
+ * Delete a file handler that may be active for this socket if this is a
+ * server socket - the file handler was created automatically by Tcl as
+ * part of the mechanism to accept new client connections. Channel
+ * handlers are already deleted in the generic IO channel closing code
+ * that called this function, so we do not have to delete them here.
+ */
+
+ for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
+ if (fds->fd < 0) {
+ continue;
+ }
+ Tcl_DeleteFileHandler(fds->fd);
+ if (close(fds->fd) < 0) {
+ errorCode = errno;
+ }
+
+ }
+ fds = statePtr->fds.next;
+ while (fds != NULL) {
+ TcpFdList *next = fds->next;
+
+ ckfree(fds);
+ fds = next;
+ }
+ if (statePtr->addrlist != NULL) {
+ freeaddrinfo(statePtr->addrlist);
+ }
+ if (statePtr->myaddrlist != NULL) {
+ freeaddrinfo(statePtr->myaddrlist);
+ }
+ ckfree(statePtr);
+ return errorCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpClose2Proc --
+ *
+ * This function is called by the generic IO level to perform the channel
+ * type specific part of a half-close: namely, a shutdown() on a socket.
+ *
+ * Results:
+ * 0 if successful, the value of errno if failed.
+ *
+ * Side effects:
+ * Shuts down one side of the socket.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TcpClose2Proc(
+ ClientData instanceData, /* The socket to close. */
+ Tcl_Interp *interp, /* For error reporting. */
+ int flags) /* Flags that indicate which side to close. */
+{
+ TcpState *statePtr = instanceData;
+ int errorCode = 0;
+ int sd;
+
+ /*
+ * Shutdown the OS socket handle.
+ */
+
+ switch(flags) {
+ case TCL_CLOSE_READ:
+ sd = SHUT_RD;
+ break;
+ case TCL_CLOSE_WRITE:
+ sd = SHUT_WR;
+ break;
+ default:
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "socket close2proc called bidirectionally", -1));
+ }
+ return TCL_ERROR;
+ }
+ if (shutdown(statePtr->fds.fd,sd) < 0) {
+ errorCode = errno;
+ }
+
+ return errorCode;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpHostPortList --
+ *
+ * This function is called by the -gethostname and -getpeername switches
+ * of TcpGetOptionProc() to add three list elements with the textual
+ * representation of the given address to the given DString.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Adds three elements do dsPtr
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifndef NEED_FAKE_RFC2553
+#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
+static inline int
+IPv6AddressNeedsNumericRendering(
+ struct in6_addr addr)
+{
+ if (IN6_ARE_ADDR_EQUAL(&addr, &in6addr_any)) {
+ return 1;
+ }
+
+ /*
+ * The IN6_IS_ADDR_V4MAPPED macro has a problem with aliasing warnings on
+ * at least some versions of OSX.
+ */
+
+ if (!IN6_IS_ADDR_V4MAPPED(&addr)) {
+ return 0;
+ }
+
+ return (addr.s6_addr[12] == 0 && addr.s6_addr[13] == 0
+ && addr.s6_addr[14] == 0 && addr.s6_addr[15] == 0);
+}
+#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+#pragma GCC diagnostic pop
+#endif
+#endif /* NEED_FAKE_RFC2553 */
+
+static void
+TcpHostPortList(
+ Tcl_Interp *interp,
+ Tcl_DString *dsPtr,
+ address addr,
+ socklen_t salen)
+{
+#define SUPPRESS_RDNS_VAR "::tcl::unsupported::noReverseDNS"
+ char host[NI_MAXHOST], nhost[NI_MAXHOST], nport[NI_MAXSERV];
+ int flags = 0;
+
+ getnameinfo(&addr.sa, salen, nhost, sizeof(nhost), nport, sizeof(nport),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ Tcl_DStringAppendElement(dsPtr, nhost);
+
+ /*
+ * We don't want to resolve INADDR_ANY and sin6addr_any; they can
+ * sometimes cause problems (and never have a name).
+ */
+
+ if (addr.sa.sa_family == AF_INET) {
+ if (addr.sa4.sin_addr.s_addr == INADDR_ANY) {
+ flags |= NI_NUMERICHOST;
+ }
+#ifndef NEED_FAKE_RFC2553
+ } else if (addr.sa.sa_family == AF_INET6) {
+ if (IPv6AddressNeedsNumericRendering(addr.sa6.sin6_addr)) {
+ flags |= NI_NUMERICHOST;
+ }
+#endif /* NEED_FAKE_RFC2553 */
+ }
+
+ /*
+ * Check if reverse DNS has been switched off globally.
+ */
+
+ if (interp != NULL &&
+ Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
+ flags |= NI_NUMERICHOST;
+ }
+ if (getnameinfo(&addr.sa, salen, host, sizeof(host), NULL, 0,
+ flags) == 0) {
+ /*
+ * Reverse mapping worked.
+ */
+
+ Tcl_DStringAppendElement(dsPtr, host);
+ } else {
+ /*
+ * Reverse mapping failed - use the numeric rep once more.
+ */
+
+ Tcl_DStringAppendElement(dsPtr, nhost);
+ }
+ Tcl_DStringAppendElement(dsPtr, nport);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpGetOptionProc --
+ *
+ * Computes an option value for a TCP socket based channel, or a list of
+ * all options and their values.
+ *
+ * Note: This code is based on code contributed by John Haxby.
+ *
+ * Results:
+ * A standard Tcl result. The value of the specified option or a list of
+ * all options and their values is returned in the supplied DString. Sets
+ * Error message if needed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TcpGetOptionProc(
+ ClientData instanceData, /* Socket state. */
+ Tcl_Interp *interp, /* For error reporting - can be NULL. */
+ const char *optionName, /* Name of the option to retrieve the value
+ * for, or NULL to get all options and their
+ * values. */
+ Tcl_DString *dsPtr) /* Where to store the computed value;
+ * initialized by caller. */
+{
+ TcpState *statePtr = instanceData;
+ size_t len = 0;
+
+ WaitForConnect(statePtr, NULL);
+
+ if (optionName != NULL) {
+ len = strlen(optionName);
+ }
+
+ if ((len > 1) && (optionName[1] == 'e') &&
+ (strncmp(optionName, "-error", len) == 0)) {
+ socklen_t optlen = sizeof(int);
+
+ if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
+ /*
+ * Suppress errors as long as we are not done.
+ */
+
+ errno = 0;
+ } else if (statePtr->connectError != 0) {
+ errno = statePtr->connectError;
+ statePtr->connectError = 0;
+ } else {
+ int err;
+
+ getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR, (char *) &err,
+ &optlen);
+ errno = err;
+ }
+ if (errno != 0) {
+ Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(errno), -1);
+ }
+ return TCL_OK;
+ }
+
+ if ((len > 1) && (optionName[1] == 'c') &&
+ (strncmp(optionName, "-connecting", len) == 0)) {
+ Tcl_DStringAppend(dsPtr,
+ GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT) ? "1" : "0", -1);
+ return TCL_OK;
+ }
+
+ if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
+ (strncmp(optionName, "-peername", len) == 0))) {
+ address peername;
+ socklen_t size = sizeof(peername);
+
+ if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
+ /*
+ * In async connect output an empty string
+ */
+
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-peername");
+ Tcl_DStringAppendElement(dsPtr, "");
+ } else {
+ return TCL_OK;
+ }
+ } else if (getpeername(statePtr->fds.fd, &peername.sa, &size) >= 0) {
+ /*
+ * Peername fetch succeeded - output list
+ */
+
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-peername");
+ Tcl_DStringStartSublist(dsPtr);
+ }
+ TcpHostPortList(interp, dsPtr, peername, size);
+ if (len) {
+ return TCL_OK;
+ }
+ Tcl_DStringEndSublist(dsPtr);
+ } else {
+ /*
+ * getpeername failed - but if we were asked for all the options
+ * (len==0), don't flag an error at that point because it could be
+ * an fconfigure request on a server socket (which have no peer).
+ * Same must be done on win&mac.
+ */
+
+ if (len) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't get peername: %s",
+ Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if ((len == 0) || ((len > 1) && (optionName[1] == 's') &&
+ (strncmp(optionName, "-sockname", len) == 0))) {
+ TcpFdList *fds;
+ address sockname;
+ socklen_t size;
+ int found = 0;
+
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-sockname");
+ Tcl_DStringStartSublist(dsPtr);
+ }
+ if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
+ /*
+ * In async connect output an empty string
+ */
+
+ found = 1;
+ } else {
+ for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
+ size = sizeof(sockname);
+ if (getsockname(fds->fd, &(sockname.sa), &size) >= 0) {
+ found = 1;
+ TcpHostPortList(interp, dsPtr, sockname, size);
+ }
+ }
+ }
+ if (found) {
+ if (len) {
+ return TCL_OK;
+ }
+ Tcl_DStringEndSublist(dsPtr);
+ } else {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't get sockname: %s", Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+ }
+
+ if (len > 0) {
+ return Tcl_BadChannelOption(interp, optionName,
+ "connecting peername sockname");
+ }
+
+ return TCL_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * TcpWatchProc --
+ *
+ * Initialize the notifier to watch the fd from this channel.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets up the notifier so that a future event on the channel will be
+ * seen by Tcl.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static void
+WrapNotify(
+ ClientData clientData,
+ int mask)
+{
+ TcpState *statePtr = (TcpState *) clientData;
+ int newmask = mask & statePtr->interest;
+
+ if (newmask == 0) {
+ /*
+ * There was no overlap between the states the channel is interested
+ * in notifications for, and the states that are reported present on
+ * the file descriptor by select(). The only way that can happen is
+ * when the channel is interested in a writable condition, and only a
+ * readable state is reported present (see TcpWatchProc() below). In
+ * that case, signal back to the caller the writable state, which is
+ * really an error condition. As an extra check on that assumption,
+ * check for a non-zero value of errno before reporting an artificial
+ * writable state.
+ */
+
+ if (errno == 0) {
+ return;
+ }
+ newmask = TCL_WRITABLE;
+ }
+ Tcl_NotifyChannel(statePtr->channel, newmask);
+}
+
+static void
+TcpWatchProc(
+ ClientData instanceData, /* The socket state. */
+ int mask) /* Events of interest; an OR-ed combination of
+ * TCL_READABLE, TCL_WRITABLE and
+ * TCL_EXCEPTION. */
+{
+ TcpState *statePtr = instanceData;
+
+ if (statePtr->acceptProc != NULL) {
+ /*
+ * Make sure we don't mess with server sockets since they will never
+ * be readable or writable at the Tcl level. This keeps Tcl scripts
+ * from interfering with the -accept behavior (bug #3394732).
+ */
+
+ return;
+ }
+
+ if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
+ /*
+ * Async sockets use a FileHandler internally while connecting, so we
+ * need to cache this request until the connection has succeeded.
+ */
+
+ statePtr->filehandlers = mask;
+ } else if (mask) {
+
+ /*
+ * Whether it is a bug or feature or otherwise, it is a fact of life
+ * that on at least some Linux kernels select() fails to report that a
+ * socket file descriptor is writable when the other end of the socket
+ * is closed. This is in contrast to the guarantees Tcl makes that
+ * its channels become writable and fire writable events on an error
+ * conditon. This has caused a leak of file descriptors in a state of
+ * background flushing. See Tcl ticket 1758a0b603.
+ *
+ * As a workaround, when our caller indicates an interest in writable
+ * notifications, we must tell the notifier built around select() that
+ * we are interested in the readable state of the file descriptor as
+ * well, as that is the only reliable means to get notified of error
+ * conditions. Then it is the task of WrapNotify() above to untangle
+ * the meaning of these channel states and report the chan events as
+ * best it can. We save a copy of the mask passed in to assist with
+ * that.
+ */
+
+ statePtr->interest = mask;
+ Tcl_CreateFileHandler(statePtr->fds.fd, mask|TCL_READABLE,
+ (Tcl_FileProc *) WrapNotify, statePtr);
+ } else {
+ Tcl_DeleteFileHandler(statePtr->fds.fd);
+ }
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * TcpGetHandleProc --
+ *
+ * Called from Tcl_GetChannelHandle to retrieve OS handles from inside a
+ * TCP socket based channel.
+ *
+ * Results:
+ * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no
+ * handle for the specified direction.
+ *
+ * Side effects:
+ * None.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static int
+TcpGetHandleProc(
+ ClientData instanceData, /* The socket state. */
+ int direction, /* Not used. */
+ ClientData *handlePtr) /* Where to store the handle. */
+{
+ TcpState *statePtr = instanceData;
+
+ *handlePtr = INT2PTR(statePtr->fds.fd);
+ return TCL_OK;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * TcpAsyncCallback --
+ *
+ * Called by the event handler that TcpConnect sets up internally for
+ * [socket -async] to get notified when the asyncronous connection
+ * attempt has succeeded or failed.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static void
+TcpAsyncCallback(
+ ClientData clientData, /* The socket state. */
+ int mask) /* Events of interest; an OR-ed combination of
+ * TCL_READABLE, TCL_WRITABLE and
+ * TCL_EXCEPTION. */
+{
+ TcpConnect(NULL, clientData);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * TcpConnect --
+ *
+ * This function opens a new socket in client mode.
+ *
+ * Results:
+ * TCL_OK, if the socket was successfully connected or an asynchronous
+ * connection is in progress. If an error occurs, TCL_ERROR is returned
+ * and an error message is left in interp.
+ *
+ * Side effects:
+ * Opens a socket.
+ *
+ * Remarks:
+ * A single host name may resolve to more than one IP address, e.g. for
+ * an IPv4/IPv6 dual stack host. For handling asyncronously connecting
+ * sockets in the background for such hosts, this function can act as a
+ * coroutine. On the first call, it sets up the control variables for the
+ * two nested loops over the local and remote addresses. Once the first
+ * connection attempt is in progress, it sets up itself as a writable
+ * event handler for that socket, and returns. When the callback occurs,
+ * control is transferred to the "reenter" label, right after the initial
+ * return and the loops resume as if they had never been interrupted.
+ * For syncronously connecting sockets, the loops work the usual way.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+static int
+TcpConnect(
+ Tcl_Interp *interp, /* For error reporting; can be NULL. */
+ TcpState *statePtr)
+{
+ socklen_t optlen;
+ int async_callback = GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING);
+ int ret = -1, error = EHOSTUNREACH;
+ int async = GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
+
+ if (async_callback) {
+ goto reenter;
+ }
+
+ for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL;
+ statePtr->addr = statePtr->addr->ai_next) {
+ for (statePtr->myaddr = statePtr->myaddrlist;
+ statePtr->myaddr != NULL;
+ statePtr->myaddr = statePtr->myaddr->ai_next) {
+ int reuseaddr = 1;
+
+ /*
+ * No need to try combinations of local and remote addresses of
+ * different families.
+ */
+
+ if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) {
+ continue;
+ }
+
+ /*
+ * Close the socket if it is still open from the last unsuccessful
+ * iteration.
+ */
+
+ if (statePtr->fds.fd >= 0) {
+ close(statePtr->fds.fd);
+ statePtr->fds.fd = -1;
+ errno = 0;
+ }
+
+ statePtr->fds.fd = socket(statePtr->addr->ai_family, SOCK_STREAM,
+ 0);
+ if (statePtr->fds.fd < 0) {
+ continue;
+ }
+
+ /*
+ * Set the close-on-exec flag so that the socket will not get
+ * inherited by child processes.
+ */
+
+ fcntl(statePtr->fds.fd, F_SETFD, FD_CLOEXEC);
+
+ /*
+ * Set kernel space buffering
+ */
+
+ TclSockMinimumBuffers(INT2PTR(statePtr->fds.fd), SOCKET_BUFSIZE);
+
+ if (async) {
+ ret = TclUnixSetBlockingMode(statePtr->fds.fd,
+ TCL_MODE_NONBLOCKING);
+ if (ret < 0) {
+ continue;
+ }
+ }
+
+ /*
+ * Must reset the error variable here, before we use it for the
+ * first time in this iteration.
+ */
+
+ error = 0;
+
+ (void) setsockopt(statePtr->fds.fd, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &reuseaddr, sizeof(reuseaddr));
+ ret = bind(statePtr->fds.fd, statePtr->myaddr->ai_addr,
+ statePtr->myaddr->ai_addrlen);
+ if (ret < 0) {
+ error = errno;
+ continue;
+ }
+
+ /*
+ * Attempt to connect. The connect may fail at present with an
+ * EINPROGRESS but at a later time it will complete. The caller
+ * will set up a file handler on the socket if she is interested
+ * in being informed when the connect completes.
+ */
+
+ ret = connect(statePtr->fds.fd, statePtr->addr->ai_addr,
+ statePtr->addr->ai_addrlen);
+ if (ret < 0) {
+ error = errno;
+ }
+ if (ret < 0 && errno == EINPROGRESS) {
+ Tcl_CreateFileHandler(statePtr->fds.fd,
+ TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback,
+ statePtr);
+ errno = EWOULDBLOCK;
+ SET_BITS(statePtr->flags, TCP_ASYNC_PENDING);
+ return TCL_OK;
+
+ reenter:
+ CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING);
+ Tcl_DeleteFileHandler(statePtr->fds.fd);
+
+ /*
+ * Read the error state from the socket to see if the async
+ * connection has succeeded or failed. As this clears the
+ * error condition, we cache the status in the socket state
+ * struct for later retrieval by [fconfigure -error].
+ */
+
+ optlen = sizeof(int);
+
+ getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR,
+ (char *) &error, &optlen);
+ errno = error;
+ }
+ if (error == 0) {
+ goto out;
+ }
+ }
+ }
+
+ out:
+ statePtr->connectError = error;
+ CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
+ if (async_callback) {
+ /*
+ * An asynchonous connection has finally succeeded or failed.
+ */
+
+ TcpWatchProc(statePtr, statePtr->filehandlers);
+ TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking);
+
+ if (error != 0) {
+ SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);
+ }
+
+ /*
+ * We need to forward the writable event that brought us here, bcasue
+ * upon reading of getsockopt(SO_ERROR), at least some OSes clear the
+ * writable state from the socket, and so a subsequent select() on
+ * behalf of a script level [fileevent] would not fire. It doesn't
+ * hurt that this is also called in the successful case and will save
+ * the event mechanism one roundtrip through select().
+ */
+
+ if (statePtr->cachedBlocking == TCL_MODE_NONBLOCKING) {
+ Tcl_NotifyChannel(statePtr->channel, TCL_WRITABLE);
+ }
+ }
+ if (error != 0) {
+ /*
+ * Failure for either a synchronous connection, or an async one that
+ * failed before it could enter background mode, e.g. because an
+ * invalid -myaddr was given.
+ */
+
+ if (interp != NULL) {
+ errno = error;
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't open socket: %s", Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_OpenTcpClient --
+ *
+ * Opens a TCP client socket and creates a channel around it.
+ *
+ * Results:
+ * The channel or NULL if failed. An error message is returned in the
+ * interpreter on failure.
+ *
+ * Side effects:
+ * Opens a client socket and creates a new channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+Tcl_OpenTcpClient(
+ Tcl_Interp *interp, /* For error reporting; can be NULL. */
+ int port, /* Port number to open. */
+ const char *host, /* Host on which to open port. */
+ const char *myaddr, /* Client-side address */
+ int myport, /* Client-side port */
+ int async) /* If nonzero, attempt to do an asynchronous
+ * connect. Otherwise we do a blocking
+ * connect. */
+{
+ TcpState *statePtr;
+ const char *errorMsg = NULL;
+ struct addrinfo *addrlist = NULL, *myaddrlist = NULL;
+ char channelName[SOCK_CHAN_LENGTH];
+
+ /*
+ * Do the name lookups for the local and remote addresses.
+ */
+
+ if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg)
+ || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
+ &errorMsg)) {
+ if (addrlist != NULL) {
+ freeaddrinfo(addrlist);
+ }
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't open socket: %s", errorMsg));
+ }
+ return NULL;
+ }
+
+ /*
+ * Allocate a new TcpState for this socket.
+ */
+
+ statePtr = ckalloc(sizeof(TcpState));
+ memset(statePtr, 0, sizeof(TcpState));
+ statePtr->flags = async ? TCP_ASYNC_CONNECT : 0;
+ statePtr->cachedBlocking = TCL_MODE_BLOCKING;
+ statePtr->addrlist = addrlist;
+ statePtr->myaddrlist = myaddrlist;
+ statePtr->fds.fd = -1;
+
+ /*
+ * Create a new client socket and wrap it in a channel.
+ */
+
+ if (TcpConnect(interp, statePtr) != TCL_OK) {
+ TcpCloseProc(statePtr, NULL);
+ return NULL;
+ }
+
+ sprintf(channelName, SOCK_TEMPLATE, (long) statePtr);
+
+ statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
+ statePtr, TCL_READABLE | TCL_WRITABLE);
+ if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation",
+ "auto crlf") == TCL_ERROR) {
+ Tcl_Close(NULL, statePtr->channel);
+ return NULL;
+ }
+ return statePtr->channel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_MakeTcpClientChannel --
+ *
+ * Creates a Tcl_Channel from an existing client TCP socket.
+ *
+ * Results:
+ * The Tcl_Channel wrapped around the preexisting TCP socket.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+Tcl_MakeTcpClientChannel(
+ ClientData sock) /* The socket to wrap up into a channel. */
+{
+ return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock,
+ TCL_READABLE | TCL_WRITABLE);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpMakeTcpClientChannelMode --
+ *
+ * Creates a Tcl_Channel from an existing client TCP socket
+ * with given mode.
+ *
+ * Results:
+ * The Tcl_Channel wrapped around the preexisting TCP socket.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void *
+TclpMakeTcpClientChannelMode(
+ void *sock, /* The socket to wrap up into a channel. */
+ int mode) /* ORed combination of TCL_READABLE and
+ * TCL_WRITABLE to indicate file mode. */
+{
+ TcpState *statePtr;
+ char channelName[SOCK_CHAN_LENGTH];
+
+ statePtr = ckalloc(sizeof(TcpState));
+ memset(statePtr, 0, sizeof(TcpState));
+ statePtr->fds.fd = PTR2INT(sock);
+ statePtr->flags = 0;
+
+ sprintf(channelName, SOCK_TEMPLATE, (long)statePtr);
+
+ statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
+ statePtr, mode);
+ if (Tcl_SetChannelOption(NULL, statePtr->channel, "-translation",
+ "auto crlf") == TCL_ERROR) {
+ Tcl_Close(NULL, statePtr->channel);
+ return NULL;
+ }
+ return statePtr->channel;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_OpenTcpServerEx --
+ *
+ * Opens a TCP server socket and creates a channel around it.
+ *
+ * Results:
+ * The channel or NULL if failed. If an error occurred, an error message
+ * is left in the interp's result if interp is not NULL.
+ *
+ * Side effects:
+ * Opens a server socket and creates a new channel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Channel
+Tcl_OpenTcpServerEx(
+ Tcl_Interp *interp, /* For error reporting - may be NULL. */
+ const char *service, /* Port number to open. */
+ const char *myHost, /* Name of local host. */
+ unsigned int flags, /* Flags. */
+ Tcl_TcpAcceptProc *acceptProc,
+ /* Callback for accepting connections from new
+ * clients. */
+ ClientData acceptProcData) /* Data for the callback. */
+{
+ int status = 0, sock = -1, optvalue, port, chosenport;
+ struct addrinfo *addrlist = NULL, *addrPtr; /* socket address */
+ TcpState *statePtr = NULL;
+ char channelName[SOCK_CHAN_LENGTH];
+ const char *errorMsg = NULL;
+ TcpFdList *fds = NULL, *newfds;
+
+ /*
+ * Try to record and return the most meaningful error message, i.e. the
+ * one from the first socket that went the farthest before it failed.
+ */
+
+ enum { LOOKUP, SOCKET, BIND, LISTEN } howfar = LOOKUP;
+ int my_errno = 0;
+
+ /*
+ * If we were called with port 0 to listen on a random port number, we
+ * copy the port number from the first member of the addrinfo list to all
+ * subsequent members, so that IPv4 and IPv6 listen on the same port. This
+ * might fail to bind() with EADDRINUSE if a port is free on the first
+ * address family in the list but already used on the other. In this case
+ * we revert everything we've done so far and start from scratch hoping
+ * that next time we'll find a port number that is usable on all address
+ * families. We try this at most MAXRETRY times to avoid an endless loop
+ * if all ports are taken.
+ */
+
+ int retry = 0;
+#define MAXRETRY 10
+
+ repeat:
+ if (retry > 0) {
+ if (statePtr != NULL) {
+ TcpCloseProc(statePtr, NULL);
+ statePtr = NULL;
+ }
+ if (addrlist != NULL) {
+ freeaddrinfo(addrlist);
+ addrlist = NULL;
+ }
+ if (retry >= MAXRETRY) {
+ goto error;
+ }
+ }
+ retry++;
+ chosenport = 0;
+
+ if (TclSockGetPort(interp, service, "tcp", &port) != TCL_OK) {
+ errorMsg = "invalid port number";
+ goto error;
+ }
+
+ if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1,
+ &errorMsg)) {
+ my_errno = errno;
+ goto error;
+ }
+
+ for (addrPtr = addrlist; addrPtr != NULL; addrPtr = addrPtr->ai_next) {
+ sock = socket(addrPtr->ai_family, addrPtr->ai_socktype,
+ addrPtr->ai_protocol);
+ if (sock == -1) {
+ if (howfar < SOCKET) {
+ howfar = SOCKET;
+ my_errno = errno;
+ }
+ continue;
+ }
+
+ /*
+ * Set the close-on-exec flag so that the socket will not get
+ * inherited by child processes.
+ */
+
+ fcntl(sock, F_SETFD, FD_CLOEXEC);
+
+ /*
+ * Set kernel space buffering
+ */
+
+ TclSockMinimumBuffers(INT2PTR(sock), SOCKET_BUFSIZE);
+
+ /*
+ * Set up to reuse server addresses and/or ports if requested.
+ */
+
+ if (GOT_BITS(flags, TCL_TCPSERVER_REUSEADDR)) {
+ optvalue = 1;
+ (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &optvalue, sizeof(optvalue));
+ }
+
+ if (GOT_BITS(flags, TCL_TCPSERVER_REUSEPORT)) {
+#ifndef SO_REUSEPORT
+ /*
+ * If the platform doesn't support the SO_REUSEPORT flag we can't
+ * do much beside erroring out.
+ */
+
+ errorMsg = "SO_REUSEPORT isn't supported by this platform";
+ goto error;
+#else
+ optvalue = 1;
+ (void) setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
+ (char *) &optvalue, sizeof(optvalue));
+#endif
+ }
+
+ /*
+ * Make sure we use the same port number when opening two server
+ * sockets for IPv4 and IPv6 on a random port.
+ *
+ * As sockaddr_in6 uses the same offset and size for the port member
+ * as sockaddr_in, we can handle both through the IPv4 API.
+ */
+
+ if (port == 0 && chosenport != 0) {
+ ((struct sockaddr_in *) addrPtr->ai_addr)->sin_port =
+ htons(chosenport);
+ }
+
+#ifdef IPV6_V6ONLY
+ /*
+ * Missing on: Solaris 2.8
+ */
+
+ if (addrPtr->ai_family == AF_INET6) {
+ int v6only = 1;
+
+ (void) setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ &v6only, sizeof(v6only));
+ }
+#endif /* IPV6_V6ONLY */
+
+ status = bind(sock, addrPtr->ai_addr, addrPtr->ai_addrlen);
+ if (status == -1) {
+ if (howfar < BIND) {
+ howfar = BIND;
+ my_errno = errno;
+ }
+ close(sock);
+ sock = -1;
+ if (port == 0 && errno == EADDRINUSE) {
+ goto repeat;
+ }
+ continue;
+ }
+ if (port == 0 && chosenport == 0) {
+ address sockname;
+ socklen_t namelen = sizeof(sockname);
+
+ /*
+ * Synchronize port numbers when binding to port 0 of multiple
+ * addresses.
+ */
+
+ if (getsockname(sock, &sockname.sa, &namelen) >= 0) {
+ chosenport = ntohs(sockname.sa4.sin_port);
+ }
+ }
+ status = listen(sock, SOMAXCONN);
+ if (status < 0) {
+ if (howfar < LISTEN) {
+ howfar = LISTEN;
+ my_errno = errno;
+ }
+ close(sock);
+ sock = -1;
+ if (port == 0 && errno == EADDRINUSE) {
+ goto repeat;
+ }
+ continue;
+ }
+ if (statePtr == NULL) {
+ /*
+ * Allocate a new TcpState for this socket.
+ */
+
+ statePtr = ckalloc(sizeof(TcpState));
+ memset(statePtr, 0, sizeof(TcpState));
+ statePtr->acceptProc = acceptProc;
+ statePtr->acceptProcData = acceptProcData;
+ sprintf(channelName, SOCK_TEMPLATE, (long) statePtr);
+ newfds = &statePtr->fds;
+ } else {
+ newfds = ckalloc(sizeof(TcpFdList));
+ memset(newfds, (int) 0, sizeof(TcpFdList));
+ fds->next = newfds;
+ }
+ newfds->fd = sock;
+ newfds->statePtr = statePtr;
+ fds = newfds;
+
+ /*
+ * Set up the callback mechanism for accepting connections from new
+ * clients.
+ */
+
+ Tcl_CreateFileHandler(sock, TCL_READABLE, TcpAccept, fds);
+ }
+
+ error:
+ if (addrlist != NULL) {
+ freeaddrinfo(addrlist);
+ }
+ if (statePtr != NULL) {
+ statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
+ statePtr, 0);
+ return statePtr->channel;
+ }
+ if (interp != NULL) {
+ Tcl_Obj *errorObj = Tcl_NewStringObj("couldn't open socket: ", -1);
+
+ if (errorMsg == NULL) {
+ errno = my_errno;
+ Tcl_AppendToObj(errorObj, Tcl_PosixError(interp), -1);
+ } else {
+ Tcl_AppendToObj(errorObj, errorMsg, -1);
+ }
+ Tcl_SetObjResult(interp, errorObj);
+ }
+ if (sock != -1) {
+ close(sock);
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TcpAccept --
+ * Accept a TCP socket connection. This is called by the event loop.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates a new connection socket. Calls the registered callback for the
+ * connection acceptance mechanism.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+TcpAccept(
+ ClientData data, /* Callback token. */
+ int mask) /* Not used. */
+{
+ TcpFdList *fds = data; /* Client data of server socket. */
+ int newsock; /* The new client socket */
+ TcpState *newSockState; /* State for new socket. */
+ address addr; /* The remote address */
+ socklen_t len; /* For accept interface */
+ char channelName[SOCK_CHAN_LENGTH];
+ char host[NI_MAXHOST], port[NI_MAXSERV];
+
+ len = sizeof(addr);
+ newsock = accept(fds->fd, &addr.sa, &len);
+ if (newsock < 0) {
+ return;
+ }
+
+ /*
+ * Set close-on-exec flag to prevent the newly accepted socket from being
+ * inherited by child processes.
+ */
+
+ (void) fcntl(newsock, F_SETFD, FD_CLOEXEC);
+
+ newSockState = ckalloc(sizeof(TcpState));
+ memset(newSockState, 0, sizeof(TcpState));
+ newSockState->flags = 0;
+ newSockState->fds.fd = newsock;
+
+ sprintf(channelName, SOCK_TEMPLATE, (long) newSockState);
+ newSockState->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
+ newSockState, TCL_READABLE | TCL_WRITABLE);
+
+ Tcl_SetChannelOption(NULL, newSockState->channel, "-translation",
+ "auto crlf");
+
+ if (fds->statePtr->acceptProc != NULL) {
+ getnameinfo(&addr.sa, len, host, sizeof(host), port, sizeof(port),
+ NI_NUMERICHOST|NI_NUMERICSERV);
+ fds->statePtr->acceptProc(fds->statePtr->acceptProcData,
+ newSockState->channel, host, atoi(port));
+ }
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/unix/tclUnixTest.c b/unix/tclUnixTest.c
new file mode 100644
index 0000000..ceb64d9
--- /dev/null
+++ b/unix/tclUnixTest.c
@@ -0,0 +1,781 @@
+/*
+ * tclUnixTest.c --
+ *
+ * Contains platform specific test commands for the Unix platform.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef USE_TCL_STUBS
+# define USE_TCL_STUBS
+#endif
+#include "tclInt.h"
+
+/*
+ * The headers are needed for the testalarm command that verifies the use of
+ * SA_RESTART in signal handlers.
+ */
+
+#include <signal.h>
+#include <sys/resource.h>
+
+/*
+ * The following macros convert between TclFile's and fd's. The conversion
+ * simple involves shifting fd's up by one to ensure that no valid fd is ever
+ * the same as NULL. Note that this code is duplicated from tclUnixPipe.c
+ */
+
+#define MakeFile(fd) ((TclFile)INT2PTR(((int)(fd))+1))
+#define GetFd(file) (PTR2INT(file)-1)
+
+/*
+ * The stuff below is used to keep track of file handlers created and
+ * exercised by the "testfilehandler" command.
+ */
+
+typedef struct {
+ TclFile readFile; /* File handle for reading from the pipe. NULL
+ * means pipe doesn't exist yet. */
+ TclFile writeFile; /* File handle for writing from the pipe. */
+ int readCount; /* Number of times the file handler for this
+ * file has triggered and the file was
+ * readable. */
+ int writeCount; /* Number of times the file handler for this
+ * file has triggered and the file was
+ * writable. */
+} Pipe;
+
+#define MAX_PIPES 10
+static Pipe testPipes[MAX_PIPES];
+
+/*
+ * The stuff below is used by the testalarm and testgotsig ommands.
+ */
+
+static const char *gotsig = "0";
+
+/*
+ * Forward declarations of functions defined later in this file:
+ */
+
+static Tcl_CmdProc TestalarmCmd;
+static Tcl_ObjCmdProc TestchmodCmd;
+static Tcl_CmdProc TestfilehandlerCmd;
+static Tcl_CmdProc TestfilewaitCmd;
+static Tcl_CmdProc TestfindexecutableCmd;
+static Tcl_ObjCmdProc TestforkObjCmd;
+static Tcl_ObjCmdProc TestgetencpathObjCmd;
+static Tcl_CmdProc TestgetopenfileCmd;
+static Tcl_CmdProc TestgotsigCmd;
+static Tcl_ObjCmdProc TestsetencpathObjCmd;
+static Tcl_FileProc TestFileHandlerProc;
+static void AlarmHandler(int signum);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclplatformtestInit --
+ *
+ * Defines commands that test platform specific functionality for Unix
+ * platforms.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Defines new commands.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclplatformtestInit(
+ Tcl_Interp *interp) /* Interpreter to add commands to. */
+{
+ Tcl_CreateObjCommand(interp, "testchmod", TestchmodCmd,
+ NULL, NULL);
+ Tcl_CreateCommand(interp, "testfilehandler", TestfilehandlerCmd,
+ NULL, NULL);
+ Tcl_CreateCommand(interp, "testfilewait", TestfilewaitCmd,
+ NULL, NULL);
+ Tcl_CreateCommand(interp, "testfindexecutable", TestfindexecutableCmd,
+ NULL, NULL);
+ Tcl_CreateObjCommand(interp, "testfork", TestforkObjCmd,
+ NULL, NULL);
+ Tcl_CreateCommand(interp, "testgetopenfile", TestgetopenfileCmd,
+ NULL, NULL);
+ Tcl_CreateObjCommand(interp, "testgetencpath", TestgetencpathObjCmd,
+ NULL, NULL);
+ Tcl_CreateObjCommand(interp, "testsetencpath", TestsetencpathObjCmd,
+ NULL, NULL);
+ Tcl_CreateCommand(interp, "testalarm", TestalarmCmd,
+ NULL, NULL);
+ Tcl_CreateCommand(interp, "testgotsig", TestgotsigCmd,
+ NULL, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestfilehandlerCmd --
+ *
+ * This function implements the "testfilehandler" command. It is used to
+ * test Tcl_CreateFileHandler, Tcl_DeleteFileHandler, and TclWaitForFile.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestfilehandlerCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ Pipe *pipePtr;
+ int i, mask, timeout;
+ static int initialized = 0;
+ char buffer[4000];
+ TclFile file;
+
+ /*
+ * NOTE: When we make this code work on Windows also, the following
+ * variable needs to be made Unix-only.
+ */
+
+ if (!initialized) {
+ for (i = 0; i < MAX_PIPES; i++) {
+ testPipes[i].readFile = NULL;
+ }
+ initialized = 1;
+ }
+
+ if (argc < 2) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ " option ... \"", NULL);
+ return TCL_ERROR;
+ }
+ pipePtr = NULL;
+ if (argc >= 3) {
+ if (Tcl_GetInt(interp, argv[2], &i) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (i >= MAX_PIPES) {
+ Tcl_AppendResult(interp, "bad index ", argv[2], NULL);
+ return TCL_ERROR;
+ }
+ pipePtr = &testPipes[i];
+ }
+
+ if (strcmp(argv[1], "close") == 0) {
+ for (i = 0; i < MAX_PIPES; i++) {
+ if (testPipes[i].readFile != NULL) {
+ TclpCloseFile(testPipes[i].readFile);
+ testPipes[i].readFile = NULL;
+ TclpCloseFile(testPipes[i].writeFile);
+ testPipes[i].writeFile = NULL;
+ }
+ }
+ } else if (strcmp(argv[1], "clear") == 0) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"",
+ argv[0], " clear index\"", NULL);
+ return TCL_ERROR;
+ }
+ pipePtr->readCount = pipePtr->writeCount = 0;
+ } else if (strcmp(argv[1], "counts") == 0) {
+ char buf[TCL_INTEGER_SPACE * 2];
+
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"",
+ argv[0], " counts index\"", NULL);
+ return TCL_ERROR;
+ }
+ sprintf(buf, "%d %d", pipePtr->readCount, pipePtr->writeCount);
+ Tcl_AppendResult(interp, buf, NULL);
+ } else if (strcmp(argv[1], "create") == 0) {
+ if (argc != 5) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"",
+ argv[0], " create index readMode writeMode\"", NULL);
+ return TCL_ERROR;
+ }
+ if (pipePtr->readFile == NULL) {
+ if (!TclpCreatePipe(&pipePtr->readFile, &pipePtr->writeFile)) {
+ Tcl_AppendResult(interp, "couldn't open pipe: ",
+ Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+#ifdef O_NONBLOCK
+ fcntl(GetFd(pipePtr->readFile), F_SETFL, O_NONBLOCK);
+ fcntl(GetFd(pipePtr->writeFile), F_SETFL, O_NONBLOCK);
+#else
+ Tcl_AppendResult(interp, "can't make pipes non-blocking",
+ NULL);
+ return TCL_ERROR;
+#endif
+ }
+ pipePtr->readCount = 0;
+ pipePtr->writeCount = 0;
+
+ if (strcmp(argv[3], "readable") == 0) {
+ Tcl_CreateFileHandler(GetFd(pipePtr->readFile), TCL_READABLE,
+ TestFileHandlerProc, pipePtr);
+ } else if (strcmp(argv[3], "off") == 0) {
+ Tcl_DeleteFileHandler(GetFd(pipePtr->readFile));
+ } else if (strcmp(argv[3], "disabled") == 0) {
+ Tcl_CreateFileHandler(GetFd(pipePtr->readFile), 0,
+ TestFileHandlerProc, pipePtr);
+ } else {
+ Tcl_AppendResult(interp, "bad read mode \"", argv[3], "\"", NULL);
+ return TCL_ERROR;
+ }
+ if (strcmp(argv[4], "writable") == 0) {
+ Tcl_CreateFileHandler(GetFd(pipePtr->writeFile), TCL_WRITABLE,
+ TestFileHandlerProc, pipePtr);
+ } else if (strcmp(argv[4], "off") == 0) {
+ Tcl_DeleteFileHandler(GetFd(pipePtr->writeFile));
+ } else if (strcmp(argv[4], "disabled") == 0) {
+ Tcl_CreateFileHandler(GetFd(pipePtr->writeFile), 0,
+ TestFileHandlerProc, pipePtr);
+ } else {
+ Tcl_AppendResult(interp, "bad read mode \"", argv[4], "\"", NULL);
+ return TCL_ERROR;
+ }
+ } else if (strcmp(argv[1], "empty") == 0) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"",
+ argv[0], " empty index\"", NULL);
+ return TCL_ERROR;
+ }
+
+ while (read(GetFd(pipePtr->readFile), buffer, 4000) > 0) {
+ /* Empty loop body. */
+ }
+ } else if (strcmp(argv[1], "fill") == 0) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"",
+ argv[0], " fill index\"", NULL);
+ return TCL_ERROR;
+ }
+
+ memset(buffer, 'a', 4000);
+ while (write(GetFd(pipePtr->writeFile), buffer, 4000) > 0) {
+ /* Empty loop body. */
+ }
+ } else if (strcmp(argv[1], "fillpartial") == 0) {
+ char buf[TCL_INTEGER_SPACE];
+
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"",
+ argv[0], " fillpartial index\"", NULL);
+ return TCL_ERROR;
+ }
+
+ memset(buffer, 'b', 10);
+ TclFormatInt(buf, write(GetFd(pipePtr->writeFile), buffer, 10));
+ Tcl_AppendResult(interp, buf, NULL);
+ } else if (strcmp(argv[1], "oneevent") == 0) {
+ Tcl_DoOneEvent(TCL_FILE_EVENTS|TCL_DONT_WAIT);
+ } else if (strcmp(argv[1], "wait") == 0) {
+ if (argc != 5) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"",
+ argv[0], " wait index readable|writable timeout\"", NULL);
+ return TCL_ERROR;
+ }
+ if (pipePtr->readFile == NULL) {
+ Tcl_AppendResult(interp, "pipe ", argv[2], " doesn't exist", NULL);
+ return TCL_ERROR;
+ }
+ if (strcmp(argv[3], "readable") == 0) {
+ mask = TCL_READABLE;
+ file = pipePtr->readFile;
+ } else {
+ mask = TCL_WRITABLE;
+ file = pipePtr->writeFile;
+ }
+ if (Tcl_GetInt(interp, argv[4], &timeout) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ i = TclUnixWaitForFile(GetFd(file), mask, timeout);
+ if (i & TCL_READABLE) {
+ Tcl_AppendElement(interp, "readable");
+ }
+ if (i & TCL_WRITABLE) {
+ Tcl_AppendElement(interp, "writable");
+ }
+ } else if (strcmp(argv[1], "windowevent") == 0) {
+ Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT);
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", argv[1],
+ "\": must be close, clear, counts, create, empty, fill, "
+ "fillpartial, oneevent, wait, or windowevent", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+static void
+TestFileHandlerProc(
+ ClientData clientData, /* Points to a Pipe structure. */
+ int mask) /* Indicates which events happened:
+ * TCL_READABLE or TCL_WRITABLE. */
+{
+ Pipe *pipePtr = clientData;
+
+ if (mask & TCL_READABLE) {
+ pipePtr->readCount++;
+ }
+ if (mask & TCL_WRITABLE) {
+ pipePtr->writeCount++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestfilewaitCmd --
+ *
+ * This function implements the "testfilewait" command. It is used to
+ * test TclUnixWaitForFile.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestfilewaitCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ int mask, result, timeout;
+ Tcl_Channel channel;
+ int fd;
+ ClientData data;
+
+ if (argc != 4) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ " file readable|writable|both timeout\"", NULL);
+ return TCL_ERROR;
+ }
+ channel = Tcl_GetChannel(interp, argv[1], NULL);
+ if (channel == NULL) {
+ return TCL_ERROR;
+ }
+ if (strcmp(argv[2], "readable") == 0) {
+ mask = TCL_READABLE;
+ } else if (strcmp(argv[2], "writable") == 0){
+ mask = TCL_WRITABLE;
+ } else if (strcmp(argv[2], "both") == 0){
+ mask = TCL_WRITABLE|TCL_READABLE;
+ } else {
+ Tcl_AppendResult(interp, "bad argument \"", argv[2],
+ "\": must be readable, writable, or both", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetChannelHandle(channel,
+ (mask & TCL_READABLE) ? TCL_READABLE : TCL_WRITABLE,
+ (ClientData*) &data) != TCL_OK) {
+ Tcl_AppendResult(interp, "couldn't get channel file", NULL);
+ return TCL_ERROR;
+ }
+ fd = PTR2INT(data);
+ if (Tcl_GetInt(interp, argv[3], &timeout) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ result = TclUnixWaitForFile(fd, mask, timeout);
+ if (result & TCL_READABLE) {
+ Tcl_AppendElement(interp, "readable");
+ }
+ if (result & TCL_WRITABLE) {
+ Tcl_AppendElement(interp, "writable");
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestfindexecutableCmd --
+ *
+ * This function implements the "testfindexecutable" command. It is used
+ * to test TclpFindExecutable.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestfindexecutableCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ Tcl_Obj *saveName;
+
+ if (argc != 2) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
+ " argv0\"", NULL);
+ return TCL_ERROR;
+ }
+
+ saveName = TclGetObjNameOfExecutable();
+ Tcl_IncrRefCount(saveName);
+
+ TclpFindExecutable(argv[1]);
+ Tcl_SetObjResult(interp, TclGetObjNameOfExecutable());
+
+ TclSetObjNameOfExecutable(saveName, NULL);
+ Tcl_DecrRefCount(saveName);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestgetopenfileCmd --
+ *
+ * This function implements the "testgetopenfile" command. It is used to
+ * get a FILE * value from a registered channel.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestgetopenfileCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ ClientData filePtr;
+
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " channelName forWriting\"", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetOpenFile(interp, argv[1], atoi(argv[2]), 1, &filePtr)
+ == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (filePtr == NULL) {
+ Tcl_AppendResult(interp,
+ "Tcl_GetOpenFile succeeded but FILE * NULL!", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestsetencpathCmd --
+ *
+ * This function implements the "testsetencpath" command. It is used to
+ * test Tcl_SetDefaultEncodingDir().
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestsetencpathObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Argument strings. */
+{
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "defaultDir");
+ return TCL_ERROR;
+ }
+
+ Tcl_SetEncodingSearchPath(objv[1]);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestforkObjCmd --
+ *
+ * This function implements the "testfork" command. It is used to
+ * fork the Tcl process for specific test cases.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestforkObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Argument strings. */
+{
+ pid_t pid;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "");
+ return TCL_ERROR;
+ }
+ pid = fork();
+ if (pid == -1) {
+ Tcl_AppendResult(interp,
+ "Cannot fork", NULL);
+ return TCL_ERROR;
+ }
+ /* Only needed when pthread_atfork is not present,
+ * should not hurt otherwise. */
+ if (pid==0) {
+ Tcl_InitNotifier();
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(pid));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestgetencpathObjCmd --
+ *
+ * This function implements the "testgetencpath" command. It is used to
+ * test Tcl_GetEncodingSearchPath().
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestgetencpathObjCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Argument strings. */
+{
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "");
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath());
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestalarmCmd --
+ *
+ * Test that EINTR is handled correctly by generating and handling a
+ * signal. This requires using the SA_RESTART flag when registering the
+ * signal handler.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Sets up an signal and async handlers.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestalarmCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+#ifdef SA_RESTART
+ unsigned int sec;
+ struct sigaction action;
+
+ if (argc > 1) {
+ Tcl_GetInt(interp, argv[1], (int *)&sec);
+ } else {
+ sec = 1;
+ }
+
+ /*
+ * Setup the signal handling that automatically retries any interrupted
+ * I/O system calls.
+ */
+
+ action.sa_handler = AlarmHandler;
+ memset((void *) &action.sa_mask, 0, sizeof(sigset_t));
+ action.sa_flags = SA_RESTART;
+
+ if (sigaction(SIGALRM, &action, NULL) < 0) {
+ Tcl_AppendResult(interp, "sigaction: ", Tcl_PosixError(interp), NULL);
+ return TCL_ERROR;
+ }
+ (void) alarm(sec);
+ return TCL_OK;
+#else
+ Tcl_AppendResult(interp,
+ "warning: sigaction SA_RESTART not support on this platform",
+ NULL);
+ return TCL_ERROR;
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AlarmHandler --
+ *
+ * Signal handler for the alarm command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Calls the Tcl Async handler.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AlarmHandler(
+ int signum)
+{
+ gotsig = "1";
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestgotsigCmd --
+ *
+ * Verify the signal was handled after the testalarm command.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Resets the value of gotsig back to '0'.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TestgotsigCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ const char **argv) /* Argument strings. */
+{
+ Tcl_AppendResult(interp, gotsig, NULL);
+ gotsig = "0";
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TestchmodCmd --
+ *
+ * Implements the "testchmod" cmd. Used when testing "file" command.
+ * The only attribute used by the Windows platform is the user write
+ * flag; if this is not set, the file is made read-only. Otehrwise, the
+ * file is made read-write.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Changes permissions of specified files.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+TestchmodCmd(
+ ClientData dummy, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Argument strings. */
+{
+ int i, mode;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "mode file ?file ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[1], &mode) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ for (i = 2; i < objc; i++) {
+ Tcl_DString buffer;
+ const char *translated;
+
+ translated = Tcl_TranslateFileName(interp, Tcl_GetString(objv[i]), &buffer);
+ if (translated == NULL) {
+ return TCL_ERROR;
+ }
+ if (chmod(translated, (unsigned) mode) != 0) {
+ Tcl_AppendResult(interp, translated, ": ", Tcl_PosixError(interp),
+ NULL);
+ return TCL_ERROR;
+ }
+ Tcl_DStringFree(&buffer);
+ }
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * tab-width: 8
+ * End:
+ */
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c
new file mode 100644
index 0000000..f475aed
--- /dev/null
+++ b/unix/tclUnixThrd.c
@@ -0,0 +1,815 @@
+/*
+ * tclUnixThrd.c --
+ *
+ * This file implements the UNIX-specific thread support.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2008 by George Peter Staplin
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+
+#ifdef TCL_THREADS
+
+typedef struct {
+ char nabuf[16];
+} ThreadSpecificData;
+
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * masterLock is used to serialize creation of mutexes, condition variables,
+ * and thread local storage. This is the only place that can count on the
+ * ability to statically initialize the mutex.
+ */
+
+static pthread_mutex_t masterLock = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * initLock is used to serialize initialization and finalization of Tcl. It
+ * cannot use any dyamically allocated storage.
+ */
+
+static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * allocLock is used by Tcl's version of malloc for synchronization. For
+ * obvious reasons, cannot use any dyamically allocated storage.
+ */
+
+static pthread_mutex_t allocLock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t *allocLockPtr = &allocLock;
+
+#endif /* TCL_THREADS */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadCreate --
+ *
+ * This procedure creates a new thread.
+ *
+ * Results:
+ * TCL_OK if the thread could be created. The thread ID is returned in a
+ * parameter.
+ *
+ * Side effects:
+ * A new thread is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TclpThreadCreate(
+ Tcl_ThreadId *idPtr, /* Return, the ID of the thread */
+ Tcl_ThreadCreateProc *proc, /* Main() function of the thread */
+ ClientData clientData, /* The one argument to Main() */
+ int stackSize, /* Size of stack for the new thread */
+ int flags) /* Flags controlling behaviour of the new
+ * thread. */
+{
+#ifdef TCL_THREADS
+ pthread_attr_t attr;
+ pthread_t theThread;
+ int result;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+
+#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
+ if (stackSize != TCL_THREAD_STACK_DEFAULT) {
+ pthread_attr_setstacksize(&attr, (size_t) stackSize);
+#ifdef TCL_THREAD_STACK_MIN
+ } else {
+ /*
+ * Certain systems define a thread stack size that by default is too
+ * small for many operations. The user has the option of defining
+ * TCL_THREAD_STACK_MIN to a value large enough to work for their
+ * needs. This would look like (for 128K min stack):
+ * make MEM_DEBUG_FLAGS=-DTCL_THREAD_STACK_MIN=131072L
+ *
+ * This solution is not optimal, as we should allow the user to
+ * specify a size at runtime, but we don't want to slow this function
+ * down, and that would still leave the main thread at the default.
+ */
+
+ size_t size;
+
+ result = pthread_attr_getstacksize(&attr, &size);
+ if (!result && (size < TCL_THREAD_STACK_MIN)) {
+ pthread_attr_setstacksize(&attr, (size_t) TCL_THREAD_STACK_MIN);
+ }
+#endif /* TCL_THREAD_STACK_MIN */
+ }
+#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
+
+ if (! (flags & TCL_THREAD_JOINABLE)) {
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+ }
+
+ if (pthread_create(&theThread, &attr,
+ (void * (*)(void *))proc, (void *)clientData) &&
+ pthread_create(&theThread, NULL,
+ (void * (*)(void *))proc, (void *)clientData)) {
+ result = TCL_ERROR;
+ } else {
+ *idPtr = (Tcl_ThreadId)theThread;
+ result = TCL_OK;
+ }
+ pthread_attr_destroy(&attr);
+ return result;
+#else
+ return TCL_ERROR;
+#endif /* TCL_THREADS */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_JoinThread --
+ *
+ * This procedure waits upon the exit of the specified thread.
+ *
+ * Results:
+ * TCL_OK if the wait was successful, TCL_ERROR else.
+ *
+ * Side effects:
+ * The result area is set to the exit code of the thread we waited upon.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_JoinThread(
+ Tcl_ThreadId threadId, /* Id of the thread to wait upon. */
+ int *state) /* Reference to the storage the result of the
+ * thread we wait upon will be written into.
+ * May be NULL. */
+{
+#ifdef TCL_THREADS
+ int result;
+ unsigned long retcode, *retcodePtr = &retcode;
+
+ result = pthread_join((pthread_t) threadId, (void**) retcodePtr);
+ if (state) {
+ *state = (int) retcode;
+ }
+ return (result == 0) ? TCL_OK : TCL_ERROR;
+#else
+ return TCL_ERROR;
+#endif
+}
+
+#ifdef TCL_THREADS
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadExit --
+ *
+ * This procedure terminates the current thread.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * This procedure terminates the current thread.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpThreadExit(
+ int status)
+{
+ pthread_exit(INT2PTR(status));
+}
+#endif /* TCL_THREADS */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetCurrentThread --
+ *
+ * This procedure returns the ID of the currently running thread.
+ *
+ * Results:
+ * A thread ID.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_ThreadId
+Tcl_GetCurrentThread(void)
+{
+#ifdef TCL_THREADS
+ return (Tcl_ThreadId) pthread_self();
+#else
+ return (Tcl_ThreadId) 0;
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpInitLock
+ *
+ * This procedure is used to grab a lock that serializes initialization
+ * and finalization of Tcl. On some platforms this may also initialize
+ * the mutex used to serialize creation of more mutexes and thread local
+ * storage keys.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Acquire the initialization mutex.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpInitLock(void)
+{
+#ifdef TCL_THREADS
+ pthread_mutex_lock(&initLock);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFinalizeLock
+ *
+ * This procedure is used to destroy all private resources used in this
+ * file.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Destroys everything private. TclpInitLock must be held entering this
+ * function.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFinalizeLock(void)
+{
+#ifdef TCL_THREADS
+ /*
+ * You do not need to destroy mutexes that were created with the
+ * PTHREAD_MUTEX_INITIALIZER macro. These mutexes do not need any
+ * destruction: masterLock, allocLock, and initLock.
+ */
+
+ pthread_mutex_unlock(&initLock);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpInitUnlock
+ *
+ * This procedure is used to release a lock that serializes
+ * initialization and finalization of Tcl.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Release the initialization mutex.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpInitUnlock(void)
+{
+#ifdef TCL_THREADS
+ pthread_mutex_unlock(&initLock);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpMasterLock
+ *
+ * This procedure is used to grab a lock that serializes creation and
+ * finalization of serialization objects. This interface is only needed
+ * in finalization; it is hidden during creation of the objects.
+ *
+ * This lock must be different than the initLock because the initLock is
+ * held during creation of syncronization objects.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Acquire the master mutex.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpMasterLock(void)
+{
+#ifdef TCL_THREADS
+ pthread_mutex_lock(&masterLock);
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpMasterUnlock
+ *
+ * This procedure is used to release a lock that serializes creation and
+ * finalization of synchronization objects.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Release the master mutex.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpMasterUnlock(void)
+{
+#ifdef TCL_THREADS
+ pthread_mutex_unlock(&masterLock);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetAllocMutex
+ *
+ * This procedure returns a pointer to a statically initialized mutex for
+ * use by the memory allocator. The alloctor must use this lock, because
+ * all other locks are allocated...
+ *
+ * Results:
+ * A pointer to a mutex that is suitable for passing to Tcl_MutexLock and
+ * Tcl_MutexUnlock.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Mutex *
+Tcl_GetAllocMutex(void)
+{
+#ifdef TCL_THREADS
+ pthread_mutex_t **allocLockPtrPtr = &allocLockPtr;
+ return (Tcl_Mutex *) allocLockPtrPtr;
+#else
+ return NULL;
+#endif
+}
+
+#ifdef TCL_THREADS
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_MutexLock --
+ *
+ * This procedure is invoked to lock a mutex. This procedure handles
+ * initializing the mutex, if necessary. The caller can rely on the fact
+ * that Tcl_Mutex is an opaque pointer. This routine will change that
+ * pointer from NULL after first use.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May block the current thread. The mutex is aquired when this returns.
+ * Will allocate memory for a pthread_mutex_t and initialize this the
+ * first time this Tcl_Mutex is used.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_MutexLock(
+ Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */
+{
+ pthread_mutex_t *pmutexPtr;
+
+ if (*mutexPtr == NULL) {
+ pthread_mutex_lock(&masterLock);
+ if (*mutexPtr == NULL) {
+ /*
+ * Double inside master lock check to avoid a race condition.
+ */
+
+ pmutexPtr = ckalloc(sizeof(pthread_mutex_t));
+ pthread_mutex_init(pmutexPtr, NULL);
+ *mutexPtr = (Tcl_Mutex)pmutexPtr;
+ TclRememberMutex(mutexPtr);
+ }
+ pthread_mutex_unlock(&masterLock);
+ }
+ pmutexPtr = *((pthread_mutex_t **)mutexPtr);
+ pthread_mutex_lock(pmutexPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_MutexUnlock --
+ *
+ * This procedure is invoked to unlock a mutex. The mutex must have been
+ * locked by Tcl_MutexLock.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The mutex is released when this returns.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_MutexUnlock(
+ Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */
+{
+ pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **) mutexPtr;
+
+ pthread_mutex_unlock(pmutexPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFinalizeMutex --
+ *
+ * This procedure is invoked to clean up one mutex. This is only safe to
+ * call at the end of time.
+ *
+ * This assumes the Master Lock is held.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The mutex list is deallocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpFinalizeMutex(
+ Tcl_Mutex *mutexPtr)
+{
+ pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **) mutexPtr;
+
+ if (pmutexPtr != NULL) {
+ pthread_mutex_destroy(pmutexPtr);
+ ckfree(pmutexPtr);
+ *mutexPtr = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ConditionWait --
+ *
+ * This procedure is invoked to wait on a condition variable. The mutex
+ * is automically released as part of the wait, and automatically grabbed
+ * when the condition is signaled.
+ *
+ * The mutex must be held when this procedure is called.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May block the current thread. The mutex is aquired when this returns.
+ * Will allocate memory for a pthread_mutex_t and initialize this the
+ * first time this Tcl_Mutex is used.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_ConditionWait(
+ Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */
+ Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */
+ const Tcl_Time *timePtr) /* Timeout on waiting period */
+{
+ pthread_cond_t *pcondPtr;
+ pthread_mutex_t *pmutexPtr;
+ struct timespec ptime;
+
+ if (*condPtr == NULL) {
+ pthread_mutex_lock(&masterLock);
+
+ /*
+ * Double check inside mutex to avoid race, then initialize condition
+ * variable if necessary.
+ */
+
+ if (*condPtr == NULL) {
+ pcondPtr = ckalloc(sizeof(pthread_cond_t));
+ pthread_cond_init(pcondPtr, NULL);
+ *condPtr = (Tcl_Condition) pcondPtr;
+ TclRememberCondition(condPtr);
+ }
+ pthread_mutex_unlock(&masterLock);
+ }
+ pmutexPtr = *((pthread_mutex_t **)mutexPtr);
+ pcondPtr = *((pthread_cond_t **)condPtr);
+ if (timePtr == NULL) {
+ pthread_cond_wait(pcondPtr, pmutexPtr);
+ } else {
+ Tcl_Time now;
+
+ /*
+ * Make sure to take into account the microsecond component of the
+ * current time, including possible overflow situations. [Bug #411603]
+ */
+
+ Tcl_GetTime(&now);
+ ptime.tv_sec = timePtr->sec + now.sec +
+ (timePtr->usec + now.usec) / 1000000;
+ ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);
+ pthread_cond_timedwait(pcondPtr, pmutexPtr, &ptime);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_ConditionNotify --
+ *
+ * This procedure is invoked to signal a condition variable.
+ *
+ * The mutex must be held during this call to avoid races, but this
+ * interface does not enforce that.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May unblock another thread.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_ConditionNotify(
+ Tcl_Condition *condPtr)
+{
+ pthread_cond_t *pcondPtr = *((pthread_cond_t **)condPtr);
+ if (pcondPtr != NULL) {
+ pthread_cond_broadcast(pcondPtr);
+ } else {
+ /*
+ * Noone has used the condition variable, so there are no waiters.
+ */
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFinalizeCondition --
+ *
+ * This procedure is invoked to clean up a condition variable. This is
+ * only safe to call at the end of time.
+ *
+ * This assumes the Master Lock is held.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The condition variable is deallocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpFinalizeCondition(
+ Tcl_Condition *condPtr)
+{
+ pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr;
+
+ if (pcondPtr != NULL) {
+ pthread_cond_destroy(pcondPtr);
+ ckfree(pcondPtr);
+ *condPtr = NULL;
+ }
+}
+#endif /* TCL_THREADS */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpReaddir, TclpInetNtoa --
+ *
+ * These procedures replace core C versions to be used in a threaded
+ * environment.
+ *
+ * Results:
+ * See documentation of C functions.
+ *
+ * Side effects:
+ * See documentation of C functions.
+ *
+ * Notes:
+ * TclpReaddir is no longer used by the core (see 1095909), but it
+ * appears in the internal stubs table (see #589526).
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifndef TCL_NO_DEPRECATED
+Tcl_DirEntry *
+TclpReaddir(
+ DIR * dir)
+{
+ return TclOSreaddir(dir);
+}
+
+#undef TclpInetNtoa
+char *
+TclpInetNtoa(
+ struct in_addr addr)
+{
+#ifdef TCL_THREADS
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ unsigned char *b = (unsigned char*) &addr.s_addr;
+
+ sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]);
+ return tsdPtr->nabuf;
+#else
+ return inet_ntoa(addr);
+#endif
+}
+#endif /* TCL_NO_DEPRECATED */
+
+#ifdef TCL_THREADS
+/*
+ * Additions by AOL for specialized thread memory allocator.
+ */
+
+#ifdef USE_THREAD_ALLOC
+static pthread_key_t key;
+
+typedef struct {
+ Tcl_Mutex tlock;
+ pthread_mutex_t plock;
+} allocMutex;
+
+Tcl_Mutex *
+TclpNewAllocMutex(void)
+{
+ allocMutex *lockPtr;
+ register pthread_mutex_t *plockPtr;
+
+ lockPtr = malloc(sizeof(allocMutex));
+ if (lockPtr == NULL) {
+ Tcl_Panic("could not allocate lock");
+ }
+ plockPtr = &lockPtr->plock;
+ lockPtr->tlock = (Tcl_Mutex) plockPtr;
+ pthread_mutex_init(&lockPtr->plock, NULL);
+ return &lockPtr->tlock;
+}
+
+void
+TclpFreeAllocMutex(
+ Tcl_Mutex *mutex) /* The alloc mutex to free. */
+{
+ allocMutex* lockPtr = (allocMutex*) mutex;
+ if (!lockPtr) {
+ return;
+ }
+ pthread_mutex_destroy(&lockPtr->plock);
+ free(lockPtr);
+}
+
+void
+TclpInitAllocCache(void)
+{
+ pthread_key_create(&key, NULL);
+}
+
+void
+TclpFreeAllocCache(
+ void *ptr)
+{
+ if (ptr != NULL) {
+ /*
+ * Called by TclFinalizeThreadAllocThread() during the thread
+ * finalization initiated from Tcl_FinalizeThread()
+ */
+
+ TclFreeAllocCache(ptr);
+ pthread_setspecific(key, NULL);
+
+ } else {
+ /*
+ * Called by TclFinalizeThreadAlloc() during the process
+ * finalization initiated from Tcl_Finalize()
+ */
+
+ pthread_key_delete(key);
+ }
+}
+
+void *
+TclpGetAllocCache(void)
+{
+ return pthread_getspecific(key);
+}
+
+void
+TclpSetAllocCache(
+ void *arg)
+{
+ pthread_setspecific(key, arg);
+}
+#endif /* USE_THREAD_ALLOC */
+
+void *
+TclpThreadCreateKey(void)
+{
+ pthread_key_t *ptkeyPtr;
+
+ ptkeyPtr = TclpSysAlloc(sizeof *ptkeyPtr, 0);
+ if (NULL == ptkeyPtr) {
+ Tcl_Panic("unable to allocate thread key!");
+ }
+
+ if (pthread_key_create(ptkeyPtr, NULL)) {
+ Tcl_Panic("unable to create pthread key!");
+ }
+
+ return ptkeyPtr;
+}
+
+void
+TclpThreadDeleteKey(
+ void *keyPtr)
+{
+ pthread_key_t *ptkeyPtr = keyPtr;
+
+ if (pthread_key_delete(*ptkeyPtr)) {
+ Tcl_Panic("unable to delete key!");
+ }
+
+ TclpSysFree(keyPtr);
+}
+
+void
+TclpThreadSetMasterTSD(
+ void *tsdKeyPtr,
+ void *ptr)
+{
+ pthread_key_t *ptkeyPtr = tsdKeyPtr;
+
+ if (pthread_setspecific(*ptkeyPtr, ptr)) {
+ Tcl_Panic("unable to set master TSD value");
+ }
+}
+
+void *
+TclpThreadGetMasterTSD(
+ void *tsdKeyPtr)
+{
+ pthread_key_t *ptkeyPtr = tsdKeyPtr;
+
+ return pthread_getspecific(*ptkeyPtr);
+}
+
+#endif /* TCL_THREADS */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclUnixThrd.h b/unix/tclUnixThrd.h
new file mode 100644
index 0000000..f03b530
--- /dev/null
+++ b/unix/tclUnixThrd.h
@@ -0,0 +1,19 @@
+/*
+ * tclUnixThrd.h --
+ *
+ * This header file defines things for thread support.
+ *
+ * Copyright (c) 1998 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef _TCLUNIXTHRD
+#define _TCLUNIXTHRD
+
+#ifdef TCL_THREADS
+
+
+#endif /* TCL_THREADS */
+#endif /* _TCLUNIXTHRD */
diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c
new file mode 100644
index 0000000..6a73ac2
--- /dev/null
+++ b/unix/tclUnixTime.c
@@ -0,0 +1,548 @@
+/*
+ * tclUnixTime.c --
+ *
+ * Contains Unix specific versions of Tcl functions that obtain time
+ * values from the operating system.
+ *
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tclInt.h"
+#include <locale.h>
+#if defined(TCL_WIDE_CLICKS) && defined(MAC_OSX_TCL)
+#include <mach/mach_time.h>
+#endif
+
+/*
+ * TclpGetDate is coded to return a pointer to a 'struct tm'. For thread
+ * safety, this structure must be in thread-specific data. The 'tmKey'
+ * variable is the key to this buffer.
+ */
+
+#ifndef TCL_NO_DEPRECATED
+static Tcl_ThreadDataKey tmKey;
+typedef struct {
+ struct tm gmtime_buf;
+ struct tm localtime_buf;
+} ThreadSpecificData;
+
+/*
+ * If we fall back on the thread-unsafe versions of gmtime and localtime, use
+ * this mutex to try to protect them.
+ */
+
+TCL_DECLARE_MUTEX(tmMutex)
+
+static char *lastTZ = NULL; /* Holds the last setting of the TZ
+ * environment variable, or an empty string if
+ * the variable was not set. */
+
+/*
+ * Static functions declared in this file.
+ */
+
+static void SetTZIfNecessary(void);
+static void CleanupMemory(ClientData clientData);
+#endif /* TCL_NO_DEPRECATED */
+
+static void NativeScaleTime(Tcl_Time *timebuf,
+ ClientData clientData);
+static void NativeGetTime(Tcl_Time *timebuf,
+ ClientData clientData);
+
+/*
+ * TIP #233 (Virtualized Time): Data for the time hooks, if any.
+ */
+
+Tcl_GetTimeProc *tclGetTimeProcPtr = NativeGetTime;
+Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime;
+ClientData tclTimeClientData = NULL;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGetSeconds --
+ *
+ * This procedure returns the number of seconds from the epoch. On most
+ * Unix systems the epoch is Midnight Jan 1, 1970 GMT.
+ *
+ * Results:
+ * Number of seconds from the epoch.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+unsigned long
+TclpGetSeconds(void)
+{
+ return time(NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGetClicks --
+ *
+ * This procedure returns a value that represents the highest resolution
+ * clock available on the system. There are no garantees on what the
+ * resolution will be. In Tcl we will call this value a "click". The
+ * start time is also system dependant.
+ *
+ * Results:
+ * Number of clicks from some start time.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+unsigned long
+TclpGetClicks(void)
+{
+ unsigned long now;
+
+#ifdef NO_GETTOD
+ if (tclGetTimeProcPtr != NativeGetTime) {
+ Tcl_Time time;
+
+ tclGetTimeProcPtr(&time, tclTimeClientData);
+ now = time.sec*1000000 + time.usec;
+ } else {
+ /*
+ * A semi-NativeGetTime, specialized to clicks.
+ */
+ struct tms dummy;
+
+ now = (unsigned long) times(&dummy);
+ }
+#else
+ Tcl_Time time;
+
+ tclGetTimeProcPtr(&time, tclTimeClientData);
+ now = time.sec*1000000 + time.usec;
+#endif
+
+ return now;
+}
+#ifdef TCL_WIDE_CLICKS
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGetWideClicks --
+ *
+ * This procedure returns a WideInt value that represents the highest
+ * resolution clock available on the system. There are no garantees on
+ * what the resolution will be. In Tcl we will call this value a "click".
+ * The start time is also system dependant.
+ *
+ * Results:
+ * Number of WideInt clicks from some start time.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_WideInt
+TclpGetWideClicks(void)
+{
+ Tcl_WideInt now;
+
+ if (tclGetTimeProcPtr != NativeGetTime) {
+ Tcl_Time time;
+
+ tclGetTimeProcPtr(&time, tclTimeClientData);
+ now = ((Tcl_WideInt)time.sec)*1000000 + time.usec;
+ } else {
+#ifdef MAC_OSX_TCL
+ now = (Tcl_WideInt) (mach_absolute_time() & INT64_MAX);
+#else
+#error Wide high-resolution clicks not implemented on this platform
+#endif
+ }
+
+ return now;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpWideClicksToNanoseconds --
+ *
+ * This procedure converts click values from the TclpGetWideClicks native
+ * resolution to nanosecond resolution.
+ *
+ * Results:
+ * Number of nanoseconds from some start time.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+double
+TclpWideClicksToNanoseconds(
+ Tcl_WideInt clicks)
+{
+ double nsec;
+
+ if (tclGetTimeProcPtr != NativeGetTime) {
+ nsec = clicks * 1000;
+ } else {
+#ifdef MAC_OSX_TCL
+ static mach_timebase_info_data_t tb;
+ static uint64_t maxClicksForUInt64;
+
+ if (!tb.denom) {
+ mach_timebase_info(&tb);
+ maxClicksForUInt64 = UINT64_MAX / tb.numer;
+ }
+ if ((uint64_t) clicks < maxClicksForUInt64) {
+ nsec = ((uint64_t) clicks) * tb.numer / tb.denom;
+ } else {
+ nsec = ((long double) (uint64_t) clicks) * tb.numer / tb.denom;
+ }
+#else
+#error Wide high-resolution clicks not implemented on this platform
+#endif
+ }
+
+ return nsec;
+}
+#endif /* TCL_WIDE_CLICKS */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_GetTime --
+ *
+ * Gets the current system time in seconds and microseconds since the
+ * beginning of the epoch: 00:00 UCT, January 1, 1970.
+ *
+ * This function is hooked, allowing users to specify their own virtual
+ * system time.
+ *
+ * Results:
+ * Returns the current time in timePtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_GetTime(
+ Tcl_Time *timePtr) /* Location to store time information. */
+{
+ tclGetTimeProcPtr(timePtr, tclTimeClientData);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGetDate --
+ *
+ * This function converts between seconds and struct tm. If useGMT is
+ * true, then the returned date will be in Greenwich Mean Time (GMT).
+ * Otherwise, it will be in the local time zone.
+ *
+ * Results:
+ * Returns a static tm structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifndef TCL_NO_DEPRECATED
+struct tm *
+TclpGetDate(
+ const time_t *time,
+ int useGMT)
+{
+ if (useGMT) {
+ return TclpGmtime(time);
+ } else {
+ return TclpLocaltime(time);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGmtime --
+ *
+ * Wrapper around the 'gmtime' library function to make it thread safe.
+ *
+ * Results:
+ * Returns a pointer to a 'struct tm' in thread-specific data.
+ *
+ * Side effects:
+ * Invokes gmtime or gmtime_r as appropriate.
+ *
+ *----------------------------------------------------------------------
+ */
+
+struct tm *
+TclpGmtime(
+ const time_t *timePtr) /* Pointer to the number of seconds since the
+ * local system's epoch */
+{
+ /*
+ * Get a thread-local buffer to hold the returned time.
+ */
+
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tmKey);
+
+#ifdef HAVE_GMTIME_R
+ gmtime_r(timePtr, &tsdPtr->gmtime_buf);
+#else
+ Tcl_MutexLock(&tmMutex);
+ memcpy(&tsdPtr->gmtime_buf, gmtime(timePtr), sizeof(struct tm));
+ Tcl_MutexUnlock(&tmMutex);
+#endif
+
+ return &tsdPtr->gmtime_buf;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpLocaltime --
+ *
+ * Wrapper around the 'localtime' library function to make it thread
+ * safe.
+ *
+ * Results:
+ * Returns a pointer to a 'struct tm' in thread-specific data.
+ *
+ * Side effects:
+ * Invokes localtime or localtime_r as appropriate.
+ *
+ *----------------------------------------------------------------------
+ */
+
+struct tm *
+TclpLocaltime(
+ const time_t *timePtr) /* Pointer to the number of seconds since the
+ * local system's epoch */
+{
+ /*
+ * Get a thread-local buffer to hold the returned time.
+ */
+
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tmKey);
+
+ SetTZIfNecessary();
+#ifdef HAVE_LOCALTIME_R
+ localtime_r(timePtr, &tsdPtr->localtime_buf);
+#else
+ Tcl_MutexLock(&tmMutex);
+ memcpy(&tsdPtr->localtime_buf, localtime(timePtr), sizeof(struct tm));
+ Tcl_MutexUnlock(&tmMutex);
+#endif
+
+ return &tsdPtr->localtime_buf;
+}
+#endif /* TCL_NO_DEPRECATED */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SetTimeProc --
+ *
+ * TIP #233 (Virtualized Time): Registers two handlers for the
+ * virtualization of Tcl's access to time information.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Remembers the handlers, alters core behaviour.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_SetTimeProc(
+ Tcl_GetTimeProc *getProc,
+ Tcl_ScaleTimeProc *scaleProc,
+ ClientData clientData)
+{
+ tclGetTimeProcPtr = getProc;
+ tclScaleTimeProcPtr = scaleProc;
+ tclTimeClientData = clientData;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_QueryTimeProc --
+ *
+ * TIP #233 (Virtualized Time): Query which time handlers are registered.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tcl_QueryTimeProc(
+ Tcl_GetTimeProc **getProc,
+ Tcl_ScaleTimeProc **scaleProc,
+ ClientData *clientData)
+{
+ if (getProc) {
+ *getProc = tclGetTimeProcPtr;
+ }
+ if (scaleProc) {
+ *scaleProc = tclScaleTimeProcPtr;
+ }
+ if (clientData) {
+ *clientData = tclTimeClientData;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NativeScaleTime --
+ *
+ * TIP #233: Scale from virtual time to the real-time. For native scaling
+ * the relationship is 1:1 and nothing has to be done.
+ *
+ * Results:
+ * Scales the time in timePtr.
+ *
+ * Side effects:
+ * See above.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+NativeScaleTime(
+ Tcl_Time *timePtr,
+ ClientData clientData)
+{
+ /* Native scale is 1:1. Nothing is done */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NativeGetTime --
+ *
+ * TIP #233: Gets the current system time in seconds and microseconds
+ * since the beginning of the epoch: 00:00 UCT, January 1, 1970.
+ *
+ * Results:
+ * Returns the current time in timePtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+NativeGetTime(
+ Tcl_Time *timePtr,
+ ClientData clientData)
+{
+ struct timeval tv;
+
+ (void) gettimeofday(&tv, NULL);
+ timePtr->sec = tv.tv_sec;
+ timePtr->usec = tv.tv_usec;
+}
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetTZIfNecessary --
+ *
+ * Determines whether a call to 'tzset' is needed prior to the next call
+ * to 'localtime' or examination of the 'timezone' variable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If 'tzset' has never been called in the current process, or if the
+ * value of the environment variable TZ has changed since the last call
+ * to 'tzset', then 'tzset' is called again.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifndef TCL_NO_DEPRECATED
+static void
+SetTZIfNecessary(void)
+{
+ const char *newTZ = getenv("TZ");
+
+ Tcl_MutexLock(&tmMutex);
+ if (newTZ == NULL) {
+ newTZ = "";
+ }
+ if (lastTZ == NULL || strcmp(lastTZ, newTZ)) {
+ tzset();
+ if (lastTZ == NULL) {
+ Tcl_CreateExitHandler(CleanupMemory, NULL);
+ } else {
+ ckfree(lastTZ);
+ }
+ lastTZ = ckalloc(strlen(newTZ) + 1);
+ strcpy(lastTZ, newTZ);
+ }
+ Tcl_MutexUnlock(&tmMutex);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CleanupMemory --
+ *
+ * Releases the private copy of the TZ environment variable upon exit
+ * from Tcl.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees allocated memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CleanupMemory(
+ ClientData ignored)
+{
+ ckfree(lastTZ);
+}
+#endif /* TCL_NO_DEPRECATED */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclXtNotify.c b/unix/tclXtNotify.c
new file mode 100644
index 0000000..26db9f2
--- /dev/null
+++ b/unix/tclXtNotify.c
@@ -0,0 +1,667 @@
+/*
+ * tclXtNotify.c --
+ *
+ * This file contains the notifier driver implementation for the Xt
+ * intrinsics.
+ *
+ * Copyright (c) 1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef USE_TCL_STUBS
+# define USE_TCL_STUBS
+#endif
+#include <X11/Intrinsic.h>
+#include "tclInt.h"
+
+/*
+ * This structure is used to keep track of the notifier info for a a
+ * registered file.
+ */
+
+typedef struct FileHandler {
+ int fd;
+ int mask; /* Mask of desired events: TCL_READABLE,
+ * etc. */
+ int readyMask; /* Events that have been seen since the last
+ * time FileHandlerEventProc was called for
+ * this file. */
+ XtInputId read; /* Xt read callback handle. */
+ XtInputId write; /* Xt write callback handle. */
+ XtInputId except; /* Xt exception callback handle. */
+ Tcl_FileProc *proc; /* Procedure to call, in the style of
+ * Tcl_CreateFileHandler. */
+ ClientData clientData; /* Argument to pass to proc. */
+ struct FileHandler *nextPtr;/* Next in list of all files we care about. */
+} FileHandler;
+
+/*
+ * The following structure is what is added to the Tcl event queue when file
+ * handlers are ready to fire.
+ */
+
+typedef struct {
+ Tcl_Event header; /* Information that is standard for all
+ * events. */
+ int fd; /* File descriptor that is ready. Used to find
+ * the FileHandler structure for the file
+ * (can't point directly to the FileHandler
+ * structure because it could go away while
+ * the event is queued). */
+} FileHandlerEvent;
+
+/*
+ * The following static structure contains the state information for the Xt
+ * based implementation of the Tcl notifier.
+ */
+
+static struct NotifierState {
+ XtAppContext appContext; /* The context used by the Xt notifier. Can be
+ * set with TclSetAppContext. */
+ int appContextCreated; /* Was it created by us? */
+ XtIntervalId currentTimeout;/* Handle of current timer. */
+ FileHandler *firstFileHandlerPtr;
+ /* Pointer to head of file handler list. */
+} notifier;
+
+/*
+ * The following static indicates whether this module has been initialized.
+ */
+
+static int initialized = 0;
+
+/*
+ * Static routines defined in this file.
+ */
+
+static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
+static void FileProc(XtPointer clientData, int *source,
+ XtInputId *id);
+static void NotifierExitHandler(ClientData clientData);
+static void TimerProc(XtPointer clientData, XtIntervalId *id);
+static void CreateFileHandler(int fd, int mask,
+ Tcl_FileProc *proc, ClientData clientData);
+static void DeleteFileHandler(int fd);
+static void SetTimer(const Tcl_Time * timePtr);
+static int WaitForEvent(const Tcl_Time * timePtr);
+
+/*
+ * Functions defined in this file for use by users of the Xt Notifier:
+ */
+
+MODULE_SCOPE void InitNotifier(void);
+MODULE_SCOPE XtAppContext TclSetAppContext(XtAppContext ctx);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclSetAppContext --
+ *
+ * Set the notifier application context.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the application context used by the notifier. Panics if the
+ * context is already set when called.
+ *
+ *----------------------------------------------------------------------
+ */
+
+XtAppContext
+TclSetAppContext(
+ XtAppContext appContext)
+{
+ if (!initialized) {
+ InitNotifier();
+ }
+
+ /*
+ * If we already have a context we check whether we were asked to set a
+ * new context. If so, we panic because we try to prevent switching
+ * contexts by mistake. Otherwise, we return the one we have.
+ */
+
+ if (notifier.appContext != NULL) {
+ if (appContext != NULL) {
+ /*
+ * We already have a context. We do not allow switching contexts
+ * after initialization, so we panic.
+ */
+
+ Tcl_Panic("TclSetAppContext: multiple application contexts");
+ }
+ } else {
+ /*
+ * If we get here we have not yet gotten a context, so either create
+ * one or use the one supplied by our caller.
+ */
+
+ if (appContext == NULL) {
+ /*
+ * We must create a new context and tell our caller what it is, so
+ * she can use it too.
+ */
+
+ notifier.appContext = XtCreateApplicationContext();
+ notifier.appContextCreated = 1;
+ } else {
+ /*
+ * Otherwise we remember the context that our caller gave us and
+ * use it.
+ */
+
+ notifier.appContextCreated = 0;
+ notifier.appContext = appContext;
+ }
+ }
+
+ return notifier.appContext;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitNotifier --
+ *
+ * Initializes the notifier state.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates a new exit handler.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+InitNotifier(void)
+{
+ Tcl_NotifierProcs np;
+
+ /*
+ * Only reinitialize if we are not in exit handling. The notifier can get
+ * reinitialized after its own exit handler has run, because of exit
+ * handlers for the I/O and timer sub-systems (order dependency).
+ */
+
+ if (TclInExit()) {
+ return;
+ }
+
+ np.createFileHandlerProc = CreateFileHandler;
+ np.deleteFileHandlerProc = DeleteFileHandler;
+ np.setTimerProc = SetTimer;
+ np.waitForEventProc = WaitForEvent;
+ np.initNotifierProc = Tcl_InitNotifier;
+ np.finalizeNotifierProc = Tcl_FinalizeNotifier;
+ np.alertNotifierProc = Tcl_AlertNotifier;
+ np.serviceModeHookProc = Tcl_ServiceModeHook;
+ Tcl_SetNotifier(&np);
+
+ /*
+ * DO NOT create the application context yet; doing so would prevent
+ * external applications from setting it for us to their own ones.
+ */
+
+ initialized = 1;
+ memset(&np, 0, sizeof(np));
+ Tcl_CreateExitHandler(NotifierExitHandler, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NotifierExitHandler --
+ *
+ * This function is called to cleanup the notifier state before Tcl is
+ * unloaded.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Destroys the notifier window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+NotifierExitHandler(
+ ClientData clientData) /* Not used. */
+{
+ if (notifier.currentTimeout != 0) {
+ XtRemoveTimeOut(notifier.currentTimeout);
+ }
+ for (; notifier.firstFileHandlerPtr != NULL; ) {
+ Tcl_DeleteFileHandler(notifier.firstFileHandlerPtr->fd);
+ }
+ if (notifier.appContextCreated) {
+ XtDestroyApplicationContext(notifier.appContext);
+ notifier.appContextCreated = 0;
+ notifier.appContext = NULL;
+ }
+ initialized = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetTimer --
+ *
+ * This procedure sets the current notifier timeout value.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Replaces any previous timer.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SetTimer(
+ const Tcl_Time *timePtr) /* Timeout value, may be NULL. */
+{
+ long timeout;
+
+ if (!initialized) {
+ InitNotifier();
+ }
+
+ TclSetAppContext(NULL);
+ if (notifier.currentTimeout != 0) {
+ XtRemoveTimeOut(notifier.currentTimeout);
+ }
+ if (timePtr) {
+ timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
+ notifier.currentTimeout = XtAppAddTimeOut(notifier.appContext,
+ (unsigned long) timeout, TimerProc, NULL);
+ } else {
+ notifier.currentTimeout = 0;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TimerProc --
+ *
+ * This procedure is the XtTimerCallbackProc used to handle timeouts.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Processes all queued events.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TimerProc(
+ XtPointer clientData, /* Not used. */
+ XtIntervalId *id)
+{
+ if (*id != notifier.currentTimeout) {
+ return;
+ }
+ notifier.currentTimeout = 0;
+
+ Tcl_ServiceAll();
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateFileHandler --
+ *
+ * This procedure registers a file handler with the Xt notifier.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates a new file handler structure and registers one or more input
+ * procedures with Xt.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CreateFileHandler(
+ int fd, /* Handle of stream to watch. */
+ int mask, /* OR'ed combination of TCL_READABLE,
+ * TCL_WRITABLE, and TCL_EXCEPTION: indicates
+ * conditions under which proc should be
+ * called. */
+ Tcl_FileProc *proc, /* Procedure to call for each selected
+ * event. */
+ ClientData clientData) /* Arbitrary data to pass to proc. */
+{
+ FileHandler *filePtr;
+
+ if (!initialized) {
+ InitNotifier();
+ }
+
+ TclSetAppContext(NULL);
+
+ for (filePtr = notifier.firstFileHandlerPtr; filePtr != NULL;
+ filePtr = filePtr->nextPtr) {
+ if (filePtr->fd == fd) {
+ break;
+ }
+ }
+ if (filePtr == NULL) {
+ filePtr = ckalloc(sizeof(FileHandler));
+ filePtr->fd = fd;
+ filePtr->read = 0;
+ filePtr->write = 0;
+ filePtr->except = 0;
+ filePtr->readyMask = 0;
+ filePtr->mask = 0;
+ filePtr->nextPtr = notifier.firstFileHandlerPtr;
+ notifier.firstFileHandlerPtr = filePtr;
+ }
+ filePtr->proc = proc;
+ filePtr->clientData = clientData;
+
+ /*
+ * Register the file with the Xt notifier, if it hasn't been done yet.
+ */
+
+ if (mask & TCL_READABLE) {
+ if (!(filePtr->mask & TCL_READABLE)) {
+ filePtr->read = XtAppAddInput(notifier.appContext, fd,
+ INT2PTR(XtInputReadMask), FileProc, filePtr);
+ }
+ } else {
+ if (filePtr->mask & TCL_READABLE) {
+ XtRemoveInput(filePtr->read);
+ }
+ }
+ if (mask & TCL_WRITABLE) {
+ if (!(filePtr->mask & TCL_WRITABLE)) {
+ filePtr->write = XtAppAddInput(notifier.appContext, fd,
+ INT2PTR(XtInputWriteMask), FileProc, filePtr);
+ }
+ } else {
+ if (filePtr->mask & TCL_WRITABLE) {
+ XtRemoveInput(filePtr->write);
+ }
+ }
+ if (mask & TCL_EXCEPTION) {
+ if (!(filePtr->mask & TCL_EXCEPTION)) {
+ filePtr->except = XtAppAddInput(notifier.appContext, fd,
+ INT2PTR(XtInputExceptMask), FileProc, filePtr);
+ }
+ } else {
+ if (filePtr->mask & TCL_EXCEPTION) {
+ XtRemoveInput(filePtr->except);
+ }
+ }
+ filePtr->mask = mask;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteFileHandler --
+ *
+ * Cancel a previously-arranged callback arrangement for a file.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If a callback was previously registered on file, remove it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DeleteFileHandler(
+ int fd) /* Stream id for which to remove callback
+ * procedure. */
+{
+ FileHandler *filePtr, *prevPtr;
+
+ if (!initialized) {
+ InitNotifier();
+ }
+
+ TclSetAppContext(NULL);
+
+ /*
+ * Find the entry for the given file (and return if there isn't one).
+ */
+
+ for (prevPtr = NULL, filePtr = notifier.firstFileHandlerPtr; ;
+ prevPtr = filePtr, filePtr = filePtr->nextPtr) {
+ if (filePtr == NULL) {
+ return;
+ }
+ if (filePtr->fd == fd) {
+ break;
+ }
+ }
+
+ /*
+ * Clean up information in the callback record.
+ */
+
+ if (prevPtr == NULL) {
+ notifier.firstFileHandlerPtr = filePtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = filePtr->nextPtr;
+ }
+ if (filePtr->mask & TCL_READABLE) {
+ XtRemoveInput(filePtr->read);
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ XtRemoveInput(filePtr->write);
+ }
+ if (filePtr->mask & TCL_EXCEPTION) {
+ XtRemoveInput(filePtr->except);
+ }
+ ckfree(filePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileProc --
+ *
+ * These procedures are called by Xt when a file becomes readable,
+ * writable, or has an exception.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Makes an entry on the Tcl event queue if the event is interesting.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FileProc(
+ XtPointer clientData,
+ int *fd,
+ XtInputId *id)
+{
+ FileHandler *filePtr = (FileHandler *)clientData;
+ FileHandlerEvent *fileEvPtr;
+ int mask = 0;
+
+ /*
+ * Determine which event happened.
+ */
+
+ if (*id == filePtr->read) {
+ mask = TCL_READABLE;
+ } else if (*id == filePtr->write) {
+ mask = TCL_WRITABLE;
+ } else if (*id == filePtr->except) {
+ mask = TCL_EXCEPTION;
+ }
+
+ /*
+ * Ignore unwanted or duplicate events.
+ */
+
+ if (!(filePtr->mask & mask) || (filePtr->readyMask & mask)) {
+ return;
+ }
+
+ /*
+ * This is an interesting event, so put it onto the event queue.
+ */
+
+ filePtr->readyMask |= mask;
+ fileEvPtr = ckalloc(sizeof(FileHandlerEvent));
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
+
+ /*
+ * Process events on the Tcl event queue before returning to Xt.
+ */
+
+ Tcl_ServiceAll();
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileHandlerEventProc --
+ *
+ * This procedure is called by Tcl_ServiceEvent when a file event reaches
+ * the front of the event queue. This procedure is responsible for
+ * actually handling the event by invoking the callback for the file
+ * handler.
+ *
+ * Results:
+ * Returns 1 if the event was handled, meaning it should be removed from
+ * the queue. Returns 0 if the event was not handled, meaning it should
+ * stay on the queue. The only time the event isn't handled is if the
+ * TCL_FILE_EVENTS flag bit isn't set.
+ *
+ * Side effects:
+ * Whatever the file handler's callback procedure does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+FileHandlerEventProc(
+ Tcl_Event *evPtr, /* Event to service. */
+ int flags) /* Flags that indicate what events to handle,
+ * such as TCL_FILE_EVENTS. */
+{
+ FileHandler *filePtr;
+ FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr;
+ int mask;
+
+ if (!(flags & TCL_FILE_EVENTS)) {
+ return 0;
+ }
+
+ /*
+ * Search through the file handlers to find the one whose handle matches
+ * the event. We do this rather than keeping a pointer to the file handler
+ * directly in the event, so that the handler can be deleted while the
+ * event is queued without leaving a dangling pointer.
+ */
+
+ for (filePtr = notifier.firstFileHandlerPtr; filePtr != NULL;
+ filePtr = filePtr->nextPtr) {
+ if (filePtr->fd != fileEvPtr->fd) {
+ continue;
+ }
+
+ /*
+ * The code is tricky for two reasons:
+ * 1. The file handler's desired events could have changed since the
+ * time when the event was queued, so AND the ready mask with the
+ * desired mask.
+ * 2. The file could have been closed and re-opened since the time
+ * when the event was queued. This is why the ready mask is stored
+ * in the file handler rather than the queued event: it will be
+ * zeroed when a new file handler is created for the newly opened
+ * file.
+ */
+
+ mask = filePtr->readyMask & filePtr->mask;
+ filePtr->readyMask = 0;
+ if (mask != 0) {
+ filePtr->proc(filePtr->clientData, mask);
+ }
+ break;
+ }
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WaitForEvent --
+ *
+ * This function is called by Tcl_DoOneEvent to wait for new events on
+ * the message queue. If the block time is 0, then Tcl_WaitForEvent just
+ * polls without blocking.
+ *
+ * Results:
+ * Returns 1 if an event was found, else 0. This ensures that
+ * Tcl_DoOneEvent will return 1, even if the event is handled by non-Tcl
+ * code.
+ *
+ * Side effects:
+ * Queues file events that are detected by the select.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WaitForEvent(
+ const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
+{
+ int timeout;
+
+ if (!initialized) {
+ InitNotifier();
+ }
+
+ TclSetAppContext(NULL);
+
+ if (timePtr) {
+ timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
+ if (timeout == 0) {
+ if (XtAppPending(notifier.appContext)) {
+ goto process;
+ } else {
+ return 0;
+ }
+ } else {
+ Tcl_SetTimer(timePtr);
+ }
+ }
+
+ process:
+ XtAppProcessEvent(notifier.appContext, XtIMAll);
+ return 1;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */
diff --git a/unix/tclXtTest.c b/unix/tclXtTest.c
new file mode 100644
index 0000000..cb70b58
--- /dev/null
+++ b/unix/tclXtTest.c
@@ -0,0 +1,134 @@
+/*
+ * tclXtTest.c --
+ *
+ * Contains commands for Xt notifier specific tests on Unix.
+ *
+ * Copyright (c) 1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef USE_TCL_STUBS
+# define USE_TCL_STUBS
+#endif
+#include <X11/Intrinsic.h>
+#include "tcl.h"
+
+static Tcl_ObjCmdProc TesteventloopCmd;
+extern DLLEXPORT Tcl_PackageInitProc Tclxttest_Init;
+
+/*
+ * Functions defined in tclXtNotify.c for use by users of the Xt Notifier:
+ */
+
+extern void InitNotifier(void);
+extern XtAppContext TclSetAppContext(XtAppContext ctx);
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tclxttest_Init --
+ *
+ * This procedure performs application-specific initialization. Most
+ * applications, especially those that incorporate additional packages,
+ * will have their own version of this procedure.
+ *
+ * Results:
+ * Returns a standard Tcl completion code, and leaves an error message in
+ * the interp's result if an error occurs.
+ *
+ * Side effects:
+ * Depends on the startup script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tclxttest_Init(
+ Tcl_Interp *interp) /* Interpreter for application. */
+{
+ if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
+ return TCL_ERROR;
+ }
+ XtToolkitInitialize();
+ InitNotifier();
+ Tcl_CreateObjCommand(interp, "testeventloop", TesteventloopCmd,
+ NULL, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TesteventloopCmd --
+ *
+ * This procedure implements the "testeventloop" command. It is used to
+ * test the Tcl notifier from an "external" event loop (i.e. not
+ * Tcl_DoOneEvent()).
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TesteventloopCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ static int *framePtr = NULL;/* Pointer to integer on stack frame of
+ * innermost invocation of the "wait"
+ * subcommand. */
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ...");
+ return TCL_ERROR;
+ }
+ if (strcmp(Tcl_GetString(objv[1]), "done") == 0) {
+ *framePtr = 1;
+ } else if (strcmp(Tcl_GetString(objv[1]), "wait") == 0) {
+ int *oldFramePtr;
+ int done;
+ int oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+
+ /*
+ * Save the old stack frame pointer and set up the current frame.
+ */
+
+ oldFramePtr = framePtr;
+ framePtr = &done;
+
+ /*
+ * Enter an Xt event loop until the flag changes. Note that we do not
+ * explicitly call Tcl_ServiceEvent().
+ */
+
+ done = 0;
+ while (!done) {
+ XtAppProcessEvent(TclSetAppContext(NULL), XtIMAll);
+ }
+ (void) Tcl_SetServiceMode(oldMode);
+ framePtr = oldFramePtr;
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
+ "\": must be done or wait", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * tab-width: 8
+ * End:
+ */
diff --git a/unix/tclooConfig.sh b/unix/tclooConfig.sh
new file mode 100644
index 0000000..4c2068c
--- /dev/null
+++ b/unix/tclooConfig.sh
@@ -0,0 +1,19 @@
+# tclooConfig.sh --
+#
+# This shell script (for sh) is generated automatically by TclOO's configure
+# script, or would be except it has no values that we substitute. It will
+# create shell variables for most of the configuration options discovered by
+# the configure script. This script is intended to be included by TEA-based
+# configure scripts for TclOO extensions so that they don't have to figure
+# this all out for themselves.
+#
+# The information in this file is specific to a single platform.
+
+# These are mostly empty because no special steps are ever needed from Tcl 8.6
+# onwards; all libraries and include files are just part of Tcl.
+TCLOO_LIB_SPEC=""
+TCLOO_STUB_LIB_SPEC=""
+TCLOO_INCLUDE_SPEC=""
+TCLOO_PRIVATE_INCLUDE_SPEC=""
+TCLOO_CFLAGS=""
+TCLOO_VERSION=1.2.0