home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Exception Library -- General exception handling for ANSI C programs
- **
- ** Copyright (C) 1992 Computational Vision and Active Perception Lab. (CVAP),
- ** Royal Institute of Technology, Stockholm.
- **
- ** This library is free software; you can redistribute it and/or
- ** modify it under the terms of the GNU Library General Public
- ** License as published by the Free Software Foundation; either
- ** version 2 of the License, or (at your option) any later version.
- **
- ** This library is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ** Library General Public License for more details.
- **
- ** You should have received a copy of the GNU Library General Public
- ** License along with this library (see COPYING-LIB); if not, write to
- ** the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- ** USA.
- **
- ** Written by
- **
- ** Harald Winroth, Matti Rendahl
- ** Computational Vision and Active Perception Laboratory
- ** Royal Institute of Technology
- ** S-100 44 Stockholm
- ** Sweden
- **
- ** Report bugs to candela-bug@bion.kth.se, and direct all inquiries to
- ** candela@bion.kth.se.
- **
- */
-
- #ifndef EXCEPTION_EXCEPTION_H
- #define EXCEPTION_EXCEPTION_H
-
- #include <setjmp.h>
- #include <stdarg.h>
-
- #include <exception/config.h>
-
- typedef enum
- {
- excNoCallback = 0x0,
-
- excBeginCallback = 0x1,
- excEndCallback = 0x2,
- excThrowCallback = 0x4,
- excRecoverCallback = 0x8,
-
- excCompleteCallback = excBeginCallback | \
- excEndCallback | \
- excThrowCallback | \
- excRecoverCallback
- } excCallbackTag;
-
- typedef struct _excBuf
- {
- volatile struct _excBuf *prev, *prev_dynamic;
- unsigned int level;
- unsigned int cb_list_len;
- unsigned int try_data_sp;
- int in_unwind; /* True if longjmp has been taken */
- jmp_buf buf;
- void *local_try_data[EXC_LOCAL_TRY_DATA_SIZE];
-
- } excBuf;
-
- typedef void (*excCallback) (excCallbackTag tag, void *cb_data,
- void **try_data);
- typedef int (*excHandler) (void *e, void *e_type, void *h_data);
-
- /*
- * Place holders (to generate unique addresses)
- */
-
- extern int exc_any; /* Can be used with EXC_INSTALL_HANDLER() */
- extern int exc_undefined;
-
- #define EXC_ANY (&exc_any)
- #define EXC_UNDEFINED (&exc_undefined)
-
- /*
- * Functions for manipulating the signal mask saved at the throw-point.
- * If and when the program recovers from the pending exception, this mask
- * will be restored. These functions are equivalent to the SYSV sigsetops(3)
- * but the signal set argument (sigset_t*) is implicit.
- */
-
- extern int exc_sigemptyset (void);
- extern int exc_sigfillset (void);
- extern int exc_sigaddset (int signo);
- extern int exc_sigdelset (int signo);
- extern int exc_sigismember (int signo);
-
- /*
- * Exported functions
- */
-
- extern void exc_breakpoint (void); /* Set breakpoints in this dummy function */
-
- extern void exc_throw_typed (void *e, void *e_type);
- extern void exc_throw (void *e);
- extern void exc_rethrow ();
-
- extern void *exc_exception (void);
- extern void *exc_type (void);
-
- extern int exc_in_domain (void *e, void *domain, unsigned long sizeof_domain);
- extern int exc_equal (void *e1, void *e2);
-
- extern void exc_install_callback (excCallbackTag tags, excCallback cb,
- void *cb_data);
- extern void exc_remove_callback (excCallbackTag tags, excCallback cb,
- void *cb_data);
-
- extern void exc_install_handler (void *e, unsigned long e_size,
- excHandler h, void *h_data);
- extern void exc_remove_handler (void *e, unsigned long e_size, excHandler h,
- void *h_data);
-
-
- /*
- * Private -- don't use these in application programs
- */
-
- extern volatile excBuf *exc_current_buf;
-
- extern volatile excBuf exc_buf; /* Dummy */
- extern char exc_in_try; /* Dummy */
- extern char exc_in_tret; /* Dummy */
- extern char exc_in_unwind; /* Dummy */
- extern char exception; /* Dummy */
-
- extern void *exc_malloc (unsigned long size);
- extern void *exc_calloc (unsigned long count, unsigned long size);
- extern void *exc_realloc (void *s, unsigned long size);
- extern void exc_free (void *s);
- extern char *exc_strdup (char *s);
-
- extern void exc_vfatal (char *format, va_list list);
- extern void exc_fatal (char *format, ...);
- extern void exc_panic (void);
- extern void exc_assertion_failed (char *file, int line);
-
- #define EXC_ASSERT(condition) \
- if (!(condition)) exc_assertion_failed (__FILE__, __LINE__);
-
- extern void exc_begin (volatile excBuf *buf, int inside_try);
- extern void exc_end (volatile excBuf *buf);
- extern int exc_tret (volatile excBuf *buf, int in_tret, char *file, int line);
-
- extern void exc_break_in_try_err (char *file, int line);
- extern void exc_rethrow_err (char *file, int line);
- extern int exc_catch_outside_unwind_err (char *file, int line);
- extern void exc_ret_in_try_err (char *file, int line);
- extern int exc_tret_err (char *file, int line);
-
- #if 0 /* Run-time overhead */
- #define EXC_IN_TRY (exc_in_try)
- #define EXC_IN_TRET (exc_in_tret)
- #define EXC_IN_UNWIND (exc_in_unwind)
- #else
- #define EXC_IN_TRY (sizeof (exc_in_try) > 1)
- #define EXC_IN_TRET (sizeof (exc_in_tret) > 1)
- #define EXC_IN_UNWIND (sizeof (exc_in_unwind) > 1)
- #endif
-
- #define return switch (EXC_IN_TRY ? \
- exc_tret (&exc_buf, EXC_IN_TRET, __FILE__, __LINE__) : 0) \
- default: return
-
- /*
- Note: In tryreturn() below, the argument 'X' must be an lvalue.
- The (0 ? &(X) : 0) expression returns a NULL pointer of X's type.
- The ((char *) &(X)) expression evaluates 'X' in the current TRY
- scope, which is important if 'X' contains an expression that might
- throw an exception, such as 'idx()' in 'array[idx()]'.
- */
-
- #define tryreturn(X) /* Note: X must be a lvalue */ \
- do { \
- long exc_in_tret = EXC_IN_TRY ? 1 : exc_tret_err (__FILE__, __LINE__);\
- char *exc_tret_tmp = (char *) &(X); \
- return (0 ? &(X) : 0) \
- [(exc_tret_tmp-(char *)0)/sizeof(X)]; \
- } while(0)
-
- #define TRY(TRYFORMS, CATCHFORMS) \
- do { \
- volatile excBuf exc_buf; \
- exc_begin (&exc_buf, EXC_IN_TRY); \
- { \
- long exc_in_try = 1; \
- \
- if (EXC_SETJMP (exc_buf.buf) == 0) \
- { \
- exc_current_buf = &exc_buf; \
- \
- do { \
- switch (0) { default: { TRYFORMS ; } continue; } \
- exc_break_in_try_err (__FILE__, __LINE__); \
- exc_in_try++; /* Not reached */ \
- } while (0); \
- \
- exc_end (&exc_buf); \
- } \
- else { \
- do { \
- void *exception = exc_exception (); \
- long exc_in_unwind = 1; \
- \
- switch (0) \
- { \
- default: \
- EXC_ASSERT (exc_current_buf == &exc_buf); \
- { CATCHFORMS ; } \
- THROW (exception); \
- } \
- exc_break_in_try_err (__FILE__, __LINE__); \
- } while (0); \
- \
- exc_end (&exc_buf); \
- } \
- } \
- } while (0)
-
- #define EXC_IN_DOMAIN(EXCEPTION, DOMAIN) \
- exc_in_domain ((EXCEPTION), & DOMAIN, sizeof (DOMAIN))
-
- #define EXC_EQUAL(EXCEPTION, MEMBER) \
- exc_equal ((EXCEPTION), & MEMBER)
-
- #define CATCH(DOMAIN, FORMS) \
- switch (EXC_IN_UNWIND ? EXC_IN_DOMAIN (exc_exception (), DOMAIN) \
- : exc_catch_outside_unwind_err (__FILE__, __LINE__)) \
- { \
- case 0: break; \
- default: { FORMS ; } continue; \
- }
-
- #define THROW_TYPED(EXCEPTION, TYPE) \
- if ((void *) & EXCEPTION == (void *) & exception) \
- { \
- if (EXC_IN_UNWIND) \
- exc_rethrow (); \
- else \
- exc_rethrow_err (__FILE__, __LINE__); \
- } \
- else \
- exc_throw_typed (& EXCEPTION, & TYPE)
-
- #define THROW(EXCEPTION) THROW_TYPED (EXCEPTION, EXCEPTION)
-
- #define RETHROW() THROW (exception) /* alternative syntax */
-
- #define UNWIND_PROTECT(PROTECTEDFORMS, CLEANUPFORMS) \
- do { \
- static int _unwind_protect; \
- \
- TRY ( \
- { \
- { PROTECTEDFORMS ; } \
- THROW (_unwind_protect); \
- }, \
- { \
- { CLEANUPFORMS ; } \
- CATCH (_unwind_protect, continue); \
- } \
- ); \
- } while (0)
-
- #define EXC_INSTALL_HANDLER(E, HANDLER, HANDLER_DATA) \
- exc_install_handler (&E, sizeof (E), (HANDLER), (HANDLER_DATA))
-
- #define EXC_REMOVE_HANDLER(E, HANDLER, HANDLER_DATA) \
- exc_remove_handler (&E, sizeof (E), (HANDLER), (HANDLER_DATA))
-
- /*
- * Note: EXC_LONGJMP must NOT affect the curret signal mask. THROW blocks
- * all signals, and the signals must remain blocked until all unwind code
- * has been executed.
- *
- * The (jmp_buf *) cast is to avoid a type clash: buf is volatile.
- */
-
- #if defined(SVR4) || defined(SYSV) || defined(_SYSV_)
- #define EXC_SETJMP(buf) setjmp (*(jmp_buf *)&(buf))
- #define EXC_LONGJMP(buf, val) longjmp(*(jmp_buf *)&(buf), val)
- #else
- #define EXC_SETJMP(buf) _setjmp (*(jmp_buf *)&(buf))
- #define EXC_LONGJMP(buf, val) _longjmp(*(jmp_buf *)&(buf), val)
- #endif
-
- #endif /* EXCEPTION_EXCEPTION_H */
-