SHOW:
|
|
- or go back to the newest paste.
| 1 | #ifndef _CEXC_H_ | |
| 2 | #define _CEXC_H_ | |
| 3 | ||
| 4 | #include <assert.h> | |
| 5 | #include <setjmp.h> | |
| 6 | #include <unistd.h> | |
| 7 | #include <unwind.h> | |
| 8 | ||
| 9 | ||
| 10 | struct cexc_ctx {
| |
| 11 | struct _Unwind_Exception uexc; | |
| 12 | void *exc; | |
| 13 | }; | |
| 14 | ||
| 15 | typedef void * cexc_t; | |
| 16 | ||
| 17 | ||
| 18 | #define CEXC_TRY { \
| |
| 19 | jmp_buf cexc_jmp_; \ | |
| 20 | struct cexc_ctx cexc_ctx_ = { \
| |
| 21 | .exc = NULL \ | |
| 22 | }; \ | |
| 23 | \ | |
| 24 | if (cexc_ctx == NULL) \ | |
| 25 | cexc_ctx = &cexc_ctx_; \ | |
| 26 | \ | |
| 27 | if (setjmp(cexc_jmp_) == 0) { \
| |
| 28 | void cexc_landingpad_(int *unwind_) \ | |
| 29 | { \
| |
| 30 | if (*unwind_ == 0) \ | |
| 31 | return; \ | |
| 32 | \ | |
| 33 | longjmp(cexc_jmp_, 1); \ | |
| 34 | } \ | |
| 35 | __attribute__((cleanup(cexc_landingpad_))) int cexc_unwind_ = 1; | |
| 36 | ||
| 37 | ||
| 38 | #define CEXC_CATCH(exc_...) \ | |
| 39 | cexc_unwind_ = 0; \ | |
| 40 | if (cexc_ctx == &cexc_ctx_) \ | |
| 41 | cexc_ctx = NULL; \ | |
| 42 | } else { \
| |
| 43 | cexc_t unused_exc_ __attribute__((unused)), ##exc_ = cexc_ctx->exc; \ | |
| 44 | \ | |
| 45 | if (cexc_ctx == &cexc_ctx_) \ | |
| 46 | cexc_ctx = NULL; | |
| 47 | ||
| 48 | #define CEXC_END \ | |
| 49 | } \ | |
| 50 | } | |
| 51 | ||
| 52 | #define CEXC_THROW(e_...) ({ \
| |
| 53 | assert("uncaught throw" && cexc_ctx != NULL); \
| |
| 54 | _Pragma("GCC diagnostic ignored \"-Wunused-value\"") \
| |
| 55 | cexc_ctx->exc = (cexc_ctx->exc, ##e_); \ | |
| 56 | _Pragma("GCC diagnostic pop") \
| |
| 57 | _Unwind_ForcedUnwind(&cexc_ctx->uexc, cexc_unwind_stop, 0); \ | |
| 58 | assert("exception handling must be enabled (-fexceptions)" && 0); \
| |
| 59 | *(int *)0 = 0; \ | |
| 60 | }) | |
| 61 | ||
| 62 | ||
| 63 | static inline _Unwind_Reason_Code cexc_unwind_stop() | |
| 64 | {
| |
| 65 | return _URC_NO_REASON; | |
| 66 | } | |
| 67 | ||
| 68 | ||
| 69 | #ifndef CEXC_SOURCE | |
| 70 | extern | |
| 71 | #endif | |
| 72 | struct cexc_ctx *cexc_ctx; | |
| 73 | ||
| 74 | #endif // _CEXC_H_ |