189099Sfjoe/*
289099Sfjoe * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
389099Sfjoe *	All rights reserved.
4139823Simp *
589099Sfjoe * By using this file, you agree to the terms and conditions set
689099Sfjoe * forth in the LICENSE file which can be found at the top level of
789099Sfjoe * the sendmail distribution.
889099Sfjoe *
989099Sfjoe *	$Id: exc.h,v 1.24 2013-11-22 20:51:31 ca Exp $
1089099Sfjoe */
1189099Sfjoe
1289099Sfjoe/*
1389099Sfjoe**  libsm exception handling
1489099Sfjoe**  See libsm/exc.html for documentation.
1589099Sfjoe*/
1689099Sfjoe
1789099Sfjoe#ifndef SM_EXC_H
1889099Sfjoe# define SM_EXC_H
1989099Sfjoe
2089099Sfjoe#include <sm/setjmp.h>
2189099Sfjoe#include <sm/io.h>
2289099Sfjoe#include <sm/gen.h>
2389099Sfjoe#include <sm/assert.h>
2489099Sfjoe
2589099Sfjoetypedef struct sm_exc SM_EXC_T;
2689099Sfjoetypedef struct sm_exc_type SM_EXC_TYPE_T;
2789099Sfjoetypedef union sm_val SM_VAL_T;
2889099Sfjoe
2989099Sfjoe/*
3089099Sfjoe**  Exception types
3189099Sfjoe*/
3289099Sfjoe
3389099Sfjoeextern const char SmExcTypeMagic[];
3489099Sfjoe
3589099Sfjoestruct sm_exc_type
3689099Sfjoe{
3789099Sfjoe	const char	*sm_magic;
3889099Sfjoe	const char	*etype_category;
3989099Sfjoe	const char	*etype_argformat;
4089099Sfjoe	void		(*etype_print) __P((SM_EXC_T *, SM_FILE_T *));
4189099Sfjoe	const char	*etype_printcontext;
4289099Sfjoe};
43109771Sfjoe
4489099Sfjoeextern const SM_EXC_TYPE_T SmEtypeOs;
4589099Sfjoeextern const SM_EXC_TYPE_T SmEtypeErr;
4689099Sfjoe
4789099Sfjoeextern void
48129880Sphksm_etype_printf __P((
4989099Sfjoe	SM_EXC_T *_exc,
5089099Sfjoe	SM_FILE_T *_stream));
5189099Sfjoe
5289099Sfjoe/*
5389099Sfjoe**  Exception objects
5489099Sfjoe*/
5589099Sfjoe
5689099Sfjoeextern const char SmExcMagic[];
5789099Sfjoe
5889099Sfjoeunion sm_val
5989099Sfjoe{
6089099Sfjoe	int		v_int;
6189099Sfjoe	long		v_long;
6289099Sfjoe	char		*v_str;
6389099Sfjoe	SM_EXC_T	*v_exc;
6489099Sfjoe};
6589099Sfjoe
6689099Sfjoestruct sm_exc
67186119Sqingli{
6889099Sfjoe	const char		*sm_magic;
6989099Sfjoe	size_t			exc_refcount;
7089099Sfjoe	const SM_EXC_TYPE_T	*exc_type;
7189099Sfjoe	SM_VAL_T		*exc_argv;
7289099Sfjoe};
7389099Sfjoe
7489099Sfjoe# define SM_EXC_INITIALIZER(type, argv) \
7589099Sfjoe	{ \
7689099Sfjoe		SmExcMagic, \
7789099Sfjoe		0, \
7889099Sfjoe		type, \
79109771Sfjoe		argv, \
80109771Sfjoe	}
81109771Sfjoe
82109771Sfjoeextern SM_EXC_T *
83109771Sfjoesm_exc_new_x __P((
8489099Sfjoe	const SM_EXC_TYPE_T *_type,
8589099Sfjoe	...));
8692725Salfred
87109771Sfjoeextern SM_EXC_T *
88109771Sfjoesm_exc_addref __P((
8989099Sfjoe	SM_EXC_T *_exc));
9089099Sfjoe
9189099Sfjoeextern void
92110106Sfjoesm_exc_free __P((
93110106Sfjoe	SM_EXC_T *_exc));
9489099Sfjoe
95109771Sfjoeextern bool
96109771Sfjoesm_exc_match __P((
9789099Sfjoe	SM_EXC_T *_exc,
9889099Sfjoe	const char *_pattern));
9989099Sfjoe
10089099Sfjoeextern void
10189099Sfjoesm_exc_write __P((
10289099Sfjoe	SM_EXC_T *_exc,
10389099Sfjoe	SM_FILE_T *_stream));
104157681Srwatson
105191148Skmacyextern void
10689099Sfjoesm_exc_print __P((
10789099Sfjoe	SM_EXC_T *_exc,
10889099Sfjoe	SM_FILE_T *_stream));
10989099Sfjoe
110109771Sfjoeextern SM_DEAD(void
111110106Sfjoesm_exc_raise_x __P((
112193891Sbz	SM_EXC_T *_exc)));
113186119Sqingli
114193891Sbzextern SM_DEAD(void
11589099Sfjoesm_exc_raisenew_x __P((
116148887Srwatson	const SM_EXC_TYPE_T *_type,
117148887Srwatson	...)));
11889099Sfjoe
11989099Sfjoe/*
12089099Sfjoe**  Exception handling
12189099Sfjoe*/
12289099Sfjoe
12389099Sfjoetypedef void (*SM_EXC_DEFAULT_HANDLER_T) __P((SM_EXC_T *));
12489099Sfjoe
12589099Sfjoeextern void
12689099Sfjoesm_exc_newthread __P((
12789099Sfjoe	SM_EXC_DEFAULT_HANDLER_T _handle));
12889099Sfjoe
12989099Sfjoetypedef struct sm_exc_handler SM_EXC_HANDLER_T;
13089099Sfjoestruct sm_exc_handler
13189099Sfjoe{
13289099Sfjoe	SM_EXC_T		*eh_value;
133128636Sluigi	SM_JMPBUF_T		eh_context;
134191148Skmacy	SM_EXC_HANDLER_T	*eh_parent;
135191148Skmacy	int			eh_state;
136128636Sluigi};
137128636Sluigi
138128636Sluigi/* values for eh_state */
13989099Sfjoeenum
14089099Sfjoe{
14189099Sfjoe	SM_EH_PUSHED = 2,
14289099Sfjoe	SM_EH_POPPED = 0,
143127260Smdodd	SM_EH_HANDLED = 1
144127260Smdodd};
145127260Smdodd
146127260Smdoddextern SM_EXC_HANDLER_T *SmExcHandler;
147127260Smdodd
148127260Smdodd# define SM_TRY		{ SM_EXC_HANDLER_T _h; \
149127260Smdodd			  do { \
150127260Smdodd			    _h.eh_value = NULL; \
151127260Smdodd			    _h.eh_parent = SmExcHandler; \
152127260Smdodd			    _h.eh_state = SM_EH_PUSHED; \
153127260Smdodd			    SmExcHandler = &_h; \
154127275Smdodd			    if (sm_setjmp_nosig(_h.eh_context) == 0) {
155127260Smdodd
156127260Smdodd# define SM_FINALLY	      SM_ASSERT(SmExcHandler == &_h); \
157127260Smdodd			    } \
158127260Smdodd			    if (sm_setjmp_nosig(_h.eh_context) == 0) {
159127275Smdodd
160127260Smdodd# define SM_EXCEPT(e,pat)   } \
161127260Smdodd			    if (_h.eh_state == SM_EH_HANDLED) \
162127260Smdodd			      break; \
163127260Smdodd			    if (_h.eh_state == SM_EH_PUSHED) { \
164127290Smdodd			      SM_ASSERT(SmExcHandler == &_h); \
165127260Smdodd			      SmExcHandler = _h.eh_parent; \
166127290Smdodd			    } \
167127260Smdodd			    _h.eh_state = sm_exc_match(_h.eh_value,pat) \
168127260Smdodd			      ? SM_EH_HANDLED : SM_EH_POPPED; \
169127260Smdodd			    if (_h.eh_state == SM_EH_HANDLED) { \
17089099Sfjoe			      SM_UNUSED(SM_EXC_T *e) = _h.eh_value;
17189099Sfjoe
17289099Sfjoe# define SM_END_TRY	  } \
173186217Sqingli			  } while (0); \
174128636Sluigi			  if (_h.eh_state == SM_EH_PUSHED) { \
175128636Sluigi			    SM_ASSERT(SmExcHandler == &_h); \
17689099Sfjoe			    SmExcHandler = _h.eh_parent; \
17789099Sfjoe			    if (_h.eh_value != NULL) \
17889099Sfjoe			      sm_exc_raise_x(_h.eh_value); \
179109771Sfjoe			  } else if (_h.eh_state == SM_EH_POPPED) { \
180109771Sfjoe			    if (_h.eh_value != NULL) \
181109771Sfjoe			      sm_exc_raise_x(_h.eh_value); \
182109771Sfjoe			  } else \
183109771Sfjoe			    sm_exc_free(_h.eh_value); \
184109771Sfjoe			}
185109771Sfjoe
186109771Sfjoe#endif /* SM_EXC_H */
18789099Sfjoe