summaryrefslogtreecommitdiff
path: root/src/setjmp/_setjmp.h
blob: ec478e3ae3b081a53bc9f0b153278d43f60ea2b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#ifndef ___SETJMP_H__
#define ___SETJMP_H__

#include <setjmp.h>
#include "_safety.h"

extern struct __setjmp_h {
	struct valid_jmp_buf {
		unsigned long int *buf;
		unsigned long int sum;
	} *valid;
	size_t nvalid;
} __setjmp_h;

#ifndef NDEBUG
static inline unsigned long int jmp_sum(jmp_buf env)
{
	long unsigned int ret = 0;
	for (size_t i = 0; i < sizeof(jmp_buf) / sizeof(unsigned long int); i++) {
		ret ^= env[i];
	}
	return ret;
}

#define ADD_JMP_BUF(__env) do { \
	struct valid_jmp_buf __v = { \
		(unsigned long int *)(__env), \
		jmp_sum(__env), \
	}; \
	ADD_PREV(__v, __setjmp_h.valid, __setjmp_h.nvalid); \
} while (0)

#define ASSERT_JMP_BUF(__env) do { \
	int __found = 0; \
	for (size_t __i = 0; __i < __setjmp_h.nvalid; __i++) { \
		if (__setjmp_h.valid[__i].buf == (unsigned long int *)(__env)) { \
			if (jmp_sum(__env) != __setjmp_h.valid[__i].sum) { \
				UNDEFINED("jmp_buf has been modified!"); \
			} \
			__found = 1; \
			break; \
		} \
	} \
	if (!__found) { \
		UNDEFINED("In call to longjmp(): Provided jmp_buf was not returned by a previous call to setjmp()"); \
	} \
} while (0)

#else
#define ADD_JMP_BUF(__env) (void)(__env)
#define ASSERT_JMP_BUF(__env) (void)(__env)
#endif

#endif