b6b9d458 |
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 | .. |
fbf20b5b |
14 | .TH exc 3 "20 June 1999" "Straylight/Edgeware" "mLib utilities library" |
b6b9d458 |
15 | .SH NAME |
16 | exc \- exception handling for C programs |
08da152e |
17 | .\" @TRY |
18 | .\" @CATCH |
19 | .\" @END_TRY |
20 | .\" @THROW |
21 | .\" @RETHROW |
22 | .\" |
d2a91066 |
23 | .\" @exc_uncaught |
08da152e |
24 | .\" |
25 | .\" @EXC_PAIR |
26 | .\" @EXC_ALLOC |
27 | .\" @EXC_ALLOCN |
28 | .\" @EXC_ALLOCI |
29 | .\" @EXC_ALLOCP |
30 | .\" @EXC_ALLOCS |
31 | .\" |
b6b9d458 |
32 | .SH SYNOPSIS |
d2a91066 |
33 | .B "#include <mLib/exc.h>" |
b6b9d458 |
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 |
d2a91066 |
257 | The call to an exception handler is achieved using |
b6b9d458 |
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. |
08da152e |
264 | .SH "SEE ALSO" |
265 | .BR mLib (3). |
b6b9d458 |
266 | .SH AUTHOR |
9b5ac6ff |
267 | Mark Wooding, <mdw@distorted.org.uk> |