Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/tendra5-amd64/src/lib/cpp/src/exception.cc – Rev 5

Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
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 "implement.h"
32
#include <cstdio>
33
#include <exception>
34
using namespace std ;
35
 
36
 
37
/*
38
    CURRENT EXCEPTION
39
 
40
    This value gives information on the current exception.  This
41
    implementation, with a single current exception variable, will need
42
    to be modified for a multi-threaded environment.  Basically there
43
    needs to be one current exception per thread.
44
*/
45
 
46
static JUMP_BUFFER top_level = {
47
    &top_level, NULL
48
} ;
49
 
50
EXCEPTION __TCPPLUS_except = {
51
    NULL, NULL, { NULL, NULL }, { &top_level, NULL, NULL }, false
52
} ;
53
 
54
 
55
/*
56
    THROW AN EXCEPTION
57
 
58
    This routine throws an exception with value v and type corresponding
59
    to the type information structure p and the destructor d.  p is the
60
    null pointer to indicating the re-throwing of the current exception.
61
*/
62
 
63
void __TCPPLUS_throw ( void *v, TYPE_INFO *p, DESTRUCTOR d )
64
{
65
#ifdef NO_EXCEPTIONS
66
    // Allow suppression of exception routines
67
    terminate () ;
68
#else
69
    EXCEPTION &ex = __TCPPLUS_except ;
70
    TYPE_INFO *q = ex.type ;
71
    if ( p ) {
72
	// Throwing new exception
73
	if ( q ) {
74
	    // Check existing exception
75
	    if ( ex.unwinding ) {
76
		// Still in stack unwinding
77
		terminate () ;
78
		return ;
79
	    }
80
	    __TCPPLUS_handled () ;
81
	}
82
	ex.value [0] = v ;
83
	ex.type = p ;
84
	ex.dtor = d ;
85
    } else {
86
	// Re-throwing current exception
87
	if ( q == NULL ) {
88
	    // No exception to re-throw
89
	    terminate () ;
90
	    return ;
91
	}
92
	p = q ;
93
    }
94
    JUMP_BUFFER *jmp = ex.buf [0] ;
95
    ASSERT ( jmp != NULL ) ;
96
    ex.unwinding = true ;
97
    ex.allocated = false ;
98
    ex.buf [0] = jmp->next ;
99
    ex.buf [1] = jmp ;
100
    DTOR_LIST *dtors = jmp->dtors ;
101
    jmp->dtors = NULL ;
102
    while ( dtors ) {
103
	// Perform stack unwinding
104
	ASSERT ( dtors->func != NULL && dtors->arg != NULL ) ;
105
	dtors->func ( dtors->arg, 2 ) ;
106
	dtors = dtors->next ;
107
    }
108
    if ( jmp == &top_level ) {
109
	// No further handlers
110
	terminate () ;
111
	return ;
112
    }
113
    long_jump ( jmp->frame, jmp->label ) ;
114
#endif
115
}
116
 
117
 
118
/*
119
    CATCH AN EXCEPTION
120
 
121
    This routine checks whether the current exception can be caught by a
122
    handler with type corresponding to the type information structure p.
123
*/
124
 
125
int __TCPPLUS_catch ( TYPE_INFO *p )
126
{
127
    EXCEPTION &ex = __TCPPLUS_except ;
128
    void *r = ex.value [0] ;
129
    r = __TCPPLUS_catch_cast ( r, ex.type, p, 1, 0 ) ;
130
    if ( r ) {
131
	ex.value [1] = r ;
132
	ex.buf [2] = NULL ;
133
	return ( 1 ) ;
134
    }
135
    return ( 0 ) ;
136
}
137
 
138
 
139
/*
140
    EXCEPTION VALUE BUFFERS
141
 
142
    Whenever possible one of these buffers is used to hold the value
143
    thrown by an exception (this is to avoid the mess which would arise
144
    by dynamically allocating space for the value if the exception was
145
    raised to indicated memory exhaustion).  There are two buffers
146
    because when a handler throws an exception the new value is
147
    created before the old one is destroyed.
148
*/
149
 
150
static char ebuff1 [100] ;
151
static char ebuff2 [100] ;
152
static bool ebuff1_used = false ;
153
static bool ebuff2_used = false ;
154
 
155
 
156
/*
157
    ALLOCATE SPACE FOR AN EXCEPTION VALUE
158
 
159
    This routine allocates sz bytes of space to store an exception value.
160
    If sz is sufficiently small one of the buffers above is used, otherwise
161
    the memory is dynamically allocated.
162
*/
163
 
164
void *__TCPPLUS_alloc_except ( size_t sz )
165
{
166
    if ( __TCPPLUS_except.allocated ) {
167
	// Two allocates without a throw
168
	terminate () ;
169
    }
170
    __TCPPLUS_except.allocated = true ;
171
    if ( sz <= sizeof ( ebuff1 ) ) {
172
	if ( !ebuff1_used ) {
173
	    ebuff1_used = true ;
174
	    return ( ( void * ) &ebuff1 ) ;
175
	}
176
	if ( !ebuff2_used ) {
177
	    ebuff2_used = true ;
178
	    return ( ( void * ) &ebuff2 ) ;
179
	}
180
    }
181
    void *p = malloc ( sz ) ;
182
    if ( p == NULL ) terminate () ;
183
    return ( p ) ;
184
}
185
 
