1 #ifndef __EXCEPTIONS_H__
2 #define __EXCEPTIONS_H__
8 /* Ethereal has only one exception group, to make these macros simple */
9 #define XCEPT_GROUP_ETHEREAL 1
11 /* Ethereal's exceptions */
12 #define BoundsError 1 /* Index is out of range */
13 #define ReportedBoundsError 2 /* Index is beyond reported length (not cap_len) */
14 #define TypeError 3 /* During dfilter parsing */
26 * CATCH2(exception1, exception2) {
40 * ********* Never use 'goto' or 'return' inside the TRY, CATCH, CATCH_ALL,
41 * ********* or FINALLY blocks. Execution must proceed through ENDTRY before
42 * ********* branching out.
44 * This is really something like:
57 * else if (x == 3 || x == 4) {
66 * All CATCH's must precede a CATCH_ALL.
67 * FINALLY must occur after any CATCH or CATCH_ALL.
68 * ENDTRY marks the end of the TRY code.
69 * TRY and ENDTRY are the mandatory parts of a TRY block.
70 * CATCH, CATCH_ALL, and FINALLY are all optional (although
71 * you'll probably use at least one, otherwise why "TRY"?)
73 * GET_MESSAGE returns string ptr to exception message
74 * when exception is thrown via THROW_MESSAGE()
76 * To throw/raise an exception.
79 * RETHROW rethrow the caught exception
81 * A cleanup callback is a function called in case an exception occurs
82 * and is not caught. It should be used to free any dynamically-allocated data.
83 * A pop or call_and_pop should occur at the same statement-nesting level
86 * CLEANUP_CB_PUSH(func, data)
88 * CLEANUP_CB_CALL_AND_POP
96 static const except_id_t catch_spec[] = { \
97 { XCEPT_GROUP_ETHEREAL, XCEPT_CODE_ANY } }; \
98 except_try_push(catch_spec, 1, &exc); \
100 /* user's code goes here */
109 else if (exc->except_id.except_code == (x)) { \
110 /* user's code goes here */
112 #define CATCH2(x,y) \
114 else if (exc->except_id.except_code == (x) || exc->except_id.except_code == (y)) { \
115 /* user's code goes here */
120 /* user's code goes here */
125 /* user's code goes here */
128 except_throw(XCEPT_GROUP_ETHEREAL, (x), "XCEPT_GROUP_ETHEREAL")
130 #define THROW_MESSAGE(x, y) \
131 except_throw(XCEPT_GROUP_ETHEREAL, (x), (y))
133 #define GET_MESSAGE except_message(exc)
135 #define RETHROW except_rethrow(exc)
137 #define EXCEPT_CODE except_code(exc)
139 /* Register cleanup functions in case an exception is thrown and not caught.
140 * From the Kazlib documentation, with modifications for use with the
141 * Ethereal-specific macros:
143 * CLEANUP_PUSH(func, arg)
145 * The call to CLEANUP_PUSH shall be matched with a call to
146 * CLEANUP_CALL_AND_POP or CLEANUP_POP which must occur in the same
147 * statement block at the same level of nesting. This requirement allows
148 * an implementation to provide a CLEANUP_PUSH macro which opens up a
149 * statement block and a CLEANUP_POP which closes the statement block.
150 * The space for the registered pointers can then be efficiently
151 * allocated from automatic storage.
153 * The CLEANUP_PUSH macro registers a cleanup handler that will be
154 * called if an exception subsequently occurs before the matching
155 * CLEANUP_[CALL_AND_]POP is executed, and is not intercepted and
156 * handled by a try-catch region that is nested between the two.
158 * The first argument to CLEANUP_PUSH is a pointer to the cleanup
159 * handler, a function that returns nothing and takes a single
160 * argument of type void*. The second argument is a void* value that
161 * is registered along with the handler. This value is what is passed
162 * to the registered handler, should it be called.
164 * Cleanup handlers are called in the reverse order of their nesting:
165 * inner handlers are called before outer handlers.
167 * The program shall not leave the cleanup region between
168 * the call to the macro CLEANUP_PUSH and the matching call to
169 * CLEANUP_[CALL_AND_]POP by means other than throwing an exception,
170 * or calling CLEANUP_[CALL_AND_]POP.
172 * Within the call to the cleanup handler, it is possible that new
173 * exceptions may happen. Such exceptions must be handled before the
174 * cleanup handler terminates. If the call to the cleanup handler is
175 * terminated by an exception, the behavior is undefined. The exception
176 * which triggered the cleanup is not yet caught; thus the program
177 * would be effectively trying to replace an exception with one that
178 * isn't in a well-defined state.
181 * CLEANUP_POP and CLEANUP_CALL_AND_POP
183 * A call to the CLEANUP_POP or CLEANUP_CALL_AND_POP macro shall match
184 * each call to CLEANUP_PUSH which shall be in the same statement block
185 * at the same nesting level. It shall match the most recent such a
186 * call that is not matched by a previous CLEANUP_[CALL_AND_]POP at
189 * These macros causes the registered cleanup handler to be removed. If
190 * CLEANUP_CALL_AND_POP is called, the cleanup handler is called.
191 * In that case, the registered context pointer is passed to the cleanup
192 * handler. If CLEANUP_POP is called, the cleanup handler is not called.
194 * The program shall not leave the region between the call to the
195 * macro CLEANUP_PUSH and the matching call to CLEANUP_[CALL_AND_]POP
196 * other than by throwing an exception, or by executing the
197 * CLEANUP_CALL_AND_POP.
202 #define CLEANUP_PUSH(f,a) except_cleanup_push((f),(a))
203 #define CLEANUP_POP except_cleanup_pop(0)
204 #define CLEANUP_CALL_AND_POP except_cleanup_pop(1)
206 #endif /* __EXCEPTIONS_H__ */