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
/**** exception.h --- Exception handling.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 **** Commentary:
36
 *
37
 ***=== INTRODUCTION =========================================================
38
 *
39
 * This file specifies the interface to an exception handling facility.  The
40
 * facility is built on top of the ANSI C non-local exit mechanism (``setjmp''
41
 * and ``longjmp''), and should be used in preference to it.  The mechanism is
42
 * implemented as a set of macros.
43
 *
44
 * This file requires that two external functions are provided:
45
 *
46
 *	extern void			E_exception_unhandled
47
 *			PROTO_S ((ExceptionP, CStringP, unsigned));
48
 *	extern void			E_exception_corrupt_handler
49
 *			PROTO_S ((CStringP, unsigned));
50
 *
51
 * The first of these functions will be called if there is an unhandled
52
 * exception.  The exception will be given as an argument, along with the name
53
 * of the file, and the line within that file that the exception was thrown
54
 * from.  The second function will be called if a corrupt exception handler
55
 * stack is detected.  It will be called with the file name, and line number
56
 * where the corrupt handler was established.  Neither of these functions
57
 * should return.  If either function raises an exception, the program will
58
 * abort.
59
 *
60
 * If the ``PO_EXCEPTION_STACK_DIRECTION'' macro is defined, then an attempt
61
 * is made to detect corrupt exception handler stacks (almost certainly due to
62
 * missing or excessive calls to the ``UNHANDLE'' macro).  If the macro is
63
 * defined to be less than zero, it is assumed that the (system) stack grows
64
 * downwards; if it defined to be greater than zero, then it is assumed that
65
 * the (system) stack grows upwards; if it is defined to be zero, then a
66
 * weaker check that doesn't use the stack direction is used.
67
 *
68
 ***=== TYPES ================================================================
69
 *
70
 ** Type:	ExceptionP
71
 ** Repr:	<private>
72
 *
73
 * This is the type of an exception.  Exceptions are initialised using the
74
 * ``EXCEPTION'' macro (see later).  Once initialised, the exception should
75
 * not be changed.
76
 *
77
 ** Type:	ThrowDataT
78
 ** Type:	ThrowDataP
79
 ** Repr:	<private>
80
 *
81
 * This type is used internally to store data about the exception being
82
 * thrown.
83
 *
84
 ** Type:	HandlerT
85
 ** Type:	HandlerP
86
 ** Repr:	<private>
87
 *
88
 * This type is used internally to store data about the exception handler
89
 * stack.
90
 *
91
 ***=== FUNCTIONS ============================================================
92
 *
93
 ** Function:	CStringP		exception_name
94
 *			PROTO_S ((ExceptionP exception))
95
 *
96
 * This function returns the name of the specified exception.  The return
97
 * value should not be modified or deallocated.
98
 *
99
 ***=== MACROS ===============================================================
100
 *
101
 ** Macro:	EXCEPTION (name)
102
 *
103
 * This macro is used to initialise an exception, e.g.:
104
 *
105
 *	ExceptionP XX_exception = EXCEPTION ("an exception");
106
 *
107
 * This creates an exception object called ``XX_exception''.  The string used
108
 * as an argument to the ``EXCEPTION'' macro is a description of the
109
 * exception.  This string is used as a message to be printed when an
110
 * exception is thrown but not handled.  It can also be accessed through the
111
 * ``exception_name'' function.  The string should be different for each
112
 * exception (the string content should be different as well, as some
113
 * compilers put strings with the same content into the same memory location,
114
 * and the address of the string is used to make the exception unique).
115
 *
116
 * Exceptions should only be defined in global scope. Exceptions with
117
 * automatic scope may cause problems if they are not handled within their
118
 * scope.
119
 *
120
 ** Macro:	THROW (exception)
121
 *
122
 * This macro raises an exception.  The specified exception is thrown, and
123
 * control passes to the innermost exception handler.  If there are no
124
 * exception handlers, a message is printed and the program is aborted.
125
 *
126
 ** Macro:	THROW_VALUE (exception, value)
127
 *
128
 * This macro raises an exception.  The specified exception is thrown, and
129
 * control passes to the innermost exception handler.  If there are no
130
 * exception handlers, a message is printed and the program is aborted.
131
 * Unlike the ``THROW'' macro, this macro also passes a value to the exception
132
 * handler.  The value should be a pointer to a non-function object.  The
133
 * object pointed to should not be automatically allocated (unless it is
134
 * guaranteed to be caught within its scope).
135
 *
136
 ** Macro:	HANDLE
137
 ** Macro:	WITH
138
 ** Macro:	END_HANDLE
139
 *
140
 * These macros are used to handle an exception. They should be used as in the
141
 * following example:
142
 *
143
 *	HANDLE
144
 *		normal code - possible variable corruption here
145
 *	WITH
146
 *		exception handler code
147
 *	END_HANDLE
148
 *
149
 * The ``HANDLE'' macro begins an exception handler construct.  This should be
150
 * followed by the normal code to be executed.  The ``WITH'' macro begins the
151
 * exception handler region.  This macro is followed by the code to handle the
152
 * exception.  The ``END_HANDLE'' macro terminates the exception handler
153
 * construct.
154
 *
155
 * If any part of the construct is omitted, the code will not compile, or the
156
 * exception handler stack will become corrupted at run time.
157
 *
158
 * The exception handler is removed by the ``WITH'' macro, so throwing another
159
 * exception in the exception handler region (between the ``WITH'' macro and
160
 * the ``END_HANDLE'' macro) will cause the next error handler to be invoked.
161
 *
162
 * When an exception is caught, it is possible that some of the variables in
163
 * scope will not contain the correct value.  It is best to declare any
164
 * variables you wish to use inside an exception handler as ``volatile''.
165
 * This program assumes that what the ANSI C library specifiaction says about
166
 * ``setjmp'' and ``longjmp'' holds, so only non-volatile automatic variables
167
 * in the indicated region should become corrupted.
168
 *
169
 ** Macro:	EXCEPTION_EXCEPTION ()
170
 *
171
 * This macro returns the current exception.  It should only be used within
172
 * the exception handler region (between the ``WITH'' and ``END_HANDLE''
173
 * macros).
174
 *
175
 ** Macro:	EXCEPTION_VALUE ()
176
 *
177
 * This macro returns the data that was thrown with the current exception.  It
178
 * should only be used within the exception handler region (between the
179
 * ``WITH'' and ``END_HANDLE'' macros).
180
 *
181
 ** Macro:	EXCEPTION_LINE ()
182
 *
183
 * This macro returns the line from which the current exception was thrown.
184
 * It should only be used within the exception handler region (between the
185
 * ``WITH'' and ``END_HANDLE'' macros).
186
 *
187
 ** Macro:	EXCEPTION_FILE ()
188
 *
189
 * This macro returns the file from which the current exception was thrown.
190
 * It should only be used within the exception handler region (between the
191
 * ``WITH'' and ``END_HANDLE'' macros).
192
 *
193
 ** Macro:	RETHROW ()
194
 *
195
 * This macro should only be used in the exception handler region (between the
196
 * ``WITH'' and ``END_HANDLE'' macros), and causes the current exception to be
197
 * rethrown (to be caught by the next outermost exception handler).
198
 *
199
 ** Macro:	UNHANDLE
200
 *
201
 * This macro MUST be used before using a ``goto'' or ``return'' that would
202
 * cause the normal code region (between the ``HANDLE'' and ``WITH'' macros)
203
 * to be exited (otherwise the exception handler stack will become corrupt at
204
 * run time).
205
 *
206
 **** Change Log:
207
 * $Log: exception.h,v $
208
 * Revision 1.1.1.1  1998/01/17  15:57:45  release
209
 * First version to be checked into rolling release.
210
 *
211
 * Revision 1.2  1994/12/12  11:45:34  smf
212
 * Performing changes for 'CR94_178.sid+tld-update' - bringing in line with
213
 * OSSG C Coding Standards.
214
 *
215
 * Revision 1.1.1.1  1994/07/25  16:06:10  smf
216
 * Initial import of os-interface shared files.
217
 *
218
**/
219
 