186
 
187
/*
188
    COMPLETE AN EXCEPTION
189
 
190
    This routine is called when the current exception has been completely
191
    handled.  It calls the destructor for the current exception value and
192
    frees the space it used.
193
*/
194
 
195
void __TCPPLUS_handled ()
196
{
197
    EXCEPTION &ex = __TCPPLUS_except ;
198
    DESTRUCTOR dtor = ex.dtor ;
199
    ex.unwinding = false ;
200
    ex.type = NULL ;
201
    ex.dtor = NULL ;
202
    void *p = ex.value [0] ;
203
    if ( p ) {
204
	if ( dtor ) dtor ( ( CLASS * ) p , 2 ) ;
205
	if ( p == ( void * ) &ebuff1 ) {
206
	    ebuff1_used = false ;
207
	} else if ( p == ( void * ) &ebuff2 ) {
208
	    ebuff2_used = false ;
209
	} else {
210
	    free ( p ) ;
211
	}
212
	ex.value [0] = NULL ;
213
    }
214
    return ;
215
}
216
 
217
 
218
/*
219
    DEFAULT TERMINATE HANDLER
220
 
221
    This routine gives the default terminate handler function.
222
*/
223
 
224
static void terminator ()
225
{
226
    abort () ;
227
}
228
 
229
 
230
/*
231
    CURRENT TERMINATE HANDLER
232
 
233
    This variable gives the current terminate handler function.
234
*/
235
 
236
static terminate_handler crt_terminate_handler = terminator ;
237
 
238
 
239
/*
240
    SET TERMINATE HANDLER
241
 
242
    This routine sets the current terminate handler to f, returning the
243
    old value.
244
*/
245
 
246
terminate_handler std::set_terminate ( terminate_handler f ) throw ()
247
{
248
    terminate_handler g = crt_terminate_handler ;
249
    if ( f == NULL ) f = ( terminate_handler ) abort ;
250
    crt_terminate_handler = f ;
251
    return ( g ) ;
252
}
253
 
254
 
255
/*
256
    CALL TERMINATE HANDLER
257
 
258
    This routine calls the current terminate handler.
259
*/
260
 
261
void std::terminate ()
262
{
263
    __TCPPLUS_except.unwinding = false ;
264
    crt_terminate_handler () ;
265
    return ;
266
}
267
 
268
 
269
/*
270
    CURRENT UNEXPECTED HANDLER
271
 
272
    This variable gives the current unexpected handler function.
273
*/
274
 
275
static unexpected_handler crt_unexpected_handler = terminate ;
276
 
277
 
278
/*
279
    SET UNEXPECTED HANDLER
280
 
281
    This routine sets the current unexpected handler to f, returning the
282
    old value.
283
*/
284
 
285
unexpected_handler std::set_unexpected ( unexpected_handler f ) throw ()
286
{
287
    unexpected_handler g = crt_unexpected_handler ;
288
    if ( f == NULL ) f = terminate ;
289
    crt_unexpected_handler = f ;
290
    return ( g ) ;
291
}
292
 
293
 
294
/*
295
    CALL UNEXPECTED HANDLER
296
 
297
    This routine calls the current unexpected handler.
298
*/
299
 
300
void std::unexpected ()
301
{
302
    __TCPPLUS_except.unwinding = false ;
303
    crt_unexpected_handler () ;
304
    return ;
305
}
306
 
307
 
308
/*
309
    HANDLE AN UNEXPECTED EXCEPTION
310
 
311
    This routine is called if a thrown exception does not match the
312
    exception specification of an enclosing function.  Note that the
313
    jump buffer stack is hacked so that any exception thrown by
314
    unexpected will be re-examined by the exception specification.
315
    If it is still does not match then either terminate is called
316
    or a bad_exception is thrown.
317
*/
318
 
319
void __TCPPLUS_unexpected ( int have_bad )
320
{
321
    EXCEPTION &ex = __TCPPLUS_except ;
322
    ex.unwinding = false ;
323
    JUMP_BUFFER *jmp = ex.buf [1] ;
324
    if ( jmp == ex.buf [2] ) {
325
	if ( have_bad ) throw bad_exception () ;
326
	terminate () ;
327
	return ;
328
    }
329
    ex.buf [2] = jmp ;
330
    ex.buf [0] = jmp ;
331
    unexpected () ;
332
    return ;
333
}
334
 
335
 
336
/*
337
    IS THERE AN UNCAUGHT EXCEPTION?
338
 
339
    This routine returns true if an exception has been thrown but not
340
    yet caught.
341
*/
342
 
343
bool std::uncaught_exception ()
344
{
345
    return ( __TCPPLUS_except.unwinding ) ;
346
}
347
 
348
 
349
/*
350
    PRINT AN ASSERTION
351
 
352
    This routine prints an error message if an assertion has failed.
353
*/
354
 
355
void __TCPPLUS_assert ( const char *fn, int ln )
356
{
357
    printf ( "Assertion failed, %s, line %d.\n", fn, ln ) ;
358
    abort () ;
359
}