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
27typedef struct sm_exc SM_EXC_T;
28typedef struct sm_exc_type SM_EXC_TYPE_T;
29typedef union sm_val SM_VAL_T;
30
31/*
32**  Exception types
33*/
34
35extern const char SmExcTypeMagic[];
36
37struct 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
46extern const SM_EXC_TYPE_T SmEtypeOs;
47extern const SM_EXC_TYPE_T SmEtypeErr;
48
49extern void
50sm_etype_printf __P((
51	SM_EXC_T *_exc,
52	SM_FILE_T *_stream));
53
54/*
55**  Exception objects
56*/
57
58extern const char SmExcMagic[];
59
60union sm_val
61{
62	int		v_int;
63	long		v_long;
64	char		*v_str;
65	SM_EXC_T	*v_exc;
66};
67
68struct 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
84extern SM_EXC_T *
85sm_exc_new_x __P((
86	const SM_EXC_TYPE_T *_type,
87	...));
88
89extern SM_EXC_T *
90sm_exc_addref __P((
91	SM_EXC_T *_exc));
92
93extern void
94sm_exc_free __P((
95	SM_EXC_T *_exc));
96
97extern bool
98sm_exc_match __P((
99	SM_EXC_T *_exc,
100	const char *_pattern));
101
102extern void
103sm_exc_write __P((
104	SM_EXC_T *_exc,
105	SM_FILE_T *_stream));
106
107extern void
108sm_exc_print __P((
109	SM_EXC_T *_exc,
110	SM_FILE_T *_stream));
111
112extern SM_DEAD(void
113sm_exc_raise_x __P((
114	SM_EXC_T *_exc)));
115
116extern SM_DEAD(void
117sm_exc_raisenew_x __P((
118	const SM_EXC_TYPE_T *_type,
119	...)));
120
121/*
122**  Exception handling
123*/
124
125typedef void (*SM_EXC_DEFAULT_HANDLER_T) __P((SM_EXC_T *));
126
127extern void
128sm_exc_newthread __P((
129	SM_EXC_DEFAULT_HANDLER_T _handle));
130
131typedef struct sm_exc_handler SM_EXC_HANDLER_T;
132struct 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 */
141enum
142{
143	SM_EH_PUSHED = 2,
144	SM_EH_POPPED = 0,
145	SM_EH_HANDLED = 1
146};
147
148extern 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