PageRenderTime 57ms CodeModel.GetById 21ms RepoModel.GetById 11ms app.codeStats 0ms

/lib_duktape/src-separate/duk_error.h

https://bitbucket.org/xixs/lua
C Header | 250 lines | 110 code | 44 blank | 96 comment | 15 complexity | 76b5aee466d327ac7751eea9aa988c72 MD5 | raw file
Possible License(s): Zlib, BSD-3-Clause, CC0-1.0, GPL-3.0, GPL-2.0, CPL-1.0, MPL-2.0-no-copyleft-exception, LGPL-2.0, LGPL-2.1, LGPL-3.0, 0BSD, Cube
  1. /*
  2. * Error handling macros, assertion macro, error codes.
  3. *
  4. * There are three level of 'errors':
  5. *
  6. * 1. Ordinary errors, relative to a thread, cause a longjmp, catchable.
  7. * 2. Fatal errors, relative to a heap, cause fatal handler to be called.
  8. * 3. Panic errors, unrelated to a heap and cause a process exit.
  9. *
  10. * Panics are used by the default fatal error handler and by debug code
  11. * such as assertions. By providing a proper fatal error handler, user
  12. * code can avoid panics in non-debug builds.
  13. */
  14. #ifndef DUK_ERROR_H_INCLUDED
  15. #define DUK_ERROR_H_INCLUDED
  16. /*
  17. * Error codes: defined in duktape.h
  18. *
  19. * Error codes are used as a shorthand to throw exceptions from inside
  20. * the implementation. The appropriate Ecmascript object is constructed
  21. * based on the code. Ecmascript code throws objects directly. The error
  22. * codes are defined in the public API header because they are also used
  23. * by calling code.
  24. */
  25. /*
  26. * Normal error
  27. *
  28. * Normal error is thrown with a longjmp() through the current setjmp()
  29. * catchpoint record in the duk_heap. The 'curr_thread' of the duk_heap
  30. * identifies the throwing thread.
  31. *
  32. * Error formatting is not always necessary but there are no separate calls
  33. * (to minimize code size). Error object creation will consume a considerable
  34. * amount of time, compared to which formatting is probably trivial. Note
  35. * that special formatting (provided by DUK_DEBUG macros) is NOT available.
  36. *
  37. * The _RAW variants allow the caller to specify file and line. This makes
  38. * it easier to write checked calls which want to use the call site of the
  39. * checked function, not the error macro call inside the checked function.
  40. *
  41. * We prefer the standard variadic macros; if they are not available, we
  42. * fall back to awkward hacks.
  43. */
  44. #ifdef DUK_USE_VERBOSE_ERRORS
  45. #ifdef DUK_USE_VARIADIC_MACROS
  46. /* __VA_ARGS__ has comma issues for empty lists, so we mandate at least 1 argument for '...' (format string) */
  47. #define DUK_ERROR(thr,err,...) duk_err_handle_error(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (err), __VA_ARGS__)
  48. #define DUK_ERROR_RAW(file,line,thr,err,...) duk_err_handle_error((file), (line), (thr), (err), __VA_ARGS__)
  49. #else /* DUK_USE_VARIADIC_MACROS */
  50. /* Parameter passing here is not thread safe. We rely on the __FILE__
  51. * pointer being a constant which can be passed through a global.
  52. */
  53. #define DUK_ERROR \
  54. (void) (duk_err_file_stash = (const char *) DUK_FILE_MACRO, \
  55. duk_err_line_stash = (duk_int_t) DUK_LINE_MACRO, \
  56. duk_err_handle_error_stash) /* arguments follow */
  57. #define DUK_ERROR_RAW duk_err_handle_error
  58. #endif /* DUK_USE_VARIADIC_MACROS */
  59. #else /* DUK_USE_VERBOSE_ERRORS */
  60. #ifdef DUK_USE_VARIADIC_MACROS
  61. #define DUK_ERROR(thr,err,...) duk_err_handle_error((thr), (err))
  62. #define DUK_ERROR_RAW(file,line,thr,err,...) duk_err_handle_error((thr), (err))
  63. #else /* DUK_USE_VARIADIC_MACROS */
  64. /* This is sub-optimal because arguments will be passed but ignored, and the strings
  65. * will go into the object file. Can't think of how to do this portably and still
  66. * relatively conveniently.
  67. */
  68. #define DUK_ERROR duk_err_handle_error_nonverbose1
  69. #define DUK_ERROR_RAW duk_err_handle_error_nonverbose2
  70. #endif /* DUK_USE_VARIADIC_MACROS */
  71. #endif /* DUK_USE_VERBOSE_ERRORS */
  72. /*
  73. * Fatal error
  74. *
  75. * There are no fatal error macros at the moment. There are so few call
  76. * sites that the fatal error handler is called directly.
  77. */
  78. /*
  79. * Panic error
  80. *
  81. * Panic errors are not relative to either a heap or a thread, and cause
  82. * DUK_PANIC() macro to be invoked. Unlesa a user provides DUK_OPT_PANIC_HANDLER,
  83. * DUK_PANIC() calls a helper which prints out the error and causes a process
  84. * exit.
  85. *
  86. * The user can override the macro to provide custom handling. A macro is
  87. * used to allow the user to have inline panic handling if desired (without
  88. * causing a potentially risky function call).
  89. *
  90. * Panics are only used in debug code such as assertions, and by the default
  91. * fatal error handler.
  92. */
  93. #if defined(DUK_USE_PANIC_HANDLER)
  94. /* already defined, good */
  95. #define DUK_PANIC(code,msg) DUK_USE_PANIC_HANDLER((code),(msg))
  96. #else
  97. #define DUK_PANIC(code,msg) duk_default_panic_handler((code),(msg))
  98. #endif /* DUK_USE_PANIC_HANDLER */
  99. /*
  100. * Assert macro: failure causes panic.
  101. */
  102. #ifdef DUK_USE_ASSERTIONS
  103. /* the message should be a compile time constant without formatting (less risk);
  104. * we don't care about assertion text size because they're not used in production
  105. * builds.
  106. */
  107. #define DUK_ASSERT(x) do { \
  108. if (!(x)) { \
  109. DUK_PANIC(DUK_ERR_ASSERTION_ERROR, \
  110. "assertion failed: " #x \
  111. " (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
  112. } \
  113. } while (0)
  114. #else /* DUK_USE_ASSERTIONS */
  115. #define DUK_ASSERT(x) do { /* assertion omitted */ } while(0)
  116. #endif /* DUK_USE_ASSERTIONS */
  117. /* this variant is used when an assert would generate a compile warning by
  118. * being always true (e.g. >= 0 comparison for an unsigned value
  119. */
  120. #define DUK_ASSERT_DISABLE(x) do { /* assertion disabled */ } while(0)
  121. /*
  122. * Assertion helpers
  123. */
  124. #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
  125. #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) do { \
  126. DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
  127. } while (0)
  128. #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) do { \
  129. if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
  130. DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
  131. } \
  132. } while (0)
  133. #else
  134. #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) /* no refcount check */
  135. #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) /* no refcount check */
  136. #endif
  137. #define DUK_ASSERT_TOP(ctx,n) DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
  138. #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
  139. #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) do { \
  140. duk_double_union assert_tmp_du; \
  141. assert_tmp_du.d = (dval); \
  142. DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&assert_tmp_du)); \
  143. } while (0)
  144. #else
  145. #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) /* nop */
  146. #endif
  147. /*
  148. * Helper for valstack space
  149. *
  150. * Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
  151. * required for its own use, and any child calls which are not (a) Duktape API calls
  152. * or (b) Duktape calls which involve extending the valstack (e.g. getter call).
  153. */
  154. #define DUK_VALSTACK_ASSERT_EXTRA 5 /* this is added to checks to allow for Duktape
  155. * API calls in addition to function's own use
  156. */
  157. #if defined(DUK_USE_ASSERTIONS)
  158. #define DUK_ASSERT_VALSTACK_SPACE(thr,n) do { \
  159. DUK_ASSERT((thr) != NULL); \
  160. DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
  161. } while (0)
  162. #else
  163. #define DUK_ASSERT_VALSTACK_SPACE(thr,n) /* no valstack space check */
  164. #endif
  165. /*
  166. * Prototypes
  167. */
  168. #ifdef DUK_USE_VERBOSE_ERRORS
  169. #ifdef DUK_USE_VARIADIC_MACROS
  170. DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
  171. #else /* DUK_USE_VARIADIC_MACROS */
  172. #if !defined(DUK_SINGLE_FILE)
  173. DUK_INTERNAL_DECL const char *duk_err_file_stash;
  174. DUK_INTERNAL_DECL duk_int_t duk_err_line_stash;
  175. #endif /* !DUK_SINGLE_FILE */
  176. DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
  177. DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_stash(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
  178. #endif /* DUK_USE_VARIADIC_MACROS */
  179. #else /* DUK_USE_VERBOSE_ERRORS */
  180. #ifdef DUK_USE_VARIADIC_MACROS
  181. DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
  182. #else /* DUK_USE_VARIADIC_MACROS */
  183. DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_nonverbose1(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
  184. DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_nonverbose2(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
  185. #endif /* DUK_USE_VARIADIC_MACROS */
  186. #endif /* DUK_USE_VERBOSE_ERRORS */
  187. #ifdef DUK_USE_VERBOSE_ERRORS
  188. DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line));
  189. #else
  190. DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
  191. #endif
  192. DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
  193. #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
  194. DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_bool_t noblame_fileline);
  195. #endif
  196. #if defined(DUK_USE_AUGMENT_ERROR_THROW)
  197. DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
  198. #endif
  199. DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));
  200. DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg));
  201. #if !defined(DUK_USE_PANIC_HANDLER)
  202. DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_panic_handler(duk_errcode_t code, const char *msg));
  203. #endif
  204. DUK_INTERNAL_DECL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type);
  205. DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
  206. #endif /* DUK_ERROR_H_INCLUDED */