bc2b3c3a96ea059f96321f026dd0689e829534f8
[reactos.git] / reactos / include / reactos / libs / pseh / framebased.h
1 /*
2 Copyright (c) 2004/2005 KJK::Hyperion
3
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files (the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 DEALINGS IN THE SOFTWARE.
21 */
22
23 #ifndef KJK_PSEH_FRAMEBASED_H_
24 #define KJK_PSEH_FRAMEBASED_H_
25
26 #include <pseh/framebased/internal.h>
27 #include <pseh/excpt.h>
28
29 #ifndef offsetof
30 # include <stddef.h>
31 #endif
32
33 unsigned long __cdecl DbgPrint(const char * format, ...);
34
35 /*
36 Fall back to non-optimal, non-native NLG implementation for environments
37 without their own (e.g., currently, kernel-mode ReactOS/Windows). THIS IS NOT
38 RECOMMENDED AND IT WILL BE DROPPED IN A FUTURE VERSION BECAUSE IT MAY CAUSE
39 SEVERE STACK CORRUPTION. REIMPLEMENT OR PORT YOUR COMPILER'S NATIVE NLG
40 IMPLEMENTATION INSTEAD.
41 */
42 #ifdef _SEH_NO_NATIVE_NLG
43 # include <pseh/setjmp.h>
44 #else
45 # include <setjmp.h>
46 # define _SEHLongJmp longjmp
47 # define _SEHSetJmp setjmp
48 # define _SEHJmpBuf_t jmp_buf
49 #endif
50
51 #ifdef __cplusplus
52 # define _SEH_INIT_CONST static const
53 #else
54 # define _SEH_INIT_CONST register const
55 #endif
56
57 typedef struct __SEHFrame
58 {
59 _SEHPortableFrame_t SEH_Header;
60 void * SEH_Locals;
61 }
62 _SEHFrame_t;
63
64 typedef struct __SEHTryLevel
65 {
66 _SEHPortableTryLevel_t ST_Header;
67 _SEHJmpBuf_t ST_JmpBuf;
68 }
69 _SEHTryLevel_t;
70
71 static __declspec(noreturn) __inline void __stdcall _SEHCompilerSpecificHandler
72 (
73 _SEHPortableTryLevel_t * trylevel
74 )
75 {
76 /*
77 * help detetct if pseh going into endless loop
78 * if we see this debug msg repet never break
79 * we known something cause pseh going into
80 * endless loop, but it should never happen
81 */
82 DbgPrint("_SEHCompilerSpecificHandler(%p)\n", trylevel);
83 _SEHTryLevel_t * mytrylevel;
84 mytrylevel = _SEH_CONTAINING_RECORD(trylevel, _SEHTryLevel_t, ST_Header);
85 _SEHLongJmp(mytrylevel->ST_JmpBuf, 1);
86 }
87
88 static const int _SEHScopeKind = 1;
89 static _SEHPortableFrame_t * const _SEHPortableFrame = 0;
90
91 /* SHARED LOCALS */
92 /* Access the locals for the current frame */
93 #define _SEH_ACCESS_LOCALS(LOCALS_) \
94 _SEH_LOCALS_TYPENAME(LOCALS_) * _SEHPLocals; \
95 _SEHPLocals = \
96 _SEH_PVOID_CAST \
97 ( \
98 _SEH_LOCALS_TYPENAME(LOCALS_) *, \
99 _SEH_CONTAINING_RECORD(_SEHPortableFrame, _SEHFrame_t, SEH_Header) \
100 ->SEH_Locals \
101 );
102
103 /* Access local variable VAR_ */
104 #define _SEH_VAR(VAR_) _SEHPLocals->VAR_
105
106 /* FILTER FUNCTIONS */
107 /* Declares a filter function's prototype */
108 #define _SEH_FILTER(NAME_) \
109 long __stdcall NAME_ \
110 ( \
111 struct _EXCEPTION_POINTERS * _SEHExceptionPointers, \
112 struct __SEHPortableFrame * _SEHPortableFrame \
113 )
114
115 /* Declares a static filter */
116 #define _SEH_STATIC_FILTER(ACTION_) ((_SEHFilter_t)((ACTION_) + 2))
117
118 /* Declares a PSEH filter wrapping a regular filter function */
119 #define _SEH_WRAP_FILTER(WRAPPER_, NAME_) \
120 static __inline _SEH_FILTER(WRAPPER_) \
121 { \
122 return (NAME_)(_SEHExceptionPointers); \
123 }
124
125 /* FINALLY FUNCTIONS */
126 /* Declares a finally function's prototype */
127 #define _SEH_FINALLYFUNC(NAME_) \
128 void __stdcall NAME_ \
129 ( \
130 struct __SEHPortableFrame * _SEHPortableFrame \
131 )
132
133 /* Declares a PSEH finally function wrapping a regular function */
134 #define _SEH_WRAP_FINALLY(WRAPPER_, NAME_) \
135 _SEH_WRAP_FINALLY_ARGS(WRAPPER_, NAME_, ())
136
137 #define _SEH_WRAP_FINALLY_ARGS(WRAPPER_, NAME_, ARGS_) \
138 static __inline _SEH_FINALLYFUNC(WRAPPER_) \
139 { \
140 NAME_ ARGS_; \
141 }
142
143 #define _SEH_WRAP_FINALLY_LOCALS_ARGS(WRAPPER_, LOCALS_, NAME_, ARGS_) \
144 static __inline _SEH_FINALLYFUNC(WRAPPER_) \
145 { \
146 _SEH_ACCESS_LOCALS(LOCALS_); \
147 NAME_ ARGS_; \
148 }
149
150 /* SAFE BLOCKS */
151 #define _SEHX_TRY_FINALLY(FINALLY_) \
152 _SEH_TRY_FILTER_FINALLY \
153 ( \
154 _SEH_STATIC_FILTER(_SEH_CONTINUE_SEARCH), \
155 (FINALLY_) \
156 )
157
158 #define _SEHX_END_FINALLY _SEH_HANDLE _SEH_END
159
160 #define _SEHX_TRY_FILTER(FILTER_) \
161 _SEH_TRY_FILTER_FINALLY((FILTER_), 0)
162
163 #define _SEHX_TRY_HANDLE_FINALLY(FINALLY_) \
164 _SEH_TRY_FILTER_FINALLY \
165 ( \
166 _SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER), \
167 (FINALLY_) \
168 )
169
170 #define _SEHX_TRY \
171 _SEH_TRY_HANDLE_FINALLY(0)
172
173 #ifdef __cplusplus
174 # define _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_) \
175 static const _SEHHandlers_t _SEHHandlers = { (FILTER_), (FINALLY_) };
176 #else
177 # define _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_) \
178 _SEHHandlers_t _SEHHandlers = { (0), (0) }; \
179 _SEHHandlers.SH_Filter = (FILTER_); \
180 _SEHHandlers.SH_Finally = (FINALLY_);
181 #endif
182
183 #define _SEHX_TRY_FILTER_FINALLY(FILTER_, FINALLY_) \
184 { \
185 _SEHPortableFrame_t * const _SEHCurPortableFrame = _SEHPortableFrame; \
186 \
187 { \
188 _SEHFrame_t _SEHFrame; \
189 _SEHTryLevel_t _SEHTryLevel; \
190 _SEHPortableFrame_t * const _SEHPortableFrame = \
191 _SEHScopeKind ? &_SEHFrame.SEH_Header : _SEHCurPortableFrame; \
192 \
193 (void)_SEHPortableFrame; \
194 \
195 _SEH_DECLARE_HANDLERS((FILTER_), (FINALLY_)); \
196 \
197 _SEHTryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
198 \
199 if(_SEHScopeKind) \
200 { \
201 if(&_SEHLocals != _SEHDummyLocals) \
202 _SEHFrame.SEH_Locals = &_SEHLocals; \
203 \
204 _SEHFrame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; \
205 _SEHEnterFrame(&_SEHFrame.SEH_Header, &_SEHTryLevel.ST_Header); \
206 } \
207 else \
208 _SEHEnterTry(&_SEHTryLevel.ST_Header); \
209 \
210 { \
211 _SEH_INIT_CONST int _SEHScopeKind = 0; \
212 (void)_SEHScopeKind; \
213 \
214 if(_SEHSetJmp(_SEHTryLevel.ST_JmpBuf) == 0) \
215 { \
216 for(;;) \
217 {
218
219 #define _SEHX_HANDLE \
220 \
221 break; \
222 } \
223 \
224 _SEHLeave(); \
225 } \
226 else \
227 { \
228 _SEHLeave();
229
230 #define _SEHX_END \
231 } \
232 \
233 if(_SEHHandlers.SH_Finally) \
234 _SEHHandlers.SH_Finally(_SEHPortableFrame); \
235 } \
236 } \
237 }
238
239 #define _SEHX_LEAVE break
240
241 #define _SEHX_GetExceptionCode() (unsigned long)(_SEHPortableFrame->SPF_Code)
242
243 #define _SEHX_GetExceptionPointers() \
244 ((struct _EXCEPTION_POINTERS *)_SEHExceptionPointers)
245
246 #define _SEHX_AbnormalTermination() (_SEHPortableFrame->SPF_Code != 0)
247
248 /* New syntax */
249
250 #define _SEH_LEAVE break
251
252 #define _SEH_TRY \
253 { \
254 _SEH_INIT_CONST int _SEHTopTryLevel = (_SEHScopeKind != 0); \
255 _SEHPortableFrame_t * const _SEHCurPortableFrame = _SEHPortableFrame; \
256 \
257 { \
258 _SEH_INIT_CONST int _SEHScopeKind = 0; \
259 register int _SEHState = 0; \
260 register int _SEHHandle = 0; \
261 _SEHFrame_t _SEHFrame; \
262 _SEHTryLevel_t _SEHTryLevel; \
263 _SEHPortableFrame_t * const _SEHPortableFrame = \
264 _SEHTopTryLevel ? &_SEHFrame.SEH_Header : _SEHCurPortableFrame; \
265 \
266 (void)_SEHScopeKind; \
267 (void)_SEHPortableFrame; \
268 (void)_SEHHandle; \
269 \
270 for(;;) \
271 { \
272 if(_SEHState) \
273 { \
274 for(;;) \
275 { \
276 {
277
278 #define _SEH_EXCEPT(FILTER_) \
279 } \
280 \
281 break; \
282 } \
283 \
284 break; \
285 } \
286 else \
287 { \
288 _SEH_DECLARE_HANDLERS((FILTER_), 0); \
289 \
290 _SEHTryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
291 \
292 if(_SEHTopTryLevel) \
293 { \
294 if(&_SEHLocals != _SEHDummyLocals) \
295 _SEHFrame.SEH_Locals = &_SEHLocals; \
296 \
297 _SEH_EnableTracing(_SEH_DO_DEFAULT_TRACING); \
298 _SEHFrame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; \
299 _SEHEnterFrame(&_SEHFrame.SEH_Header, &_SEHTryLevel.ST_Header); \
300 } \
301 else \
302 _SEHEnterTry(&_SEHTryLevel.ST_Header); \
303 \
304 if((_SEHHandle = _SEHSetJmp(_SEHTryLevel.ST_JmpBuf)) == 0) \
305 { \
306 ++ _SEHState; \
307 continue; \
308 } \
309 else \
310 { \
311 break; \
312 } \
313 } \
314 \
315 break; \
316 } \
317 \
318 _SEHLeave(); \
319 \
320 if(_SEHHandle) \
321 {
322
323 #define _SEH_FINALLY(FINALLY_) \
324 } \
325 \
326 break; \
327 } \
328 \
329 _SEHLeave(); \
330 break; \
331 } \
332 else \
333 { \
334 _SEH_DECLARE_HANDLERS(0, (FINALLY_)); \
335 \
336 _SEHTryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
337 \
338 if(_SEHTopTryLevel) \
339 { \
340 if(&_SEHLocals != _SEHDummyLocals) \
341 _SEHFrame.SEH_Locals = &_SEHLocals; \
342 \
343 _SEH_EnableTracing(_SEH_DO_DEFAULT_TRACING); \
344 _SEHFrame.SEH_Header.SPF_Handler = 0; \
345 _SEHEnterFrame(&_SEHFrame.SEH_Header, &_SEHTryLevel.ST_Header); \
346 } \
347 else \
348 _SEHEnterTry(&_SEHTryLevel.ST_Header); \
349 \
350 ++ _SEHState; \
351 continue; \
352 } \
353 \
354 break; \
355 } \
356 \
357 (FINALLY_)(&_SEHFrame.SEH_Header); \
358 \
359 if(0) \
360 {
361
362 #define _SEH_END \
363 } \
364 } \
365 }
366
367 #define _SEH_HANDLE _SEH_EXCEPT(_SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER))
368
369 #define _SEH_GetExceptionCode _SEHX_GetExceptionCode
370 #define _SEH_GetExceptionPointers _SEHX_GetExceptionPointers
371 #define _SEH_AbnormalTermination _SEHX_AbnormalTermination
372
373 #define _SEH_EnableTracing(LEVEL_) ((void)(_SEHPortableFrame->SPF_Tracing = (LEVEL_)))
374 #define _SEH_DisableTracing() ((void)(_SEHPortableFrame->SPF_Tracing = _SEH_DO_TRACE_NONE))
375
376 #endif
377
378 /* EOF */