2 Copyright (c) 2004/2005 KJK::Hyperion
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:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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.
23 #ifndef KJK_PSEH_FRAMEBASED_H_
24 #define KJK_PSEH_FRAMEBASED_H_
26 #include <pseh/framebased/internal.h>
27 #include <pseh/excpt.h>
33 unsigned long __cdecl
DbgPrint(const char * format
, ...);
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.
42 #ifdef _SEH_NO_NATIVE_NLG
43 # include <pseh/setjmp.h>
46 # define _SEHLongJmp longjmp
47 # define _SEHSetJmp setjmp
48 # define _SEHJmpBuf_t jmp_buf
52 # define _SEH_INIT_CONST static const
54 # define _SEH_INIT_CONST register const
57 typedef struct __SEHFrame
59 _SEHPortableFrame_t SEH_Header
;
64 typedef struct __SEHTryLevel
66 _SEHPortableTryLevel_t ST_Header
;
67 _SEHJmpBuf_t ST_JmpBuf
;
71 static __declspec(noreturn
) __inline
void __stdcall _SEHCompilerSpecificHandler
73 _SEHPortableTryLevel_t
* trylevel
76 _SEHTryLevel_t
* mytrylevel
;
77 DbgPrint("_SEHCompilerSpecificHandler(%p)\n", trylevel
);
78 mytrylevel
= _SEH_CONTAINING_RECORD(trylevel
, _SEHTryLevel_t
, ST_Header
);
79 _SEHLongJmp(mytrylevel
->ST_JmpBuf
, 1);
82 static const int _SEHScopeKind
= 1;
83 static _SEHPortableFrame_t
* const _SEHPortableFrame
= 0;
86 /* Access the locals for the current frame */
87 #define _SEH_ACCESS_LOCALS(LOCALS_) \
88 _SEH_LOCALS_TYPENAME(LOCALS_) * _SEHPLocals; \
92 _SEH_LOCALS_TYPENAME(LOCALS_) *, \
93 _SEH_CONTAINING_RECORD(_SEHPortableFrame, _SEHFrame_t, SEH_Header) \
97 /* Access local variable VAR_ */
98 #define _SEH_VAR(VAR_) _SEHPLocals->VAR_
100 /* FILTER FUNCTIONS */
101 /* Declares a filter function's prototype */
102 #define _SEH_FILTER(NAME_) \
103 long __stdcall NAME_ \
105 struct _EXCEPTION_POINTERS * _SEHExceptionPointers, \
106 struct __SEHPortableFrame * _SEHPortableFrame \
109 /* Declares a static filter */
110 #define _SEH_STATIC_FILTER(ACTION_) ((_SEHFilter_t)((ACTION_) + 2))
112 /* Declares a PSEH filter wrapping a regular filter function */
113 #define _SEH_WRAP_FILTER(WRAPPER_, NAME_) \
114 static __inline _SEH_FILTER(WRAPPER_) \
116 return (NAME_)(_SEHExceptionPointers); \
119 /* FINALLY FUNCTIONS */
120 /* Declares a finally function's prototype */
121 #define _SEH_FINALLYFUNC(NAME_) \
122 void __stdcall NAME_ \
124 struct __SEHPortableFrame * _SEHPortableFrame \
127 /* Declares a PSEH finally function wrapping a regular function */
128 #define _SEH_WRAP_FINALLY(WRAPPER_, NAME_) \
129 _SEH_WRAP_FINALLY_ARGS(WRAPPER_, NAME_, ())
131 #define _SEH_WRAP_FINALLY_ARGS(WRAPPER_, NAME_, ARGS_) \
132 static __inline _SEH_FINALLYFUNC(WRAPPER_) \
137 #define _SEH_WRAP_FINALLY_LOCALS_ARGS(WRAPPER_, LOCALS_, NAME_, ARGS_) \
138 static __inline _SEH_FINALLYFUNC(WRAPPER_) \
140 _SEH_ACCESS_LOCALS(LOCALS_); \
145 #define _SEHX_TRY_FINALLY(FINALLY_) \
146 _SEH_TRY_FILTER_FINALLY \
148 _SEH_STATIC_FILTER(_SEH_CONTINUE_SEARCH), \
152 #define _SEHX_END_FINALLY _SEH_HANDLE _SEH_END
154 #define _SEHX_TRY_FILTER(FILTER_) \
155 _SEH_TRY_FILTER_FINALLY((FILTER_), 0)
157 #define _SEHX_TRY_HANDLE_FINALLY(FINALLY_) \
158 _SEH_TRY_FILTER_FINALLY \
160 _SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER), \
165 _SEH_TRY_HANDLE_FINALLY(0)
168 # define _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_) \
169 static const _SEHHandlers_t _SEHHandlers = { (FILTER_), (FINALLY_) };
171 # define _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_) \
172 _SEHHandlers_t _SEHHandlers = { (0), (0) }; \
173 _SEHHandlers.SH_Filter = (FILTER_); \
174 _SEHHandlers.SH_Finally = (FINALLY_);
177 #define _SEHX_TRY_FILTER_FINALLY(FILTER_, FINALLY_) \
179 _SEHPortableFrame_t * const _SEHCurPortableFrame = _SEHPortableFrame; \
182 _SEHFrame_t _SEHFrame; \
183 _SEHTryLevel_t _SEHTryLevel; \
184 _SEHPortableFrame_t * const _SEHPortableFrame = \
185 _SEHScopeKind ? &_SEHFrame.SEH_Header : _SEHCurPortableFrame; \
187 (void)_SEHPortableFrame; \
189 _SEH_DECLARE_HANDLERS((FILTER_), (FINALLY_)); \
191 _SEHTryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
195 if(&_SEHLocals != _SEHDummyLocals) \
196 _SEHFrame.SEH_Locals = &_SEHLocals; \
198 _SEHFrame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; \
199 _SEHEnterFrame(&_SEHFrame.SEH_Header, &_SEHTryLevel.ST_Header); \
202 _SEHEnterTry(&_SEHTryLevel.ST_Header); \
205 _SEH_INIT_CONST int _SEHScopeKind = 0; \
206 (void)_SEHScopeKind; \
208 if(_SEHSetJmp(_SEHTryLevel.ST_JmpBuf) == 0) \
213 #define _SEHX_HANDLE \
227 if(_SEHHandlers.SH_Finally) \
228 _SEHHandlers.SH_Finally(_SEHPortableFrame); \
233 #define _SEHX_LEAVE break
235 #define _SEHX_GetExceptionCode() (unsigned long)(_SEHPortableFrame->SPF_Code)
237 #define _SEHX_GetExceptionPointers() \
238 ((struct _EXCEPTION_POINTERS *)_SEHExceptionPointers)
240 #define _SEHX_AbnormalTermination() (_SEHPortableFrame->SPF_Code != 0)
244 #define _SEH_LEAVE break
248 _SEH_INIT_CONST int _SEHTopTryLevel = (_SEHScopeKind != 0); \
249 _SEHPortableFrame_t * const _SEHCurPortableFrame = _SEHPortableFrame; \
252 _SEH_INIT_CONST int _SEHScopeKind = 0; \
253 register int _SEHState = 0; \
254 register int _SEHHandle = 0; \
255 _SEHFrame_t _SEHFrame; \
256 _SEHTryLevel_t _SEHTryLevel; \
257 _SEHPortableFrame_t * const _SEHPortableFrame = \
258 _SEHTopTryLevel ? &_SEHFrame.SEH_Header : _SEHCurPortableFrame; \
260 (void)_SEHScopeKind; \
261 (void)_SEHPortableFrame; \
272 #define _SEH_EXCEPT(FILTER_) \
282 _SEH_DECLARE_HANDLERS((FILTER_), 0); \
284 _SEHTryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
286 if(_SEHTopTryLevel) \
288 if(&_SEHLocals != _SEHDummyLocals) \
289 _SEHFrame.SEH_Locals = &_SEHLocals; \
291 _SEH_EnableTracing(_SEH_DO_DEFAULT_TRACING); \
292 _SEHFrame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; \
293 _SEHEnterFrame(&_SEHFrame.SEH_Header, &_SEHTryLevel.ST_Header); \
296 _SEHEnterTry(&_SEHTryLevel.ST_Header); \
298 if((_SEHHandle = _SEHSetJmp(_SEHTryLevel.ST_JmpBuf)) == 0) \
317 #define _SEH_FINALLY(FINALLY_) \
328 _SEH_DECLARE_HANDLERS(0, (FINALLY_)); \
330 _SEHTryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
332 if(_SEHTopTryLevel) \
334 if(&_SEHLocals != _SEHDummyLocals) \
335 _SEHFrame.SEH_Locals = &_SEHLocals; \
337 _SEH_EnableTracing(_SEH_DO_DEFAULT_TRACING); \
338 _SEHFrame.SEH_Header.SPF_Handler = 0; \
339 _SEHEnterFrame(&_SEHFrame.SEH_Header, &_SEHTryLevel.ST_Header); \
342 _SEHEnterTry(&_SEHTryLevel.ST_Header); \
351 (FINALLY_)(&_SEHFrame.SEH_Header); \
361 #define _SEH_HANDLE _SEH_EXCEPT(_SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER))
363 #define _SEH_GetExceptionCode _SEHX_GetExceptionCode
364 #define _SEH_GetExceptionPointers _SEHX_GetExceptionPointers
365 #define _SEH_AbnormalTermination _SEHX_AbnormalTermination
367 #define _SEH_EnableTracing(LEVEL_) ((void)(_SEHPortableFrame->SPF_Tracing = (LEVEL_)))
368 #define _SEH_DisableTracing() ((void)(_SEHPortableFrame->SPF_Tracing = _SEH_DO_TRACE_NONE))