1 /* 2 ** OSSP ex - Exception Handling 3 ** Copyright (c) 2002-2005 Ralf S. Engelschall <rse@engelschall.com> 4 ** Copyright (c) 2002-2005 The OSSP Project <http://www.ossp.org/> 5 ** Copyright (c) 2002-2005 Cable & Wireless <http://www.cw.com/> 6 ** 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/. 9 ** 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 13 ** copies. 14 ** 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 26 ** SUCH DAMAGE. 27 ** 28 ** ex.h: exception handling (pre-processor part) 29 */ 30 31 #ifndef __EX_H__ 32 #define __EX_H__ 33 34 /* required ISO-C standard facilities */ 35 #include <stdio.h> 36 37 /* convenience define */ 38 #ifndef NULL 39 #define NULL (void *)0 40 #endif 41 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__) \ 49 && ( __GNUC__ > 2 \ 50 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))) 51 #define __EX_FUNC__ __FUNCTION__ /* gcc >= 2.8 */ 52 #else 53 #define __EX_FUNC__ "#NA#" /* not available */ 54 #endif 55 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) 63 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) 70 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) 77 #endif 78 79 /* declare the machine context type */ 80 typedef struct { __ex_mctx_struct } __ex_mctx_t; 81 82 /* declare the exception type (public) */ 83 typedef struct { 84 /* throw value */ 85 void *ex_class; 86 void *ex_object; 87 void *ex_value; 88 /* throw point */ 89 const char *ex_file; 90 int ex_line; 91 const char *ex_func; 92 } ex_t; 93 94 /* declare the context type (private) */ 95 typedef struct { 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 */ 104 } ex_ctx_t; 105 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) \ 110 do { \ 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; \ 124 } while (0) 125 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); 130 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); 135 136 /* the block for trying execution */ 137 #define ex_try \ 138 { \ 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)) { \ 146 if (1) 147 148 /* the optional(!) block for cleanup */ 149 #define ex_cleanup \ 150 else { \ 151 } \ 152 __ex_ctx_ptr->ctx_caught = 0; \ 153 } \ 154 else { \ 155 __ex_mctx_restored(&__ex_mctx_me); \ 156 __ex_ctx_ptr->ctx_caught = 1; \ 157 } \ 158 __ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \ 159 __ex_cleanup = 1; \ 160 if (1) { \ 161 if (1) 162 163 /* the block for catching an exception */ 164 #define ex_catch(e) \ 165 else { \ 166 } \ 167 if (!(__ex_cleanup)) \ 168 __ex_ctx_ptr->ctx_caught = 0; \ 169 } \ 170 else { \ 171 if (!(__ex_cleanup)) { \ 172 __ex_mctx_restored(&__ex_mctx_me); \ 173 __ex_ctx_ptr->ctx_caught = 1; \ 174 } \ 175 } \ 176 __ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \ 177 } \ 178 if ( !(__ex_ctx()->ctx_caught) \ 179 || ((e) = __ex_ctx()->ctx_ex, 0)) { \ 180 } \ 181 else 182 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) )))) 198 199 /* the re-throwing of an already caught exception */ 200 #define ex_rethrow \ 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) )) 206 207 /* shield an operation from exception handling */ 208 #define ex_shield \ 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--) 214 215 /* defer immediate exception handling */ 216 #define ex_defer \ 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)) 222 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) 230 231 /* optional namespace mapping */ 232 #if defined(__EX_NS_UCCXX__) 233 #define Try ex_try 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__)) 241 #define try ex_try 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 248 #endif 249 250 #endif /* __EX_H__ */ 251 252