chiark / gitweb /
99b2905cba1b5a0205d75c1fbeb35cb8ffa06d99
[mLib] / man / exc.3
1 .\" -*-nroff-*-
2 .de VS
3 .sp 1
4 .in +5n
5 .ft B
6 .nf
7 ..
8 .de VE
9 .ft R
10 .in -5n
11 .sp 1
12 .fi
13 ..
14 .TH exc 3 "20 June 1999" mLib
15 .SH NAME
16 exc \- exception handling for C programs
17 .\" @TRY
18 .\" @CATCH
19 .\" @END_TRY
20 .\" @THROW
21 .\" @RETHROW
22 .\"
23 .\" @exc_encaught
24 .\"
25 .\" @EXC_PAIR
26 .\" @EXC_ALLOC
27 .\" @EXC_ALLOCN
28 .\" @EXC_ALLOCI
29 .\" @EXC_ALLOCP
30 .\" @EXC_ALLOCS
31 .\"
32 .SH SYNOPSIS
33 .B "#include <mLib/exc.h>
34 .sp 1
35 .B TRY
36 .I statement
37 .B CATCH
38 .I statement
39 .B END_TRY;
40 .br
41 .B EXIT_TRY;
42 .sp 1
43 .BI "THROW(exc_extype " type
44 .RB [ ,
45 .IR data ]\fB);
46 .br
47 .B RETHROW;
48 .sp 1
49 .nf
50 .B "typedef void (*exc__uncaught)(exc_extype, exc_exval);"
51 .BI "exc__uncaught exc_uncaught(exc__uncaught " proc );
52
53 .BI "exc_extype EXC_PAIR(unsigned char " x ", unsigned char " y );
54 .BI "exc_extype EXC_ALLOC(exc_extype " owner ", exc_extype " type );
55 .BI "exc_extype EXC_ALLOCN(exc_extype " owner ", exc_extype " type );
56 .BI "exc_extype EXC_ALLOCI(exc_extype " owner ", exc_extype " type );
57 .BI "exc_extype EXC_ALLOCP(exc_extype " owner ", exc_extype " type );
58 .BI "exc_extype EXC_ALLOCS(exc_extype " owner ", exc_extype " type );
59 .fi
60 .SH DESCRIPTION
61 The header file
62 .B <mLib/exc.h>
63 introduces some new syntax and definitions to support exception handling
64 in C.  The marriage is not particularly successful, although it works
65 well enough in practice.
66 .PP
67 The syntax introduced consists of new
68 .B TRY
69 and
70 .B EXIT_TRY
71 statements and a pair of new expression types
72 .B THROW
73 and
74 .BR RETHROW .
75 It's unfortunately important to remember that the syntax is provided
76 using macro expansion and standard C facilities; some of the
77 restrictions of these features show through.
78 .SS "The TRY statement"
79 The
80 .B TRY
81 statement associates an exception handler with a piece of code.  The
82 second statement is an
83 .IR "exception handler" .
84 Its
85 .I "dynamic scope"
86 is the duration of the first statement's execution, together with the
87 duration of any functions called within the dynamic scope.  (Note in
88 particular that an exception handler is not within its own dynamic
89 scope.)  A thrown exception causes the exception handler with
90 dynamically innermost scope to be executed.
91 .PP
92 Two special variables are provided to the exception handler:
93 .TP
94 .B exc_type
95 The
96 .I type
97 of the exception caught.  This is value of type
98 .B exc_extype
99 (described below).
100 .TP
101 .B exc_val
102 The
103 .I value
104 of the exception.  This has a union type, with members
105 .BR "int i",
106 .B "void *p"
107 and
108 .BR "char *s" .
109 Only one of the members is valid; you should be able to work out which
110 from the exception type.  There are abbreviations
111 .BR "exc_i",
112 .B exc_p
113 and
114 .B exc_s
115 which refer to members of
116 .B exc_val
117 directly.
118 .SS "The EXIT_TRY statement"
119 It is not safe to leave the dynamic scope of an exception handler early
120 (e.g., by a
121 .B goto
122 statement).  You can force a safe exit from a dynamic scope using the
123 .B EXIT_TRY
124 statement from within the
125 .I lexical
126 scope of the
127 .B TRY
128 statement.
129 .SS "The THROW and RETHROW statements"
130 The
131 .B THROW
132 expression throws an exception.  The first argument is the type of
133 exception; the second is some data to attach to the exception.  The type
134 of data, integer, string or pointer, is determined from the exception
135 type.
136 .PP
137 Control is immediately passed to the exception handler with the
138 innermost enclosing dynamic scope.
139 .PP
140 The
141 .B RETHROW
142 expression is only valid within an exception handler.  It rethrows the
143 last exception caught by the handler.
144 .PP
145 Neither
146 .B THROW
147 nor
148 .B RETHROW
149 yields any value.
150 .SS "Exception type allocation"
151 Exception types are 32-bit values.  The top 16 bits are an
152 .IR "owner identifier" .
153 The idea is that each library can have an owner identifier, and it can
154 then allocate exceptions for its own use from the remaining space.  Two
155 special owner codes are defined:
156 .TP
157 .B "EXC_GLOBAL (0x0000)"
158 The global space defined for everyone's benefit.  Don't define your own
159 exceptions in this space.
160 .TP
161 .B "EXC_SHARED (0xffff)"
162 A shared space.  You can use this for any exceptions which won't be seen
163 by anyone else.
164 .PP
165 Other owner codes may be allocated by choosing two characters (probably
166 letters) which best suit your application and applying the
167 .B EXC_PAIR
168 macro to them.  For example, the owner code for
169 .B mLib
170 would probably be
171 .BR "EXC_PAIR('m', 'L')" ,
172 if
173 .B mLib
174 defined any exceptions other then the global ones.
175 .PP
176 The bottom 16 bits are the actual exception type, and the data type
177 which gets passed around with the exception.  The data type is
178 (bizarrely) in bits 6 and 7 of the type word.  The data type code is one
179 of the following:
180 .TP
181 .B EXC_NOVAL
182 There is no data associated with this exception.
183 .TP
184 .B EXC_INTVAL
185 The data is an integer, with type
186 .BR int .
187 .TP
188 .B EXC_PTRVAL
189 The data is a pointer to some data structure, with type
190 .BR "void *" .
191 Note that you probably have to do an explicit cast to
192 .B "void *"
193 in the
194 .B THROW
195 expression.
196 .TP
197 .B EXC_STRVAL
198 The data is a pointer to a string of characters, of type
199 .BR "char *" .
200 .PP
201 If the data to be thrown is a pointer, make sure that the object pointed
202 to has a long enough lifetime for it to actually get to its exception
203 handler intact.  In particular, don't pass pointers to automatic
204 variables unless you're
205 .I sure
206 they were allocated outside the handler's dynamic scope.
207 .PP
208 Individual exceptions are allocated by the macros
209 .BI EXC_ALLOC t\fR,
210 where
211 .I t
212 is one of:
213 .TP
214 .B N
215 The exception has no data
216 .TP
217 .B I
218 The exception data is an integer.
219 .TP
220 .B P
221 The exception data is a pointer.
222 .TP
223 .B S
224 The exception data is a character string.
225 .PP
226 The
227 .BI EXC_ALLOC t
228 macros take two arguments: the owner code (usually allocated with
229 .B EXC_PAIR
230 as described above), and the type code.  The data type is encoded into
231 the exception type by the allocation macro.
232 .SS "Predefined exceptions"
233 The following exceptions are predefined:
234 .TP
235 .B EXC_NOMEM
236 No data.  Signals an out-of-memory condition.
237 .TP
238 .B EXC_ERRNO
239 Integer data.  Signals an operating system error.  The data is the value
240 of
241 .B errno
242 associated with the error.
243 .TP
244 .B EXC_OSERROR
245 Pointer data.  Signals a RISC\ OS error.  The data is a pointer to the
246 RISC\ OS error block.  (Non RISC\ OS programmers don't need to worry
247 about this.)
248 .TP
249 .B EXC_SIGNAL
250 Integer data.  Signals a raised operating system signal.  The data is
251 the signal number.
252 .TP
253 .B EXC_FAIL
254 String data.  Signals a miscellaneous failure.  The data is a pointer to
255 an explanatory string.
256 .SH BUGS
257 The call to an exception handler is acheived using
258 .BR longjmp (3).
259 Therefore all the caveats about
260 .B longjmp
261 and automatic data apply.  Also, note that status such as the signal
262 mask is not reset, so you might have to do that manually in order to
263 recover from a signal.
264 .SH "SEE ALSO"
265 .BR mLib (3).
266 .SH AUTHOR
267 Mark Wooding, <mdw@nsict.org>