View difference between Paste ID: uijqUg32 and XrZUxNxh
SHOW: | | - or go back to the newest paste.
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_