1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
/*
* Copyright (c) 2000-2001 Proofpoint, 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.24 2013-11-22 20:51:31 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 */
|