2010-08-28  Kai Tietz  <kai.tietz@onevision.com>

        * crt/crtexe.c: Prepare x64 SEH support.
        * crt/crt_handler.c: Correct some stuff and moved
        default handler from crtexe.c here.



git-svn-id: svn+ssh://svn.code.sf.net/p/mingw-w64/code/trunk@3444 4407c894-4637-0410-b4f5-ada5f102cad1
diff --git a/mingw-w64-crt/ChangeLog b/mingw-w64-crt/ChangeLog
index 5a6eb97..536e2a1 100644
--- a/mingw-w64-crt/ChangeLog
+++ b/mingw-w64-crt/ChangeLog
@@ -1,3 +1,9 @@
+2010-08-28  Kai Tietz  <kai.tietz@onevision.com>
+
+	* crt/crtexe.c: Prepare x64 SEH support.
+	* crt/crt_handler.c: Correct some stuff and moved
+	default handler from crtexe.c here.
+
 2010-08-13  Jonathan Yong  <jon_y@sourceforge.net>
 
 	* lib32/secur32.def: Update from Win7.
diff --git a/mingw-w64-crt/crt/cinitexe.c b/mingw-w64-crt/crt/cinitexe.c
index b69eebe..58e52ab 100644
--- a/mingw-w64-crt/crt/cinitexe.c
+++ b/mingw-w64-crt/crt/cinitexe.c
@@ -1,7 +1,8 @@
 #include <stdio.h>
-#include <internal.h>
 #include <sect_attribs.h>
 
+typedef void (__cdecl *_PVFV)(void);
+
 _CRTALLOC(".CRT$XIA") _PVFV __xi_a[] = { NULL };
 _CRTALLOC(".CRT$XIZ") _PVFV __xi_z[] = { NULL };
 _CRTALLOC(".CRT$XCA") _PVFV __xc_a[] = { NULL };
