Platon Technologies
not logged in Login Registration
EnglishSlovak
open source software development celebrating 10 years of open source development! Friday, March 29, 2024

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/
Copyright © 2002-2006 Platon Group
Site powered by Metafox CMS
Go to Top