33 #define P00_JMP_BUF_TOP P99_THREAD_LOCAL(p00_jmp_buf_top)
36 void p00_jmp_skip(p00_jmp_buf0 * p00_des) {
37 P99_LIFO(p00_jmp_buf0_ptr)* p00_head = &P00_JMP_BUF_TOP;
38 p00_jmp_buf0 * p00_ret = 0;
41 }
while (p00_ret && (p00_ret != p00_des));
45 void p00_jmp_push(p00_jmp_buf0 * p00_des) {
71 p00_constraint_report(p00_cond, 0, 0, 0);
76 void p00_jmp_abort(
errno_t p00_cond,
char const* p00_file,
char const* p00_context,
char const* p00_info) {
77 p00_constraint_report(p00_cond, p00_file, p00_context, p00_info);
79 if (p00_func == exit_handler_s) {
81 set_constraint_handler_s(abort_handler_s);
90 void p00_jmp_throw(
errno_t p00_cond, p00_jmp_buf0 * p00_top,
char const* p00_file,
char const* p00_context,
char const* p00_info) {
91 if (p00_file) P00_JMP_BUF_FILE = p00_file;
92 if (p00_context) P00_JMP_BUF_CONTEXT = p00_context;
93 if (p00_info) P00_JMP_BUF_INFO = p00_info;
95 if (
P99_LIKELY(p00_top)) p00_longjmp(p00_top, p00_cond);
96 else p00_jmp_abort(p00_cond, p00_file, p00_context, p00_info);
128 #define P99_THROW(X) p00_jmp_throw((X), p00_unwind_top, P99_STRINGIFY(__LINE__), __func__, "throw")
132 void p00_throw_errno(p00_jmp_buf0 * p00_top,
errno_t p00_def,
char const* p00_file,
char const* p00_context,
char const* p00_info) {
134 if (!p00_err) p00_err = (p00_def ? p00_def :
EINVAL);
136 p00_jmp_throw(p00_err, p00_top, p00_file, p00_context, p00_info);
140 void p00_throw_call_range(p00_jmp_buf0 * p00_top,
errno_t p00_sign,
char const* p00_file,
char const* p00_context,
char const* p00_info) {
144 case ERANGE:
if (p00_sign) p00_err = p00_sign;
147 p00_jmp_throw(p00_err, p00_top, p00_file, p00_context, p00_info);
150 #define P00_ALMOST_ZERO(X) \
152 ((X) > 0 ? (X) <= FLT_MIN : -(X) >= FLT_MIN), \
153 (float, ((X) > 0 ? (X) <= LDBL_MIN : -(X) >= LDBL_MIN)), \
154 (long double, ((X) > 0 ? (X) <= LDBL_MIN : -(X) >= LDBL_MIN)) \
161 #define P00_THROW_CALL_RANGE(T, F, ...) \
163 T P99_PASTE2(p00_throw_call_range_, T)(p00_jmp_buf0 * p00_top, \
165 char const* p00_file, \
166 char const* p00_context, \
167 char const* p00_info) { \
168 if (P99_UNLIKELY(P99_IS_ONE(p00_val, 0, __VA_ARGS__)) \
169 P99_IF_EQ_1(F)(|| P99_UNLIKELY(P00_ALMOST_ZERO(p00_val)))() \
171 p00_throw_call_range(p00_top, \
176 ? ((p00_val >= 1) ? INT_MAX : 0) \
177 : (((T)-p00_val >= 1) ? INT_MIN : 0)), \
178 p00_file, p00_context, p00_info); \
181 P99_MACRO_END(P00_THROW_CALL_RANGE, T)
183 P00_THROW_CALL_RANGE(_Bool, 0, 1);
184 P00_THROW_CALL_RANGE(
char, 0, CHAR_MAX, CHAR_MIN);
185 P00_THROW_CALL_RANGE(
schar, 0, SCHAR_MAX, SCHAR_MIN);
186 P00_THROW_CALL_RANGE(
short, 0, SHRT_MAX, SHRT_MIN);
187 P00_THROW_CALL_RANGE(
int, 0, INT_MAX, INT_MIN);
188 P00_THROW_CALL_RANGE(
long, 0, LONG_MAX, LONG_MIN);
189 P00_THROW_CALL_RANGE(
llong, 0, LLONG_MAX, LLONG_MIN);
190 P00_THROW_CALL_RANGE(
uchar, 0, UCHAR_MAX);
191 P00_THROW_CALL_RANGE(
ushort, 0, USHRT_MAX);
192 P00_THROW_CALL_RANGE(
unsigned, 0, UINT_MAX);
193 P00_THROW_CALL_RANGE(
ulong, 0, ULONG_MAX);
194 P00_THROW_CALL_RANGE(
ullong, 0, ULLONG_MAX);
196 P00_THROW_CALL_RANGE(
float, 1, HUGE_VALF, -HUGE_VALF);
199 P00_THROW_CALL_RANGE(
double, 1, HUGE_VAL, -HUGE_VAL);
202 P00_THROW_CALL_RANGE(
ldouble, 1, HUGE_VALL, -HUGE_VALL);
205 #define P00_THROW_CALL_RANGE_CASE(T) ,(T, P99_PASTE2(p00_throw_call_range_, T))
207 #define P00_THROW_CALL_RANGE_(F, CASES, ...) \
208 P99_GENERIC((F)(__VA_ARGS__), P00_ROBUST CASES) \
209 (p00_unwind_top, F(__VA_ARGS__), P99_STRINGIFY(__LINE__), __func__, #F ", range check")
211 #define P99_THROW_CALL_RANGE_ARG_0 permitted
212 #define P99_THROW_CALL_RANGE_ARG_1 permitted
213 #define P99_THROW_CALL_RANGE_ARG_2 permitted
214 #define P99_THROW_CALL_RANGE_ARG_3 permitted
215 #define P99_THROW_CALL_RANGE_ARG_4 permitted
251 #define P99_THROW_CALL_RANGE(F, ...) \
252 P00_THROW_CALL_RANGE_ \
254 (P99_SER(P00_THROW_CALL_RANGE_CASE, P99_STD_REAL_TYPES)), \
270 #if defined(noreturn) || defined(_Noreturn)
271 #define P99_THROW_ERRNO p00_throw_errno(p00_unwind_top, EINVAL, P99_STRINGIFY(__LINE__), __func__, "THROW_ERRNO")
273 #define P99_THROW_ERRNO \
275 errno_t p00_err = errno; \
276 if (!p00_err) p00_err = EINVAL; \
278 P99_THROW(p00_err); \
283 int p00_throw_call_zero(
int p00_err,
285 p00_jmp_buf0 * p00_top,
286 char const* p00_file,
287 char const* p00_context,
288 char const* p00_info) {
289 if (
P99_UNLIKELY(p00_err)) p00_throw_errno(p00_top, p00_def, p00_file, p00_context, p00_info);
312 #define P99_THROW_CALL_ZERO(F, E, ...) \
313 p00_throw_call_zero(F(__VA_ARGS__), E, p00_unwind_top, P99_STRINGIFY(__LINE__), __func__, #F ", non-zero return")
325 #define P99_THROW_ASSERT(E, ...) \
326 (void)p00_throw_call_zero(!(__VA_ARGS__), E, p00_unwind_top, P99_STRINGIFY(__LINE__), __func__, "failed assertion: ``" #__VA_ARGS__ "''")
328 #define P99_THROW_ASSERT(...) P99_NOP
339 #define P99_THROW_CALL_NOT_ZERO(F, E, ...) \
340 p00_throw_call_zero(!F(__VA_ARGS__), E, p00_unwind_top, P99_STRINGIFY(__LINE__), __func__, #F ", zero return")
343 int p00_throw_call_thrd(
int p00_err,
344 p00_jmp_buf0 * p00_top,
345 char const* p00_file,
346 char const* p00_context,
347 char const* p00_info) {
349 p00_jmp_throw(p00_err, p00_top, p00_file, p00_context, p00_info);
374 #define P99_THROW_CALL_THRD(F, ...) \
375 p00_throw_call_thrd(F(__VA_ARGS__), p00_unwind_top, P99_STRINGIFY(__LINE__), __func__, #F ", no thrd_success")
378 int p00_throw_call_neg(
int p00_neg,
380 p00_jmp_buf0 * p00_top,
381 char const* p00_file,
382 char const* p00_context,
383 char const* p00_info) {
384 if (
P99_UNLIKELY(p00_neg < 0)) p00_throw_errno(p00_top, p00_def, p00_file, p00_context, p00_info);
388 #define P00_THROW_CALL_NEG(F, E, ...) \
389 p00_throw_call_neg(F(__VA_ARGS__), E, p00_unwind_top, P99_STRINGIFY(__LINE__), __func__, #F ", neg return")
410 #define P99_THROW_CALL_NEG(F, E, ...) P00_THROW_CALL_NEG(F, E, __VA_ARGS__)
413 int p00_throw_call_negate(
int p00_neg,
415 p00_jmp_buf0 * p00_top,
416 char const* p00_file,
417 char const* p00_context,
418 char const* p00_info) {
420 if (
P99_UNLIKELY(p00_neg < 0)) p00_jmp_throw(-p00_neg, p00_top, p00_file, p00_context, p00_info);
424 #define P00_THROW_CALL_NEGATE(F, E, ...) \
425 p00_throw_call_negate(F(__VA_ARGS__), E, p00_unwind_top, P99_STRINGIFY(__LINE__), __func__, #F ", neg return")
451 #define P99_THROW_CALL_NEGATE(F, E, ...) P00_THROW_CALL_NEGATE(F, E, __VA_ARGS__)
454 void* p00_throw_call_voidp(
void* p00_p,
456 p00_jmp_buf0 * p00_top,
457 char const* p00_file,
458 char const* p00_context,
459 char const* p00_info) {
460 if (
P99_UNLIKELY(!p00_p || (p00_p == (
void*)-1))) p00_throw_errno(p00_top, p00_def, p00_file, p00_context, p00_info);
464 #define P00_THROW_CALL_VOIDP(F, E, ...) \
465 p00_throw_call_voidp(F(__VA_ARGS__), E, p00_unwind_top, P99_STRINGIFY(__LINE__), __func__, #F ", invalid return")
489 #define P99_THROW_CALL_VOIDP(F, E, ...) P00_THROW_CALL_VOIDP(F, E, __VA_ARGS__)
497 #define P99_RETHROW p00_jmp_throw(p00_code, p00_unwind_top, 0, 0, 0)
590 for (register unsigned p00_pha = 0; p00_pha < 2u; ++p00_pha) \
594 P00_BLK_BEFORE(p00_jmp_push(p00_unwind_top)) \
597 #define P00_FINALLY \
598 while (0); else case 0: \
600 P00_BLK_BEFORE(p00_code = p00_unwind_top[0].p00_code) \
601 P00_BLK_BEFORE(p00_unw = !!p00_code) \
603 P00_BLK_BEFORE(p00_pha = 2u) \
605 P00_BLK_BEFORE(p00_jmp_skip(p00_unwind_top)) \
608 P00_BLK_DECL(p00_jmp_buf0*, p00_unwind_top, p00_unwind_prev)
633 #define P99_FINALLY \
635 P00_BLK_AFTER(p00_unw ? P99_RETHROW : P99_NOP)
679 #define P99_CATCH(...) \
681 P99_IF_EMPTY(__VA_ARGS__)()(P00_BLK_BEFORE(__VA_ARGS__ = p00_code)) \
682 P00_BLK_BEFORE(p00_unw = 0) \
683 P00_BLK_AFTER(p00_code ? (void)((P00_JMP_BUF_FILE = 0), (P00_JMP_BUF_CONTEXT = 0)) : P99_NOP)