VirtualBox

source: vbox/trunk/src/libs/libpng-1.2.8/contrib/visupng/cexcept.h@ 11115

Last change on this file since 11115 was 6395, checked in by vboxsync, 17 years ago

export libpng and zlib so Windows and OS/2 build cleanly.

  • Property svn:eol-style set to native
File size: 9.8 KB
Line 
1/*===
2cexcept.h 2.0.0 (2001-Jul-12-Thu)
3Adam M. Costello <amc@cs.berkeley.edu>
4
5An interface for exception-handling in ANSI C (C89 and subsequent ISO
6standards), developed jointly with Cosmin Truta <cosmin@cs.toronto.edu>.
7
8 Copyright (c) 2001 Adam M. Costello and Cosmin Truta. Everyone
9 is hereby granted permission to do whatever they like with this
10 file, provided that if they modify it they take reasonable steps to
11 avoid confusing or misleading people about the authors, version,
12 and terms of use of the derived file. The copyright holders make
13 no guarantees regarding this file, and are not responsible for any
14 damage resulting from its use.
15
16Only user-defined exceptions are supported, not "real" exceptions like
17division by zero or memory segmentation violations.
18
19If this interface is used by multiple .c files, they shouldn't include
20this header file directly. Instead, create a wrapper header file that
21includes this header file and then invokes the define_exception_type
22macro (see below), and let your .c files include that header file.
23
24The interface consists of one type, one well-known name, and six macros.
25
26
27define_exception_type(type_name);
28
29 This macro is used like an external declaration. It specifies
30 the type of object that gets copied from the exception thrower to
31 the exception catcher. The type_name can be any type that can be
32 assigned to, that is, a non-constant arithmetic type, struct, union,
33 or pointer. Examples:
34
35 define_exception_type(int);
36
37 enum exception { out_of_memory, bad_arguments, disk_full };
38 define_exception_type(enum exception);
39
40 struct exception { int code; const char *msg; };
41 define_exception_type(struct exception);
42
43 Because throwing an exception causes the object to be copied (not
44 just once, but twice), programmers may wish to consider size when
45 choosing the exception type.
46
47
48struct exception_context;
49
50 This type may be used after the define_exception_type() macro has
51 been invoked. A struct exception_context must be known to both
52 the thrower and the catcher. It is expected that there be one
53 context for each thread that uses exceptions. It would certainly
54 be dangerous for multiple threads to access the same context.
55 One thread can use multiple contexts, but that is likely to be
56 confusing and not typically useful. The application can allocate
57 this structure in any way it pleases--automatic, static, or dynamic.
58 The application programmer should pretend not to know the structure
59 members, which are subject to change.
60
61
62struct exception_context *the_exception_context;
63
64 The Try/Catch and Throw statements (described below) implicitly
65 refer to a context, using the name the_exception_context. It is
66 the application's responsibility to make sure that this name yields
67 the address of a mutable (non-constant) struct exception_context
68 wherever those statements are used. Subject to that constraint, the
69 application may declare a variable of this name anywhere it likes
70 (inside a function, in a parameter list, or externally), and may
71 use whatever storage class specifiers (static, extern, etc) or type
72 qualifiers (const, volatile, etc) it likes. Examples:
73
74 static struct exception_context
75 * const the_exception_context = &foo;
76
77 { struct exception_context *the_exception_context = bar; ... }
78
79 int blah(struct exception_context *the_exception_context, ...);
80
81 extern struct exception_context the_exception_context[1];
82
83 The last example illustrates a trick that avoids creating a pointer
84 object separate from the structure object.
85
86 The name could even be a macro, for example:
87
88 struct exception_context ec_array[numthreads];
89 #define the_exception_context (ec_array + thread_id)
90
91 Be aware that the_exception_context is used several times by the
92 Try/Catch/Throw macros, so it shouldn't be expensive or have side
93 effects. The expansion must be a drop-in replacement for an
94 identifier, so it's safest to put parentheses around it.
95
96
97void init_exception_context(struct exception_context *ec);
98
99 For context structures allocated statically (by an external
100 definition or using the "static" keyword), the implicit
101 initialization to all zeros is sufficient, but contexts allocated
102 by other means must be initialized using this macro before they
103 are used by a Try/Catch statement. It does no harm to initialize
104 a context more than once (by using this macro on a statically
105 allocated context, or using this macro twice on the same context),
106 but a context must not be re-initialized after it has been used by a
107 Try/Catch statement.
108
109
110Try statement
111Catch (expression) statement
112
113 The Try/Catch/Throw macros are capitalized in order to avoid
114 confusion with the C++ keywords, which have subtly different
115 semantics.
116
117 A Try/Catch statement has a syntax similar to an if/else statement,
118 except that the parenthesized expression goes after the second
119 keyword rather than the first. As with if/else, there are two
120 clauses, each of which may be a simple statement ending with a
121 semicolon or a brace-enclosed compound statement. But whereas
122 the else clause is optional, the Catch clause is required. The
123 expression must be a modifiable lvalue (something capable of being
124 assigned to) of the same type (disregarding type qualifiers) that
125 was passed to define_exception_type().
126
127 If a Throw that uses the same exception context as the Try/Catch is
128 executed within the Try clause (typically within a function called
129 by the Try clause), and the exception is not caught by a nested
130 Try/Catch statement, then a copy of the exception will be assigned
131 to the expression, and control will jump to the Catch clause. If no
132 such Throw is executed, then the assignment is not performed, and
133 the Catch clause is not executed.
134
135 The expression is not evaluated unless and until the exception is
136 caught, which is significant if it has side effects, for example:
137
138 Try foo();
139 Catch (p[++i].e) { ... }
140
141 IMPORTANT: Jumping into or out of a Try clause (for example via
142 return, break, continue, goto, longjmp) is forbidden--the compiler
143 will not complain, but bad things will happen at run-time. Jumping
144 into or out of a Catch clause is okay, and so is jumping around
145 inside a Try clause. In many cases where one is tempted to return
146 from a Try clause, it will suffice to use Throw, and then return
147 from the Catch clause. Another option is to set a flag variable and
148 use goto to jump to the end of the Try clause, then check the flag
149 after the Try/Catch statement.
150
151 IMPORTANT: The values of any non-volatile automatic variables
152 changed within the Try clause are undefined after an exception is
153 caught. Therefore, variables modified inside the Try block whose
154 values are needed later outside the Try block must either use static
155 storage or be declared with the "volatile" type qualifier.
156
157
158Throw expression;
159
160 A Throw statement is very much like a return statement, except that
161 the expression is required. Whereas return jumps back to the place
162 where the current function was called, Throw jumps back to the Catch
163 clause of the innermost enclosing Try clause. The expression must
164 be compatible with the type passed to define_exception_type(). The
165 exception must be caught, otherwise the program may crash.
166
167 Slight limitation: If the expression is a comma-expression it must
168 be enclosed in parentheses.
169
170
171Try statement
172Catch_anonymous statement
173
174 When the value of the exception is not needed, a Try/Catch statement
175 can use Catch_anonymous instead of Catch (expression).
176
177
178Everything below this point is for the benefit of the compiler. The
179application programmer should pretend not to know any of it, because it
180is subject to change.
181
182===*/
183
184
185#ifndef CEXCEPT_H
186#define CEXCEPT_H
187
188
189#include <setjmp.h>
190
191#define define_exception_type(etype) \
192struct exception_context { \
193 jmp_buf *penv; \
194 int caught; \
195 volatile struct { etype etmp; } v; \
196}
197
198/* etmp must be volatile because the application might use automatic */
199/* storage for the_exception_context, and etmp is modified between */
200/* the calls to setjmp() and longjmp(). A wrapper struct is used to */
201/* avoid warnings about a duplicate volatile qualifier in case etype */
202/* already includes it. */
203
204#define init_exception_context(ec) ((void)((ec)->penv = 0))
205
206#define Try \
207 { \
208 jmp_buf *exception__prev, exception__env; \
209 exception__prev = the_exception_context->penv; \
210 the_exception_context->penv = &exception__env; \
211 if (setjmp(exception__env) == 0) { \
212 if (&exception__prev)
213
214#define exception__catch(action) \
215 else { } \
216 the_exception_context->caught = 0; \
217 } \
218 else { \
219 the_exception_context->caught = 1; \
220 } \
221 the_exception_context->penv = exception__prev; \
222 } \
223 if (!the_exception_context->caught || action) { } \
224 else
225
226#define Catch(e) exception__catch(((e) = the_exception_context->v.etmp, 0))
227#define Catch_anonymous exception__catch(0)
228
229/* Try ends with if(), and Catch begins and ends with else. This */
230/* ensures that the Try/Catch syntax is really the same as the */
231/* if/else syntax. */
232/* */
233/* We use &exception__prev instead of 1 to appease compilers that */
234/* warn about constant expressions inside if(). Most compilers */
235/* should still recognize that &exception__prev is never zero and */
236/* avoid generating test code. */
237
238#define Throw \
239 for (;; longjmp(*the_exception_context->penv, 1)) \
240 the_exception_context->v.etmp =
241
242
243#endif /* CEXCEPT_H */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette