2 ** OSSP ex - Exception Handling
3 ** Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com>
4 ** Copyright (c) 2002-2004 The OSSP Project <http://www.ossp.org/>
5 ** Copyright (c) 2002-2004 Cable & Wireless <http://www.cw.com/>
7 ** This file is part of OSSP ex, an exception handling library
8 ** which can be found at http://www.ossp.org/pkg/lib/ex/.
10 ** Permission to use, copy, modify, and distribute this software for
11 ** any purpose with or without fee is hereby granted, provided that
12 ** the above copyright notice and this permission notice appear in all
15 ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
16 ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
19 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22 ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 ** ex.h: exception handling (pre-processor part)
34 /* required ISO-C standard facilities */
37 /* convenience define */
39 #define NULL (void *)0
42 /* determine how the current function name can be fetched */
43 #if ( defined(__STDC__) \
44 && defined(__STDC_VERSION__) \
45 && __STDC_VERSION__ >= 199901L)
46 #define __EX_FUNC__ __func__ /* ISO-C99 compliant */
47 #elif ( defined(__GNUC__) \
48 && defined(__GNUC_MINOR__) \
50 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)))
51 #define __EX_FUNC__ __FUNCTION__ /* gcc >= 2.8 */
53 #define __EX_FUNC__ "#NA#" /* not available */
56 /* the machine context */
57 #if defined(__EX_MCTX_MCSC__)
58 #include <ucontext.h> /* POSIX.1 ucontext(3) */
59 #define __ex_mctx_struct ucontext_t uc;
60 #define __ex_mctx_save(mctx) (getcontext(&(mctx)->uc) == 0)
61 #define __ex_mctx_restored(mctx) /* noop */
62 #define __ex_mctx_restore(mctx) (void)setcontext(&(mctx)->uc)
64 #elif defined(__EX_MCTX_SSJLJ__)
65 #include <setjmp.h> /* POSIX.1 sigjmp_buf(3) */
66 #define __ex_mctx_struct sigjmp_buf jb;
67 #define __ex_mctx_save(mctx) (sigsetjmp((mctx)->jb, 1) == 0)
68 #define __ex_mctx_restored(mctx) /* noop */
69 #define __ex_mctx_restore(mctx) (void)siglongjmp((mctx)->jb, 1)
71 #elif defined(__EX_MCTX_SJLJ__) || !defined(__EX_MCTX_CUSTOM__)
72 #include <setjmp.h> /* ISO-C jmp_buf(3) */
73 #define __ex_mctx_struct jmp_buf jb;
74 #define __ex_mctx_save(mctx) (setjmp((mctx)->jb) == 0)
75 #define __ex_mctx_restored(mctx) /* noop */
76 #define __ex_mctx_restore(mctx) (void)longjmp((mctx)->jb, 1)
79 /* declare the machine context type */
80 typedef struct { __ex_mctx_struct } __ex_mctx_t;
82 /* declare the exception type (public) */
94 /* declare the context type (private) */
96 __ex_mctx_t *ctx_mctx; /* permanent machine context of enclosing try/catch */
97 int ctx_deferred; /* permanent flag whether exception is deferred */
98 int ctx_deferring;/* permanent counter of exception deferring level */
99 int ctx_defer; /* temporary flag for exception deferring macro */
100 int ctx_shielding;/* permanent counter of exception shielding level */
101 int ctx_shield; /* temporary flag for exception shielding macro */
102 int ctx_caught; /* temporary flag whether exception was caught */
103 volatile ex_t ctx_ex; /* temporary exception storage */
106 /* the static and dynamic initializers for a context structure */
107 #define EX_CTX_INITIALIZER \
108 { NULL, 0, 0, 0, 0, 0, 0, { NULL, NULL, NULL, NULL, 0, NULL } }
109 #define EX_CTX_INITIALIZE(ctx) \
111 (ctx)->ctx_mctx = NULL; \
112 (ctx)->ctx_deferred = 0; \
113 (ctx)->ctx_deferring = 0; \
114 (ctx)->ctx_defer = 0; \
115 (ctx)->ctx_shielding = 0; \
116 (ctx)->ctx_shield = 0; \
117 (ctx)->ctx_caught = 0; \
118 (ctx)->ctx_ex.ex_class = NULL; \
119 (ctx)->ctx_ex.ex_object = NULL; \
120 (ctx)->ctx_ex.ex_value = NULL; \
121 (ctx)->ctx_ex.ex_file = NULL; \
122 (ctx)->ctx_ex.ex_line = 0; \
123 (ctx)->ctx_ex.ex_func = NULL; \
126 /* the exception context */
127 typedef ex_ctx_t *(*ex_ctx_cb_t)(void);
128 extern ex_ctx_cb_t __ex_ctx;
129 extern ex_ctx_t *__ex_ctx_default(void);
131 /* the termination handler */
132 typedef void (*ex_term_cb_t)(ex_t *);
133 extern ex_term_cb_t __ex_terminate;
134 extern void __ex_terminate_default(ex_t *e);
136 /* the block for trying execution */
139 ex_ctx_t *__ex_ctx_ptr = __ex_ctx(); \
140 int __ex_cleanup = 0; \
141 __ex_mctx_t *__ex_mctx_en; \
142 __ex_mctx_t __ex_mctx_me; \
143 __ex_mctx_en = __ex_ctx_ptr->ctx_mctx; \
144 __ex_ctx_ptr->ctx_mctx = &__ex_mctx_me; \
145 if (__ex_mctx_save(&__ex_mctx_me)) { \
148 /* the optional(!) block for cleanup */
152 __ex_ctx_ptr->ctx_caught = 0; \
155 __ex_mctx_restored(&__ex_mctx_me); \
156 __ex_ctx_ptr->ctx_caught = 1; \
158 __ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \
163 /* the block for catching an exception */
164 #define ex_catch(e) \
167 if (!(__ex_cleanup)) \
168 __ex_ctx_ptr->ctx_caught = 0; \
171 if (!(__ex_cleanup)) { \
172 __ex_mctx_restored(&__ex_mctx_me); \
173 __ex_ctx_ptr->ctx_caught = 1; \
176 __ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \
178 if ( !(__ex_ctx()->ctx_caught) \
179 || ((e) = __ex_ctx()->ctx_ex, 0)) { \
183 /* the throwing of a new exception */
184 #define ex_throw(c,o,v) \
185 (( __ex_ctx()->ctx_shielding > 0 \
186 || (__ex_ctx()->ctx_deferring > 0 && __ex_ctx()->ctx_deferred == 1)) ? 0 : \
187 (__ex_ctx()->ctx_ex.ex_class = (void *)(c), \
188 __ex_ctx()->ctx_ex.ex_object = (void *)(o), \
189 __ex_ctx()->ctx_ex.ex_value = (void *)(v), \
190 __ex_ctx()->ctx_ex.ex_file = __FILE__, \
191 __ex_ctx()->ctx_ex.ex_line = __LINE__, \
192 __ex_ctx()->ctx_ex.ex_func = __EX_FUNC__, \
193 __ex_ctx()->ctx_deferred = 1, \
194 (__ex_ctx()->ctx_deferring > 0 ? 0 : \
195 (__ex_ctx()->ctx_mctx == NULL \
196 ? (__ex_terminate((ex_t *)&(__ex_ctx()->ctx_ex)), -1) \
197 : (__ex_mctx_restore(__ex_ctx()->ctx_mctx), 1) ))))
199 /* the re-throwing of an already caught exception */
201 (( __ex_ctx()->ctx_shielding > 0 \
202 || __ex_ctx()->ctx_deferring > 0) ? 0 : \
203 ( __ex_ctx()->ctx_mctx == NULL \
204 ? (__ex_terminate((ex_t *)&(__ex_ctx()->ctx_ex)), -1) \
205 : (__ex_mctx_restore(__ex_ctx()->ctx_mctx), 1) ))
207 /* shield an operation from exception handling */
209 for (__ex_ctx()->ctx_shielding++, \
210 __ex_ctx()->ctx_shield = 1; \
211 __ex_ctx()->ctx_shield == 1; \
212 __ex_ctx()->ctx_shield = 0, \
213 __ex_ctx()->ctx_shielding--)
215 /* defer immediate exception handling */
217 for (((__ex_ctx()->ctx_deferring)++ == 0 ? __ex_ctx()->ctx_deferred = 0 : 0), \
218 __ex_ctx()->ctx_defer = 1; \
219 __ex_ctx()->ctx_defer == 1; \
220 __ex_ctx()->ctx_defer = 0, \
221 ((--(__ex_ctx()->ctx_deferring) == 0 && __ex_ctx()->ctx_deferred == 1) ? ex_rethrow : 0))
223 /* exception handling tests */
224 #define ex_catching \
225 (__ex_ctx()->ctx_mctx != NULL)
226 #define ex_shielding \
227 (__ex_ctx()->ctx_shielding > 0)
228 #define ex_deferring \
229 (__ex_ctx()->ctx_deferring > 0)
231 /* optional namespace mapping */
232 #if defined(__EX_NS_UCCXX__)
234 #define Cleanup ex_cleanup
235 #define Catch ex_catch
236 #define Throw ex_throw
237 #define Rethrow ex_rethrow
238 #define Shield ex_shield
239 #define Defer ex_defer
240 #elif defined(__EX_NS_CXX__) || (!defined(__cplusplus) && !defined(__EX_NS_CUSTOM__))
242 #define cleanup ex_cleanup
243 #define catch ex_catch
244 #define throw ex_throw
245 #define rethrow ex_rethrow
246 #define shield ex_shield
247 #define defer ex_defer
250 #endif /* __EX_H__ */