Big merge: thanks alex and greatlord. Not a complete merge but most
[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 copy of
5 this software and associated documentation files (the "Software"), to deal in
6 the Software without restriction, including without limitation the rights to
7 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 of the Software, and to permit persons to whom the Software is furnished to do
9 so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in all
12 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 FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 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 /*
34 Fall back to non-optimal, non-native NLG implementation for environments
35 without their own (e.g., currently, kernel-mode ReactOS/Windows). THIS IS NOT
36 RECOMMENDED AND IT WILL BE DROPPED IN A FUTURE VERSION BECAUSE IT MAY CAUSE
37 SEVERE STACK CORRUPTION. REIMPLEMENT OR PORT YOUR COMPILER'S NATIVE NLG
38 IMPLEMENTATION INSTEAD.
39 */
40 #ifdef _SEH_NO_NATIVE_NLG
41 # include <pseh/setjmp.h>
42 #else
43 # include <setjmp.h>
44 # define _SEHLongJmp longjmp
45 # define _SEHSetJmp setjmp
46 # define _SEHJmpBuf_t jmp_buf
47 #endif
48 typedef struct __SEHFrame
49 {
50 _SEHPortableFrame_t SEH_Header;
51 void * SEH_Locals;
52 }
53 _SEHFrame_t;
54
55 typedef struct __SEHTryLevel
56 {
57 _SEHPortableTryLevel_t ST_Header;
58 _SEHJmpBuf_t ST_JmpBuf;
59 }
60 _SEHTryLevel_t;
61
62 static __declspec(noreturn) __inline void __stdcall _SEHCompilerSpecificHandler
63 (
64 _SEHPortableTryLevel_t * trylevel
65 )
66 {
67 _SEHTryLevel_t * mytrylevel;
68 mytrylevel = _SEH_CONTAINING_RECORD(trylevel, _SEHTryLevel_t, ST_Header);
69 _SEHLongJmp(mytrylevel->ST_JmpBuf, 1);
70 }
71
72 static const int _SEHScopeKind = 1;
73 static _SEHPortableFrame_t * const _SEHPortableFrame = 0;
74
75 /* SHARED LOCALS */
76 /* Access the locals for the current frame */
77 #define _SEH_ACCESS_LOCALS(LOCALS_) \
78 _SEH_LOCALS_TYPENAME(LOCALS_) * _SEHPLocals; \
79 _SEHPLocals = \
80 _SEH_PVOID_CAST \
81 ( \
82 _SEH_LOCALS_TYPENAME(LOCALS_) *, \
83 _SEH_CONTAINING_RECORD(_SEHPortableFrame, _SEHFrame_t, SEH_Header) \
84 ->SEH_Locals \
85 );
86
87 /* Access local variable VAR_ */
88 #define _SEH_VAR(VAR_) _SEHPLocals->VAR_
89
90 /* FILTER FUNCTIONS */
91 /* Declares a filter function's prototype */
92 #define _SEH_FILTER(NAME_) \
93 long __stdcall NAME_ \
94 ( \
95 struct _EXCEPTION_POINTERS * _SEHExceptionPointers, \
96 struct __SEHPortableFrame * _SEHPortableFrame \
97 )
98
99 /* Declares a static filter */
100 #define _SEH_STATIC_FILTER(ACTION_) ((_SEHFilter_t)((ACTION_) + 2))
101
102 /* Declares a PSEH filter wrapping a regular filter function */
103 #define _SEH_WRAP_FILTER(WRAPPER_, NAME_) \
104 static __inline _SEH_FILTER(WRAPPER_) \
105 { \
106 return (NAME_)(_SEHExceptionPointers); \
107 }
108
109 /* FINALLY FUNCTIONS */
110 /* Declares a finally function's prototype */
111 #define _SEH_FINALLYFUNC(NAME_) \
112 void __stdcall NAME_ \
113 ( \
114 struct __SEHPortableFrame * _SEHPortableFrame \
115 )
116
117 /* Declares a PSEH finally function wrapping a regular function */
118 #define _SEH_WRAP_FINALLY(WRAPPER_, NAME_) \
119 _SEH_WRAP_FINALLY_ARGS(WRAPPER_, NAME_, ())
120
121 #define _SEH_WRAP_FINALLY_ARGS(WRAPPER_, NAME_, ARGS_) \
122 static __inline _SEH_FINALLYFUNC(WRAPPER_) \
123 { \
124 NAME_ ARGS_; \
125 }
126
127 #define _SEH_WRAP_FINALLY_LOCALS_ARGS(WRAPPER_, LOCALS_, NAME_, ARGS_) \
128 static __inline _SEH_FINALLYFUNC(WRAPPER_) \
129 { \
130 _SEH_ACCESS_LOCALS(LOCALS_); \
131 NAME_ ARGS_; \
132 }
133
134 /* SAFE BLOCKS */
135 #define _SEHX_TRY_FINALLY(FINALLY_) \
136 _SEH_TRY_FILTER_FINALLY \
137 ( \
138 _SEH_STATIC_FILTER(_SEH_CONTINUE_SEARCH), \
139 (FINALLY_) \
140 )
141
142 #define _SEHX_END_FINALLY _SEH_HANDLE _SEH_END
143
144 #define _SEHX_TRY_FILTER(FILTER_) \
145 _SEH_TRY_FILTER_FINALLY((FILTER_), 0)
146
147 #define _SEHX_TRY_HANDLE_FINALLY(FINALLY_) \
148 _SEH_TRY_FILTER_FINALLY \
149 ( \
150 _SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER), \
151 (FINALLY_) \
152 )
153
154 #define _SEHX_TRY \
155 _SEH_TRY_HANDLE_FINALLY(0)
156
157 #ifdef __cplusplus
158 # define _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_) \
159 static const _SEHHandlers_t _SEHHandlers = { (FILTER_), (FINALLY_) };
160 #else
161 # define _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_) \
162 _SEHHandlers_t _SEHHandlers = { (0), (0) }; \
163 _SEHHandlers.SH_Filter = (FILTER_); \
164 _SEHHandlers.SH_Finally = (FINALLY_);
165 #endif
166
167 #define _SEHX_TRY_FILTER_FINALLY(FILTER_, FINALLY_) \
168 { \
169 _SEHPortableFrame_t * const _SEHCurPortableFrame = _SEHPortableFrame; \
170 \
171 { \
172 _SEHFrame_t _SEHFrame; \
173 _SEHTryLevel_t _SEHTryLevel; \
174 _SEHPortableFrame_t * const _SEHPortableFrame = \
175 _SEHScopeKind ? &_SEHFrame.SEH_Header : _SEHCurPortableFrame; \
176 \
177 (void)_SEHPortableFrame; \
178 \
179 _SEH_DECLARE_HANDLERS((FILTER_), (FINALLY_)); \
180 \
181 _SEHTryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
182 \
183 if(_SEHScopeKind) \
184 { \
185 if(&_SEHLocals != _SEHDummyLocals) \
186 _SEHFrame.SEH_Locals = &_SEHLocals; \
187 \
188 _SEHFrame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; \
189 _SEHEnterFrame(&_SEHFrame.SEH_Header, &_SEHTryLevel.ST_Header); \
190 } \
191 else \
192 _SEHEnterTry(&_SEHTryLevel.ST_Header); \
193 \
194 { \
195 static const int _SEHScopeKind = 0; \
196 (void)_SEHScopeKind; \
197 \
198 if(_SEHSetJmp(_SEHTryLevel.ST_JmpBuf) == 0) \
199 { \
200 for(;;) \
201 {
202
203 #define _SEHX_HANDLE \
204 \
205 break; \
206 } \
207 \
208 _SEHLeave(); \
209 } \
210 else \
211 { \
212 _SEHLeave();
213
214 #define _SEHX_END \
215 } \
216 \
217 if(_SEHHandlers.SH_Finally) \
218 _SEHHandlers.SH_Finally(_SEHPortableFrame); \
219 } \
220 } \
221 }
222
223 #define _SEHX_LEAVE break
224
225 #define _SEHX_GetExceptionCode() (unsigned long)(_SEHPortableFrame->SPF_Code)
226
227 #define _SEHX_GetExceptionPointers() \
228 ((struct _EXCEPTION_POINTERS *)_SEHExceptionPointers)
229
230 #define _SEHX_AbnormalTermination() (_SEHPortableFrame->SPF_Code != 0)
231
232 /* New syntax */
233
234 /*
235 NOTE: do not move, remove or modify any instance of _SEH2_ASSUME and
236 _SEH2_ASSUMING without doing extensive tests for correctness. Compilers can
237 generate the wrong code in presence of __assume in unpredictable ways. BE SURE
238 IT DOESN'T HAPPEN
239 */
240 #if defined(_MSC_VER) && (_MSC_VER > 1200)
241 # define _SEH2_ASSUME(X_) __assume(X_)
242 # if !defined(_SEH_NO_NATIVE_NLG)
243 /*
244 If we use the native setjmp, the compiler stops keeping track of variables, so
245 their actual values don't matter anymore. Optimize out some assignments
246 */
247 # define _SEH2_ASSUMING(X_)
248 # else
249 /* No native setjmp, no magic, no assumptions. Actually set the values */
250 # define _SEH2_ASSUMING(X_) X_
251 # endif
252 #else
253 # define _SEH2_ASSUME(X_)
254 # define _SEH2_ASSUMING(X_) X_
255 #endif
256
257 #ifdef __cplusplus
258 # define _SEH2_INIT_CONST static const
259 #else
260 # define _SEH2_INIT_CONST register const
261 #endif
262
263 #define _SEH_LEAVE break
264
265 #define _SEH_TRY \
266 { \
267 _SEH2_INIT_CONST int _SEH2TopTryLevel = (_SEHScopeKind != 0); \
268 _SEHPortableFrame_t * const _SEH2CurPortableFrame = _SEHPortableFrame; \
269 \
270 { \
271 static const int _SEHScopeKind = 0; \
272 register int _SEH2State = 0; \
273 register int _SEH2Handle = 0; \
274 _SEHFrame_t _SEH2Frame; \
275 _SEHTryLevel_t _SEH2TryLevel; \
276 _SEHPortableFrame_t * const _SEHPortableFrame = \
277 _SEH2TopTryLevel ? &_SEH2Frame.SEH_Header : _SEH2CurPortableFrame; \
278 \
279 (void)_SEHScopeKind; \
280 (void)_SEHPortableFrame; \
281 (void)_SEH2Handle; \
282 \
283 for(;;) \
284 { \
285 if(_SEH2State) \
286 { \
287 for(;;) \
288 { \
289 {
290
291 #define _SEH_EXCEPT(FILTER_) \
292 } \
293 \
294 break; \
295 } \
296 \
297 _SEH2_ASSUME(_SEH2Handle == 0); \
298 break; \
299 } \
300 else \
301 { \
302 _SEH_DECLARE_HANDLERS((FILTER_), 0); \
303 \
304 _SEH2TryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
305 \
306 if(_SEH2TopTryLevel) \
307 { \
308 if(&_SEHLocals != _SEHDummyLocals) \
309 _SEH2Frame.SEH_Locals = &_SEHLocals; \
310 \
311 _SEH2Frame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; \
312 _SEHEnterFrame(&_SEH2Frame.SEH_Header, &_SEH2TryLevel.ST_Header); \
313 } \
314 else \
315 _SEHEnterTry(&_SEH2TryLevel.ST_Header); \
316 \
317 if((_SEH2Handle = _SEHSetJmp(_SEH2TryLevel.ST_JmpBuf)) == 0) \
318 { \
319 _SEH2_ASSUMING(++ _SEH2State); \
320 _SEH2_ASSUME(_SEH2State != 0); \
321 continue; \
322 } \
323 else \
324 { \
325 break; \
326 } \
327 } \
328 \
329 break; \
330 } \
331 \
332 _SEHLeave(); \
333 \
334 if(_SEH2Handle) \
335 {
336
337 #define _SEH_FINALLY(FINALLY_) \
338 } \
339 \
340 break; \
341 } \
342 \
343 _SEHLeave(); \
344 break; \
345 } \
346 else \
347 { \
348 _SEH_DECLARE_HANDLERS(0, (FINALLY_)); \
349 \
350 _SEH2TryLevel.ST_Header.SPT_Handlers = &_SEHHandlers; \
351 \
352 if(_SEH2TopTryLevel) \
353 { \
354 if(&_SEHLocals != _SEHDummyLocals) \
355 _SEH2Frame.SEH_Locals = &_SEHLocals; \
356 \
357 _SEH2Frame.SEH_Header.SPF_Handler = 0; \
358 _SEHEnterFrame(&_SEH2Frame.SEH_Header, &_SEH2TryLevel.ST_Header); \
359 } \
360 else \
361 _SEHEnterTry(&_SEH2TryLevel.ST_Header); \
362 \
363 ++ _SEH2State; \
364 _SEH2_ASSUME(_SEH2State != 0); \
365 continue; \
366 } \
367 \
368 break; \
369 } \
370 \
371 (FINALLY_)(&_SEH2Frame.SEH_Header); \
372 if(0) \
373 {
374
375 #define _SEH_END \
376 } \
377 } \
378 }
379
380 #define _SEH_HANDLE _SEH_EXCEPT(_SEH_STATIC_FILTER(_SEH_EXECUTE_HANDLER))
381
382 #define _SEH_GetExceptionCode _SEHX_GetExceptionCode
383 #define _SEH_GetExceptionPointers _SEHX_GetExceptionPointers
384 #define _SEH_AbnormalTermination _SEHX_AbnormalTermination
385
386 #endif
387
388 /* EOF */