exc.h revision 261363
1187938Semax/*
2187938Semax * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
3187938Semax *	All rights reserved.
4187938Semax *
5187938Semax * By using this file, you agree to the terms and conditions set
6187938Semax * forth in the LICENSE file which can be found at the top level of
7187938Semax * the sendmail distribution.
8187938Semax *
9187938Semax *	$Id: exc.h,v 1.24 2013/11/22 20:51:31 ca Exp $
10187938Semax */
11187938Semax
12187938Semax/*
13187938Semax**  libsm exception handling
14187938Semax**  See libsm/exc.html for documentation.
15187938Semax*/
16187938Semax
17187938Semax#ifndef SM_EXC_H
18187938Semax# define SM_EXC_H
19187938Semax
20187938Semax#include <sm/setjmp.h>
21187938Semax#include <sm/io.h>
22187938Semax#include <sm/gen.h>
23187938Semax#include <sm/assert.h>
24187938Semax
25187938Semaxtypedef struct sm_exc SM_EXC_T;
26187938Semaxtypedef struct sm_exc_type SM_EXC_TYPE_T;
27187938Semaxtypedef union sm_val SM_VAL_T;
28187938Semax
29187938Semax/*
30187938Semax**  Exception types
31187938Semax*/
32187938Semax
33187938Semaxextern const char SmExcTypeMagic[];
34187938Semax
35187938Semaxstruct sm_exc_type
36187938Semax{
37187938Semax	const char	*sm_magic;
38187938Semax	const char	*etype_category;
39187938Semax	const char	*etype_argformat;
40187938Semax	void		(*etype_print) __P((SM_EXC_T *, SM_FILE_T *));
41187938Semax	const char	*etype_printcontext;
42187938Semax};
43187938Semax
44187938Semaxextern const SM_EXC_TYPE_T SmEtypeOs;
45187938Semaxextern const SM_EXC_TYPE_T SmEtypeErr;
46187938Semax
47187938Semaxextern void
48187938Semaxsm_etype_printf __P((
49187938Semax	SM_EXC_T *_exc,
50187938Semax	SM_FILE_T *_stream));
51187938Semax
52187938Semax/*
53187938Semax**  Exception objects
54187938Semax*/
55187938Semax
56187938Semaxextern const char SmExcMagic[];
57187938Semax
58187938Semaxunion sm_val
59187938Semax{
60187938Semax	int		v_int;
61187938Semax	long		v_long;
62187938Semax	char		*v_str;
63187938Semax	SM_EXC_T	*v_exc;
64187938Semax};
65187938Semax
66187938Semaxstruct sm_exc
67187938Semax{
68187938Semax	const char		*sm_magic;
69187938Semax	size_t			exc_refcount;
70187938Semax	const SM_EXC_TYPE_T	*exc_type;
71187938Semax	SM_VAL_T		*exc_argv;
72187938Semax};
73
74# define SM_EXC_INITIALIZER(type, argv) \
75	{ \
76		SmExcMagic, \
77		0, \
78		type, \
79		argv, \
80	}
81
82extern SM_EXC_T *
83sm_exc_new_x __P((
84	const SM_EXC_TYPE_T *_type,
85	...));
86
87extern SM_EXC_T *
88sm_exc_addref __P((
89	SM_EXC_T *_exc));
90
91extern void
92sm_exc_free __P((
93	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