diff --git a/mingw-w64-crt/crt/crt_handler.c b/mingw-w64-crt/crt/crt_handler.c
index 8e47df0..7f75eac 100644
--- a/mingw-w64-crt/crt/crt_handler.c
+++ b/mingw-w64-crt/crt/crt_handler.c
@@ -93,7 +93,7 @@
 			   struct _CONTEXT* ContextRecord __attribute__ ((unused)),
 			   void *DispatcherContext __attribute__ ((unused)))
 {
-  EXCEPTION_DISPOSITION action = EXCEPTION_CONTINUE_SEARCH;
+  EXCEPTION_DISPOSITION action = ExceptionContinueSearch; /* EXCEPTION_CONTINUE_SEARCH; */
   void (*old_handler) (int);
   int reset_fpu = 0;
 
@@ -107,6 +107,101 @@
 	  /* this is undefined if the signal was raised by anything other
 	     than raise ().  */
 	  signal (SIGSEGV, SIG_IGN);
+	  action = 0; //EXCEPTION_CONTINUE_EXECUTION;
+	}
+      else if (old_handler != SIG_DFL)
+	{
+	  /* This means 'old' is a user defined function. Call it */
+	  (*old_handler) (SIGSEGV);
+	  action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+	}
+      else
+        action = 4; /* EXCEPTION_EXECUTE_HANDLER; */
+      break;
+    case EXCEPTION_ILLEGAL_INSTRUCTION:
+    case EXCEPTION_PRIV_INSTRUCTION:
+      /* test if the user has set SIGILL */
+      old_handler = signal (SIGILL, SIG_DFL);
+      if (old_handler == SIG_IGN)
+	{
+	  /* this is undefined if the signal was raised by anything other
+	     than raise ().  */
+	  signal (SIGILL, SIG_IGN);
+	  action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+	}
+      else if (old_handler != SIG_DFL)
+	{
+	  /* This means 'old' is a user defined function. Call it */
+	  (*old_handler) (SIGILL);
+	  action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+	}
+      else
+        action = 4; /* EXCEPTION_EXECUTE_HANDLER;*/
+      break;
+    case EXCEPTION_FLT_INVALID_OPERATION:
+    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+    case EXCEPTION_FLT_DENORMAL_OPERAND:
+    case EXCEPTION_FLT_OVERFLOW:
+    case EXCEPTION_FLT_UNDERFLOW:
+    case EXCEPTION_FLT_INEXACT_RESULT:
+      reset_fpu = 1;
+      /* fall through. */
+
+    case EXCEPTION_INT_DIVIDE_BY_ZERO:
+      /* test if the user has set SIGFPE */
+      old_handler = signal (SIGFPE, SIG_DFL);
+      if (old_handler == SIG_IGN)
+	{
+	  signal (SIGFPE, SIG_IGN);
+	  if (reset_fpu)
+	    _fpreset ();
+	  action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+	}
+      else if (old_handler != SIG_DFL)
+	{
+	  /* This means 'old' is a user defined function. Call it */
+	  (*old_handler) (SIGFPE);
+	  action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+	}
+      break;
+    case EXCEPTION_DATATYPE_MISALIGNMENT:
+    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+    case EXCEPTION_FLT_STACK_CHECK:
+    case EXCEPTION_INT_OVERFLOW:
+    case EXCEPTION_INVALID_HANDLE:
+    /*case EXCEPTION_POSSIBLE_DEADLOCK: */
+      action = 0; // EXCEPTION_CONTINUE_EXECUTION;
+      break;
+    default:
+      break;
+    }
+  return action;
+}
+
+#endif
+
+LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler = NULL;
+
+long CALLBACK
+_gnu_exception_handler (EXCEPTION_POINTERS *exception_data);
+
+long CALLBACK
+_gnu_exception_handler (EXCEPTION_POINTERS *exception_data)
+{
+  void (*old_handler) (int);
+  long action = EXCEPTION_CONTINUE_SEARCH;
+  int reset_fpu = 0;
+
+  switch (exception_data->ExceptionRecord->ExceptionCode)
+    {
+    case EXCEPTION_ACCESS_VIOLATION:
+      /* test if the user has set SIGSEGV */
+      old_handler = signal (SIGSEGV, SIG_DFL);
+      if (old_handler == SIG_IGN)
+	{
+	  /* this is undefined if the signal was raised by anything other
+	     than raise ().  */
+	  signal (SIGSEGV, SIG_IGN);
 	  action = EXCEPTION_CONTINUE_EXECUTION;
 	}
       else if (old_handler != SIG_DFL)
@@ -115,9 +210,8 @@
 	  (*old_handler) (SIGSEGV);
 	  action = EXCEPTION_CONTINUE_EXECUTION;
 	}
-      else
-        action = EXCEPTION_EXECUTE_HANDLER;
       break;
+
     case EXCEPTION_ILLEGAL_INSTRUCTION:
     case EXCEPTION_PRIV_INSTRUCTION:
       /* test if the user has set SIGILL */
@@ -135,9 +229,8 @@
 	  (*old_handler) (SIGILL);
 	  action = EXCEPTION_CONTINUE_EXECUTION;
 	}
-      else
-        action = EXCEPTION_EXECUTE_HANDLER;
       break;
+
     case EXCEPTION_FLT_INVALID_OPERATION:
     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
     case EXCEPTION_FLT_DENORMAL_OPERAND:
@@ -164,6 +257,7 @@
 	  action = EXCEPTION_CONTINUE_EXECUTION;
 	}
       break;
+#ifdef _WIN64
     case EXCEPTION_DATATYPE_MISALIGNMENT:
     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
     case EXCEPTION_FLT_STACK_CHECK:
@@ -172,10 +266,12 @@
     /*case EXCEPTION_POSSIBLE_DEADLOCK: */
       action = EXCEPTION_CONTINUE_EXECUTION;
       break;
+#endif
     default:
       break;
     }
+
+  if (action == EXCEPTION_CONTINUE_SEARCH && __mingw_oldexcpt_handler)
+    action = (*__mingw_oldexcpt_handler)(exception_data);
   return action;
 }
-
-#endif
diff --git a/mingw-w64-crt/crt/crtexe.c b/mingw-w64-crt/crt/crtexe.c
index 802990c..34e71ab 100644
--- a/mingw-w64-crt/crt/crtexe.c
+++ b/mingw-w64-crt/crt/crtexe.c
@@ -85,10 +85,10 @@
 static int managedapp;
 static int has_cctor = 0;
 static _startupinfo startinfo;
-static LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler = NULL;
+extern LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler;
 
 extern void _pei386_runtime_relocator (void);
-static long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
+long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
 #ifdef WPRFLAG
 static void duplicate_ppstrings (int ac, wchar_t ***av);
 #else
