2 |
7u83 |
1 |
/*
|
|
|
2 |
Crown Copyright (c) 1997
|
|
|
3 |
|
|
|
4 |
This TenDRA(r) Computer Program is subject to Copyright
|
|
|
5 |
owned by the United Kingdom Secretary of State for Defence
|
|
|
6 |
acting through the Defence Evaluation and Research Agency
|
|
|
7 |
(DERA). It is made available to Recipients with a
|
|
|
8 |
royalty-free licence for its use, reproduction, transfer
|
|
|
9 |
to other parties and amendment for any purpose not excluding
|
|
|
10 |
product development provided that any such use et cetera
|
|
|
11 |
shall be deemed to be acceptance of the following conditions:-
|
|
|
12 |
|
|
|
13 |
(1) Its Recipients shall ensure that this Notice is
|
|
|
14 |
reproduced upon any copies or amended versions of it;
|
|
|
15 |
|
|
|
16 |
(2) Any amended version of it shall be clearly marked to
|
|
|
17 |
show both the nature of and the organisation responsible
|
|
|
18 |
for the relevant amendment or amendments;
|
|
|
19 |
|
|
|
20 |
(3) Its onward transfer from a recipient to another
|
|
|
21 |
party shall be deemed to be that party's acceptance of
|
|
|
22 |
these conditions;
|
|
|
23 |
|
|
|
24 |
(4) DERA gives no warranty or assurance as to its
|
|
|
25 |
quality or suitability for any purpose and DERA accepts
|
|
|
26 |
no liability whatsoever in relation to any use to which
|
|
|
27 |
it may be put.
|
|
|
28 |
*/
|
|
|
29 |
|
|
|
30 |
|
|
|
31 |
#include "config.h"
|
|
|
32 |
#include "version.h"
|
|
|
33 |
#include "c_types.h"
|
|
|
34 |
#include "exp_ops.h"
|
|
|
35 |
#include "type_ops.h"
|
|
|
36 |
#include "error.h"
|
|
|
37 |
#include "tdf.h"
|
|
|
38 |
#include "allocate.h"
|
|
|
39 |
#include "basetype.h"
|
|
|
40 |
#include "capsule.h"
|
|
|
41 |
#include "chktype.h"
|
|
|
42 |
#include "compile.h"
|
|
|
43 |
#include "destroy.h"
|
|
|
44 |
#include "diag.h"
|
|
|
45 |
#include "encode.h"
|
|
|
46 |
#include "exception.h"
|
|
|
47 |
#include "exp.h"
|
|
|
48 |
#include "init.h"
|
|
|
49 |
#include "inttype.h"
|
|
|
50 |
#include "shape.h"
|
|
|
51 |
#include "statement.h"
|
|
|
52 |
#include "stmt.h"
|
|
|
53 |
#include "struct.h"
|
|
|
54 |
#include "syntax.h"
|
|
|
55 |
#include "throw.h"
|
|
|
56 |
#include "tok.h"
|
|
|
57 |
#include "typeid.h"
|
|
|
58 |
#include "ustring.h"
|
|
|
59 |
#if TDF_OUTPUT
|
|
|
60 |
|
|
|
61 |
|
|
|
62 |
/*
|
|
|
63 |
ENCODE THE ADDRESS OF A DESTRUCTOR
|
|
|
64 |
|
|
|
65 |
This routine adds the address of the destructor function corresponding
|
|
|
66 |
to d to the bitstream bs.
|
|
|
67 |
*/
|
|
|
68 |
|
|
|
69 |
BITSTREAM *enc_destr_func
|
|
|
70 |
PROTO_N ( ( bs, d ) )
|
|
|
71 |
PROTO_T ( BITSTREAM *bs X EXP d )
|
|
|
72 |
{
|
|
|
73 |
if ( !IS_NULL_exp ( d ) ) {
|
|
|
74 |
EXP f ;
|
|
|
75 |
while ( IS_exp_nof ( d ) ) {
|
|
|
76 |
d = DEREF_exp ( exp_nof_pad ( d ) ) ;
|
|
|
77 |
}
|
|
|
78 |
f = DEREF_exp ( exp_destr_call ( d ) ) ;
|
|
|
79 |
if ( IS_exp_func_id ( f ) ) {
|
|
|
80 |
ulong n ;
|
|
|
81 |
IDENTIFIER fn = DEREF_id ( exp_func_id_id ( f ) ) ;
|
|
|
82 |
IGNORE capsule_id ( fn, VAR_tag ) ;
|
|
|
83 |
n = unit_no ( bs, fn, VAR_tag, 0 ) ;
|
|
|
84 |
ENC_obtain_tag ( bs ) ;
|
|
|
85 |
ENC_make_tag ( bs, n ) ;
|
|
|
86 |
return ( bs ) ;
|
|
|
87 |
}
|
|
|
88 |
}
|
|
|
89 |
ENC_make_null_proc ( bs ) ;
|
|
|
90 |
return ( bs ) ;
|
|
|
91 |
}
|
|
|
92 |
|
|
|
93 |
|
|
|
94 |
/*
|
|
|
95 |
EXCEPTION HANDLING ROUTINES
|
|
|
96 |
|
|
|
97 |
The exception handling routines are only included in the C++ producer.
|
|
|
98 |
*/
|
|
|
99 |
|
|
|
100 |
#if LANGUAGE_CPP
|
|
|
101 |
|
|
|
102 |
|
|
|
103 |
/*
|
|
|
104 |
ENCODE A CATCH STATEMENT
|
|
|
105 |
|
|
|
106 |
This routine adds the start of a catch statement to the bitstream bs.
|
|
|
107 |
It checks whether the type t can handle the current exception. If
|
|
|
108 |
the label lab is given then catching the exception causes a jump to
|
|
|
109 |
lab. Otherwise the handler body, consisting of seq statements,
|
|
|
110 |
followed by the code if the exception is not caught, needs to be
|
|
|
111 |
added later.
|
|
|
112 |
*/
|
|
|
113 |
|
|
|
114 |
static BITSTREAM *enc_catch
|
|
|
115 |
PROTO_N ( ( bs, t, lab, seq ) )
|
|
|
116 |
PROTO_T ( BITSTREAM *bs X TYPE t X ulong lab X unsigned seq )
|
|
|
117 |
{
|
|
|
118 |
BITSTREAM *ts ;
|
|
|
119 |
NTEST tst = ntest_eq ;
|
|
|
120 |
if ( lab == LINK_NONE ) {
|
|
|
121 |
/* Create label if necessary */
|
|
|
122 |
lab = unit_no ( bs, NULL_id, VAR_label, 1 ) ;
|
|
|
123 |
ENC_conditional ( bs ) ;
|
|
|
124 |
ENC_make_label ( bs, lab ) ;
|
|
|
125 |
ENC_SEQUENCE ( bs, seq ) ;
|
|
|
126 |
tst = ntest_not_eq ;
|
|
|
127 |
}
|
|
|
128 |
ENC_integer_test ( bs ) ;
|
|
|
129 |
ENC_OFF ( bs ) ;
|
|
|
130 |
bs = enc_ntest ( bs, tst ) ;
|
|
|
131 |
ENC_make_label ( bs, lab ) ;
|
|
|
132 |
bs = enc_special ( bs, TOK_except_catch ) ;
|
|
|
133 |
ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
|
|
|
134 |
ts = enc_rtti_type ( ts, t, lex_typeid ) ;
|
|
|
135 |
bs = enc_bitstream ( bs, ts ) ;
|
|
|
136 |
bs = enc_make_int ( bs, type_sint, 0 ) ;
|
|
|
137 |
return ( bs ) ;
|
|
|
138 |
}
|
|
|
139 |
|
|
|
140 |
|
|
|
141 |
/*
|
|
|
142 |
ENCODE THE START OF A TRY BLOCK
|
|
|
143 |
|
|
|
144 |
This routine adds the start of a try block to the bitstream bs. seq
|
|
|
145 |
gives the number of statements to follow.
|
|
|
146 |
*/
|
|
|
147 |
|
|
|
148 |
BITSTREAM *enc_try_start
|
|
|
149 |
PROTO_N ( ( bs, pn, seq ) )
|
|
|
150 |
PROTO_T ( BITSTREAM *bs X ulong *pn X unsigned seq )
|
|
|
151 |
{
|
|
|
152 |
ulong n ;
|
|
|
153 |
ulong lab ;
|
|
|
154 |
BITSTREAM *ts ;
|
|
|
155 |
|
|
|
156 |
/* Must be in a function definition */
|
|
|
157 |
if ( in_dynamic_init ) output_init = 1 ;
|
|
|
158 |
|
|
|
159 |
/* Encode the try block jump buffer */
|
|
|
160 |
n = unit_no ( bs, NULL_id, VAR_tag, 1 ) ;
|
|
|
161 |
ENC_variable ( bs ) ;
|
|
|
162 |
bs = enc_access ( bs, crt_func_access ) ;
|
|
|
163 |
ENC_make_tag ( bs, n ) ;
|
|
|
164 |
ENC_make_value ( bs ) ;
|
|
|
165 |
bs = enc_special ( bs, TOK_try_type ) ;
|
|
|
166 |
*pn = n ;
|
|
|
167 |
|
|
|
168 |
/* Encode the try block label */
|
|
|
169 |
lab = unit_no ( bs, NULL_id, VAR_label, 1 ) ;
|
|
|
170 |
ENC_conditional ( bs ) ;
|
|
|
171 |
ENC_make_label ( bs, lab ) ;
|
|
|
172 |
|
|
|
173 |
/* Encode the try block body */
|
|
|
174 |
ENC_SEQUENCE ( bs, seq ) ;
|
|
|
175 |
bs = enc_special ( bs, TOK_try_begin ) ;
|
|
|
176 |
ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
|
|
|
177 |
ENC_obtain_tag ( ts ) ;
|
|
|
178 |
ENC_make_tag ( ts, n ) ;
|
|
|
179 |
ENC_current_env ( ts ) ;
|
|
|
180 |
ENC_make_local_lv ( ts ) ;
|
|
|
181 |
ENC_make_label ( ts, lab ) ;
|
|
|
182 |
bs = enc_bitstream ( bs, ts ) ;
|
|
|
183 |
return ( bs ) ;
|
|
|
184 |
}
|
|
|
185 |
|
|
|
186 |
|
|
|
187 |
/*
|
|
|
188 |
ENCODE THE END OF A TRY BLOCK
|
|
|
189 |
|
|
|
190 |
This routine adds the end of the current try block to the bitstream bs.
|
|
|
191 |
*/
|
|
|
192 |
|
|
|
193 |
BITSTREAM *enc_try_end
|
|
|
194 |
PROTO_N ( ( bs, n ) )
|
|
|
195 |
PROTO_T ( BITSTREAM *bs X ulong n )
|
|
|
196 |
{
|
|
|
197 |
BITSTREAM *ts ;
|
|
|
198 |
bs = enc_special ( bs, TOK_try_end ) ;
|
|
|
199 |
ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
|
|
|
200 |
ENC_obtain_tag ( ts ) ;
|
|
|
201 |
ENC_make_tag ( ts, n ) ;
|
|
|
202 |
bs = enc_bitstream ( bs, ts ) ;
|
|
|
203 |
return ( bs ) ;
|
|
|
204 |
}
|
|
|
205 |
|
|
|
206 |
|
|
|
207 |
/*
|
|
|
208 |
ENCODE A TRY BLOCK
|
|
|
209 |
|
|
|
210 |
This routine adds the try block e to the bitstream bs.
|
|
|
211 |
*/
|
|
|
212 |
|
|
|
213 |
BITSTREAM *enc_try
|
|
|
214 |
PROTO_N ( ( bs, e ) )
|
|
|
215 |
PROTO_T ( BITSTREAM *bs X EXP e )
|
|
|
216 |
{
|
|
|
217 |
int uc ;
|
|
|
218 |
ulong ex ;
|
|
|
219 |
unsigned seq ;
|
|
|
220 |
EXP a = DEREF_exp ( exp_try_block_body ( e ) ) ;
|
|
|
221 |
LIST ( EXP ) p = DEREF_list ( exp_try_block_handlers ( e ) ) ;
|
|
|
222 |
LIST ( TYPE ) q = DEREF_list ( exp_try_block_htypes ( e ) ) ;
|
|
|
223 |
EXP c = DEREF_exp ( exp_try_block_ellipsis ( e ) ) ;
|
|
|
224 |
|
|
|
225 |
/* Ignore handlers if exception handling disabled */
|
|
|
226 |
if ( !output_except ) {
|
|
|
227 |
bs = enc_stmt ( bs, a ) ;
|
|
|
228 |
return ( bs ) ;
|
|
|
229 |
}
|
|
|
230 |
|
|
|
231 |
/* Encode the try block */
|
|
|
232 |
no_destructors++ ;
|
|
|
233 |
if ( output_new_diag ) {
|
|
|
234 |
seq = 2 ;
|
|
|
235 |
} else {
|
|
|
236 |
seq = stmt_length ( a ) + 1 ;
|
|
|
237 |
}
|
|
|
238 |
bs = enc_try_start ( bs, &ex, seq ) ;
|
|
|
239 |
COPY_ulong ( exp_try_block_no ( e ), ex ) ;
|
|
|
240 |
if ( output_new_diag ) {
|
|
|
241 |
BITSTREAM *ts = enc_diag_begin ( &bs ) ;
|
|
|
242 |
ts = enc_stmt ( ts, a ) ;
|
|
|
243 |
bs = enc_diag_end ( bs, ts, e, 1 ) ;
|
|
|
244 |
} else {
|
|
|
245 |
bs = enc_compound_stmt ( bs, a ) ;
|
|
|
246 |
}
|
|
|
247 |
bs = enc_try_end ( bs, ex ) ;
|
|
|
248 |
uc = unreached_code ;
|
|
|
249 |
|
|
|
250 |
/* Encode the handlers */
|
|
|
251 |
while ( !IS_NULL_list ( p ) ) {
|
|
|
252 |
EXP b = DEREF_exp ( HEAD_list ( p ) ) ;
|
|
|
253 |
TYPE t = DEREF_type ( HEAD_list ( q ) ) ;
|
|
|
254 |
unreached_code = 0 ;
|
|
|
255 |
if ( !output_new_diag ) {
|
|
|
256 |
b = DEREF_exp ( exp_handler_body ( b ) ) ;
|
|
|
257 |
}
|
|
|
258 |
seq = stmt_length ( b ) + 1 ;
|
|
|
259 |
bs = enc_catch ( bs, t, LINK_NONE, seq ) ;
|
|
|
260 |
bs = enc_compound_stmt ( bs, b ) ;
|
|
|
261 |
bs = enc_special ( bs, TOK_except_end ) ;
|
|
|
262 |
if ( !unreached_code ) uc = 0 ;
|
|
|
263 |
q = TAIL_list ( q ) ;
|
|
|
264 |
p = TAIL_list ( p ) ;
|
|
|
265 |
}
|
|
|
266 |
|
|
|
267 |
/* Encode the default handler */
|
|
|
268 |
unreached_code = 0 ;
|
|
|
269 |
if ( IS_exp_handler ( c ) ) {
|
|
|
270 |
if ( !output_new_diag ) {
|
|
|
271 |
c = DEREF_exp ( exp_handler_body ( c ) ) ;
|
|
|
272 |
}
|
|
|
273 |
seq = stmt_length ( c ) ;
|
|
|
274 |
if ( seq ) {
|
|
|
275 |
ENC_SEQUENCE ( bs, seq ) ;
|
|
|
276 |
bs = enc_compound_stmt ( bs, c ) ;
|
|
|
277 |
}
|
|
|
278 |
bs = enc_special ( bs, TOK_except_end ) ;
|
|
|
279 |
} else {
|
|
|
280 |
/* Re-throw current exception */
|
|
|
281 |
bs = enc_exp ( bs, c ) ;
|
|
|
282 |
}
|
|
|
283 |
if ( !unreached_code ) uc = 0 ;
|
|
|
284 |
unreached_code = uc ;
|
|
|
285 |
no_destructors-- ;
|
|
|
286 |
return ( bs ) ;
|
|
|
287 |
}
|
|
|
288 |
|
|
|
289 |
|
|
|
290 |
/*
|
|
|
291 |
RETHROW THE CURRENT EXCEPTION
|
|
|
292 |
|
|
|
293 |
This routine adds the expression 'throw' to the bitstream bs.
|
|
|
294 |
*/
|
|
|
295 |
|
|
|
296 |
BITSTREAM *enc_rethrow
|
|
|
297 |
PROTO_N ( ( bs ) )
|
|
|
298 |
PROTO_T ( BITSTREAM *bs )
|
|
|
299 |
{
|
|
|
300 |
if ( output_except ) {
|
|
|
301 |
bs = enc_special ( bs, TOK_except_rethrow ) ;
|
|
|
302 |
} else {
|
|
|
303 |
BITSTREAM *ts ;
|
|
|
304 |
bs = enc_special ( bs, TOK_except_bad ) ;
|
|
|
305 |
ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
|
|
|
306 |
ts = enc_make_snat ( ts, 0 ) ;
|
|
|
307 |
bs = enc_bitstream ( bs, ts ) ;
|
|
|
308 |
}
|
|
|
309 |
unreached_code = 1 ;
|
|
|
310 |
return ( bs ) ;
|
|
|
311 |
}
|
|
|
312 |
|
|
|
313 |
|
|
|
314 |
/*
|
|
|
315 |
ENCODE A THROW EXPRESSION
|
|
|
316 |
|
|
|
317 |
This routine adds the expression 'throw a' to the bitstream bs. If
|
|
|
318 |
a is the null expression then the current exception is rethrown. b
|
|
|
319 |
and d give the size and destructor for the exception type.
|
|
|
320 |
*/
|
|
|
321 |
|
|
|
322 |
BITSTREAM *enc_throw
|
|
|
323 |
PROTO_N ( ( bs, a, b, d ) )
|
|
|
324 |
PROTO_T ( BITSTREAM *bs X EXP a X EXP b X EXP d )
|
|
|
325 |
{
|
|
|
326 |
if ( !IS_NULL_exp ( a ) && output_except ) {
|
|
|
327 |
/* Set up variable */
|
|
|
328 |
EXP c ;
|
|
|
329 |
BITSTREAM *ts, *us ;
|
|
|
330 |
TYPE t = DEREF_type ( exp_type ( a ) ) ;
|
|
|
331 |
ulong n = unit_no ( bs, NULL_id, VAR_tag, 1 ) ;
|
|
|
332 |
ENC_variable ( bs ) ;
|
|
|
333 |
bs = enc_access ( bs, dspec_none ) ;
|
|
|
334 |
ENC_make_tag ( bs, n ) ;
|
|
|
335 |
MAKE_exp_dummy ( t, NULL_exp, n, NULL_off, 2, c ) ;
|
|
|
336 |
|
|
|
337 |
/* Allocate space for exception value */
|
|
|
338 |
bs = enc_special ( bs, TOK_from_ptr_void ) ;
|
|
|
339 |
ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
|
|
|
340 |
ts = enc_alignment ( ts, t ) ;
|
|
|
341 |
ts = enc_special ( ts, TOK_except_alloc ) ;
|
|
|
342 |
us = start_bitstream ( NIL ( FILE ), ts->link ) ;
|
|
|
343 |
us = enc_exp ( us, b ) ;
|
|
|
344 |
ts = enc_bitstream ( ts, us ) ;
|
|
|
345 |
bs = enc_bitstream ( bs, ts ) ;
|
|
|
346 |
|
|
|
347 |
/* Assign exception value */
|
|
|
348 |
ENC_SEQ_SMALL ( bs, 1 ) ;
|
|
|
349 |
bs = enc_init_tag ( bs, n, NULL_off, 1, t, a, NULL_exp, 0 ) ;
|
|
|
350 |
|
|
|
351 |
/* Throw the exception */
|
|
|
352 |
bs = enc_special ( bs, TOK_except_throw ) ;
|
|
|
353 |
ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
|
|
|
354 |
ts = enc_special ( ts, TOK_to_ptr_void ) ;
|
|
|
355 |
us = start_bitstream ( NIL ( FILE ), ts->link ) ;
|
|
|
356 |
us = enc_alignment ( us, t ) ;
|
|
|
357 |
us = enc_exp ( us, c ) ;
|
|
|
358 |
ts = enc_bitstream ( ts, us ) ;
|
|
|
359 |
ts = enc_rtti_type ( ts, t, lex_typeid ) ;
|
|
|
360 |
ts = enc_destr_func ( ts, d ) ;
|
|
|
361 |
bs = enc_bitstream ( bs, ts ) ;
|
|
|
362 |
unreached_code = 1 ;
|
|
|
363 |
free_exp ( c, 1 ) ;
|
|
|
364 |
|
|
|
365 |
} else {
|
|
|
366 |
/* Rethrow the current exception */
|
|
|
367 |
bs = enc_rethrow ( bs ) ;
|
|
|
368 |
}
|
|
|
369 |
return ( bs ) ;
|
|
|
370 |
}
|
|
|
371 |
|
|
|
372 |
|
|
|
373 |
/*
|
|
|
374 |
ENCODE A CAUGHT EXPRESSION
|
|
|
375 |
|
|
|
376 |
This routine adds the initialiser for an exception handler variable
|
|
|
377 |
of type t to the bitstream bs. This is obtained by casting the
|
|
|
378 |
current exception value to a pointer to t.
|
|
|
379 |
*/
|
|
|
380 |
|
|
|
381 |
BITSTREAM *enc_thrown
|
|
|
382 |
PROTO_N ( ( bs, t ) )
|
|
|
383 |
PROTO_T ( BITSTREAM *bs X TYPE t )
|
|
|
384 |
{
|
|
|
385 |
BITSTREAM *ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
|
|
|
386 |
bs = enc_special ( bs, TOK_from_ptr_void ) ;
|
|
|
387 |
ts = enc_alignment ( ts, t ) ;
|
|
|
388 |
ts = enc_special ( ts, TOK_except_value ) ;
|
|
|
389 |
bs = enc_bitstream ( bs, ts ) ;
|
|
|
390 |
return ( bs ) ;
|
|
|
391 |
}
|
|
|
392 |
|
|
|
393 |
|
|
|
394 |
/*
|
|
|
395 |
EXCEPTION SPECIFICATION FLAG
|
|
|
396 |
|
|
|
397 |
This flag is set to true if the current function has an exception
|
|
|
398 |
specification.
|
|
|
399 |
*/
|
|
|
400 |
|
|
|
401 |
int in_exception_spec = 0 ;
|
|
|
402 |
|
|
|
403 |
|
|
|
404 |
/*
|
|
|
405 |
ENCODE THE START OF A FUNCTION EXCEPTION HANDLER
|
|
|
406 |
|
|
|
407 |
This routine is called at the start of a function definition declared
|
|
|
408 |
with a non-trivial exception specification. It sets up a try block
|
|
|
409 |
enclosing the complete function body.
|
|
|
410 |
*/
|
|
|
411 |
|
|
|
412 |
BITSTREAM *enc_try_func
|
|
|
413 |
PROTO_N ( ( bs, a ) )
|
|
|
414 |
PROTO_T ( BITSTREAM *bs X EXP a )
|
|
|
415 |
{
|
|
|
416 |
if ( !IS_NULL_exp ( a ) ) {
|
|
|
417 |
/* Declare counter variable */
|
|
|
418 |
EXP b = sizeof_init ( a, type_sint ) ;
|
|
|
419 |
ulong n = unit_no ( bs, NULL_id, VAR_tag, 1 ) ;
|
|
|
420 |
ENC_variable ( bs ) ;
|
|
|
421 |
bs = enc_access ( bs, crt_func_access ) ;
|
|
|
422 |
ENC_make_tag ( bs, n ) ;
|
|
|
423 |
bs = enc_exp ( bs, b ) ;
|
|
|
424 |
free_exp ( b, 1 ) ;
|
|
|
425 |
last_params [ DUMMY_count ] = n ;
|
|
|
426 |
}
|
|
|
427 |
no_destructors++ ;
|
|
|
428 |
in_exception_spec++ ;
|
|
|
429 |
ENC_SEQ_SMALL ( bs, 1 ) ;
|
|
|
430 |
bs = enc_try_start ( bs, last_params + DUMMY_catch, ( unsigned ) 1 ) ;
|
|
|
431 |
return ( bs ) ;
|
|
|
432 |
}
|
|
|
433 |
|
|
|
434 |
|
|
|
435 |
/*
|
|
|
436 |
BAD EXCEPTION TYPE
|
|
|
437 |
|
|
|
438 |
This type represents the standard class 'std::bad_exception' which has
|
|
|
439 |
a special meaning within exception specifications.
|
|
|
440 |
*/
|
|
|
441 |
|
|
|
442 |
static TYPE bad_except = NULL_type ;
|
|
|
443 |
|
|
|
444 |
|
|
|
445 |
/*
|
|
|
446 |
ENCODE THE END OF A FUNCTION EXCEPTION HANDLER
|
|
|
447 |
|
|
|
448 |
This routine is called at the end of a function definition declared
|
|
|
449 |
with the set of exceptions p. It sets up a list of exception handlers
|
|
|
450 |
for each element of p which re-throw the current exception. If the
|
|
|
451 |
exception remains uncaught then the bad exception token is called
|
|
|
452 |
(which calls unexpected).
|
|
|
453 |
*/
|
|
|
454 |
|
|
|
455 |
BITSTREAM *enc_catch_func
|
|
|
456 |
PROTO_N ( ( bs, p, a ) )
|
|
|
457 |
PROTO_T ( BITSTREAM *bs X LIST ( TYPE ) p X EXP a )
|
|
|
458 |
{
|
|
|
459 |
int rethrow = 0 ;
|
|
|
460 |
bs = enc_try_end ( bs, last_params [ DUMMY_catch ] ) ;
|
|
|
461 |
if ( !IS_NULL_exp ( a ) ) {
|
|
|
462 |
ENC_SEQ_SMALL ( bs, 1 ) ;
|
|
|
463 |
bs = enc_exp ( bs, a ) ;
|
|
|
464 |
}
|
|
|
465 |
if ( EQ_list ( p, univ_type_set ) ) {
|
|
|
466 |
/* Can throw any exception */
|
|
|
467 |
rethrow = 1 ;
|
|
|
468 |
} else {
|
|
|
469 |
BITSTREAM *ts ;
|
|
|
470 |
int have_bad = 0 ;
|
|
|
471 |
if ( !IS_NULL_list ( p ) ) {
|
|
|
472 |
/* Check list of exceptions */
|
|
|
473 |
unsigned n = 0 ;
|
|
|
474 |
LIST ( TYPE ) q = p ;
|
|
|
475 |
while ( !IS_NULL_list ( q ) ) {
|
|
|
476 |
TYPE t = DEREF_type ( HEAD_list ( q ) ) ;
|
|
|
477 |
if ( !IS_NULL_type ( t ) ) n++ ;
|
|
|
478 |
q = TAIL_list ( q ) ;
|
|
|
479 |
}
|
|
|
480 |
if ( n ) {
|
|
|
481 |
ulong lab ;
|
|
|
482 |
TYPE s = bad_except ;
|
|
|
483 |
if ( IS_NULL_type ( s ) ) {
|
|
|
484 |
s = find_std_type ( "bad_exception", 1, 0 ) ;
|
|
|
485 |
s = exception_type ( s, 0 ) ;
|
|
|
486 |
bad_except = s ;
|
|
|
487 |
}
|
|
|
488 |
lab = unit_no ( bs, NULL_id, VAR_label, 1 ) ;
|
|
|
489 |
ENC_conditional ( bs ) ;
|
|
|
490 |
ENC_make_label ( bs, lab ) ;
|
|
|
491 |
ENC_SEQUENCE ( bs, n ) ;
|
|
|
492 |
while ( !IS_NULL_list ( p ) ) {
|
|
|
493 |
TYPE t = DEREF_type ( HEAD_list ( p ) ) ;
|
|
|
494 |
if ( !IS_NULL_type ( t ) ) {
|
|
|
495 |
t = exception_type ( t, 0 ) ;
|
|
|
496 |
if ( eq_type ( t, s ) ) have_bad = 1 ;
|
|
|
497 |
bs = enc_catch ( bs, t, lab, ( unsigned ) 0 ) ;
|
|
|
498 |
}
|
|
|
499 |
p = TAIL_list ( p ) ;
|
|
|
500 |
}
|
|
|
501 |
rethrow = 1 ;
|
|
|
502 |
}
|
|
|
503 |
}
|
|
|
504 |
bs = enc_special ( bs, TOK_except_bad ) ;
|
|
|
505 |
ts = start_bitstream ( NIL ( FILE ), bs->link ) ;
|
|
|
506 |
ts = enc_make_snat ( ts, have_bad ) ;
|
|
|
507 |
bs = enc_bitstream ( bs, ts ) ;
|
|
|
508 |
}
|
|
|
509 |
if ( rethrow ) {
|
|
|
510 |
/* Re-throw the current exception */
|
|
|
511 |
bs = enc_special ( bs, TOK_except_rethrow ) ;
|
|
|
512 |
unreached_code = 1 ;
|
|
|
513 |
}
|
|
|
514 |
in_exception_spec-- ;
|
|
|
515 |
no_destructors-- ;
|
|
|
516 |
UNUSED ( a ) ;
|
|
|
517 |
return ( bs ) ;
|
|
|
518 |
}
|
|
|
519 |
|
|
|
520 |
|
|
|
521 |
#endif /* LANGUAGE_CPP */
|
|
|
522 |
#endif /* TDF_OUTPUT */
|