Advertisement
Guest User

Untitled

a guest
Jun 30th, 2015
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.73 KB | None | 0 0
  1. #ifndef SGL_EXCEPTION_H_
  2. #define SGL_EXCEPTION_H_
  3.  
  4. ////////////////////////////////////////////////////////////
  5. // Headers
  6. ////////////////////////////////////////////////////////////
  7. #include <iso646.h>
  8. #include <setjmp.h>
  9. #include <stdbool.h>
  10. #include <stdnoreturn.h>
  11.  
  12. ////////////////////////////////////////////////////////////
  13. // Exceptions
  14.  
  15. /**
  16. * @brief Basic exception type.
  17. *
  18. * The exceptions must be integers to satisfy the longjmp
  19. * function. The names used here are those of the exceptions
  20. * defined in the C++ <stdexcept> header and some other ones
  21. * from the C++ standard library. The mechanism cannot be
  22. * extended with user-defined types.
  23. *
  24. * The default sgl_exception is not meant to be thrown nor printed.
  25. * It only exists so that it can be used to catch any exception in
  26. * a catch block.
  27. */
  28. typedef enum
  29. {
  30. sgl_exception = -1,
  31. sgl_logic_error,
  32. sgl_domain_error,
  33. sgl_invalid_argument,
  34. sgl_length_error,
  35. sgl_out_of_range,
  36. sgl_runtime_error,
  37. sgl_range_error,
  38. sgl_overflow_error,
  39. sgl_underflow_error,
  40. sgl_bad_alloc,
  41. sgl_detail_exceptions_number
  42. } sgl_exception_t;
  43.  
  44. #ifndef SGL_MAX_EXCEPTIONS
  45.  
  46. /**
  47. * @def SGL_MAX_EXCEPTIONS
  48. *
  49. * Maximum number of nested exception blocks allowed in SGL.
  50. * It can be set to N with the compiler option
  51. * -DSGL_MAX_EXCEPTIONS=N
  52. */
  53. #define SGL_MAX_EXCEPTIONS 32
  54.  
  55. #endif
  56.  
  57. ////////////////////////////////////////////////////////////
  58. // Global implementation variables
  59.  
  60. // Global array of jmp_buf
  61. extern jmp_buf sgl_detail_buf_array[SGL_MAX_EXCEPTIONS];
  62.  
  63. // Whether we are in an exception catch bloc
  64. extern bool sgl_detail_in_catch_bloc[SGL_MAX_EXCEPTIONS];
  65.  
  66. // Current exception index
  67. extern int sgl_detail_exceptions_index;
  68.  
  69. // Current exception
  70. extern sgl_exception_t sgl_detail_current_exception;
  71.  
  72. ////////////////////////////////////////////////////////////
  73. // Exception handling functions
  74.  
  75. /**
  76. * Throws the given exception.
  77. */
  78. noreturn void sgl_throw(sgl_exception_t exception);
  79.  
  80. /**
  81. * Rethrows the current exception.
  82. */
  83. noreturn void sgl_rethrow();
  84.  
  85. /**
  86. * Returns whether an exception "inherits" from another
  87. * exception so that it is possible to catch several
  88. * related exceptions in a single catch block.
  89. */
  90. bool sgl_exception_inherits_from(sgl_exception_t exception,
  91. sgl_exception_t from);
  92.  
  93. /**
  94. * Returns the error message associated to the given
  95. * exception.
  96. */
  97. const char* sgl_what(sgl_exception_t exception);
  98.  
  99. ////////////////////////////////////////////////////////////
  100. // Exception handling macros
  101.  
  102. /**
  103. * @def sgl_try
  104. *
  105. * Beginning of an exception try bloc.
  106. */
  107. #define sgl_try
  108. do {
  109. ++sgl_detail_exceptions_index;
  110. sgl_detail_in_catch_bloc[sgl_detail_exceptions_index] = false;
  111. if (not setjmp(sgl_detail_buf_array[sgl_detail_exceptions_index]))
  112. {
  113.  
  114. /**
  115. * @def sgl_catch(exception)
  116. *
  117. * Catches an exception and execute the following bloc
  118. * of code if it corresponds to the thrown exceptions
  119. */
  120. #define sgl_catch(exception)
  121. }
  122. else if (sgl_exception_inherits_from(sgl_detail_current_exception, exception))
  123. {
  124. sgl_detail_in_catch_bloc[sgl_detail_exceptions_index] = true;
  125. --sgl_detail_exceptions_index;
  126.  
  127. /**
  128. * @def sgl_endtry
  129. *
  130. * If something was thrown but nothing caught, throws it again.
  131. * Prints the current exception and aborts with -1 if we are not
  132. * into a catch block.
  133. */
  134. #define sgl_endtry
  135. }
  136. else
  137. {
  138. if (sgl_detail_exceptions_index > 0)
  139. {
  140. --sgl_detail_exceptions_index;
  141. sgl_rethrow();
  142. }
  143. else
  144. {
  145. sgl_terminate();
  146. }
  147. }
  148. --sgl_detail_exceptions_index;
  149. } while (0);
  150.  
  151. ////////////////////////////////////////////////////////////
  152. // Program termination utilities
  153.  
  154. /**
  155. * Type of the function called by sgl_terminate. While it does
  156. * not appear in the typedef, termination handlers should be
  157. * noreturn functions.
  158. */
  159. typedef void (*sgl_terminate_handler)();
  160.  
  161. /**
  162. * @return the current termination handler.
  163. */
  164. sgl_terminate_handler sgl_get_terminate();
  165.  
  166. /**
  167. * Sets a new termination handler. If a new_handler is NULL,
  168. * this functions sets back the default termination handler.
  169. *
  170. * @param new_handler New termination handler.
  171. * @return the old termination handler.
  172. */
  173. sgl_terminate_handler sgl_set_terminate(sgl_terminate_handler new_handler);
  174.  
  175. /**
  176. * Calls the current termination handler. The default one
  177. * calls abort. This function is called when an exception
  178. * is thrown and not caught.
  179. */
  180. noreturn void sgl_terminate();
  181.  
  182. #endif // SGL_EXCEPTION_H_
  183.  
  184. #include <assert.h>
  185. #include <stdint.h>
  186. #include <stdio.h>
  187. #include <stdlib.h>
  188. #include <sgl/exception.h>
  189.  
  190. ////////////////////////////////////////////////////////////
  191. // Global implementation variables
  192.  
  193. jmp_buf sgl_detail_buf_array[SGL_MAX_EXCEPTIONS];
  194.  
  195. bool sgl_detail_in_catch_bloc[SGL_MAX_EXCEPTIONS];
  196.  
  197. int sgl_detail_exceptions_index = -1;
  198.  
  199. sgl_exception_t sgl_detail_current_exception;
  200.  
  201. ////////////////////////////////////////////////////////////
  202. // Throwing functions
  203.  
  204. void sgl_throw(sgl_exception_t exception)
  205. {
  206. assert(exception != sgl_exception);
  207. sgl_detail_current_exception = exception;
  208.  
  209. // Handle exceptions out of a try block
  210. if (sgl_detail_exceptions_index == -1)
  211. {
  212. sgl_terminate();
  213. }
  214.  
  215. if (sgl_detail_in_catch_bloc[sgl_detail_exceptions_index])
  216. {
  217. --sgl_detail_exceptions_index;
  218. }
  219. longjmp(sgl_detail_buf_array[sgl_detail_exceptions_index], true);
  220. }
  221.  
  222. noreturn void sgl_rethrow()
  223. {
  224. sgl_throw(sgl_detail_current_exception);
  225. }
  226.  
  227. ////////////////////////////////////////////////////////////
  228. // Exceptions inheritance emulation
  229.  
  230. bool sgl_exception_inherits_from(sgl_exception_t exception,
  231. sgl_exception_t from)
  232. {
  233. static uint_fast16_t inheritance[] = {
  234. 1 << sgl_logic_error,
  235. 1 << sgl_domain_error | 1 << sgl_logic_error,
  236. 1 << sgl_invalid_argument | 1 << sgl_logic_error,
  237. 1 << sgl_length_error | 1 << sgl_logic_error,
  238. 1 << sgl_out_of_range | 1 << sgl_logic_error,
  239. 1 << sgl_runtime_error,
  240. 1 << sgl_range_error | 1 << sgl_runtime_error,
  241. 1 << sgl_overflow_error | 1 << sgl_runtime_error,
  242. 1 << sgl_underflow_error | 1 << sgl_runtime_error,
  243. 1 << sgl_bad_alloc
  244. };
  245.  
  246. if (from == sgl_exception)
  247. {
  248. // Everything inherits from exception
  249. return true;
  250. }
  251. return inheritance[exception] & (1 << from);
  252. }
  253.  
  254. ////////////////////////////////////////////////////////////
  255. // Exception message function
  256.  
  257. const char* sgl_what(sgl_exception_t exception)
  258. {
  259. static const char* const messages[] = {
  260. "logic error",
  261. "domain error",
  262. "invalid argument",
  263. "length error",
  264. "out of range error",
  265. "runtime error",
  266. "range error",
  267. "overflow error",
  268. "underflow error",
  269. "bad allocation"
  270. };
  271.  
  272. if (exception < 0 || exception >= sgl_detail_exceptions_number)
  273. {
  274. return "unknown error";
  275. }
  276. return messages[exception];
  277. }
  278.  
  279. ////////////////////////////////////////////////////////////
  280. // Program termination utilities
  281.  
  282. // Default termination function
  283. static noreturn void default_terminate()
  284. {
  285. printf("Terminate called after throwing an exception.n");
  286. printf(" what(): %sn", sgl_what(sgl_detail_current_exception));
  287. abort();
  288. }
  289.  
  290. // Current termination function
  291. static sgl_terminate_handler current_terminate = default_terminate;
  292.  
  293. sgl_terminate_handler sgl_get_terminate()
  294. {
  295. return current_terminate;
  296. }
  297.  
  298. sgl_terminate_handler sgl_set_terminate(sgl_terminate_handler new_handler)
  299. {
  300. sgl_terminate_handler old_handler = sgl_get_terminate();
  301. if (new_handler == NULL)
  302. {
  303. new_handler = default_terminate;
  304. }
  305. current_terminate = new_handler;
  306. return old_handler;
  307. }
  308.  
  309. noreturn void sgl_terminate()
  310. {
  311. current_terminate();
  312. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement