summaryrefslogtreecommitdiff
path: root/src/setjmp/_setjmp.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/setjmp/_setjmp.h')
-rw-r--r--src/setjmp/_setjmp.h58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/setjmp/_setjmp.h b/src/setjmp/_setjmp.h
new file mode 100644
index 00000000..1bf19fe6
--- /dev/null
+++ b/src/setjmp/_setjmp.h
@@ -0,0 +1,58 @@
+#ifndef ___SETJMP_H__
+#define ___SETJMP_H__
+
+#include <setjmp.h>
+#include "_safety.h"
+
+struct __valid_jmp_buf {
+};
+
+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