exc.h revision 266692
10Sduke/* 23909Sohair * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers. 30Sduke * All rights reserved. 40Sduke * 50Sduke * By using this file, you agree to the terms and conditions set 60Sduke * forth in the LICENSE file which can be found at the top level of 70Sduke * the sendmail distribution. 80Sduke * 90Sduke * $Id: exc.h,v 1.24 2013-11-22 20:51:31 ca Exp $ 100Sduke */ 110Sduke 120Sduke/* 130Sduke** libsm exception handling 140Sduke** See libsm/exc.html for documentation. 150Sduke*/ 160Sduke 170Sduke#ifndef SM_EXC_H 180Sduke# define SM_EXC_H 192362Sohair 202362Sohair#include <sm/setjmp.h> 212362Sohair#include <sm/io.h> 220Sduke#include <sm/gen.h> 230Sduke#include <sm/assert.h> 240Sduke 253666Schegartypedef struct sm_exc SM_EXC_T; 263666Schegartypedef struct sm_exc_type SM_EXC_TYPE_T; 273666Schegartypedef union sm_val SM_VAL_T; 283666Schegar 293666Schegar/* 303666Schegar** Exception types 313666Schegar*/ 323666Schegar 330Sdukeextern const char SmExcTypeMagic[]; 340Sduke 350Sdukestruct sm_exc_type 360Sduke{ 370Sduke const char *sm_magic; 380Sduke const char *etype_category; 390Sduke const char *etype_argformat; 400Sduke void (*etype_print) __P((SM_EXC_T *, SM_FILE_T *)); 410Sduke const char *etype_printcontext; 420Sduke}; 430Sduke 440Sdukeextern const SM_EXC_TYPE_T SmEtypeOs; 450Sdukeextern const SM_EXC_TYPE_T SmEtypeErr; 460Sduke 470Sdukeextern void 480Sdukesm_etype_printf __P(( 490Sduke SM_EXC_T *_exc, 500Sduke SM_FILE_T *_stream)); 510Sduke 520Sduke/* 530Sduke** Exception objects 540Sduke*/ 550Sduke 560Sdukeextern const char SmExcMagic[]; 570Sduke 580Sdukeunion sm_val 590Sduke{ 600Sduke int v_int; 610Sduke long v_long; 620Sduke char *v_str; 630Sduke SM_EXC_T *v_exc; 640Sduke}; 650Sduke 660Sdukestruct sm_exc 670Sduke{ 680Sduke const char *sm_magic; 690Sduke size_t exc_refcount; 700Sduke const SM_EXC_TYPE_T *exc_type; 710Sduke SM_VAL_T *exc_argv; 720Sduke}; 730Sduke 740Sduke# define SM_EXC_INITIALIZER(type, argv) \ 750Sduke { \ 760Sduke SmExcMagic, \ 770Sduke 0, \ 780Sduke type, \ 790Sduke argv, \ 800Sduke } 810Sduke 820Sdukeextern SM_EXC_T * 830Sdukesm_exc_new_x __P(( 840Sduke const SM_EXC_TYPE_T *_type, 850Sduke ...)); 860Sduke 870Sdukeextern SM_EXC_T * 880Sdukesm_exc_addref __P(( 890Sduke SM_EXC_T *_exc)); 900Sduke 910Sdukeextern void 920Sdukesm_exc_free __P(( 930Sduke SM_EXC_T *_exc)); 94 95extern bool 96sm_exc_match __P(( 97 SM_EXC_T *_exc, 98 const char *_pattern)); 99 100extern void 101sm_exc_write __P(( 102 SM_EXC_T *_exc, 103 SM_FILE_T *_stream)); 104 105extern void 106sm_exc_print __P(( 107 SM_EXC_T *_exc, 108 SM_FILE_T *_stream)); 109 110extern SM_DEAD(void 111sm_exc_raise_x __P(( 112 SM_EXC_T *_exc))); 113 114extern SM_DEAD(void 115sm_exc_raisenew_x __P(( 116 const SM_EXC_TYPE_T *_type, 117 ...))); 118 119/* 120** Exception handling 121*/ 122 123typedef void (*SM_EXC_DEFAULT_HANDLER_T) __P((SM_EXC_T *)); 124 125extern void 126sm_exc_newthread __P(( 127 SM_EXC_DEFAULT_HANDLER_T _handle)); 128 129typedef struct sm_exc_handler SM_EXC_HANDLER_T; 130struct 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 */ 139enum 140{ 141 SM_EH_PUSHED = 2, 142 SM_EH_POPPED = 0, 143 SM_EH_HANDLED = 1 144}; 145 146extern 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