Merge from vendor branch OPENSSL:
[dragonfly.git] / contrib / sendmail-8.13.8 / include / sm / exc.h
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 /*
13 **  libsm exception handling
14 **  See libsm/exc.html for documentation.
15 */
16
17 #ifndef SM_EXC_H
18 # define SM_EXC_H
19
20 #include <sm/setjmp.h>
21 #include <sm/io.h>
22 #include <sm/gen.h>
23 #include <sm/assert.h>
24
25 typedef struct sm_exc SM_EXC_T;
26 typedef struct sm_exc_type SM_EXC_TYPE_T;
27 typedef union sm_val SM_VAL_T;
28
29 /*
30 **  Exception types
31 */
32
33 extern const char SmExcTypeMagic[];
34
35 struct sm_exc_type
36 {
37         const char      *sm_magic;
38         const char      *etype_category;
39         const char      *etype_argformat;
40         void            (*etype_print) __P((SM_EXC_T *, SM_FILE_T *));
41         const char      *etype_printcontext;
42 };
43
44 extern const SM_EXC_TYPE_T SmEtypeOs;
45 extern const SM_EXC_TYPE_T SmEtypeErr;
46
47 extern void
48 sm_etype_printf __P((
49         SM_EXC_T *_exc,
50         SM_FILE_T *_stream));
51
52 /*
53 **  Exception objects
54 */
55
56 extern const char SmExcMagic[];
57
58 union sm_val
59 {
60         int             v_int;
61         long            v_long;
62         char            *v_str;
63         SM_EXC_T        *v_exc;
64 };
65
66 struct sm_exc
67 {
68         const char              *sm_magic;
69         size_t                  exc_refcount;
70         const SM_EXC_TYPE_T     *exc_type;
71         SM_VAL_T                *exc_argv;
72 };
73
74 # define SM_EXC_INITIALIZER(type, argv) \
75         { \
76                 SmExcMagic, \
77                 0, \
78                 type, \
79                 argv, \
80         }
81
82 extern SM_EXC_T *
83 sm_exc_new_x __P((
84         const SM_EXC_TYPE_T *_type,
85         ...));
86
87 extern SM_EXC_T *
88 sm_exc_addref __P((
89         SM_EXC_T *_exc));
90
91 extern void
92 sm_exc_free __P((
93         SM_EXC_T *_exc));
94
95 extern bool
96 sm_exc_match __P((
97         SM_EXC_T *_exc,
98         const char *_pattern));
99
100 extern void
101 sm_exc_write __P((
102         SM_EXC_T *_exc,
103         SM_FILE_T *_stream));
104
105 extern void
106 sm_exc_print __P((
107         SM_EXC_T *_exc,
108         SM_FILE_T *_stream));
109
110 extern SM_DEAD(void
111 sm_exc_raise_x __P((
112         SM_EXC_T *_exc)));
113
114 extern SM_DEAD(void
115 sm_exc_raisenew_x __P((
116         const SM_EXC_TYPE_T *_type,
117         ...)));
118
119 /*
120 **  Exception handling
121 */
122
123 typedef void (*SM_EXC_DEFAULT_HANDLER_T) __P((SM_EXC_T *));
124
125 extern void
126 sm_exc_newthread __P((
127         SM_EXC_DEFAULT_HANDLER_T _handle));
128
129 typedef struct sm_exc_handler SM_EXC_HANDLER_T;
130 struct 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 */
139 enum
140 {
141         SM_EH_PUSHED = 2,
142         SM_EH_POPPED = 0,
143         SM_EH_HANDLED = 1
144 };
145
146 extern 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 */