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