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