source: trunk/include/excpt.h@ 21448

Last change on this file since 21448 was 21448, checked in by dmik, 15 years ago

excpt.h: Added support for try/finally/leave SEH statements.

File size: 8.2 KB
Line 
1/*
2 * Project Odin Software License can be found in LICENSE.TXT
3 *
4 * Compiler-level Win32 SEH support for OS/2
5 *
6 * Copyright 2010 Dmitry A. Kuminov
7 */
8
9/*
10 * NOTE: This __try/__except and __try/__finally/__leave implementation is not
11 * backed up by the low level compiler support and therefore the following
12 * limitations exist comparing to the MSVC implementation (breaking them will
13 * crash the application):
14 *
15 * 1. You cannot use return, goto and longjmp statements within __try or
16 * __except or __finally blocks.
17 *
18 * 2. If you use __try and friends inside a do/while/for/switch block, you will
19 * lose the meaning of break and continue statements and must not use them.
20 *
21 * 3. The scopes of C and C++ exception blocks may not overlap (i.e. you cannot
22 * use try/catch inside __try/__except and vice versa).
23 *
24 * 4. There may be some other (yet unknown) limitations.
25 *
26 * Fortunately, in most cases, these limitations may be worked around by
27 * slightly changing the original source code.
28 */
29
30#ifndef __EXCPT_H__
31#define __EXCPT_H__
32
33#include <windows.h>
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39#if defined(__GNUC__)
40
41struct ___seh_PEXCEPTION_FRAME;
42typedef int (*__seh_PEXCEPTION_HANDLER)(PEXCEPTION_RECORD,
43 struct ___seh_PEXCEPTION_FRAME *,
44 PCONTEXT, PVOID);
45
46typedef struct ___seh_PEXCEPTION_FRAME
47{
48 struct ___seh_PEXCEPTION_FRAME *pPrev;
49 __seh_PEXCEPTION_HANDLER pHandler;
50 void *pFilterCallback;
51 void *pHandlerCallback;
52 void *pHandlerContext;
53 int filterResult;
54 DWORD pTryRegs[6]; /* EBX/ESI/EDI/EBP/ESP/ExceptionHandler */
55 EXCEPTION_POINTERS Pointers;
56 int state;
57}
58__seh_PEXCEPTION_FRAME;
59
60int __seh_handler(PEXCEPTION_RECORD pRec,
61 struct ___seh_PEXCEPTION_FRAME *pFrame,
62 PCONTEXT pContext, PVOID pVoid);
63
64#define _exception_code() (__seh_frame.Pointers.ExceptionRecord->ExceptionCode)
65#define _exception_info() (&__seh_frame.Pointers)
66
67#define GetExceptionCode _exception_code
68#define GetExceptionInformation _exception_info
69
70#define __try \
71 volatile __seh_PEXCEPTION_FRAME __seh_frame; \
72 __seh_frame.Pointers.ExceptionRecord = NULL; \
73 __seh_frame.Pointers.ContextRecord = NULL; \
74 __seh_frame.state = 0; \
75 __asm__("\n0:\n"); /* pFilterCallback */ \
76 for (; __seh_frame.state <= 3; ++__seh_frame.state) \
77 if (__seh_frame.state == 0) \
78 { \
79 /* install exception handler */ \
80 __asm__ ("\n.extern ___seh_handler\n" \
81 "" \
82 "leal %0, %%ecx; " \
83 "movl %%fs:0, %%eax; " \
84 "movl %%eax, 0(%%ecx); " \
85 "movl $___seh_handler, %%eax; " \
86 "movl %%eax, 4(%%ecx); " \
87 "movl $0b, 8(%%ecx); " \
88 "" \
89 "movl %%ebx, 24(%%ecx); " \
90 "movl %%esi, 28(%%ecx); " \
91 "movl %%edi, 32(%%ecx); " \
92 "movl %%ebp, 36(%%ecx); " \
93 "movl %%esp, 40(%%ecx); " \
94 "" \
95 "pushl %%fs; " \
96 "pushl $Dos32TIB; " \
97 "popl %%fs; " \
98 "movl %%fs:0, %%eax; " \
99 "movl %%eax, 44(%%ecx); " \
100 "popl %%fs; " \
101 "" \
102 "movl %%ecx, %%fs:0; " \
103 : : "m" (__seh_frame) \
104 : "%eax", "%ecx"); \
105 {
106
107#define __except(filter_expr) \
108 } \
109 /* cause the next state to be 3 */ \
110 __seh_frame.state = 2; \
111 } \
112 else if (__seh_frame.state == 1) { \
113 /* execption caught, call filter expression */ \
114 __seh_frame.filterResult = (filter_expr); \
115 __asm__("leal %0, %%ebx; jmp *%1" \
116 : : "m"(__seh_frame), "m"(__seh_frame.pHandlerCallback) \
117 : "%ebx"); \
118 } \
119 else if (__seh_frame.state == 3) \
120 /* remove exception handler */ \
121 __asm__ ("movl %%fs:0, %%eax; " \
122 "movl 0(%%eax), %%eax; " \
123 "movl %%eax, %%fs:0; " \
124 : : \
125 : "%eax"); \
126 else /* __seh_frame.state == 2 -> execute except block */
127
128#define __finally \
129 } \
130 /* cause the next state to be 2 */ \
131 __seh_frame.state = 1; \
132 } \
133 else if (__seh_frame.state == 1) { \
134 /* execption caught, handle and proceed to the filally block */ \
135 __seh_frame.filterResult = EXCEPTION_EXECUTE_HANDLER; \
136 __asm__("leal %0, %%ebx; jmp *%1" \
137 : : "m"(__seh_frame), "m"(__seh_frame.pHandlerCallback) \
138 : "%ebx"); \
139 } \
140 else if (__seh_frame.state == 3) \
141 /* remove exception handler */ \
142 __asm__ ("movl %%fs:0, %%eax; " \
143 "movl 0(%%eax), %%eax; " \
144 "movl %%eax, %%fs:0; " \
145 : : \
146 : "%eax"); \
147 else /* __seh_frame.state == 2 -> execute finally block */
148
149#define __leave \
150 /* cause the next state to be 2 */ \
151 __seh_frame.state = 1; \
152 continue;
153
154#else /* defined(__GNUC__) */
155
156#warning "Structured exception handling is not supported for this compiler!"
157
158#endif /* defined(__GNUC__) */
159
160#ifdef __cplusplus
161}
162#endif
163
164#endif /* __EXCPT_H__ */
165
Note: See TracBrowser for help on using the repository browser.