2 * Portable Exception Handling for ANSI C.
3 * Copyright (C) 1999 Kaz Kylheku <kaz@ashi.footprints.net>
5 * Free Software License:
7 * All rights are reserved by the author, with the following exceptions:
8 * Permission is granted to freely reproduce and distribute this software,
9 * possibly in exchange for a fee, provided that this copyright notice appears
10 * intact. Permission is also granted to adapt this software to produce
11 * derivative works, as long as the modified versions carry this copyright
12 * notice and additional notices stating that the work has been modified.
13 * This source code may be translated into executable form and incorporated
14 * into proprietary software; there is no requirement for such software to
15 * contain a copyright notice related to this source.
22 * Modified to support throwing an exception with a null message pointer,
23 * and to have the message not be const (as we generate messages with
24 * "g_strdup_sprintf()", which means they need to be freed; using
25 * a null message means that we don't have to use a special string
26 * for exceptions with no message, and don't have to worry about
37 #define XCEPT_GROUP_ANY 0
38 #define XCEPT_CODE_ANY 0
39 #define XCEPT_BAD_ALLOC 1
45 enum { except_no_call, except_call };
48 unsigned long except_group;
49 unsigned long except_code;
53 except_id_t volatile except_id;
54 const char *volatile except_message;
55 void *volatile except_dyndata;
58 struct except_cleanup {
59 void (*except_func)(void *);
64 const except_id_t *except_id;
70 enum except_stacktype {
71 XCEPT_CLEANUP, XCEPT_CATCHER
74 struct except_stacknode {
75 struct except_stacknode *except_down;
76 enum except_stacktype except_type;
78 struct except_catch *except_catcher;
79 struct except_cleanup *except_cleanup;
83 /* private functions made external so they can be used in macros */
84 extern void except_setup_clean(struct except_stacknode *,
85 struct except_cleanup *, void (*)(void *), void *);
86 extern void except_setup_try(struct except_stacknode *,
87 struct except_catch *, const except_id_t [], size_t);
88 extern struct except_stacknode *except_pop(void);
90 /* public interface functions */
91 extern int except_init(void);
92 extern void except_deinit(void);
93 extern void except_rethrow(except_t *);
94 extern void except_throw(long, long, const char *);
95 extern void except_throwd(long, long, const char *, void *);
96 extern void except_throwf(long, long, const char *, ...);
97 extern void (*except_unhandled_catcher(void (*)(except_t *)))(except_t *);
98 extern unsigned long except_code(except_t *);
99 extern unsigned long except_group(except_t *);
100 extern const char *except_message(except_t *);
101 extern void *except_data(except_t *);
102 extern void *except_take_data(except_t *);
103 extern void except_set_allocator(void *(*)(size_t), void (*)(void *));
104 extern void *except_alloc(size_t);
105 extern void except_free(void *);
107 #define except_code(E) ((E)->except_id.except_code)
108 #define except_group(E) ((E)->except_id.except_group)
109 #define except_message(E) ((E)->except_message)
110 #define except_data(E) ((E)->except_dyndata)
117 * void except_cleanup_push(void (*)(void *), void *);
118 * void except_cleanup_pop(int);
119 * void except_checked_cleanup_pop(void (*)(void *), int);
120 * void except_try_push(const except_id_t [], size_t, except_t **);
121 * void except_try_pop(void);
124 #define except_cleanup_push(F, C) \
126 struct except_stacknode except_sn; \
127 struct except_cleanup except_cl; \
128 except_setup_clean(&except_sn, &except_cl, F, C)
130 #define except_cleanup_pop(E) \
133 except_cl.except_func(except_cl.except_context); \
136 #define except_checked_cleanup_pop(F, E) \
138 assert (except_cl.except_func == (F)); \
140 except_cl.except_func(except_cl.except_context); \
143 #define except_try_push(ID, NUM, PPE) \
145 struct except_stacknode except_sn; \
146 struct except_catch except_ch; \
147 except_setup_try(&except_sn, &except_ch, ID, NUM); \
148 if (setjmp(except_ch.except_jmp)) \
149 *(PPE) = &except_ch.except_obj; \
153 #define except_try_pop() \
154 except_free(except_ch.except_obj.except_dyndata); \