ossp-pkg/ex/ex.h
1.3
/*
** Copyright (c) 2001-2002 The OSSP Project <http://www.ossp.org/>
** Copyright (c) 2001-2002 Cable & Wireless Deutschland <http://www.cw.com/de/>
**
** This file is part of OSSP ex, an exception library
** which can be found at http://www.ossp.org/pkg/ex/.
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version
** 2.0 of the License, or (at your option) any later version.
**
** This program 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
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this file; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
** USA, or contact the OSSP project <ossp@ossp.org>.
**
** ex.h: exception handling (pre-processor part)
*/
#ifndef __EX_H__
#define __EX_H__
/* the required ISO-C standard facilities */
#include <stdio.h> /* for NULL */
#include <setjmp.h> /* for jmp_buf, setjmp(3), longjmp(3) */
/* 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 */
#ifndef __ex_mctx_st
#define __ex_mctx_st struct { jmp_buf jb; }
#endif
#ifndef __ex_mctx_save
#define __ex_mctx_save(mctx) (setjmp((mctx)->jb) == 0)
#endif
#ifndef __ex_mctx_restore
#define __ex_mctx_restore(mctx) (void)longjmp((mctx)->jb, 1)
#endif
#ifndef __ex_mctx_restored
#define __ex_mctx_restored(mctx) /* NOOP */
#endif
typedef __ex_mctx_st __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 exception context type (private) */
typedef struct {
__ex_mctx_t *ctx_mctx_prev; /* previous jump buffer */
int ctx_caught; /* flag whether exception was caught */
volatile ex_t ctx_ex; /* the exception temporary storage */
} ex_ctx_t;
/* exception context */
#ifndef __ex_ctx
#define __ex_ctx (&__ex_ctx_global)
#ifdef __EX_STATIC_CTX__
static ex_ctx_t __ex_ctx_global; /* for very small environments */
#else
extern ex_ctx_t __ex_ctx_global; /* for non-MT environments (require libex.a) */
#endif
#endif
/* block for trying execution */
#define ex_try \
{ \
__ex_mctx_t *__ex_mctx_prev; \
__ex_mctx_t __ex_mctx_me; \
__ex_mctx_prev = __ex_ctx->ctx_mctx_prev; \
__ex_ctx->ctx_mctx_prev = &__ex_mctx_me; \
if (__ex_mctx_save(&__ex_mctx_me)) { \
if (1)
/* block for catching an exception */
#define ex_catch(e) \
else { \
} \
__ex_ctx->ctx_caught = 0; \
} \
else { \
__ex_mctx_restored(&__ex_mctx_me); \
__ex_ctx->ctx_caught = 1; \
} \
__ex_ctx->ctx_mctx_prev = __ex_mctx_prev; \
} \
if (!__ex_ctx->ctx_caught || ((e) = __ex_ctx->ctx_ex, 0)) { \
} \
else
/* throw a new exception */
#define ex_throw(c,o,v) \
(__ex_ctx->ctx_mctx_prev == NULL ? \
(abort(), 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_mctx_restore(__ex_ctx->ctx_mctx_prev), \
0 \
) \
)
/* re-throw a caught exception */
#define ex_rethrow \
(__ex_ctx->ctx_mctx_prev == NULL ? \
(abort(), 0) : \
(__ex_mctx_restore(__ex_ctx->ctx_mctx_prev), 0) \
)
/* optional namespace mapping */
#if !defined(__cplusplus) && !defined(__EX_NO_CXX_NS__)
#define try ex_try
#define catch ex_catch
#define throw ex_throw
#define rethrow ex_rethrow
#endif
#if !defined(__EX_NO_SIMPLE_NS__)
#define Try ex_try
#define Catch ex_catch
#define Throw ex_throw
#define Rethrow ex_rethrow
#endif
#endif /* __EX_H__ */