190792Sgshapiro/*
2261363Sgshapiro * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
390792Sgshapiro *	All rights reserved.
490792Sgshapiro *
590792Sgshapiro * By using this file, you agree to the terms and conditions set
690792Sgshapiro * forth in the LICENSE file which can be found at the top level of
790792Sgshapiro * the sendmail distribution.
890792Sgshapiro *
9266692Sgshapiro *	$Id: exc.h,v 1.24 2013-11-22 20:51:31 ca Exp $
1090792Sgshapiro */
1190792Sgshapiro
1290792Sgshapiro/*
1390792Sgshapiro**  libsm exception handling
1490792Sgshapiro**  See libsm/exc.html for documentation.
1590792Sgshapiro*/
1690792Sgshapiro
1790792Sgshapiro#ifndef SM_EXC_H
1890792Sgshapiro# define SM_EXC_H
1990792Sgshapiro
2090792Sgshapiro#include <sm/setjmp.h>
2190792Sgshapiro#include <sm/io.h>
2290792Sgshapiro#include <sm/gen.h>
2390792Sgshapiro#include <sm/assert.h>
2490792Sgshapiro
2590792Sgshapirotypedef struct sm_exc SM_EXC_T;
2690792Sgshapirotypedef struct sm_exc_type SM_EXC_TYPE_T;
2790792Sgshapirotypedef union sm_val SM_VAL_T;
2890792Sgshapiro
2990792Sgshapiro/*
3090792Sgshapiro**  Exception types
3190792Sgshapiro*/
3290792Sgshapiro
3390792Sgshapiroextern const char SmExcTypeMagic[];
3490792Sgshapiro
3590792Sgshapirostruct sm_exc_type
3690792Sgshapiro{
3790792Sgshapiro	const char	*sm_magic;
3890792Sgshapiro	const char	*etype_category;
3990792Sgshapiro	const char	*etype_argformat;
4090792Sgshapiro	void		(*etype_print) __P((SM_EXC_T *, SM_FILE_T *));
4190792Sgshapiro	const char	*etype_printcontext;
4290792Sgshapiro};
4390792Sgshapiro
4490792Sgshapiroextern const SM_EXC_TYPE_T SmEtypeOs;
4590792Sgshapiroextern const SM_EXC_TYPE_T SmEtypeErr;
4690792Sgshapiro
4790792Sgshapiroextern void
4890792Sgshapirosm_etype_printf __P((
4990792Sgshapiro	SM_EXC_T *_exc,
5090792Sgshapiro	SM_FILE_T *_stream));
5190792Sgshapiro
5290792Sgshapiro/*
5390792Sgshapiro**  Exception objects
5490792Sgshapiro*/
5590792Sgshapiro
5690792Sgshapiroextern const char SmExcMagic[];
5790792Sgshapiro
5890792Sgshapirounion sm_val
5990792Sgshapiro{
6090792Sgshapiro	int		v_int;
6190792Sgshapiro	long		v_long;
6290792Sgshapiro	char		*v_str;
6390792Sgshapiro	SM_EXC_T	*v_exc;
6490792Sgshapiro};
6590792Sgshapiro
6690792Sgshapirostruct sm_exc
6790792Sgshapiro{
6890792Sgshapiro	const char		*sm_magic;
6990792Sgshapiro	size_t			exc_refcount;
7090792Sgshapiro	const SM_EXC_TYPE_T	*exc_type;
7190792Sgshapiro	SM_VAL_T		*exc_argv;
7290792Sgshapiro};
7390792Sgshapiro
7490792Sgshapiro# define SM_EXC_INITIALIZER(type, argv) \
7590792Sgshapiro	{ \
7690792Sgshapiro		SmExcMagic, \
7790792Sgshapiro		0, \
7890792Sgshapiro		type, \
7990792Sgshapiro		argv, \
8090792Sgshapiro	}
8190792Sgshapiro
8290792Sgshapiroextern SM_EXC_T *
8390792Sgshapirosm_exc_new_x __P((
8490792Sgshapiro	const SM_EXC_TYPE_T *_type,
8590792Sgshapiro	...));
8690792Sgshapiro
8790792Sgshapiroextern SM_EXC_T *
8890792Sgshapirosm_exc_addref __P((
8990792Sgshapiro	SM_EXC_T *_exc));
9090792Sgshapiro
9190792Sgshapiroextern void
9290792Sgshapirosm_exc_free __P((
9390792Sgshapiro	SM_EXC_T *_exc));
9490792Sgshapiro
9590792Sgshapiroextern bool
9690792Sgshapirosm_exc_match __P((
9790792Sgshapiro	SM_EXC_T *_exc,
9890792Sgshapiro	const char *_pattern));
9990792Sgshapiro
10090792Sgshapiroextern void
10190792Sgshapirosm_exc_write __P((
10290792Sgshapiro	SM_EXC_T *_exc,
10390792Sgshapiro	SM_FILE_T *_stream));
10490792Sgshapiro
10590792Sgshapiroextern void
10690792Sgshapirosm_exc_print __P((
10790792Sgshapiro	SM_EXC_T *_exc,
10890792Sgshapiro	SM_FILE_T *_stream));
10990792Sgshapiro
11090792Sgshapiroextern SM_DEAD(void
11190792Sgshapirosm_exc_raise_x __P((
11290792Sgshapiro	SM_EXC_T *_exc)));
11390792Sgshapiro
11490792Sgshapiroextern SM_DEAD(void
11590792Sgshapirosm_exc_raisenew_x __P((
11690792Sgshapiro	const SM_EXC_TYPE_T *_type,
11790792Sgshapiro	...)));
11890792Sgshapiro
11990792Sgshapiro/*
12090792Sgshapiro**  Exception handling
12190792Sgshapiro*/
12290792Sgshapiro
12390792Sgshapirotypedef void (*SM_EXC_DEFAULT_HANDLER_T) __P((SM_EXC_T *));
12490792Sgshapiro
12590792Sgshapiroextern void
12690792Sgshapirosm_exc_newthread __P((
12790792Sgshapiro	SM_EXC_DEFAULT_HANDLER_T _handle));
12890792Sgshapiro
12990792Sgshapirotypedef struct sm_exc_handler SM_EXC_HANDLER_T;
13090792Sgshapirostruct sm_exc_handler
13190792Sgshapiro{
13290792Sgshapiro	SM_EXC_T		*eh_value;
13390792Sgshapiro	SM_JMPBUF_T		eh_context;
13490792Sgshapiro	SM_EXC_HANDLER_T	*eh_parent;
13590792Sgshapiro	int			eh_state;
13690792Sgshapiro};
13790792Sgshapiro
13890792Sgshapiro/* values for eh_state */
13990792Sgshapiroenum
14090792Sgshapiro{
14190792Sgshapiro	SM_EH_PUSHED = 2,
14290792Sgshapiro	SM_EH_POPPED = 0,
14390792Sgshapiro	SM_EH_HANDLED = 1
14490792Sgshapiro};
14590792Sgshapiro
14690792Sgshapiroextern SM_EXC_HANDLER_T *SmExcHandler;
14790792Sgshapiro
14890792Sgshapiro# define SM_TRY		{ SM_EXC_HANDLER_T _h; \
14990792Sgshapiro			  do { \
15090792Sgshapiro			    _h.eh_value = NULL; \
15190792Sgshapiro			    _h.eh_parent = SmExcHandler; \
15290792Sgshapiro			    _h.eh_state = SM_EH_PUSHED; \
15390792Sgshapiro			    SmExcHandler = &_h; \
15490792Sgshapiro			    if (sm_setjmp_nosig(_h.eh_context) == 0) {
15590792Sgshapiro
15690792Sgshapiro# define SM_FINALLY	      SM_ASSERT(SmExcHandler == &_h); \
15790792Sgshapiro			    } \
15890792Sgshapiro			    if (sm_setjmp_nosig(_h.eh_context) == 0) {
15990792Sgshapiro
16090792Sgshapiro# define SM_EXCEPT(e,pat)   } \
16190792Sgshapiro			    if (_h.eh_state == SM_EH_HANDLED) \
16290792Sgshapiro			      break; \
16390792Sgshapiro			    if (_h.eh_state == SM_EH_PUSHED) { \
16490792Sgshapiro			      SM_ASSERT(SmExcHandler == &_h); \
16590792Sgshapiro			      SmExcHandler = _h.eh_parent; \
16690792Sgshapiro			    } \
16790792Sgshapiro			    _h.eh_state = sm_exc_match(_h.eh_value,pat) \
16890792Sgshapiro			      ? SM_EH_HANDLED : SM_EH_POPPED; \
16990792Sgshapiro			    if (_h.eh_state == SM_EH_HANDLED) { \
17090792Sgshapiro			      SM_UNUSED(SM_EXC_T *e) = _h.eh_value;
17190792Sgshapiro
17290792Sgshapiro# define SM_END_TRY	  } \
17390792Sgshapiro			  } while (0); \
17490792Sgshapiro			  if (_h.eh_state == SM_EH_PUSHED) { \
17590792Sgshapiro			    SM_ASSERT(SmExcHandler == &_h); \
17690792Sgshapiro			    SmExcHandler = _h.eh_parent; \
17790792Sgshapiro			    if (_h.eh_value != NULL) \
17890792Sgshapiro			      sm_exc_raise_x(_h.eh_value); \
17990792Sgshapiro			  } else if (_h.eh_state == SM_EH_POPPED) { \
18090792Sgshapiro			    if (_h.eh_value != NULL) \
18190792Sgshapiro			      sm_exc_raise_x(_h.eh_value); \
18290792Sgshapiro			  } else \
18390792Sgshapiro			    sm_exc_free(_h.eh_value); \
18490792Sgshapiro			}
18590792Sgshapiro
18690792Sgshapiro#endif /* SM_EXC_H */
187