220
/****************************************************************************/
221
 
222
#ifndef H_EXCEPTION
223
#define H_EXCEPTION
224
 
225
#include "os-interface.h"
226
 
227
/*--------------------------------------------------------------------------*/
228
 
229
typedef CStringP		ExceptionP;
230
 
231
typedef struct {
232
    CStringP			exception;
233
    GenericP			data;
234
    unsigned			line;
235
    CStringP			file;
236
} ThrowDataT, *ThrowDataP;
237
 
238
typedef struct HandlerT {
239
#ifdef PO_EXCEPTION_STACK_DIRECTION
240
    unsigned			magic_start;
241
    CStringP			file;
242
    unsigned			line;
243
#endif /* defined (PO_EXCEPTION_STACK_DIRECTION) */
244
    struct HandlerT	       *next;
245
    jmp_buf			buffer;
246
#ifdef PO_EXCEPTION_STACK_DIRECTION
247
    unsigned			magic_end;
248
#endif /* defined (PO_EXCEPTION_STACK_DIRECTION) */
249
} HandlerT, *HandlerP;
250
 
251
/*--------------------------------------------------------------------------*/
252
 
253
extern	CStringP		exception_name
254
	PROTO_S ((ExceptionP));
255
 
256
/*--------------------------------------------------------------------------*/
257
 
