1 /*
2 ******************************
3 * Object Oriented Programming in C
4 *
5 * Author: Laurent Deniau, Laurent.Deniau@cern.ch
6 *
7 * License Public Domain Without Warranty
8 *
9 * For more information, please see the paper:
10 * http://cern.ch/Laurent.Deniau/html/oopc/exception.html
11 *
12 ******************************
13 */
14
15 #ifndef EXCEPTION_H
16 #define EXCEPTION_H
17
18 #ifndef __STDC__
19 # error "exception.h needs ISO C compiler to work properly"
20 #endif
21
22 #include <setjmp.h>
23
24 /*
25 some useful macros
26 */
27
28 #define _makeConcat_(a,b) a ## b
29 #define _concat_(a,b) _makeConcat_(a,b)
30
31 #define _makeString_(a) # a
32 #define _string_(a) _makeString_(a)
33
34 /*
35 choose context savings
36 */
37
38 #ifdef sigsetjmp
39 # define _save_context_buffer_(context) sigsetjmp(context, 1)
40 # define _restore_context_buffer_(context, val) siglongjmp(context, val)
41 #else
42 # define _save_context_buffer_(context) setjmp(context)
43 # define _restore_context_buffer_(context, val) longjmp(context, val)
44 #endif
45
46 /*
47 some hidden types used to handle exceptions
48 */
49
50 /* type of stack of protected pointer */
51 struct _protectedPtr_ {
52 struct _protectedPtr_ *next;
53 void *ptr;
54 void (*func)(void*);
55 };
56
57 /* type of stack of exception */
58 struct _exceptionContext_ {
59 struct _exceptionContext_ *next;
60 struct _protectedPtr_ *stack;
61 jmp_buf context;
62 };
63
64 extern struct _exceptionContext_ *const _returnExceptionContext_;
65 extern struct _exceptionContext_ *_currentExceptionContext_;
66
67 /* exception keywords */
68 #define try \
69 do { \
70 struct _exceptionContext_ *const _returnExceptionContext0_ = \
71 _returnExceptionContext_; \
72 struct _exceptionContext_ *const volatile _returnExceptionContext_ = \
73 _returnExceptionContext0_ ? _returnExceptionContext0_: \
74 _currentExceptionContext_; \
75 struct _exceptionContext_ _localExceptionContext_ = \
76 { _currentExceptionContext_ }; \
77 _currentExceptionContext_ = &_localExceptionContext_; \
78 (void)_returnExceptionContext_; \
79 do { \
80 int const exception = \
81 _save_context_buffer_(_currentExceptionContext_->context); \
82 if (!exception) {
83
84 #define catch(except) \
85 } else if ((int)(except) == exception) { \
86 _currentExceptionContext_ = _currentExceptionContext_->next;
87
88 #define catch_any \
89 } else { \
90 _currentExceptionContext_ = _currentExceptionContext_->next;
91
92 #define endtry \
93 } \
94 } while(0); \
95 if (_currentExceptionContext_ == &_localExceptionContext_) { \
96 _currentExceptionContext_ = _currentExceptionContext_->next; \
97 } \
98 } while(0)
99
100 #define rethrow throw(exception)
101 #define break_try break
102 #define return_try(...) \
103 do { \
104 _currentExceptionContext_ = _returnExceptionContext_; \
105 return __VA_ARGS__; \
106 } while(0)
107
108 #ifdef DEBUG_THROW
109 #define throw(except) \
110 _exceptionThrowDebug_(__FILE__, __LINE__, __func__, \
111 _string_(except), (int)(except))
112 #else
113 #define throw(except) _exceptionThrow_((int)(except))
114 #endif /* DEBUG_THROW */
115
116 /*
117 pointer protection
118 */
119
120 #define protectPtr(ptr, func) \
121 struct _protectedPtr_ _concat_(_protected_, ptr) = \
122 _protectPtr_(&_concat_(_protected_, ptr), (ptr), (void(*)(void *))(func))
123
124 static inline struct _protectedPtr_
_protectPtr_(struct _protectedPtr_ * _ptr,void * ptr,void (* func)(void *))125 _protectPtr_(struct _protectedPtr_ *_ptr, void* ptr, void (*func)(void*))
126 {
127 if (_currentExceptionContext_) {
128 _ptr->next = _currentExceptionContext_->stack;
129 _ptr->ptr = ptr;
130 _ptr->func = func;
131 _currentExceptionContext_->stack = _ptr;
132 }
133 return *_ptr;
134 }
135
136 static inline void
unprotectPtr(void * ptr)137 unprotectPtr(void *ptr)
138 {
139 if (_currentExceptionContext_ &&
140 _currentExceptionContext_->stack &&
141 _currentExceptionContext_->stack->ptr == ptr)
142 _currentExceptionContext_->stack = _currentExceptionContext_->stack->next;
143 }
144
145 /*
146 extern declarations
147 */
148
149 extern void _exceptionThrow_(int except);
150 extern void _exceptionThrowDebug_(char const*, int, char const*, char const*,
151 int except);
152 #endif
153