Revert "rts: add Emacs 'Local Variables' to every .c file"
[ghc.git] / rts / win32 / seh_excn.h
1 #ifndef WIN32_SEH_EXCN_H
2 #define WIN32_SEH_EXCN_H
3
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 #if defined(__MINGW32__)
8 /* Stuff needed to install and use SEH exception handlers */
9 #include <excpt.h>
10 #include <setjmp.h>
11 #include <windows.h>
12 #elif defined(_MSC_VER)
13 #include <windows.h>
14 #else
15 #include <signal.h>
16 #endif
17
18 /* Exception handling.
19 *
20 * On Win32, the default action for things like division by zero and
21 * segfaults is to pop up an annoying little dialog box.
22 *
23 * This is a pain when we are SSHed into a Windows machine, or when we
24 * want to debug a problem with gdb.
25 *
26 * seh_excn provides two macros, BEGIN_CATCH and END_CATCH, which
27 * will catch such exceptions in the code they bracket and die by
28 * printing a message and calling stg_exit(1).
29 */
30 #define ON_DIV_ZERO fprintf(stdout,"divide by zero\n"); fflush(stdout);stg_exit(1)
31 #define ON_STACK_OVERFLOW fprintf(stdout,"C stack overflow in generated code\n"); fflush(stdout); stg_exit(1)
32 #define ON_SIGSEGV fprintf(stdout,"Segmentation fault/access violation in generated code\n"); fflush(stdout); stg_exit(1)
33
34 #if defined(__MINGW32__)
35 extern jmp_buf seh_unwind_to;
36 extern unsigned long seh_excn_code;
37 /*
38 * install an exception handler 'exHandler' which longjmp()s (via 'jumpBuf')
39 * to the code 'onExnCaught' when successfully catching an exception.
40 *
41 * Macro based on Andrew Begel's SEH support code posted to the mingw-users
42 * mailing list.
43 */
44 #define TRY_BEGIN(jumpBuf, exHandler, onExcnCaught) \
45 do { \
46 int signal; \
47 if ((signal = setjmp(jumpBuf)) != 0) { \
48 onExcnCaught; \
49 } else { \
50 __try1(exHandler); \
51 } \
52 } while (0);
53
54 #define TRY_END() __except1
55
56 extern
57 EXCEPTION_DISPOSITION
58 catchDivZero(struct _EXCEPTION_RECORD*,
59 void*,
60 struct _CONTEXT*,
61 void*);
62
63 #define ON_EXCN \
64 if (seh_excn_code == 1) { \
65 ON_STACK_OVERFLOW; \
66 } else if ( seh_excn_code == 2 ) { \
67 ON_SIGSEGV; \
68 } else { \
69 ON_DIV_ZERO; \
70 }
71
72 #define BEGIN_CATCH TRY_BEGIN(seh_unwind_to, catchDivZero, ON_EXCN)
73 #define END_CATCH TRY_END()
74 #elif defined(_MSC_VER)
75 #define BEGIN_CATCH __try {
76 #define END_CATCH } __except ( ( ((GetExceptionCode() == EXCEPTION_FLT_DIVIDE_BY_ZERO) || (GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO) || (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW) || (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) ) { \
77 switch ( (GetExceptionCode()) ) { \
78 case EXCEPTION_FLT_DIVIDE_BY_ZERO: \
79 case EXCEPTION_INT_DIVIDE_BY_ZERO:
80 ON_DIV_ZERO; break; \
81 case EXCEPTION_STACK_OVERFLOW: \
82 ON_STACK_OVERFLOW; break; \
83 case EXCEPTION_ACCESS_VIOLATION: \
84 ON_SIGSEGV; break; \
85 } \
86 }
87 #else
88 #error Cannot determine what sort of Windows system this is
89 #endif
90
91 #endif /* WIN32_SEH_EXCN_H */
92