Advertisement
Guest User

Untitled

a guest
Dec 6th, 2019
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.56 KB | None | 0 0
  1. #ifndef MCL_EXCEPTIONS_H
  2. #define MCL_EXCEPTIONS_H
  3.  
  4. #if defined(__cplusplus) || !defined(__STDC__) || !__STDC_HOSTED__ || __STDC_VERSION__ < 199901L
  5.     #error "MCL exception handling requires a hosted C99 (or newer) implementation."
  6. #endif
  7.  
  8. #include <assert.h>
  9. #include <setjmp.h>
  10. #include <stdbool.h>
  11. #include <stdlib.h>
  12. #if __STDC_VERSION__ >= 201112L
  13.     #include <stdnoreturn.h>
  14.     #ifndef __STDC_NO_THREADS__
  15.         #include <threads.h>
  16.     #else
  17.         #define thread_local
  18.     #endif
  19. #else
  20.     #define noreturn
  21.     #define thread_local
  22. #endif
  23.  
  24. enum mcl_exceptionstate {
  25.     MCL_TRY,
  26.     MCL_CATCH,
  27.     MCL_FINALLY
  28. };
  29.  
  30. struct mcl_exceptionframe {
  31.     struct mcl_exceptionframe *prev;
  32.     jmp_buf context;
  33.     enum mcl_exceptionstate state;
  34.     int exception;
  35.     bool mustcatch;
  36. };
  37.  
  38. extern thread_local struct mcl_exceptionframe *mcl_exceptionstack;
  39.  
  40. static inline void mcl_pushexceptionframe(struct mcl_exceptionframe **const exceptionstack) {
  41.     struct mcl_exceptionframe *topframe = malloc(sizeof *topframe);
  42.  
  43.     assert(topframe != NULL);
  44.     topframe->prev = *exceptionstack;
  45.     topframe->state = MCL_TRY;
  46.     topframe->mustcatch = false;
  47.     *exceptionstack = topframe;
  48. }
  49.  
  50. static inline void mcl_popexceptionframe(struct mcl_exceptionframe **const exceptionstack) {
  51.     struct mcl_exceptionframe *topframe = *exceptionstack;
  52.  
  53.     *exceptionstack = topframe->prev;
  54.     free(topframe);
  55. }
  56.  
  57. static inline noreturn void mcl_throw(struct mcl_exceptionframe **const exceptionstack, const int exception) {
  58.  
  59.     assert(*exceptionstack != NULL);
  60.     (*exceptionstack)->exception = exception;
  61.     (*exceptionstack)->mustcatch = true;
  62.  
  63.     switch ((*exceptionstack)->state) {
  64.     case MCL_TRY:
  65.         longjmp((*exceptionstack)->context, (*exceptionstack)->state = MCL_CATCH);
  66.     case MCL_CATCH:
  67.         longjmp((*exceptionstack)->context, (*exceptionstack)->state = MCL_FINALLY);
  68.     case MCL_FINALLY:
  69.         assert((*exceptionstack)->prev != NULL);
  70.         (*exceptionstack)->prev->exception = (*exceptionstack)->exception;
  71.         (*exceptionstack)->prev->mustcatch = (*exceptionstack)->mustcatch;
  72.         mcl_popexceptionframe(exceptionstack);
  73.         longjmp((*exceptionstack)->context, (*exceptionstack)->state = MCL_CATCH);
  74.     }
  75.  
  76.     exit(EXIT_FAILURE);
  77. }
  78.  
  79. #define try                                                                                                                                         \
  80.     for (bool mcl_done = (mcl_pushexceptionframe(&mcl_exceptionstack), false); mcl_done != true;                                                    \
  81.          mcl_exceptionstack->state != MCL_FINALLY ? longjmp(mcl_exceptionstack->context, mcl_exceptionstack->state = MCL_FINALLY)                   \
  82.                                                   : mcl_exceptionstack->mustcatch ? mcl_throw(&mcl_exceptionstack, mcl_exceptionstack->exception)   \
  83.                                                                                   : (mcl_done = true,                                               \
  84.                                                                                      mcl_popexceptionframe(&mcl_exceptionstack)))                   \
  85.         if (setjmp(mcl_exceptionstack->context) == MCL_TRY)
  86.  
  87. #define catch(e)                                                                                                                                    \
  88.         else if (mcl_exceptionstack->state == MCL_CATCH && mcl_exceptionstack->exception == (e) && !(mcl_exceptionstack->mustcatch = false))
  89.  
  90. #define mcl_catchany                                                                                                                                \
  91.         else if (mcl_exceptionstack->state == MCL_CATCH)
  92.  
  93. #define finally                                                                                                                                     \
  94.         else if (mcl_exceptionstack->state == MCL_FINALLY)
  95.  
  96. #define throw(e)                                                                                                                                    \
  97.     do                                                                                                                                              \
  98.         mcl_throw(&mcl_exceptionstack, mcl_exceptionstack->exception = e);                                                                          \
  99.     while (false)
  100.  
  101. #if __STDC_VERSION__ < 201112L
  102.     #undef noreturn
  103.     #undef thread_local
  104. #elif defined(__STDC_NO_THREADS__)
  105.     #undef thread_local
  106. #endif
  107.  
  108. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement