funny_falcon

C exceptions with unwinding

Jun 23rd, 2017
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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_
Add Comment
Please, Sign In to add comment