aboutsummaryrefslogtreecommitdiffstats
path: root/epan/exceptions.h
diff options
context:
space:
mode:
authorGilbert Ramirez <gram@alumni.rice.edu>2000-09-27 04:55:05 +0000
committerGilbert Ramirez <gram@alumni.rice.edu>2000-09-27 04:55:05 +0000
commit83ec54675c19f25cfbb2e8a8863c6ee2191d8b0c (patch)
tree35d39e43d20aca160b96d8a85ddc2b80e4646f67 /epan/exceptions.h
parentf881e13932e0ba390c26cce15d1334b2154a8062 (diff)
First step in moving core Ethereal routines to libepan.
svn path=/trunk/; revision=2458
Diffstat (limited to 'epan/exceptions.h')
-rw-r--r--epan/exceptions.h203
1 files changed, 203 insertions, 0 deletions
diff --git a/epan/exceptions.h b/epan/exceptions.h
new file mode 100644
index 0000000000..19eda9fe2b
--- /dev/null
+++ b/epan/exceptions.h
@@ -0,0 +1,203 @@
+#ifndef __EXCEPTIONS_H__
+#define __EXCEPTIONS_H__
+
+#ifndef XCEPT_H
+#include "except.h"
+#endif
+
+/* Ethereal has only one exception group, to make these macros simple */
+#define XCEPT_GROUP_ETHEREAL 1
+
+/* Ethereal's exceptions */
+#define BoundsError 1 /* Index is out of range */
+#define ReportedBoundsError 2 /* Index is beyond reported length (not cap_len) */
+
+/* Usage:
+ *
+ * TRY {
+ * code;
+ * }
+ *
+ * CATCH(exception) {
+ * code;
+ * }
+ *
+ * CATCH2(exception1, exception2) {
+ * code;
+ * }
+ *
+ * CATCH_ALL {
+ * code;
+ * }
+ *
+ * FINALLY {
+ * code;
+ * }
+ *
+ * ENDTRY;
+ *
+ * ********* Never use 'goto' or 'return' inside the TRY, CATCH, CATCH_ALL,
+ * ********* or FINALLY blocks. Execution must proceed through ENDTRY before
+ * ********* branching out.
+ *
+ * This is really something like:
+ *
+ * {
+ * x = setjmp()
+ * if (x == 0) {
+ * <TRY code>
+ * }
+ * else if (x == 1) {
+ * <CATCH(1) code>
+ * }
+ * else if (x == 2) {
+ * <CATCH(2) code>
+ * }
+ * else if (x == 3 || x == 4) {
+ * <CATCH2(3,4) code>
+ * }
+ * else {
+ * <CATCH_ALL code> {
+ * }
+ * <FINALLY code>
+ * }<ENDTRY tag>
+ *
+ * All CATCH's must precede a CATCH_ALL.
+ * FINALLY must occur after any CATCH or CATCH_ALL.
+ * ENDTRY marks the end of the TRY code.
+ * TRY and ENDTRY are the mandatory parts of a TRY block.
+ * CATCH, CATCH_ALL, and FINALLY are all optional (although
+ * you'll probably use at least one, otherwise why "TRY"?)
+ *
+ * GET_MESSAGE returns string ptr to exception message
+ * when exception is thrown via THROW_MESSAGE()
+ *
+ * To throw/raise an exception.
+ *
+ * THROW(exception)
+ * RETHROW rethrow the caught exception
+ *
+ * A cleanup callback is a function called in case an exception occurs
+ * and is not caught. It should be used to free any dynamically-allocated data.
+ * A pop or call_and_pop should occur at the same statement-nesting level
+ * as the push.
+ *
+ * CLEANUP_CB_PUSH(func, data)
+ * CLEANUP_CB_POP
+ * CLEANUP_CB_CALL_AND_POP
+ */
+
+
+
+#define TRY \
+{\
+ except_t *exc; \
+ static const except_id_t catch_spec[] = { \
+ { XCEPT_GROUP_ETHEREAL, XCEPT_CODE_ANY } }; \
+ except_try_push(catch_spec, 1, &exc); \
+ if (exc == 0) { \
+ /* user's code goes here */
+
+#define ENDTRY \
+ } \
+ except_try_pop();\
+}
+
+#define CATCH(x) \
+ } \
+ else if (exc->except_id.except_code == (x)) { \
+ /* user's code goes here */
+
+#define CATCH2(x,y) \
+ } \
+ else if (exc->except_id.except_code == (x) || exc->except_id.except_code == (y)) { \
+ /* user's code goes here */
+
+#define CATCH_ALL \
+ } \
+ else { \
+ /* user's code goes here */
+
+#define FINALLY \
+ } \
+ { \
+ /* user's code goes here */
+
+#define THROW(x) \
+ except_throw(XCEPT_GROUP_ETHEREAL, (x), "XCEPT_GROUP_ETHEREAL")
+
+#define THROW_MESSAGE(x, y) \
+ except_throw(XCEPT_GROUP_ETHEREAL, (x), (y))
+
+#define GET_MESSAGE except_message(exc)
+
+#define RETHROW except_rethrow(exc)
+
+/* Register cleanup functions in case an exception is thrown and not caught.
+ * From the Kazlib documentation, with modifications for use with the
+ * Ethereal-specific macros:
+ *
+ * CLEANUP_PUSH(func, arg)
+ *
+ * The call to CLEANUP_PUSH shall be matched with a call to
+ * CLEANUP_CALL_AND_POP or CLEANUP_POP which must occur in the same
+ * statement block at the same level of nesting. This requirement allows
+ * an implementation to provide a CLEANUP_PUSH macro which opens up a
+ * statement block and a CLEANUP_POP which closes the statement block.
+ * The space for the registered pointers can then be efficiently
+ * allocated from automatic storage.
+ *
+ * The CLEANUP_PUSH macro registers a cleanup handler that will be
+ * called if an exception subsequently occurs before the matching
+ * CLEANUP_[CALL_AND_]POP is executed, and is not intercepted and
+ * handled by a try-catch region that is nested between the two.
+ *
+ * The first argument to CLEANUP_PUSH is a pointer to the cleanup
+ * handler, a function that returns nothing and takes a single
+ * argument of type void*. The second argument is a void* value that
+ * is registered along with the handler. This value is what is passed
+ * to the registered handler, should it be called.
+ *
+ * Cleanup handlers are called in the reverse order of their nesting:
+ * inner handlers are called before outer handlers.
+ *
+ * The program shall not leave the cleanup region between
+ * the call to the macro CLEANUP_PUSH and the matching call to
+ * CLEANUP_[CALL_AND_]POP by means other than throwing an exception,
+ * or calling CLEANUP_[CALL_AND_]POP.
+ *
+ * Within the call to the cleanup handler, it is possible that new
+ * exceptions may happen. Such exceptions must be handled before the
+ * cleanup handler terminates. If the call to the cleanup handler is
+ * terminated by an exception, the behavior is undefined. The exception
+ * which triggered the cleanup is not yet caught; thus the program
+ * would be effectively trying to replace an exception with one that
+ * isn't in a well-defined state.
+ *
+ *
+ * CLEANUP_POP and CLEANUP_CALL_AND_POP
+ *
+ * A call to the CLEANUP_POP or CLEANUP_CALL_AND_POP macro shall match
+ * each call to CLEANUP_PUSH which shall be in the same statement block
+ * at the same nesting level. It shall match the most recent such a
+ * call that is not matched by a previous CLEANUP_[CALL_AND_]POP at
+ * the same level.
+ *
+ * These macros causes the registered cleanup handler to be removed. If
+ * CLEANUP_CALL_AND_POP is called, the cleanup handler is called.
+ * In that case, the registered context pointer is passed to the cleanup
+ * handler. If CLEANUP_POP is called, the cleanup handler is not called.
+ *
+ * The program shall not leave the region between the call to the
+ * macro CLEANUP_PUSH and the matching call to CLEANUP_[CALL_AND_]POP
+ * other than by throwing an exception, or by executing the
+ * CLEANUP_CALL_AND_POP.
+ *
+ */
+
+
+#define CLEANUP_PUSH(f,a) except_cleanup_push((f),(a))
+#define CLEANUP_POP except_cleanup_pop(0)
+#define CLEANUP_CALL_AND_POP except_cleanup_pop(1)
+
+#endif /* __EXCEPTIONS_H__ */