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