258
extern HandlerP			X__exception_handler_stack;
259
extern ThrowDataT		X__exception_throw_data;
260
extern NoReturnT		X__exception_throw
261
	PROTO_S ((void));
262
 
263
/*--------------------------------------------------------------------------*/
264
 
265
#define EXCEPTION(name) name
266
 
267
#define THROW(exc) \
268
{X__exception_throw_data.exception = (exc); \
269
 X__exception_throw_data.data      = NIL (GenericP); \
270
 X__exception_throw_data.line      = __LINE__; \
271
 X__exception_throw_data.file      = __FILE__; \
272
 X__exception_throw ();}
273
 
274
#define THROW_VALUE(exc,val) \
275
{X__exception_throw_data.exception = (exc); \
276
 X__exception_throw_data.data      = ((GenericP) (val)); \
277
 X__exception_throw_data.line      = __LINE__; \
278
 X__exception_throw_data.file      = __FILE__; \
279
 X__exception_throw ();}
280
 
281
#ifdef PO_EXCEPTION_STACK_DIRECTION
282
#define X__EXCEPTION_MAGIC (0x1234)
283
 
284
#define HANDLE \
285
{HandlerT X___exception_handler; \
286
 X___exception_handler.magic_start = X__EXCEPTION_MAGIC; \
287
 X___exception_handler.file        = __FILE__; \
288
 X___exception_handler.line        = __LINE__; \
289
 X___exception_handler.next        = X__exception_handler_stack; \
290
 X___exception_handler.magic_end   = X__EXCEPTION_MAGIC; \
291
 X__exception_handler_stack        = &X___exception_handler; \
292
 if (!setjmp (X___exception_handler.buffer)) {
293
#else
294
#define HANDLE \
295
{HandlerT X___exception_handler; \
296
 X___exception_handler.next = X__exception_handler_stack; \
297
 X__exception_handler_stack = &X___exception_handler; \
298
 if (!setjmp (X___exception_handler.buffer)) {
299
#endif /* defined (PO_EXCEPTION_STACK_DIRECTION) */
300
 
301
#define WITH \
302
     X__exception_handler_stack = X___exception_handler.next; \
303
 } else { \
304
     X__exception_handler_stack = X___exception_handler.next; {
305
 
306
#define END_HANDLE }}}
307
 
308
#define EXCEPTION_EXCEPTION() \
309
X__exception_throw_data.exception
310
 
311
#define EXCEPTION_VALUE() \
312
X__exception_throw_data.data
313
 
314
#define EXCEPTION_LINE() \
315
X__exception_throw_data.line
316
 
317
#define EXCEPTION_FILE() \
318
X__exception_throw_data.file
319
 
320
#define RETHROW() \
321
X__exception_throw ();
322
 
323
#define UNHANDLE X__exception_handler_stack = X___exception_handler.next;
324
 
325
#endif /* !defined (H_EXCEPTION) */