Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Prototypes to some *printf functions in public interface (badly placed, but works...
[simgrid.git] / include / xbt / ex.h
1 /*
2 **  OSSP ex - Exception Handling
3 **  Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com>
4 **  Copyright (c) 2002-2004 The OSSP Project <http://www.ossp.org/>
5 **  Copyright (c) 2002-2004 Cable & Wireless <http://www.cw.com/>
6 **
7 **  This file is part of OSSP ex, an exception handling library
8 **  which can be found at http://www.ossp.org/pkg/lib/ex/.
9 **
10 **  Permission to use, copy, modify, and distribute this software for
11 **  any purpose with or without fee is hereby granted, provided that
12 **  the above copyright notice and this permission notice appear in all
13 **  copies.
14 **
15 **  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
16 **  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 **  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 **  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
19 **  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 **  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 **  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22 **  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 **  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 **  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 **  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 **  SUCH DAMAGE.
27 **
28 **  ex.h: exception handling (pre-processor part)
29 */
30
31 #ifndef __EX_H__
32 #define __EX_H__
33
34 /* required ISO-C standard facilities */
35 #include <stdio.h>
36
37 /* convenience define */
38 #ifndef NULL
39 #define NULL (void *)0
40 #endif
41
42 /* determine how the current function name can be fetched */
43 #if (   defined(__STDC__) \
44      && defined(__STDC_VERSION__) \
45      && __STDC_VERSION__ >= 199901L)
46 #define __EX_FUNC__ __func__      /* ISO-C99 compliant */
47 #elif (   defined(__GNUC__) \
48        && defined(__GNUC_MINOR__) \
49        && (   __GNUC__ > 2 \
50            || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)))
51 #define __EX_FUNC__ __FUNCTION__  /* gcc >= 2.8 */
52 #else
53 #define __EX_FUNC__ "#NA#"        /* not available */
54 #endif
55
56 /* the machine context */
57 #if defined(__EX_MCTX_MCSC__)
58 #include <ucontext.h>            /* POSIX.1 ucontext(3) */
59 #define __ex_mctx_struct         ucontext_t uc;
60 #define __ex_mctx_save(mctx)     (getcontext(&(mctx)->uc) == 0)
61 #define __ex_mctx_restored(mctx) /* noop */
62 #define __ex_mctx_restore(mctx)  (void)setcontext(&(mctx)->uc)
63
64 #elif defined(__EX_MCTX_SSJLJ__)
65 #include <setjmp.h>              /* POSIX.1 sigjmp_buf(3) */
66 #define __ex_mctx_struct         sigjmp_buf jb;
67 #define __ex_mctx_save(mctx)     (sigsetjmp((mctx)->jb, 1) == 0)
68 #define __ex_mctx_restored(mctx) /* noop */
69 #define __ex_mctx_restore(mctx)  (void)siglongjmp((mctx)->jb, 1)
70
71 #elif defined(__EX_MCTX_SJLJ__) || !defined(__EX_MCTX_CUSTOM__)
72 #include <setjmp.h>              /* ISO-C jmp_buf(3) */
73 #define __ex_mctx_struct         jmp_buf jb;
74 #define __ex_mctx_save(mctx)     (setjmp((mctx)->jb) == 0)
75 #define __ex_mctx_restored(mctx) /* noop */
76 #define __ex_mctx_restore(mctx)  (void)longjmp((mctx)->jb, 1)
77 #endif
78
79 /* declare the machine context type */
80 typedef struct { __ex_mctx_struct } __ex_mctx_t;
81
82 /* declare the exception type (public) */
83 typedef struct {
84     /* throw value */
85     void       *ex_class;
86     void       *ex_object;
87     void       *ex_value;
88     /* throw point */
89     const char *ex_file;
90     int         ex_line;
91     const char *ex_func;
92 } ex_t;
93
94 /* declare the context type (private) */
95 typedef struct {
96     __ex_mctx_t  *ctx_mctx;     /* permanent machine context of enclosing try/catch */
97     int           ctx_deferred; /* permanent flag whether exception is deferred */
98     int           ctx_deferring;/* permanent counter of exception deferring level */
99     int           ctx_defer;    /* temporary flag for exception deferring macro */
100     int           ctx_shielding;/* permanent counter of exception shielding level */
101     int           ctx_shield;   /* temporary flag for exception shielding macro */
102     int           ctx_caught;   /* temporary flag whether exception was caught */
103     volatile ex_t ctx_ex;       /* temporary exception storage */
104 } ex_ctx_t;
105
106 /* the static and dynamic initializers for a context structure */
107 #define EX_CTX_INITIALIZER \
108     { NULL, 0, 0, 0, 0, 0, 0, { NULL, NULL, NULL, NULL, 0, NULL } }
109 #define EX_CTX_INITIALIZE(ctx) \
110     do { \
111         (ctx)->ctx_mctx         = NULL; \
112         (ctx)->ctx_deferred     = 0;    \
113         (ctx)->ctx_deferring    = 0;    \
114         (ctx)->ctx_defer        = 0;    \
115         (ctx)->ctx_shielding    = 0;    \
116         (ctx)->ctx_shield       = 0;    \
117         (ctx)->ctx_caught       = 0;    \
118         (ctx)->ctx_ex.ex_class  = NULL; \
119         (ctx)->ctx_ex.ex_object = NULL; \
120         (ctx)->ctx_ex.ex_value  = NULL; \
121         (ctx)->ctx_ex.ex_file   = NULL; \
122         (ctx)->ctx_ex.ex_line   = 0;    \
123         (ctx)->ctx_ex.ex_func   = NULL; \
124     } while (0)
125
126 /* the exception context */
127 typedef ex_ctx_t *(*ex_ctx_cb_t)(void);
128 extern ex_ctx_cb_t __ex_ctx;
129 extern ex_ctx_t *__ex_ctx_default(void);
130
131 /* the termination handler */
132 typedef void (*ex_term_cb_t)(ex_t *);
133 extern ex_term_cb_t __ex_terminate;
134 extern void __ex_terminate_default(ex_t *e);
135
136 /* the block for trying execution */
137 #define ex_try \
138     { \
139         ex_ctx_t *__ex_ctx_ptr = __ex_ctx(); \
140         int __ex_cleanup = 0; \
141         __ex_mctx_t *__ex_mctx_en; \
142         __ex_mctx_t __ex_mctx_me; \
143         __ex_mctx_en = __ex_ctx_ptr->ctx_mctx; \
144         __ex_ctx_ptr->ctx_mctx = &__ex_mctx_me; \
145         if (__ex_mctx_save(&__ex_mctx_me)) { \
146             if (1)
147
148 /* the optional(!) block for cleanup */
149 #define ex_cleanup \
150             else { \
151             } \
152             __ex_ctx_ptr->ctx_caught = 0; \
153         } \
154         else { \
155             __ex_mctx_restored(&__ex_mctx_me); \
156             __ex_ctx_ptr->ctx_caught = 1; \
157         } \
158         __ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \
159         __ex_cleanup = 1; \
160         if (1) { \
161             if (1)
162
163 /* the block for catching an exception */
164 #define ex_catch(e) \
165             else { \
166             } \
167             if (!(__ex_cleanup)) \
168                 __ex_ctx_ptr->ctx_caught = 0; \
169         } \
170         else { \
171             if (!(__ex_cleanup)) { \
172                 __ex_mctx_restored(&__ex_mctx_me); \
173                 __ex_ctx_ptr->ctx_caught = 1; \
174             } \
175         } \
176         __ex_ctx_ptr->ctx_mctx = __ex_mctx_en; \
177     } \
178     if (   !(__ex_ctx()->ctx_caught) \
179         || ((e) = __ex_ctx()->ctx_ex, 0)) { \
180     } \
181     else
182
183 /* the throwing of a new exception */
184 #define ex_throw(c,o,v) \
185     ((   __ex_ctx()->ctx_shielding > 0 \
186       || (__ex_ctx()->ctx_deferring > 0 && __ex_ctx()->ctx_deferred == 1)) ? 0 : \
187      (__ex_ctx()->ctx_ex.ex_class  = (void *)(c), \
188       __ex_ctx()->ctx_ex.ex_object = (void *)(o), \
189       __ex_ctx()->ctx_ex.ex_value  = (void *)(v), \
190       __ex_ctx()->ctx_ex.ex_file   = __FILE__, \
191       __ex_ctx()->ctx_ex.ex_line   = __LINE__, \
192       __ex_ctx()->ctx_ex.ex_func   = __EX_FUNC__, \
193       __ex_ctx()->ctx_deferred     = 1, \
194       (__ex_ctx()->ctx_deferring > 0 ? 0 : \
195        (__ex_ctx()->ctx_mctx == NULL \
196         ? (__ex_terminate((ex_t *)&(__ex_ctx()->ctx_ex)), -1) \
197         : (__ex_mctx_restore(__ex_ctx()->ctx_mctx), 1) ))))
198
199 /* the re-throwing of an already caught exception */
200 #define ex_rethrow \
201     ((   __ex_ctx()->ctx_shielding > 0 \
202       || __ex_ctx()->ctx_deferring > 0) ? 0 : \
203       (  __ex_ctx()->ctx_mctx == NULL \
204        ? (__ex_terminate((ex_t *)&(__ex_ctx()->ctx_ex)), -1) \
205        : (__ex_mctx_restore(__ex_ctx()->ctx_mctx), 1) ))
206
207 /* shield an operation from exception handling */
208 #define ex_shield \
209     for (__ex_ctx()->ctx_shielding++, \
210          __ex_ctx()->ctx_shield =  1; \
211          __ex_ctx()->ctx_shield == 1; \
212          __ex_ctx()->ctx_shield =  0, \
213          __ex_ctx()->ctx_shielding--)
214
215 /* defer immediate exception handling */
216 #define ex_defer \
217     for (((__ex_ctx()->ctx_deferring)++ == 0 ? __ex_ctx()->ctx_deferred = 0 : 0), \
218          __ex_ctx()->ctx_defer =  1;  \
219          __ex_ctx()->ctx_defer == 1;  \
220          __ex_ctx()->ctx_defer =  0,  \
221          ((--(__ex_ctx()->ctx_deferring) == 0 && __ex_ctx()->ctx_deferred == 1) ? ex_rethrow : 0))
222
223 /* exception handling tests */
224 #define ex_catching \
225     (__ex_ctx()->ctx_mctx != NULL)
226 #define ex_shielding \
227     (__ex_ctx()->ctx_shielding > 0)
228 #define ex_deferring \
229     (__ex_ctx()->ctx_deferring > 0)
230
231 /* optional namespace mapping */
232 #if defined(__EX_NS_UCCXX__)
233 #define Try      ex_try
234 #define Cleanup  ex_cleanup
235 #define Catch    ex_catch
236 #define Throw    ex_throw
237 #define Rethrow  ex_rethrow
238 #define Shield   ex_shield
239 #define Defer    ex_defer
240 #elif defined(__EX_NS_CXX__) || (!defined(__cplusplus) && !defined(__EX_NS_CUSTOM__))
241 #define try      ex_try
242 #define cleanup  ex_cleanup
243 #define catch    ex_catch
244 #define throw    ex_throw
245 #define rethrow  ex_rethrow
246 #define shield   ex_shield
247 #define defer    ex_defer
248 #endif
249
250 #endif /* __EX_H__ */
251