File: [Platon] / libco / libco / co_exception.h (download)
Revision 1.5, Sun Mar 30 10:26:52 2003 UTC (21 years ago) by yenar
Changes since 1.4: +96 -108
lines
large cleanup, separated cox_stack implementation,
allow multiple cleanup stacks [co_exception.h, co_exception.c]
|
/***{{{*******************************************************************
* This file is part of libco - object library for C *
* Copyright (c) 2002, 2003 *
* Peter Rockai (yenar) <yenar@host.sk> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
*******************************************************************}}}***/
/* {{{ file description */
/**
* @file co_exception.h
* @brief Declarations and prototypes for libco CSEH engine.
**/
/* }}} */
#ifndef __CO_EXCEPTION_H__
#define __CO_EXCEPTION_H__
#include <setjmp.h>
#include <stdbool.h>
#include <stdlib.h>
#include "co_debug.h"
#include "co_gettext.h"
#define ERR_OK 0
#define _COX_STACK_SIZE 128
typedef void (*cox_cleanup_f) (void *, const void *);
/* {{{ */
struct cox_stack_it
/// Item of cleanup stack.
{
/// Cleanup function, called when item is to be freed.
cox_cleanup_f cleanup;
/// Pointer to item data (1st argument to cleanup function).
void *item;
/// Pointer to pass as 2nd argument to cleanup function.
const void *cleanup_data;
};
typedef struct cox_stack_it cox_stack_it;
/* }}} */
/* {{{ */
struct cox_stack_seg
/// Cleanup stack segment.
{
/// Storage for items.
cox_stack_it items [_COX_STACK_SIZE];
/// Next segment (one which is above this one).
struct cox_stack_seg *n;
};
typedef struct cox_stack_seg cox_stack_seg;
/* }}} */
/* {{{ */
struct cox_handler
/// SEH handler.
{
/// Error code that was thrown.
long long error;
/// Point to which unwind cleanup stack when handler fires up.
int *stack_mark;
/// Next handler.
struct cox_handler *n; // next
/// Data for longjmp call in throw function.
jmp_buf jb;
};
typedef struct cox_handler cox_handler;
/* }}} */
/* {{{ */
struct cox_stack
/// General cleanup stack.
{
/// Cleanup stack (actually lowest segment of it).
cox_stack_seg *top;
/// Top of cleanup stack.
unsigned stack_top;
/// Max number of items current cleanup stack can hold.
unsigned stack_size;
};
typedef struct cox_stack cox_stack;
/* }}} */
/* {{{ */
struct cox_state
/// State of CSEH engine.
{
cox_stack **stacks;
int nstacks;
/// Current SEH handler ("topmost" one).
cox_handler *cur_h;
};
typedef struct cox_state cox_state;
/* }}} */
/* {{{ exception id handling */
/// Construct real co action identifier.
#define COX_ID(...) __co_id_exception_ ## __VA_ARGS__
#define COX_ID_DECL(x, y) extern unsigned COX_ID (x)
#define COX_ID_DEF(x) unsigned COX_ID (x)
#define COX_ID_NEW(x, y) COX_ID (x) = __co_exception_id_new (y)
/* }}} */
/* {{{ COX_* family of macros */
/// Begin try block.
#define COX_TRY \
{ \
cox_handler __cox_handler_DG523_GDFG6; \
_cox_handler_push (& __cox_handler_DG523_GDFG6); \
if (! setjmp (__cox_handler_DG523_GDFG6 . jb))
/// Begin catch block.
#define COX_CATCH(x) \
else { \
long long x = _cox_handler_pop (& __cox_handler_DG523_GDFG6);
/// End catch block.
#define COX_CATCH_END \
} \
if (__cox_handler_DG523_GDFG6 . error == ERR_OK) \
_cox_handler_pop (& __cox_handler_DG523_GDFG6); \
}
/// Throw exception.
#define COX_THROW(x) (CO_DEBUG (1, "throwing exception: %d", COX_ID (x)), \
__cox_throw (COX_ID (x)))
#define COX_RETHROW(x) (CO_DEBUG (1, "throwing exception: %d", x), \
__cox_throw (x))
/* }}} */
#define COX_STACK_CLEANUP 0
#define COX_STACK_MESG 1
int *_cox_get_mark (cox_state *state);
int *cox_get_mark (void);
void __co_exception_init (void);
void __co_exception_fini (void);
void __cox_throw (long long err);
void cox_state_free (cox_state *s);
/// Free handler after successful try block completion.
unsigned _cox_handler_pop (cox_handler *handler);
/// Push new handler (when starting new try block).
void _cox_handler_push (cox_handler *h);
/// Push item onto cleanup stack, with cleanup function @a cleanup.
/**
* @param stack - stack to push data onto
* @param _item - item to push
* @param cleanup - function to free item if needed
* @param data - arbitrary data pointer passed to cleanup function
**/
void _cox_stack_push (cox_stack *stack, void *_item,
cox_cleanup_f cleanup, const void *data);
void cox_stack_push (int stack, void *_item,
cox_cleanup_f cleanup, const void *data);
/// Allocate more memory for cleanup stack.
void _cox_stack_grow (cox_stack *st);
void _cox_stack_shrink (cox_stack *stack);
/// Remove all items off top of stack up to @a mark.
void _cox_stack_unwind (cox_stack *stack, int mark);
void cox_stack_unwind (int stack, int mark);
void cox_unwind (int *mark);
/// Pop cleanup handler and function, possibly free it.
/**
* @param _item - pointer to item being popped
* @param clean - if true, we will clean the item, otherwise it will remain
* intact
**/
void _cox_stack_pop (cox_stack *st, void *_item, bool clean);
void cox_stack_pop (int stack, void *_item, bool clean);
#ifndef assert
#include <assert.h>
#endif
#define RANDOM_MEM_EXHAUSTION 0
#if RANDOM_MEM_EXHAUSTION
#include <math.h>
#endif
// const char *cox_error_string (int n);
int __co_error_id_new (const char *descr);
const char *co_error_string (int id);
/* {{{ */
static inline void cox_pop (void *_item)
/// Pop item off cleanup stack (do not free it).
{
cox_stack_pop (COX_STACK_CLEANUP, _item, false);
}
/* }}} */
/* {{{ */
static inline void cox_del (void *_item)
/// Pop item off cleanup stack and free it.
{
cox_stack_pop (COX_STACK_CLEANUP, _item, true);
}
/* }}} */
/* {{{ */
static inline void cox_push (void *_item, cox_cleanup_f cleanup, void *data)
/// Push item onto cleanup stack.
{
cox_stack_push (COX_STACK_CLEANUP, _item, cleanup, data);
}
/* }}} */
void *cox_malloc (size_t size);
#define COX_FREE_PUSH(i) (cox_push (i, (cox_cleanup_f) free, 0))
#endif /* __CO_EXCEPTION_H__ */
#if 0
COX_ID_DECL (undef, co_i18n ("undefined error"));
COX_ID_DECL (nomem, co_i18n ("memory exhaustion"));
COX_ID_DECL (fixme, co_i18n ("program bug encountered"));
COX_ID_DECL (null_ptr, co_i18n ("null pointer encountered (this is a bug!)"));
#endif /* 0 */
Platon Group <platon@platon.org> http://platon.org/
|