Attachment "tcl-8.3.5.patch" to
ticket [622183ffff]
added by
kirben
2002-10-12 09:17:06.
diff -bur otcl-8.3.5/ChangeLog tcl-8.3.5/ChangeLog
--- otcl-8.3.5/ChangeLog 2002-10-11 21:50:00.000000000 +1000
+++ tcl-8.3.5/ChangeLog 2002-10-12 12:07:46.000000000 +1000
@@ -1,3 +1,77 @@
+2002-10-11 Mumit Khan <[email protected]>
+
+ * win/configure.in (SEH test): Define to be 1 instead of empty value.
+ (EXCEPTION_DISPOSITION): Add test.
+ * win/configure: Regenerate.
+
+ Adapt Mo DeJong's Tcl 8.4 CVS non-SEH compiler support patch for
+ Tcl 8.3.4 branch.
+
+ * win/configure: Regen.
+ * win/configure.in: Add configure time test for SEH
+ support in the compiler.
+ * win/tclWin32Dll.c (ESP, EBP, TclpCheckStackSpace,
+ _except_checkstackspace_handler):
+ * win/tclWinChan.c (ESP, EBP, Tcl_MakeFileChannel,
+ _except_makefilechannel_handler):
+ * win/tclWinFCmd.c (ESP, EBP, DoRenameFile,
+ _except_dorenamefile_handler,
+ DoCopyFile, _except_docopyfile_handler):
+ Implement SEH support under gcc using inline asm.
+ Tcl and Tk should now compile with Mingw 1.1. [Patch 525746]
+
+ * win/tclWinFCmd.c (DoRenameFile, DoCopyFile): Handle
+ an SEH exception with EXCEPTION_EXECUTE_HANDLER instead
+ of restarting the faulting instruction with
+ EXCEPTION_CONTINUE_EXECUTION. Bug 466102 provides an
+ example of how restarting could send Tcl into an
+ infinite loop. [Patch 525746]
+
+2002-10-11 Mumit Khan <[email protected]>
+
+ * win/tclWinFile.c (TclpMatchFilesTypes): Move the conversion to
+ POSIX to native format from here to ...
+ * generic/tclFileName.c (TclDoGlob): Here.
+
+2002-10-11 Mumit Khan <[email protected]>
+
+ Added basic Cygwin support.
+
+ * win/tcl.m4 (SC_PATH_TCLCONFIG): Support one-tree build.
+ (SC_PATH_TKCONFIG): Likewise.
+ (SC_PROG_TCLSH): Likewise.
+ (SC_ENABLE_GCC): Choose gcc by default.
+ (SC_CONFIG_CFLAGS): Assume real Cygwin port and remove -mno-cygwin
+ flags. Add -mwin32 to extra_cflags and extra_ldflags.
+ Remove ``-e _WinMain@16'' from LDFLAGS_WINDOW.
+ * win/configure.in (TCL_*_LIB_SUFFIX): Use ${VER} instead of
+ \${NODOT_VERSION}.
+ (TCL_LIB_FLAG, TCL_BUILD_LIB_SPEC, TCL_LIB_SPEC, SHLIB_SUFFIX,
+ TCL_PACKAGE_PATH): Add missing variable decls.
+ * win/configure: Regenerate.
+
+ * generic/tclEnv.c (__cygwin_environ): Declare.
+ (TclCygwin32Putenv): New function.
+ (putenv): Use.
+ * generic/tclFileName.c (Tcl_TranslateFileName): Convert POSIX
+ to native format.
+ * win/tclWinFile.c (TclpMatchFilesTypes): Likewise.
+ * generic/tclPlatDecls.h (tchar.h): Do not include on Cygwin.
+ * win/tclWinPort.h (environ, putenv, timezone): Define for Cygwin.
+ (TclpSysAlloc, TclpSysFree, TclpSysRealloc): Use C runtime rather
+ than Windows API.
+ * win/tclWin32Dll.c (TclpCheckStackSpace): Disable Win32 SEH for GCC.
+ * win/tclWinChan.c (Tcl_MakeFileChannel): Likewise.
+ * win/tclWinConsole.c (dos.h): Do not include on Cygwin.
+ * win/tclWinPipe.c (dos.h): Likewise.
+ * win/tclWinSerial.c (dos.h): Likewise.
+ * win/tclWinThrd.c (dos.h): Likewise.
+ (Tcl_CreateThread): Use Win32 instead of MSVCRT API on Cygwin.
+ (TclpThreadExit): Likewise.
+ * win/tclWinFCmd.c (DoRenameFile): Likewise.
+ (DoCopyFile): Likewise.
+ * win/tclWinFile.c (TclpReadLink): New function.
+
2002-10-10 Daniel Steffen <[email protected]>
* mac/tclMacFCmd.c: removed GenerateUniqueName(), use equivalent
diff -bur otcl-8.3.5/generic/tclEnv.c tcl-8.3.5/generic/tclEnv.c
--- otcl-8.3.5/generic/tclEnv.c 2002-10-11 21:50:04.000000000 +1000
+++ tcl-8.3.5/generic/tclEnv.c 2002-10-12 11:56:50.000000000 +1000
@@ -20,6 +20,23 @@
TCL_DECLARE_MUTEX(envMutex) /* To serialize access to environ */
+/* CYGNUS LOCAL */
+#if defined(__CYGWIN__) && defined(__WIN32__)
+
+/* Under cygwin, the environment is imported from the cygwin DLL. */
+
+__declspec(dllimport) extern char **__cygwin_environ;
+
+#define environ (__cygwin_environ)
+
+/* We need to use a special putenv function to handle PATH. */
+#ifndef USE_PUTENV
+#define USE_PUTENV
+#endif
+#define putenv TclCygwin32Putenv
+#endif
+/* END CYGNUS LOCAL */
+
static int cacheSize = 0; /* Number of env strings in environCache. */
static char **environCache = NULL;
/* Array containing all of the environment
@@ -54,6 +71,11 @@
CONST char *value));
void TclUnsetEnv _ANSI_ARGS_((CONST char *name));
+/* CYGNUS LOCAL */
+#if defined (__CYGWIN__) && defined(__WIN32__)
+static void TclCygwin32Putenv _ANSI_ARGS_((CONST char *string));
+#endif
+/* END CYGNUS LOCAL */
/*
*----------------------------------------------------------------------
@@ -683,3 +705,88 @@
#endif
}
}
+
+/* CYGNUS LOCAL */
+#if defined(__CYGWIN__) && defined(__WIN32__)
+
+#include "windows.h"
+
+/* When using cygwin, when an environment variable changes, we need
+ to synch with both the cygwin environment (in case the
+ application C code calls fork) and the Windows environment (in case
+ the application TCL code calls exec, which calls the Windows
+ CreateProcess function). */
+
+static void
+TclCygwin32Putenv(str)
+ const char *str;
+{
+ char *name, *value;
+
+ /* Get the name and value, so that we can change the environment
+ variable for Windows. */
+ name = (char *) alloca (strlen (str) + 1);
+ strcpy (name, str);
+ for (value = name; *value != '=' && *value != '\0'; ++value)
+ ;
+ if (*value == '\0')
+ {
+ /* Can't happen. */
+ return;
+ }
+ *value = '\0';
+ ++value;
+ if (*value == '\0')
+ value = NULL;
+
+ /* Set the cygwin environment variable. */
+#undef putenv
+ if (value == NULL)
+ unsetenv (name);
+ else
+ putenv(str);
+
+ /* Before changing the environment variable in Windows, if this is
+ PATH, we need to convert the value back to a Windows style path.
+
+ FIXME: The calling program may now it is running under windows,
+ and may have set the path to a Windows path, or, worse, appended
+ or prepended a Windows path to PATH. */
+ if (strcmp (name, "PATH") != 0)
+ {
+ /* If this is Path, eliminate any PATH variable, to prevent any
+ confusion. */
+ if (strcmp (name, "Path") == 0)
+ {
+ SetEnvironmentVariable ("PATH", (char *) NULL);
+ unsetenv ("PATH");
+ }
+
+ SetEnvironmentVariable (name, value);
+ }
+ else
+ {
+ char *buf;
+
+ /* Eliminate any Path variable, to prevent any confusion. */
+ SetEnvironmentVariable ("Path", (char *) NULL);
+ unsetenv ("Path");
+
+ if (value == NULL)
+ buf = NULL;
+ else
+ {
+ int size;
+
+ size = cygwin_posix_to_win32_path_list_buf_size (value);
+ buf = (char *) alloca (size + 1);
+ cygwin_posix_to_win32_path_list (value, buf);
+ }
+
+ SetEnvironmentVariable (name, buf);
+ }
+}
+
+#endif /* __CYGWIN__ */
+/* END CYGNUS LOCAL */
+
diff -bur otcl-8.3.5/generic/tclFileName.c tcl-8.3.5/generic/tclFileName.c
--- otcl-8.3.5/generic/tclFileName.c 2002-10-11 21:50:04.000000000 +1000
+++ tcl-8.3.5/generic/tclFileName.c 2002-10-12 11:57:04.000000000 +1000
@@ -1011,6 +1011,10 @@
* with name after tilde substitution. */
{
register char *p;
+#ifdef __CYGWIN__
+ extern int cygwin_conv_to_win32_path _ANSI_ARGS_((CONST char *, char *));
+ char winbuf[MAX_PATH];
+#endif /* __CYGWIN__ */
/*
* Handle tilde substitutions, if needed.
@@ -1049,6 +1053,17 @@
Tcl_JoinPath(1, (char **) &name, bufferPtr);
}
+#ifdef __CYGWIN__
+ /* In the Cygwin world, call conv_to_win32_path in order to use
+ the mount table to translate the file name into something
+ Windows will understand. Take care when converting empty strings! */
+ if (Tcl_DStringLength(bufferPtr)) {
+ cygwin_conv_to_win32_path(Tcl_DStringValue(bufferPtr), winbuf);
+ Tcl_DStringFree(bufferPtr);
+ Tcl_DStringAppend(bufferPtr, winbuf, -1);
+ }
+#endif /* __CYGWIN__ */
+
/*
* Convert forward slashes to backslashes in Windows paths because
* some system interfaces don't accept forward slashes.
@@ -1908,6 +1923,23 @@
* this is the first absolute element, or a later relative
* element. Add an extra slash if this is a UNC path.
*/
+#ifdef __CYGWIN__
+ {
+
+ extern int cygwin_conv_to_win32_path
+ _ANSI_ARGS_((CONST char *, char *));
+ char winbuf[MAX_PATH];
+
+ /* In the Cygwin world, call conv_to_win32_path in order to use
+ the mount table to translate the file name into something
+ Windows will understand. */
+ cygwin_conv_to_win32_path(Tcl_DStringValue(headPtr), winbuf);
+ Tcl_DStringFree(headPtr);
+ Tcl_DStringAppend(headPtr, winbuf, -1);
+
+ }
+#endif /* __CYGWIN__ */
+
if (*name == ':') {
Tcl_DStringAppend(headPtr, ":", 1);
diff -bur otcl-8.3.5/generic/tclPlatDecls.h tcl-8.3.5/generic/tclPlatDecls.h
--- otcl-8.3.5/generic/tclPlatDecls.h 2002-10-11 21:50:06.000000000 +1000
+++ tcl-8.3.5/generic/tclPlatDecls.h 2002-10-12 11:57:12.000000000 +1000
@@ -17,7 +17,7 @@
* of the core are matching against your project build for these
* public functions. BE AWARE.
*/
-#if defined(__WIN32__) && !defined(_INC_TCHAR)
+#if (defined(__WIN32__) && !defined(__CYGWIN__)) && !defined(_INC_TCHAR)
#include <tchar.h>
#endif
diff -bur otcl-8.3.5/win/configure.in tcl-8.3.5/win/configure.in
--- otcl-8.3.5/win/configure.in 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/configure.in 2002-10-12 11:59:48.000000000 +1000
@@ -61,6 +61,57 @@
AC_CYGWIN
+AC_CACHE_CHECK(for SEH support in compiler,
+ tcl_cv_seh,
+AC_TRY_RUN([
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+int main(int argc, char** argv) {
+ int a, b = 0;
+ __try {
+ a = 666 / b;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) {
+ return 0;
+ }
+ return 1;
+}
+],
+ tcl_cv_seh=yes,
+ tcl_cv_seh=no,
+ tcl_cv_seh=no)
+)
+if test "$tcl_cv_seh" = "no" ; then
+ AC_DEFINE(HAVE_NO_SEH,1,
+ [Defined when mingw does not support SEH])
+fi
+
+#
+# Check to see if the excpt.h include file provided contains the
+# definition for EXCEPTION_DISPOSITION; if not, which is the case
+# with Cygwin's version as of 2002-04-10, define it to be int,
+# sufficient for getting the current code to work.
+#
+AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files,
+ tcl_cv_eh_disposition,
+AC_TRY_COMPILE([
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+],
+[
+ EXCEPTION_DISPOSITION x;
+],
+ tcl_cv_eh_disposition=yes,
+ tcl_cv_eh_disposition=no)
+)
+if test "$tcl_cv_eh_disposition" = "no" ; then
+ AC_DEFINE(EXCEPTION_DISPOSITION, int,
+ [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])
+fi
+
#--------------------------------------------------------------------
# Determines the correct binary file extension (.o, .obj, .exe etc.)
#--------------------------------------------------------------------
@@ -117,19 +168,18 @@
# Perform final evaluations of variables with possible substitutions.
#--------------------------------------------------------------------
-TCL_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}"
-TCL_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
-TCL_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}"
+TCL_SHARED_LIB_SUFFIX="${VER}${DLLSUFFIX}"
+TCL_UNSHARED_LIB_SUFFIX="${VER}${LIBSUFFIX}"
+TCL_EXPORT_FILE_SUFFIX="${VER}${LIBSUFFIX}"
eval "TCL_SRC_DIR=\"`cd $srcdir/..; pwd`\""
eval "TCL_DLL_FILE=tcl${VER}${DLLSUFFIX}"
eval "TCL_LIB_FILE=${LIBPREFIX}tcl$VER${LIBSUFFIX}"
-# FIMXE: These variables decls are missing
-#TCL_LIB_FLAG
-#TCL_BUILD_LIB_SPEC
-#TCL_LIB_SPEC
+eval "TCL_LIB_FLAG=-ltcl${VER}${TCL_DBGX}"
+eval "TCL_BUILD_LIB_SPEC=\"-L`pwd` ${TCL_LIB_FLAG}\""
+eval "TCL_LIB_SPEC=\"-L${exec_prefix}/lib ${TCL_LIB_FLAG}\""
eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${VER}${LIBSUFFIX}\""
eval "TCL_STUB_LIB_FLAG=\"-ltclstub${VER}${TCL_DBGX}\""
@@ -142,6 +192,7 @@
eval "LIBPREFIX=${LIBPREFIX}"
eval "LIBSUFFIX=${LIBSUFFIX}"
eval "EXESUFFIX=${EXESUFFIX}"
+eval "SHLIB_SUFFIX=${DLLSUFFIX}"
CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}
CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}
@@ -166,6 +217,19 @@
fi
fi
+#--------------------------------------------------------------------
+# 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 "$prefix" != "$exec_prefix"; then
+ TCL_PACKAGE_PATH="${exec_prefix}/lib ${prefix}/lib"
+else
+ TCL_PACKAGE_PATH="${prefix}/lib"
+fi
+
AC_SUBST(TCL_VERSION)
AC_SUBST(TCL_MAJOR_VERSION)
AC_SUBST(TCL_MINOR_VERSION)
diff -bur otcl-8.3.5/win/tcl.m4 tcl-8.3.5/win/tcl.m4
--- otcl-8.3.5/win/tcl.m4 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/tcl.m4 2002-10-12 11:59:54.000000000 +1000
@@ -22,8 +22,10 @@
if test -d ../../tcl8.3$1/win; then
TCL_BIN_DIR_DEFAULT=../../tcl8.3$1/win
- else
+ elif test -d ../../tcl8.3/win; then
TCL_BIN_DIR_DEFAULT=../../tcl8.3/win
+ else
+ TCL_BIN_DIR_DEFAULT=../../tcl/win
fi
AC_ARG_WITH(tcl, [ --with-tcl=DIR use Tcl 8.3 binaries from DIR],
@@ -60,8 +62,10 @@
if test -d ../../tk8.3$1/win; then
TK_BIN_DIR_DEFAULT=../../tk8.3$1/win
- else
+ elif test -d ../../tk8.3/win; then
TK_BIN_DIR_DEFAULT=../../tk8.3/win
+ else
+ TK_BIN_DIR_DEFAULT=../../tk/win
fi
AC_ARG_WITH(tk, [ --with-tk=DIR use Tk 8.3 binaries from DIR],
@@ -173,7 +177,7 @@
AC_DEFUN(SC_ENABLE_GCC, [
AC_ARG_ENABLE(gcc, [ --enable-gcc allow use of gcc if available [--disable-gcc]],
- [ok=$enableval], [ok=no])
+ [ok=$enableval], [ok=yes])
if test "$ok" = "yes"; then
# Quick hack to simulate a real cross check
# The right way to do this is to use AC_CHECK_TOOL
@@ -449,12 +453,30 @@
MAKE_EXE="\${CC} -o \[$]@"
LIBPREFIX="lib"
+ #if test "$ac_cv_cygwin" = "yes"; then
+ # extra_cflags="-mno-cygwin"
+ # extra_ldflags="-mno-cygwin"
+ #else
+ # extra_cflags=""
+ # extra_ldflags=""
+ #fi
+
if test "$ac_cv_cygwin" = "yes"; then
- extra_cflags="-mno-cygwin"
- extra_ldflags="-mno-cygwin"
+ touch ac$$.c
+ if ${CC} -c -mwin32 ac$$.c >/dev/null 2>&1; then
+ case "$extra_cflags" in
+ *-mwin32*) ;;
+ *) extra_cflags="-mwin32 $extra_cflags" ;;
+ esac
+ case "$extra_ldflags" in
+ *-mwin32*) ;;
+ *) extra_ldflags="-mwin32 $extra_ldflags" ;;
+ esac
+ fi
+ rm -f ac$$.o ac$$.c
else
- extra_cflags=""
- extra_ldflags=""
+ extra_cflags=''
+ extra_ldflags=''
fi
if test "${SHARED_BUILD}" = "0" ; then
@@ -507,14 +529,19 @@
# Specify linker flags depending on the type of app being
# built -- Console vs. Window.
#
+ # ORIGINAL COMMENT:
# We need to pass -e _WinMain@16 so that ld will use
# WinMain() instead of main() as the entry point. We can't
# use autoconf to check for this case since it would need
# to run an executable and that does not work when
# cross compiling. Remove this -e workaround once we
# require a gcc that does not have this bug.
+ #
+ # MK NOTE: Tk should use a different mechanism. This causes
+ # interesting problems, such as wish dying at startup.
LDFLAGS_CONSOLE="-mconsole ${extra_ldflags}"
- LDFLAGS_WINDOW="-mwindows -e _WinMain@16 ${extra_ldflags}"
+ #LDFLAGS_WINDOW="-mwindows -e _WinMain@16 ${extra_ldflags}"
+ LDFLAGS_WINDOW="-mwindows ${extra_ldflags}"
else
if test "${SHARED_BUILD}" = "0" ; then
# static
@@ -688,7 +715,12 @@
])
if test -f "$ac_cv_path_tclsh" ; then
- TCLSH_PROG=$ac_cv_path_tclsh
+ TCLSH_PROG="$ac_cv_path_tclsh"
+ AC_MSG_RESULT($TCLSH_PROG)
+ elif test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
+ # One-tree build.
+ ac_cv_path_tclsh="$TCL_BIN_DIR/tclsh"
+ TCLSH_PROG="$ac_cv_path_tclsh"
AC_MSG_RESULT($TCLSH_PROG)
else
AC_MSG_ERROR(No tclsh found in PATH: $search_path)
diff -bur otcl-8.3.5/win/tclWin32Dll.c tcl-8.3.5/win/tclWin32Dll.c
--- otcl-8.3.5/win/tclWin32Dll.c 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/tclWin32Dll.c 2002-10-12 12:00:08.000000000 +1000
@@ -37,6 +37,11 @@
static HINSTANCE hInstance; /* HINSTANCE of this DLL. */
static int platformId; /* Running under NT, or 95/98? */
+#ifdef HAVE_NO_SEH
+static void *ESP;
+static void *EBP;
+#endif /* HAVE_NO_SEH */
+
/*
* The following function tables are used to dispatch to either the
* wide-character or multi-byte versions of the operating system calls,
@@ -338,6 +343,8 @@
int
TclpCheckStackSpace()
{
+ int retval = 0;
+
/*
* We can recurse only if there is at least TCL_WIN_STACK_THRESHOLD
* bytes of stack space left. alloca() is cheap on windows; basically
@@ -345,14 +352,56 @@
* exception if the stack pointer is set below the bottom of the stack.
*/
+#ifdef HAVE_NO_SEH
+ __asm__ __volatile__ (
+ "movl %esp, _ESP" "\n\t"
+ "movl %ebp, _EBP");
+
+ __asm__ __volatile__ (
+ "pushl $__except_checkstackspace_handler" "\n\t"
+ "pushl %fs:0" "\n\t"
+ "mov %esp, %fs:0");
+#else
__try {
+#endif /* HAVE_NO_SEH */
alloca(TCL_WIN_STACK_THRESHOLD);
- return 1;
- } __except (1) {}
+ retval = 1;
+#ifdef HAVE_NO_SEH
+ __asm__ __volatile__ (
+ "jmp checkstackspace_pop" "\n"
+ "checkstackspace_reentry:" "\n\t"
+ "movl _ESP, %esp" "\n\t"
+ "movl _EBP, %ebp");
+
+ __asm__ __volatile__ (
+ "checkstackspace_pop:" "\n\t"
+ "mov (%esp), %eax" "\n\t"
+ "mov %eax, %fs:0" "\n\t"
+ "add $8, %esp");
+#else
+ } __except (EXCEPTION_EXECUTE_HANDLER) {}
+#endif /* HAVE_NO_SEH */
- return 0;
+ /*
+ * Avoid using control flow statements in the SEH guarded block!
+ */
+ return retval;
}
-
+#ifdef HAVE_NO_SEH
+static
+__attribute__ ((cdecl))
+EXCEPTION_DISPOSITION
+_except_checkstackspace_handler(
+ struct _EXCEPTION_RECORD *ExceptionRecord,
+ void *EstablisherFrame,
+ struct _CONTEXT *ContextRecord,
+ void *DispatcherContext)
+{
+ __asm__ __volatile__ (
+ "jmp checkstackspace_reentry");
+ return 0; /* Function does not return */
+}
+#endif /* HAVE_NO_SEH */
/*
*----------------------------------------------------------------------
diff -bur otcl-8.3.5/win/tclWinChan.c tcl-8.3.5/win/tclWinChan.c
--- otcl-8.3.5/win/tclWinChan.c 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/tclWinChan.c 2002-10-12 12:00:14.000000000 +1000
@@ -118,6 +118,11 @@
NULL, /* handler proc. */
};
+#ifdef HAVE_NO_SEH
+static void *ESP;
+static void *EBP;
+#endif /* HAVE_NO_SEH */
+
/*
*----------------------------------------------------------------------
@@ -969,8 +974,39 @@
* of this duped handle which might throw EXCEPTION_INVALID_HANDLE.
*/
+#ifdef HAVE_NO_SEH
+ __asm__ __volatile__ (
+ "movl %esp, _ESP" "\n\t"
+ "movl %ebp, _EBP");
+
+ __asm__ __volatile__ (
+ "pushl $__except_makefilechannel_handler" "\n\t"
+ "pushl %fs:0" "\n\t"
+ "mov %esp, %fs:0");
+
+ result = 0;
+#else
__try {
+#endif /* HAVE_NO_SEH */
CloseHandle(dupedHandle);
+#ifdef HAVE_NO_SEH
+ __asm__ __volatile__ (
+ "jmp makefilechannel_pop" "\n"
+ "makefilechannel_reentry:" "\n\t"
+ "movl _ESP, %esp" "\n\t"
+ "movl _EBP, %ebp");
+
+ result = 1; /* True when exception was raised */
+
+ __asm__ __volatile__ (
+ "makefilechannel_pop:" "\n\t"
+ "mov (%esp), %eax" "\n\t"
+ "mov %eax, %fs:0" "\n\t"
+ "add $8, %esp");
+
+ if (result)
+ return NULL;
+#else
}
__except (EXCEPTION_EXECUTE_HANDLER) {
/*
@@ -980,6 +1016,7 @@
return NULL;
}
+#endif /* HAVE_NO_SEH */
/* Fall through, the handle is valid. */
@@ -993,6 +1030,21 @@
return channel;
}
+#ifdef HAVE_NO_SEH
+static
+__attribute__ ((cdecl))
+EXCEPTION_DISPOSITION
+_except_makefilechannel_handler(
+ struct _EXCEPTION_RECORD *ExceptionRecord,
+ void *EstablisherFrame,
+ struct _CONTEXT *ContextRecord,
+ void *DispatcherContext)
+{
+ __asm__ __volatile__ (
+ "jmp makefilechannel_reentry");
+ return 0; /* Function does not return */
+}
+#endif
/*
*----------------------------------------------------------------------
diff -bur otcl-8.3.5/win/tclWinConsole.c tcl-8.3.5/win/tclWinConsole.c
--- otcl-8.3.5/win/tclWinConsole.c 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/tclWinConsole.c 2002-10-12 12:03:54.000000000 +1000
@@ -14,7 +14,9 @@
#include "tclWinInt.h"
+#ifndef __CYGWIN__
#include <dos.h>
+#endif
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
diff -bur otcl-8.3.5/win/tclWinFCmd.c tcl-8.3.5/win/tclWinFCmd.c
--- otcl-8.3.5/win/tclWinFCmd.c 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/tclWinFCmd.c 2002-10-12 12:00:26.000000000 +1000
@@ -73,6 +73,11 @@
{GetWinFileShortName, CannotSetAttribute},
{GetWinFileAttributes, SetWinFileAttributes}};
+#ifdef HAVE_NO_SEH
+static void *ESP;
+static void *EBP;
+#endif /* HAVE_NO_SEH */
+
/*
* Prototype for the TraverseWinTree callback function.
*/
@@ -174,6 +179,7 @@
{
const TCHAR *nativeDst;
DWORD srcAttr, dstAttr;
+ int retval = -1;
nativeDst = (TCHAR *) Tcl_DStringValue(dstPtr);
@@ -182,11 +188,42 @@
* char block device.
*/
+#ifdef HAVE_NO_SEH
+ __asm__ __volatile__ (
+ "movl %esp, _ESP" "\n\t"
+ "movl %ebp, _EBP");
+
+ __asm__ __volatile__ (
+ "pushl $__except_dorenamefile_handler" "\n\t"
+ "pushl %fs:0" "\n\t"
+ "mov %esp, %fs:0");
+#else
__try {
+#endif /* HAVE_NO_SEH */
if ((*tclWinProcs->moveFileProc)(nativeSrc, nativeDst) != FALSE) {
- return TCL_OK;
+ retval = TCL_OK;
}
- } __except (-1) {}
+#ifdef HAVE_NO_SEH
+ __asm__ __volatile__ (
+ "jmp dorenamefile_pop" "\n"
+ "dorenamefile_reentry:" "\n\t"
+ "movl _ESP, %esp" "\n\t"
+ "movl _EBP, %ebp");
+
+ __asm__ __volatile__ (
+ "dorenamefile_pop:" "\n\t"
+ "mov (%esp), %eax" "\n\t"
+ "mov %eax, %fs:0" "\n\t"
+ "add $8, %esp");
+#else
+ } __except (EXCEPTION_EXECUTE_HANDLER) {}
+#endif /* HAVE_NO_SEH */
+
+ /*
+ * Avoid using control flow statements in the SEH guarded block!
+ */
+ if (retval != -1)
+ return retval;
TclWinConvertError(GetLastError());
@@ -402,6 +439,21 @@
}
return TCL_ERROR;
}
+#ifdef HAVE_NO_SEH
+static
+__attribute__ ((cdecl))
+EXCEPTION_DISPOSITION
+_except_dorenamefile_handler(
+ struct _EXCEPTION_RECORD *ExceptionRecord,
+ void *EstablisherFrame,
+ struct _CONTEXT *ContextRecord,
+ void *DispatcherContext)
+{
+ __asm__ __volatile__ (
+ "jmp dorenamefile_reentry");
+ return 0; /* Function does not return */
+}
+#endif /* HAVE_NO_SEH */
/*
*---------------------------------------------------------------------------
@@ -452,6 +504,7 @@
Tcl_DString *dstPtr) /* Pathname of file to copy to (native). */
{
CONST TCHAR *nativeSrc, *nativeDst;
+ int retval = -1;
nativeSrc = (TCHAR *) Tcl_DStringValue(srcPtr);
nativeDst = (TCHAR *) Tcl_DStringValue(dstPtr);
@@ -461,11 +514,42 @@
* block device.
*/
+#ifdef HAVE_NO_SEH
+ __asm__ __volatile__ (
+ "movl %esp, _ESP" "\n\t"
+ "movl %ebp, _EBP");
+
+ __asm__ __volatile__ (
+ "pushl $__except_docopyfile_handler" "\n\t"
+ "pushl %fs:0" "\n\t"
+ "mov %esp, %fs:0");
+#else
__try {
+#endif /* HAVE_NO_SEH */
if ((*tclWinProcs->copyFileProc)(nativeSrc, nativeDst, 0) != FALSE) {
- return TCL_OK;
+ retval = TCL_OK;
}
- } __except (-1) {}
+#ifdef HAVE_NO_SEH
+ __asm__ __volatile__ (
+ "jmp docopyfile_pop" "\n"
+ "docopyfile_reentry:" "\n\t"
+ "movl _ESP, %esp" "\n\t"
+ "movl _EBP, %ebp");
+
+ __asm__ __volatile__ (
+ "docopyfile_pop:" "\n\t"
+ "mov (%esp), %eax" "\n\t"
+ "mov %eax, %fs:0" "\n\t"
+ "add $8, %esp");
+#else
+ } __except (EXCEPTION_EXECUTE_HANDLER) {}
+#endif /* HAVE_NO_SEH */
+
+ /*
+ * Avoid using control flow statements in the SEH guarded block!
+ */
+ if (retval != -1)
+ return retval;
TclWinConvertError(GetLastError());
if (Tcl_GetErrno() == EBADF) {
@@ -503,6 +587,21 @@
}
return TCL_ERROR;
}
+#ifdef HAVE_NO_SEH
+static
+__attribute__ ((cdecl))
+EXCEPTION_DISPOSITION
+_except_docopyfile_handler(
+ struct _EXCEPTION_RECORD *ExceptionRecord,
+ void *EstablisherFrame,
+ struct _CONTEXT *ContextRecord,
+ void *DispatcherContext)
+{
+ __asm__ __volatile__ (
+ "jmp docopyfile_reentry");
+ return 0; /* Function does not return */
+}
+#endif /* HAVE_NO_SEH */
/*
*---------------------------------------------------------------------------
diff -bur otcl-8.3.5/win/tclWinFile.c tcl-8.3.5/win/tclWinFile.c
--- otcl-8.3.5/win/tclWinFile.c 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/tclWinFile.c 2002-10-12 12:00:30.000000000 +1000
@@ -144,7 +144,6 @@
Tcl_DStringAppend(&dirString, ".\\", 2);
} else {
char *p;
-
Tcl_DStringAppend(&dirString, Tcl_DStringValue(dirPtr),
Tcl_DStringLength(dirPtr));
for (p = Tcl_DStringValue(&dirString); *p != '\0'; p++) {
@@ -689,6 +688,51 @@
return 0;
}
+#ifdef __CYGWIN__
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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(path, linkPtr)
+ CONST char *path; /* Path of file to readlink (UTF-8). */
+ Tcl_DString *linkPtr; /* Uninitialized or free DString filled
+ * with contents of link (UTF-8). */
+{
+ char link[MAXPATHLEN];
+ int length;
+ 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);
+}
+#endif /* __CYGWIN__ */
+
/*
*----------------------------------------------------------------------
*
diff -bur otcl-8.3.5/win/tclWinPipe.c tcl-8.3.5/win/tclWinPipe.c
--- otcl-8.3.5/win/tclWinPipe.c 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/tclWinPipe.c 2002-10-12 12:03:30.000000000 +1000
@@ -14,7 +14,9 @@
#include "tclWinInt.h"
+#ifndef __CYGWIN__
#include <dos.h>
+#endif
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
diff -bur otcl-8.3.5/win/tclWinPort.h tcl-8.3.5/win/tclWinPort.h
--- otcl-8.3.5/win/tclWinPort.h 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/tclWinPort.h 2002-10-12 12:00:38.000000000 +1000
@@ -344,6 +344,14 @@
# endif
#endif /* _MSC_VER || __MINGW32__ */
+#ifdef __CYGWIN__
+/* On Cygwin, the environment is imported from the Cygwin DLL. */
+__declspec(dllimport) extern char **__cygwin_environ;
+# define environ __cygwin_environ
+# define putenv TclCygwinPutenv
+# define timezone _timezone
+#endif /* __CYGWIN__ */
+
/*
*---------------------------------------------------------------------------
* The following macros and declarations represent the interface between
@@ -377,12 +385,18 @@
* use by tclAlloc.c.
*/
-#define TclpSysAlloc(size, isBin) ((void*)HeapAlloc(GetProcessHeap(), \
+#ifdef __CYGWIN__
+# define TclpSysAlloc(size, isBin) malloc((size))
+# define TclpSysFree(ptr) free((ptr))
+# define TclpSysRealloc(ptr, size) realloc((ptr), (size))
+#else /* __CYGWIN__ */
+# define TclpSysAlloc(size, isBin) ((void*)HeapAlloc(GetProcessHeap(), \
(DWORD)0, (DWORD)size))
-#define TclpSysFree(ptr) (HeapFree(GetProcessHeap(), \
+# define TclpSysFree(ptr) (HeapFree(GetProcessHeap(), \
(DWORD)0, (HGLOBAL)ptr))
-#define TclpSysRealloc(ptr, size) ((void*)HeapReAlloc(GetProcessHeap(), \
+# define TclpSysRealloc(ptr, size) ((void*)HeapReAlloc(GetProcessHeap(), \
(DWORD)0, (LPVOID)ptr, (DWORD)size))
+#endif /* __CYGWIN__ */
/*
* The following defines map from standard socket names to our internal
diff -bur otcl-8.3.5/win/tclWinSerial.c tcl-8.3.5/win/tclWinSerial.c
--- otcl-8.3.5/win/tclWinSerial.c 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/tclWinSerial.c 2002-10-12 12:03:06.000000000 +1000
@@ -15,7 +15,9 @@
#include "tclWinInt.h"
+#ifndef __CYGWIN__
#include <dos.h>
+#endif
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
diff -bur otcl-8.3.5/win/tclWinThrd.c tcl-8.3.5/win/tclWinThrd.c
--- otcl-8.3.5/win/tclWinThrd.c 2002-10-11 21:50:18.000000000 +1000
+++ tcl-8.3.5/win/tclWinThrd.c 2002-10-12 12:02:40.000000000 +1000
@@ -14,7 +14,9 @@
#include "tclWinInt.h"
+#ifndef __CYGWIN__
#include <dos.h>
+#endif
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
@@ -125,8 +127,14 @@
{
HANDLE tHandle;
+#ifdef __CYGWIN__
+ tHandle = CreateThread(NULL, (DWORD) stackSize,
+ (LPTHREAD_START_ROUTINE) proc, (LPVOID) clientData,
+ (DWORD) 0, (LPWORD) idPtr);
+#else
tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize, proc,
clientData, 0, (unsigned *)idPtr);
+#endif /* __CYGWIN__ */
if (tHandle == NULL) {
return TCL_ERROR;
@@ -160,7 +168,11 @@
TclpThreadExit(status)
int status;
{
+#ifdef __CYGWIN__
+ ExitThread ((DWORD) status);
+#else
_endthreadex((DWORD)status);
+#endif /* __CYGWIN__ */
}