@@ -150,9 +150,20 @@
 
 int WinMainCRTStartup (void)
 {
+  int ret = 255;
+#ifdef __SEH__
+  asm ("\t.l_startw:\n"
+    "\t.seh_handler __C_specific_handler, @except\n"
+    "\t.seh_scope .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n"
+    );
+#endif
   mingw_app_type = 1;
   __security_init_cookie ();
-  return __tmainCRTStartup ();
+  ret = __tmainCRTStartup ();
+#ifdef __SEH__
+  asm ("\t.l_endw: nop\n");
+#endif
+  return ret;
 }
 
 int mainCRTStartup (void);
@@ -163,9 +174,20 @@
 
 int mainCRTStartup (void)
 {
+  int ret = 255;
+#ifdef __SEH__
+  asm ("\t.l_start:\n"
+    "\t.seh_handler __C_specific_handler, @except\n"
+    "\t.seh_scope .l_start, .l_end, _gnu_exception_handler, .l_end\n"
+    );
+#endif
   mingw_app_type = 0;
   __security_init_cookie ();
-  return __tmainCRTStartup ();
+  ret = __tmainCRTStartup ();
+#ifdef __SEH__
+  asm ("\t.l_end: nop\n");
+#endif
+  return ret;
 }
 
 static
@@ -317,97 +339,6 @@
   return 0;
 }
 
-static long CALLBACK
-_gnu_exception_handler (EXCEPTION_POINTERS *exception_data)
-{
-  void (*old_handler) (int);
-  long action = EXCEPTION_CONTINUE_SEARCH;
-  int reset_fpu = 0;
-
-  switch (exception_data->ExceptionRecord->ExceptionCode)
-    {
-    case EXCEPTION_ACCESS_VIOLATION:
-      /* test if the user has set SIGSEGV */
-      old_handler = signal (SIGSEGV, SIG_DFL);
-      if (old_handler == SIG_IGN)
-	{
-	  /* this is undefined if the signal was raised by anything other
-	     than raise ().  */
-	  signal (SIGSEGV, SIG_IGN);
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
-      else if (old_handler != SIG_DFL)
-	{
-	  /* This means 'old' is a user defined function. Call it */
-	  (*old_handler) (SIGSEGV);
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
-      break;
-
-    case EXCEPTION_ILLEGAL_INSTRUCTION:
-    case EXCEPTION_PRIV_INSTRUCTION:
-      /* test if the user has set SIGILL */
-      old_handler = signal (SIGILL, SIG_DFL);
-      if (old_handler == SIG_IGN)
-	{
-	  /* this is undefined if the signal was raised by anything other
-	     than raise ().  */
-	  signal (SIGILL, SIG_IGN);
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
-      else if (old_handler != SIG_DFL)
-	{
-	  /* This means 'old' is a user defined function. Call it */
-	  (*old_handler) (SIGILL);
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
-      break;
-
-    case EXCEPTION_FLT_INVALID_OPERATION:
-    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
-    case EXCEPTION_FLT_DENORMAL_OPERAND:
-    case EXCEPTION_FLT_OVERFLOW:
-    case EXCEPTION_FLT_UNDERFLOW:
-    case EXCEPTION_FLT_INEXACT_RESULT:
-      reset_fpu = 1;
-      /* fall through. */
-
-    case EXCEPTION_INT_DIVIDE_BY_ZERO:
-      /* test if the user has set SIGFPE */
-      old_handler = signal (SIGFPE, SIG_DFL);
-      if (old_handler == SIG_IGN)
-	{
-	  signal (SIGFPE, SIG_IGN);
-	  if (reset_fpu)
-	    _fpreset ();
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
-      else if (old_handler != SIG_DFL)
-	{
-	  /* This means 'old' is a user defined function. Call it */
-	  (*old_handler) (SIGFPE);
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
-      break;
-#ifdef _WIN64
-    case EXCEPTION_DATATYPE_MISALIGNMENT:
-    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
-    case EXCEPTION_FLT_STACK_CHECK:
-    case EXCEPTION_INT_OVERFLOW:
-    case EXCEPTION_INVALID_HANDLE:
-    /*case EXCEPTION_POSSIBLE_DEADLOCK: */
-      action = EXCEPTION_CONTINUE_EXECUTION;
-      break;
-#endif
-    default:
-      break;
-    }
-
-  if (action == EXCEPTION_CONTINUE_SEARCH && __mingw_oldexcpt_handler)
-    action = (*__mingw_oldexcpt_handler)(exception_data);
-  return action;
-}
-
 #ifdef WPRFLAG
 static size_t wbytelen(const wchar_t *p)
 {