/* * Portable Exception Handling for ANSI C. * Copyright (C) 1999 Kaz Kylheku * * Free Software License: * * All rights are reserved by the author, with the following exceptions: * Permission is granted to freely reproduce and distribute this software, * possibly in exchange for a fee, provided that this copyright notice appears * intact. Permission is also granted to adapt this software to produce * derivative works, as long as the modified versions carry this copyright * notice and additional notices stating that the work has been modified. * This source code may be translated into executable form and incorporated * into proprietary software; there is no requirement for such software to * contain a copyright notice related to this source. * */ /** * @file * Portable Exception Handling for ANSI C.
* Modified to support throwing an exception with a null message pointer, * and to have the message not be const (as we generate messages with * "g_strdup_sprintf()", which means they need to be freed; using * a null message means that we don't have to use a special string * for exceptions with no message, and don't have to worry about * not freeing that). */ #ifndef XCEPT_H #define XCEPT_H #include #include #include #include #include "ws_symbol_export.h" #define XCEPT_GROUP_ANY 0 #define XCEPT_CODE_ANY 0 #define XCEPT_BAD_ALLOC 1 #ifdef __cplusplus extern "C" { #endif enum { except_no_call, except_call }; typedef struct { unsigned long except_group; unsigned long except_code; } except_id_t; typedef struct { except_id_t volatile except_id; const char *volatile except_message; void *volatile except_dyndata; } except_t; struct except_cleanup { void (*except_func)(void *); void *except_context; }; struct except_catch { const except_id_t *except_id; size_t except_size; except_t except_obj; jmp_buf except_jmp; }; enum except_stacktype { XCEPT_CLEANUP, XCEPT_CATCHER }; struct except_stacknode { struct except_stacknode *except_down; enum except_stacktype except_type; union { struct except_catch *except_catcher; struct except_cleanup *except_cleanup; } except_info; }; /* private functions made external so they can be used in macros */ extern void except_setup_clean(struct except_stacknode *, struct except_cleanup *, void (*)(void *), void *); WS_DLL_PUBLIC void except_setup_try(struct except_stacknode *, struct except_catch *, const except_id_t [], size_t); WS_DLL_PUBLIC struct except_stacknode *except_pop(void); /* public interface functions */ WS_DLL_PUBLIC int except_init(void); WS_DLL_PUBLIC void except_deinit(void); WS_DLL_PUBLIC WS_MSVC_NORETURN void except_rethrow(except_t *) G_GNUC_NORETURN; WS_DLL_PUBLIC WS_MSVC_NORETURN void except_throw(long, long, const char *) G_GNUC_NORETURN; WS_DLL_PUBLIC WS_MSVC_NORETURN void except_throwd(long, long, const char *, void *) G_GNUC_NORETURN; WS_DLL_PUBLIC WS_MSVC_NORETURN void except_throwf(long, long, const char *, ...) G_GNUC_NORETURN G_GNUC_PRINTF(3, 4); WS_DLL_PUBLIC void (*except_unhandled_catcher(void (*)(except_t *)))(except_t *); extern unsigned long except_code(except_t *); extern unsigned long except_group(except_t *); extern const char *except_message(except_t *); extern void *except_data(except_t *); WS_DLL_PUBLIC void *except_take_data(except_t *); WS_DLL_PUBLIC void except_set_allocator(void *(*)(size_t), void (*)(void *)); WS_DLL_PUBLIC void *except_alloc(size_t); WS_DLL_PUBLIC void except_free(void *); #define except_code(E) ((E)->except_id.except_code) #define except_group(E) ((E)->except_id.except_group) #define except_message(E) ((E)->except_message) #define except_data(E) ((E)->except_dyndata) #ifdef __cplusplus } #endif /* * void except_cleanup_push(void (*)(void *), void *); * void except_cleanup_pop(int); * void except_checked_cleanup_pop(void (*)(void *), int); * void except_try_push(const except_id_t [], size_t, except_t **); * void except_try_pop(void); */ #define except_cleanup_push(F, C) \ { \ struct except_stacknode except_sn; \ struct except_cleanup except_cl; \ except_setup_clean(&except_sn, &except_cl, F, C) #define except_cleanup_pop(E) \ except_pop(); \ if (E) \ except_cl.except_func(except_cl.except_context); \ } #define except_checked_cleanup_pop(F, E) \ except_pop(); \ assert (except_cl.except_func == (F)); \ if (E) \ except_cl.except_func(except_cl.except_context); \ } /* --- Variants to allow nesting of except_cleanup_push w/o "shadowing" variables */ #define except_cleanup_push_pfx(pfx, F, C) \ { \ struct except_stacknode pfx##_except_sn; \ struct except_cleanup pfx##_except_cl; \ except_setup_clean(&pfx##_except_sn, &pfx##_except_cl, F, C) #define except_cleanup_pop_pfx(pfx, E) \ except_pop(); \ if (E) \ pfx##_except_cl.except_func(pfx##_except_cl.except_context);\ } #define except_checked_cleanup_pop_pfx(pfx, F, E) \ except_pop(); \ assert (pfx##_except_cl.except_func == (F)); \ if (E) \ pfx##_except_cl.except_func(pfx##_except_cl.except_context);\ } /* ---------- */ #define except_try_push(ID, NUM, PPE) \ { \ struct except_stacknode except_sn; \ struct except_catch except_ch; \ except_setup_try(&except_sn, &except_ch, ID, NUM); \ if (setjmp(except_ch.except_jmp)) \ *(PPE) = &except_ch.except_obj; \ else \ *(PPE) = 0 #define except_try_pop() \ except_free(except_ch.except_obj.except_dyndata); \ except_pop(); \ } #endif /* XCEPT_H */ /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */