ossp-pkg/ex/ex.h
1.9
/*
** OSSP ex - Exception Handling Library
** Copyright (c) 2002 Ralf S. Engelschall <rse@engelschall.com>
** Copyright (c) 2002 The OSSP Project <http://www.ossp.org/>
** Copyright (c) 2002 Cable & Wireless Deutschland <http://www.cw.com/de/>
**
** This file is part of OSSP ex, an exception handling library
** which can be found at http://www.ossp.org/pkg/ex/.
**
** Permission to use, copy, modify, and distribute this software for
** any purpose with or without fee is hereby granted, provided that
** the above copyright notice and this permission notice appear in all
** copies.
**
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
** ex.h: exception handling (pre-processor part)
*/
#ifndef __EX_H__
#define __EX_H__
/* required ISO-C standard facilities */
#include <stdio.h>
/* convinience define */
#ifndef NULL
#define NULL (void *)0
#endif
/* determine how the current function name can be fetched */
#if ( defined(__STDC__) \
&& defined(__STDC_VERSION__) \
&& __STDC_VERSION__ >= 199901L)
#define __EX_FUNC__ __func__ /* ISO C99 compliant */
#elif ( defined(__GNUC__) \
&& defined(__GNUC_MINOR__) \
&& ( __GNUC__ > 2 \
|| (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)))
#define __EX_FUNC__ __FUNCTION__ /* gcc >= 2.8 */
#else
#define __EX_FUNC__ "#NA#" /* not available */
#endif
/* the machine context */
#if defined(__EX_MCTX_USE_MCSC__)
#include <ucontext.h> /* POSIX.1 ucontext(3) */
#define __ex_mctx_struct ucontext_t uc;
#define __ex_mctx_save(mctx) (getcontext(&(mctx)->uc) == 0)
#define __ex_mctx_restored(mctx) /* noop */
#define __ex_mctx_restore(mctx) (void)setcontext(&(mctx)->uc)
#elif defined(__EX_MCTX_USE_SSJLJ__)
#include <setjmp.h> /* POSIX.1 sigjmp_buf(3) */
#define __ex_mctx_struct sigjmp_buf jb;
#define __ex_mctx_save(mctx) (sigsetjmp((mctx)->jb, 1) == 0)
#define __ex_mctx_restored(mctx) /* noop */
#define __ex_mctx_restore(mctx) (void)siglongjmp((mctx)->jb, 1)
#elif defined(__EX_MCTX_USE_SJLJ__) || !defined(__EX_MCTX_USE_CUSTOM__)
#include <setjmp.h> /* ISO C jmp_buf(3) */
#define __ex_mctx_struct jmp_buf jb;
#define __ex_mctx_save(mctx) (setjmp((mctx)->jb) == 0)
#define __ex_mctx_restored(mctx) /* noop */
#define __ex_mctx_restore(mctx) (void)longjmp((mctx)->jb, 1)
#endif
/* declare the machine context type */
typedef struct { __ex_mctx_struct } __ex_mctx_t;
/* declare the exception type (public) */
typedef struct {
/* throw value */
void *ex_class;
void *ex_object;
void *ex_value;
/* throw point */
char *ex_file;
int ex_line;
char *ex_func;
} ex_t;
/* declare the context type (private) */
typedef struct {
__ex_mctx_t *ctx_mctx; /* permanent machine context of enclosing try/catch */
int ctx_disabled; /* permanent flag whether exception handling is disabled */
int ctx_caught; /* temporary flag whether exception was caught */
volatile ex_t ctx_ex; /* temporary exception storage */
} ex_ctx_t;
/* the static and dynamic initializers for a context structure */
#define EX_CTX_INITIALIZER \
{ NULL, 0, 0, { NULL, NULL, NULL, NULL, 0, NULL } }
#define EX_CTX_INITIALIZE(ctx) \
do { \
(ctx)->ctx_mctx = NULL; \
(ctx)->ctx_disabled = 0; \
(ctx)->ctx_caught = 0; \
(ctx)->ctx_ex.ex_class = NULL; \
(ctx)->ctx_ex.ex_object = NULL; \
(ctx)->ctx_ex.ex_value = NULL; \
(ctx)->ctx_ex.ex_file = NULL; \
(ctx)->ctx_ex.ex_line = 0; \
(ctx)->ctx_ex.ex_func = NULL; \
} while (0)
/* the exception context */
#if defined(__EX_CTX_USE_STATIC__)
static ex_ctx_t __ex_ctx_global;
#define __ex_ctx (&__ex_ctx_global)
#elif defined(__EX_CTX_USE_GLOBAL__) || !defined(__EX_CTX_USE_CUSTOM__)
#define EX_CTX_GLOBAL ex_ctx_t __ex_ctx_global;
extern ex_ctx_t __ex_ctx_global;
#define __ex_ctx (&__ex_ctx_global)
#endif
/* the termination handler */
#if defined(__EX_TERMINATE_USE_NOOP__)
#define __ex_terminate(e) \
/* noop */
#elif defined(__EX_TERMINATE_USE_ABORT__) || !defined(__EX_CTX_USE_CUSTOM__)
#define __ex_terminate(e) \
( fprintf(stderr, \
"**EX: UNCAUGHT EXCEPTION: " \
"class=0x%lx object=0x%lx value=0x%lx [%s:%d@%s]\n", \
(long)((e)->ex_class), (long)((e)->ex_object), (long)((e)->ex_value), \
(e)->ex_file, (e)->ex_line, (e)->ex_func), \
abort() )
#endif
/* the block for trying execution */
#define ex_try \
{ \
ex_ctx_t *__ex_ctx_ptr = __ex_ctx; \
__ex_mctx_t *__ex_mctx_en; \
__ex_mctx_t __ex_mctx_me; \
__ex_mctx_en = __ex_ctx_ptr->ctx_mctx; \
__ex_ctx_ptr->ctx_mctx = &__ex_mctx_me; \
if (__ex_mctx_save(&__ex_mctx_me)) { \
if (1)
/* the block for catching an exception */
#define ex_catch(e) \
else { \
} \
__ex_ctx_ptr->ctx_caught = 0; \
} \
else { \
__ex_mctx_restored(&__ex_mctx_me); \
__ex_ctx_ptr->ctx_caught = 1; \
} \
__ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \
} \
if ( !(__ex_ctx->ctx_caught) \
|| ((e) = __ex_ctx->ctx_ex, 0)) { \
} \
else
/* the throwing of a new exception */
#define ex_throw(c,o,v) \
(__ex_ctx->ctx_disabled ? 0 : \
(__ex_ctx->ctx_ex.ex_class = (void *)(c), \
__ex_ctx->ctx_ex.ex_object = (void *)(o), \
__ex_ctx->ctx_ex.ex_value = (void *)(v), \
__ex_ctx->ctx_ex.ex_file = __FILE__, \
__ex_ctx->ctx_ex.ex_line = __LINE__, \
__ex_ctx->ctx_ex.ex_func = __EX_FUNC__, \
( __ex_ctx->ctx_mctx == NULL \
? (__ex_terminate(&(__ex_ctx->ctx_ex)), -1) \
: (__ex_mctx_restore(__ex_ctx->ctx_mctx), 1) )))
/* the re-throwing of an already caught exception */
#define ex_rethrow \
(__ex_ctx->ctx_disabled ? 0 : \
(__ex_ctx->ctx_mctx == NULL ? (__ex_terminate(&(__ex_ctx->ctx_ex)), -1) : \
(__ex_mctx_restore(__ex_ctx->ctx_mctx), 1) ))
/* shield an operation from exception handling */
#define ex_shield \
for (__ex_ctx->ctx_disabled = 1; \
__ex_ctx->ctx_disabled == 1; \
__ex_ctx->ctx_disabled = 0)
/* exception handling tests */
#define ex_catching \
(__ex_ctx->ctx_mctx != NULL)
#define ex_shielding \
(__ex_ctx->ctx_disabled)
/* optional namespace mapping */
#if defined(__EX_NS_USE_UCCXX__)
#define Try ex_try
#define Catch ex_catch
#define Throw ex_throw
#define Rethrow ex_rethrow
#define Shield ex_shield
#elif defined(__EX_NS_USE_CXX__) || (!defined(__cplusplus) && !defined(__EX_NS_USE_CUSTOM__))
#define try ex_try
#define catch ex_catch
#define throw ex_throw
#define rethrow ex_rethrow
#define shield ex_shield
#endif
#endif /* __EX_H__ */