1 /* 2 * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 * 9 * $Id: exc.h,v 1.23 2001/06/07 20:04:53 ca Exp $ 10 */ 11 12 #pragma ident "%Z%%M% %I% %E% SMI" 13 14 /* 15 ** libsm exception handling 16 ** See libsm/exc.html for documentation. 17 */ 18 19 #ifndef SM_EXC_H 20 # define SM_EXC_H 21 22 #include <sm/setjmp.h> 23 #include <sm/io.h> 24 #include <sm/gen.h> 25 #include <sm/assert.h> 26 27 typedef struct sm_exc SM_EXC_T; 28 typedef struct sm_exc_type SM_EXC_TYPE_T; 29 typedef union sm_val SM_VAL_T; 30 31 /* 32 ** Exception types 33 */ 34 35 extern const char SmExcTypeMagic[]; 36 37 struct sm_exc_type 38 { 39 const char *sm_magic; 40 const char *etype_category; 41 const char *etype_argformat; 42 void (*etype_print) __P((SM_EXC_T *, SM_FILE_T *)); 43 const char *etype_printcontext; 44 }; 45 46 extern const SM_EXC_TYPE_T SmEtypeOs; 47 extern const SM_EXC_TYPE_T SmEtypeErr; 48 49 extern void 50 sm_etype_printf __P(( 51 SM_EXC_T *_exc, 52 SM_FILE_T *_stream)); 53 54 /* 55 ** Exception objects 56 */ 57 58 extern const char SmExcMagic[]; 59 60 union sm_val 61 { 62 int v_int; 63 long v_long; 64 char *v_str; 65 SM_EXC_T *v_exc; 66 }; 67 68 struct sm_exc 69 { 70 const char *sm_magic; 71 size_t exc_refcount; 72 const SM_EXC_TYPE_T *exc_type; 73 SM_VAL_T *exc_argv; 74 }; 75 76 # define SM_EXC_INITIALIZER(type, argv) \ 77 { \ 78 SmExcMagic, \ 79 0, \ 80 type, \ 81 argv, \ 82 } 83 84 extern SM_EXC_T * 85 sm_exc_new_x __P(( 86 const SM_EXC_TYPE_T *_type, 87 ...)); 88 89 extern SM_EXC_T * 90 sm_exc_addref __P(( 91 SM_EXC_T *_exc)); 92 93 extern void 94 sm_exc_free __P(( 95 SM_EXC_T *_exc)); 96 97 extern bool 98 sm_exc_match __P(( 99 SM_EXC_T *_exc, 100 const char *_pattern)); 101 102 extern void 103 sm_exc_write __P(( 104 SM_EXC_T *_exc, 105 SM_FILE_T *_stream)); 106 107 extern void 108 sm_exc_print __P(( 109 SM_EXC_T *_exc, 110 SM_FILE_T *_stream)); 111 112 extern SM_DEAD(void 113 sm_exc_raise_x __P(( 114 SM_EXC_T *_exc))); 115 116 extern SM_DEAD(void 117 sm_exc_raisenew_x __P(( 118 const SM_EXC_TYPE_T *_type, 119 ...))); 120 121 /* 122 ** Exception handling 123 */ 124 125 typedef void (*SM_EXC_DEFAULT_HANDLER_T) __P((SM_EXC_T *)); 126 127 extern void 128 sm_exc_newthread __P(( 129 SM_EXC_DEFAULT_HANDLER_T _handle)); 130 131 typedef struct sm_exc_handler SM_EXC_HANDLER_T; 132 struct sm_exc_handler 133 { 134 SM_EXC_T *eh_value; 135 SM_JMPBUF_T eh_context; 136 SM_EXC_HANDLER_T *eh_parent; 137 int eh_state; 138 }; 139 140 /* values for eh_state */ 141 enum 142 { 143 SM_EH_PUSHED = 2, 144 SM_EH_POPPED = 0, 145 SM_EH_HANDLED = 1 146 }; 147 148 extern SM_EXC_HANDLER_T *SmExcHandler; 149 150 # define SM_TRY { SM_EXC_HANDLER_T _h; \ 151 do { \ 152 _h.eh_value = NULL; \ 153 _h.eh_parent = SmExcHandler; \ 154 _h.eh_state = SM_EH_PUSHED; \ 155 SmExcHandler = &_h; \ 156 if (sm_setjmp_nosig(_h.eh_context) == 0) { 157 158 # define SM_FINALLY SM_ASSERT(SmExcHandler == &_h); \ 159 } \ 160 if (sm_setjmp_nosig(_h.eh_context) == 0) { 161 162 # define SM_EXCEPT(e,pat) } \ 163 if (_h.eh_state == SM_EH_HANDLED) \ 164 break; \ 165 if (_h.eh_state == SM_EH_PUSHED) { \ 166 SM_ASSERT(SmExcHandler == &_h); \ 167 SmExcHandler = _h.eh_parent; \ 168 } \ 169 _h.eh_state = sm_exc_match(_h.eh_value,pat) \ 170 ? SM_EH_HANDLED : SM_EH_POPPED; \ 171 if (_h.eh_state == SM_EH_HANDLED) { \ 172 SM_UNUSED(SM_EXC_T *e) = _h.eh_value; 173 174 # define SM_END_TRY } \ 175 } while (0); \ 176 if (_h.eh_state == SM_EH_PUSHED) { \ 177 SM_ASSERT(SmExcHandler == &_h); \ 178 SmExcHandler = _h.eh_parent; \ 179 if (_h.eh_value != NULL) \ 180 sm_exc_raise_x(_h.eh_value); \ 181 } else if (_h.eh_state == SM_EH_POPPED) { \ 182 if (_h.eh_value != NULL) \ 183 sm_exc_raise_x(_h.eh_value); \ 184 } else \ 185 sm_exc_free(_h.eh_value); \ 186 } 187 188 #endif /* SM_EXC_H */ 189