Logo Search packages:      
Sourcecode: batv-milter version File versions  Download package

exc.h

/*
 * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
 *    All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 *    $Id: exc.h,v 1.23 2001/06/07 20:04:53 ca Exp $
 */

/*
**  libsm exception handling
**  See libsm/exc.html for documentation.
*/

#ifndef SM_EXC_H
# define SM_EXC_H

#include <sm/setjmp.h>
#include <sm/io.h>
#include <sm/gen.h>
#include <sm/assert.h>

typedef struct sm_exc SM_EXC_T;
typedef struct sm_exc_type SM_EXC_TYPE_T;
typedef union sm_val SM_VAL_T;

/*
**  Exception types
*/

extern const char SmExcTypeMagic[];

struct sm_exc_type
{
      const char  *sm_magic;
      const char  *etype_category;
      const char  *etype_argformat;
      void        (*etype_print) __P((SM_EXC_T *, SM_FILE_T *));
      const char  *etype_printcontext;
};

extern const SM_EXC_TYPE_T SmEtypeOs;
extern const SM_EXC_TYPE_T SmEtypeErr;

extern void
sm_etype_printf __P((
      SM_EXC_T *_exc,
      SM_FILE_T *_stream));

/*
**  Exception objects
*/

extern const char SmExcMagic[];

union sm_val
{
      int         v_int;
      long        v_long;
      char        *v_str;
      SM_EXC_T    *v_exc;
};

struct sm_exc
{
      const char        *sm_magic;
      size_t                  exc_refcount;
      const SM_EXC_TYPE_T     *exc_type;
      SM_VAL_T          *exc_argv;
};

# define SM_EXC_INITIALIZER(type, argv) \
      { \
            SmExcMagic, \
            0, \
            type, \
            argv, \
      }

extern SM_EXC_T *
sm_exc_new_x __P((
      const SM_EXC_TYPE_T *_type,
      ...));

extern SM_EXC_T *
sm_exc_addref __P((
      SM_EXC_T *_exc));

extern void
sm_exc_free __P((
      SM_EXC_T *_exc));

extern bool
sm_exc_match __P((
      SM_EXC_T *_exc,
      const char *_pattern));

extern void
sm_exc_write __P((
      SM_EXC_T *_exc,
      SM_FILE_T *_stream));

extern void
sm_exc_print __P((
      SM_EXC_T *_exc,
      SM_FILE_T *_stream));

extern SM_DEAD(void
sm_exc_raise_x __P((
      SM_EXC_T *_exc)));

extern SM_DEAD(void
sm_exc_raisenew_x __P((
      const SM_EXC_TYPE_T *_type,
      ...)));

/*
**  Exception handling
*/

typedef void (*SM_EXC_DEFAULT_HANDLER_T) __P((SM_EXC_T *));

extern void
sm_exc_newthread __P((
      SM_EXC_DEFAULT_HANDLER_T _handle));

typedef struct sm_exc_handler SM_EXC_HANDLER_T;
struct sm_exc_handler
{
      SM_EXC_T          *eh_value;
      SM_JMPBUF_T       eh_context;
      SM_EXC_HANDLER_T  *eh_parent;
      int               eh_state;
};

/* values for eh_state */
enum
{
      SM_EH_PUSHED = 2,
      SM_EH_POPPED = 0,
      SM_EH_HANDLED = 1
};

extern SM_EXC_HANDLER_T *SmExcHandler;

# define SM_TRY         { SM_EXC_HANDLER_T _h; \
                    do { \
                      _h.eh_value = NULL; \
                      _h.eh_parent = SmExcHandler; \
                      _h.eh_state = SM_EH_PUSHED; \
                      SmExcHandler = &_h; \
                      if (sm_setjmp_nosig(_h.eh_context) == 0) {

# define SM_FINALLY           SM_ASSERT(SmExcHandler == &_h); \
                      } \
                      if (sm_setjmp_nosig(_h.eh_context) == 0) {

# define SM_EXCEPT(e,pat)   } \
                      if (_h.eh_state == SM_EH_HANDLED) \
                        break; \
                      if (_h.eh_state == SM_EH_PUSHED) { \
                        SM_ASSERT(SmExcHandler == &_h); \
                        SmExcHandler = _h.eh_parent; \
                      } \
                      _h.eh_state = sm_exc_match(_h.eh_value,pat) \
                        ? SM_EH_HANDLED : SM_EH_POPPED; \
                      if (_h.eh_state == SM_EH_HANDLED) { \
                        SM_UNUSED(SM_EXC_T *e) = _h.eh_value;

# define SM_END_TRY       } \
                    } while (0); \
                    if (_h.eh_state == SM_EH_PUSHED) { \
                      SM_ASSERT(SmExcHandler == &_h); \
                      SmExcHandler = _h.eh_parent; \
                      if (_h.eh_value != NULL) \
                        sm_exc_raise_x(_h.eh_value); \
                    } else if (_h.eh_state == SM_EH_POPPED) { \
                      if (_h.eh_value != NULL) \
                        sm_exc_raise_x(_h.eh_value); \
                    } else \
                      sm_exc_free(_h.eh_value); \
                  }

#endif /* SM_EXC_H */

Generated by  Doxygen 1.6.0   Back to index