diff options
| author | mdejong <mdejong> | 2002-03-15 01:10:18 (GMT) | 
|---|---|---|
| committer | mdejong <mdejong> | 2002-03-15 01:10:18 (GMT) | 
| commit | 3f80f55af60f673f0519c60ac2bc8acc2c32249f (patch) | |
| tree | 69d06455b401989ef8a5ae460127b03d813d591d | |
| parent | 2d3979a4eb99440149236e31d8a4da2c05f1725c (diff) | |
| download | tcl-3f80f55af60f673f0519c60ac2bc8acc2c32249f.zip tcl-3f80f55af60f673f0519c60ac2bc8acc2c32249f.tar.gz tcl-3f80f55af60f673f0519c60ac2bc8acc2c32249f.tar.bz2 | |
	* 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]
| -rw-r--r-- | ChangeLog | 15 | ||||
| -rwxr-xr-x | win/configure | 100 | ||||
| -rw-r--r-- | win/configure.in | 30 | ||||
| -rw-r--r-- | win/tclWin32Dll.c | 48 | ||||
| -rw-r--r-- | win/tclWinChan.c | 54 | ||||
| -rw-r--r-- | win/tclWinFCmd.c | 89 | 
6 files changed, 306 insertions, 30 deletions
| @@ -1,5 +1,20 @@  2002-03-14  Mo DeJong  <mdejong@users.sourceforge.net> +	* 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] + +2002-03-14  Mo DeJong  <mdejong@users.sourceforge.net> +  	* win/tclWinFCmd.c (DoRenameFile, DoCopyFile): Handle  	an SEH exception with EXCEPTION_EXECUTE_HANDLER instead  	of restarting the faulting instruction with diff --git a/win/configure b/win/configure index 35b178c..9dc3215 100755 --- a/win/configure +++ b/win/configure @@ -533,7 +533,7 @@ fi  TCL_VERSION=8.4  TCL_MAJOR_VERSION=8  TCL_MINOR_VERSION=4 -TCL_PATCH_LEVEL="a4" +TCL_PATCH_LEVEL="a5"  VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION  TCL_DDE_VERSION=1.2 @@ -966,18 +966,70 @@ if test "$ac_cv_cygwin" = "yes" ; then      Use the Mingw version of gcc from www.mingw.org instead." 1>&2; exit 1; }  fi + +echo $ac_n "checking for SEH support in compiler""... $ac_c" 1>&6 +echo "configure:972: checking for SEH support in compiler" >&5 +if eval "test \"`echo '$''{'tcl_cv_seh'+set}'`\" = set"; then +  echo $ac_n "(cached) $ac_c" 1>&6 +else +  if test "$cross_compiling" = yes; then +  tcl_cv_seh=no +else +  cat > conftest.$ac_ext <<EOF +#line 980 "configure" +#include "confdefs.h" + +#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; +} + +EOF +if { (eval echo configure:999: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then +  tcl_cv_seh=yes +else +  echo "configure: failed program was:" >&5 +  cat conftest.$ac_ext >&5 +  rm -fr conftest* +  tcl_cv_seh=no +fi +rm -fr conftest* +fi + + +fi + +echo "$ac_t""$tcl_cv_seh" 1>&6 +if test "$tcl_cv_seh" = "no" ; then +    cat >> confdefs.h <<\EOF +#define HAVE_NO_SEH  +EOF + +fi +  #--------------------------------------------------------------------  # Determines the correct binary file extension (.o, .obj, .exe etc.)  #--------------------------------------------------------------------  echo $ac_n "checking for object suffix""... $ac_c" 1>&6 -echo "configure:975: checking for object suffix" >&5 +echo "configure:1027: checking for object suffix" >&5  if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then    echo $ac_n "(cached) $ac_c" 1>&6  else    rm -f conftest*  echo 'int i = 1;' > conftest.$ac_ext -if { (eval echo configure:981: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1033: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then    for ac_file in conftest.*; do      case $ac_file in      *.c) ;; @@ -995,19 +1047,19 @@ OBJEXT=$ac_cv_objext  ac_objext=$ac_cv_objext  echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 -echo "configure:999: checking for mingw32 environment" >&5 +echo "configure:1051: checking for mingw32 environment" >&5  if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then    echo $ac_n "(cached) $ac_c" 1>&6  else    cat > conftest.$ac_ext <<EOF -#line 1004 "configure" +#line 1056 "configure"  #include "confdefs.h"  int main() {  return __MINGW32__;  ; return 0; }  EOF -if { (eval echo configure:1011: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1063: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then    rm -rf conftest*    ac_cv_mingw32=yes  else @@ -1026,7 +1078,7 @@ test "$ac_cv_mingw32" = yes && MINGW32=yes  echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 -echo "configure:1030: checking for executable suffix" >&5 +echo "configure:1082: checking for executable suffix" >&5  if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then    echo $ac_n "(cached) $ac_c" 1>&6  else @@ -1036,7 +1088,7 @@ else    rm -f conftest*    echo 'int main () { return 0; }' > conftest.$ac_ext    ac_cv_exeext= -  if { (eval echo configure:1040: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then +  if { (eval echo configure:1092: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then      for file in conftest.*; do        case $file in        *.c | *.o | *.obj) ;; @@ -1063,7 +1115,7 @@ ac_exeext=$EXEEXT      echo $ac_n "checking for building with threads""... $ac_c" 1>&6 -echo "configure:1067: checking for building with threads" >&5 +echo "configure:1119: checking for building with threads" >&5      # Check whether --enable-threads or --disable-threads was given.  if test "${enable_threads+set}" = set; then    enableval="$enable_threads" @@ -1094,7 +1146,7 @@ EOF      echo $ac_n "checking how to build libraries""... $ac_c" 1>&6 -echo "configure:1098: checking how to build libraries" >&5 +echo "configure:1150: checking how to build libraries" >&5      # Check whether --enable-shared or --disable-shared was given.  if test "${enable_shared+set}" = set; then    enableval="$enable_shared" @@ -1135,7 +1187,7 @@ EOF      # Step 0: Enable 64 bit support?      echo $ac_n "checking if 64bit support is requested""... $ac_c" 1>&6 -echo "configure:1139: checking if 64bit support is requested" >&5 +echo "configure:1191: checking if 64bit support is requested" >&5      # Check whether --enable-64bit or --disable-64bit was given.  if test "${enable_64bit+set}" = set; then    enableval="$enable_64bit" @@ -1152,7 +1204,7 @@ fi      # Extract the first word of "cygpath", so it can be a program name with args.  set dummy cygpath; ac_word=$2  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1156: checking for $ac_word" >&5 +echo "configure:1208: checking for $ac_word" >&5  if eval "test \"`echo '$''{'ac_cv_prog_CYGPATH'+set}'`\" = set"; then    echo $ac_n "(cached) $ac_c" 1>&6  else @@ -1189,7 +1241,7 @@ fi      # set various compiler flags depending on whether we are using gcc or cl      echo $ac_n "checking compiler flags""... $ac_c" 1>&6 -echo "configure:1193: checking compiler flags" >&5 +echo "configure:1245: checking compiler flags" >&5      if test "${GCC}" = "yes" ; then  	if test "$do64bit" = "yes" ; then  	    echo "configure: warning: "64bit mode not supported with GCC on Windows"" 1>&2 @@ -1379,7 +1431,7 @@ echo "configure:1193: checking compiler flags" >&5      echo $ac_n "checking for build with symbols""... $ac_c" 1>&6 -echo "configure:1383: checking for build with symbols" >&5 +echo "configure:1435: checking for build with symbols" >&5      # Check whether --enable-symbols or --disable-symbols was given.  if test "${enable_symbols+set}" = set; then    enableval="$enable_symbols" @@ -1409,7 +1461,7 @@ TCL_DBGX=${DBGX}  #--------------------------------------------------------------------  echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1413: checking how to run the C preprocessor" >&5 +echo "configure:1465: checking how to run the C preprocessor" >&5  # On Suns, sometimes $CPP names a directory.  if test -n "$CPP" && test -d "$CPP"; then    CPP= @@ -1424,13 +1476,13 @@ else    # On the NeXT, cc -E runs the code through the compiler's parser,    # not just through cpp.    cat > conftest.$ac_ext <<EOF -#line 1428 "configure" +#line 1480 "configure"  #include "confdefs.h"  #include <assert.h>  Syntax Error  EOF  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1434: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1486: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`  if test -z "$ac_err"; then    : @@ -1441,13 +1493,13 @@ else    rm -rf conftest*    CPP="${CC-cc} -E -traditional-cpp"    cat > conftest.$ac_ext <<EOF -#line 1445 "configure" +#line 1497 "configure"  #include "confdefs.h"  #include <assert.h>  Syntax Error  EOF  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1451: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1503: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`  if test -z "$ac_err"; then    : @@ -1458,13 +1510,13 @@ else    rm -rf conftest*    CPP="${CC-cc} -nologo -E"    cat > conftest.$ac_ext <<EOF -#line 1462 "configure" +#line 1514 "configure"  #include "confdefs.h"  #include <assert.h>  Syntax Error  EOF  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1468: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1520: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`  if test -z "$ac_err"; then    : @@ -1490,17 +1542,17 @@ echo "$ac_t""$CPP" 1>&6  ac_safe=`echo "errno.h" | sed 'y%./+-%__p_%'`  echo $ac_n "checking for errno.h""... $ac_c" 1>&6 -echo "configure:1494: checking for errno.h" >&5 +echo "configure:1546: checking for errno.h" >&5  if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then    echo $ac_n "(cached) $ac_c" 1>&6  else    cat > conftest.$ac_ext <<EOF -#line 1499 "configure" +#line 1551 "configure"  #include "confdefs.h"  #include <errno.h>  EOF  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1504: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1556: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`  if test -z "$ac_err"; then    rm -rf conftest* diff --git a/win/configure.in b/win/configure.in index de84e19..067a790 100644 --- a/win/configure.in +++ b/win/configure.in @@ -3,7 +3,7 @@  # generate the file "configure", which is run during Tcl installation  # to configure the system for the local environment.  # -# RCS: @(#) $Id: configure.in,v 1.47 2002/03/06 15:20:23 dkf Exp $ +# RCS: @(#) $Id: configure.in,v 1.48 2002/03/15 01:10:19 mdejong Exp $  AC_INIT(../generic/tcl.h) @@ -83,6 +83,34 @@ if test "$ac_cv_cygwin" = "yes" ; then      Use the Mingw version of gcc from www.mingw.org instead.])  fi + +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,, +            [Defined when mingw does not support SEH]) +fi +  #--------------------------------------------------------------------  # Determines the correct binary file extension (.o, .obj, .exe etc.)  #-------------------------------------------------------------------- diff --git a/win/tclWin32Dll.c b/win/tclWin32Dll.c index dde720e..c17285e 100644 --- a/win/tclWin32Dll.c +++ b/win/tclWin32Dll.c @@ -9,7 +9,7 @@   * See the file "license.terms" for information on usage and redistribution   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * - * RCS: @(#) $Id: tclWin32Dll.c,v 1.14 2002/03/08 01:45:52 mdejong Exp $ + * RCS: @(#) $Id: tclWin32Dll.c,v 1.15 2002/03/15 01:10:19 mdejong Exp $   */  #include "tclWinInt.h" @@ -37,6 +37,11 @@ typedef VOID (WINAPI UTUNREGISTER)(HANDLE hModule);  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, @@ -349,17 +354,56 @@ TclpCheckStackSpace()       * 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);  	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 */      /*       * 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 --git a/win/tclWinChan.c b/win/tclWinChan.c index 52084a6..d850b62 100644 --- a/win/tclWinChan.c +++ b/win/tclWinChan.c @@ -9,7 +9,7 @@   * See the file "license.terms" for information on usage and redistribution   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * - * RCS: @(#) $Id: tclWinChan.c,v 1.20 2002/02/15 14:28:51 dkf Exp $ + * RCS: @(#) $Id: tclWinChan.c,v 1.21 2002/03/15 01:10:19 mdejong Exp $   */  #include "tclWinInt.h" @@ -118,6 +118,11 @@ static Tcl_ChannelType fileChannelType = {      NULL,			/* handler proc. */  }; +#ifdef HAVE_NO_SEH +static void *ESP; +static void *EBP; +#endif /* HAVE_NO_SEH */ +  /*   *---------------------------------------------------------------------- @@ -983,8 +988,39 @@ Tcl_MakeFileChannel(rawHandle, mode)  	 * 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) {  	    /* @@ -994,6 +1030,7 @@ Tcl_MakeFileChannel(rawHandle, mode)  	    return NULL;  	} +#endif /* HAVE_NO_SEH */  	/* Fall through, the handle is valid. */ @@ -1007,6 +1044,21 @@ Tcl_MakeFileChannel(rawHandle, mode)      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 --git a/win/tclWinFCmd.c b/win/tclWinFCmd.c index b3104f1..1843e8d 100644 --- a/win/tclWinFCmd.c +++ b/win/tclWinFCmd.c @@ -9,7 +9,7 @@   * See the file "license.terms" for information on usage and redistribution   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * - * RCS: @(#) $Id: tclWinFCmd.c,v 1.26 2002/03/14 20:51:44 mdejong Exp $ + * RCS: @(#) $Id: tclWinFCmd.c,v 1.27 2002/03/15 01:10:19 mdejong Exp $   */  #include "tclWinInt.h" @@ -73,6 +73,11 @@ CONST TclFileAttrProcs tclpFileAttrProcs[] = {  	{GetWinFileShortName, CannotSetAttribute},  	{GetWinFileAttributes, SetWinFileAttributes}}; +#ifdef HAVE_NO_SEH +static void *ESP; +static void *EBP; +#endif /* HAVE_NO_SEH */ +  /*   * Prototype for the TraverseWinTree callback function.   */ @@ -182,11 +187,36 @@ DoRenameFile(       * if one of the arguments is a 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) {  	    retval = TCL_OK;  	} +#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! @@ -408,6 +438,21 @@ DoRenameFile(      }      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 */  /*   *--------------------------------------------------------------------------- @@ -467,12 +512,37 @@ DoCopyFile(       * The CopyFile API would throw an exception under NT if one       * of the arguments is a char 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) {  	    retval = TCL_OK;  	} +#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! @@ -516,6 +586,21 @@ DoCopyFile(      }      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 */  /*   *--------------------------------------------------------------------------- | 
