Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
/**** exception.h --- Exception handling.
62
 *
63
 ** Author: Steve Folkes <smf@hermes.mod.uk>
64
 *
65
 **** Commentary:
66
 *
67
 ***=== INTRODUCTION =========================================================
68
 *
69
 * This file specifies the interface to an exception handling facility.  The
70
 * facility is built on top of the ANSI C non-local exit mechanism (``setjmp''
71
 * and ``longjmp''), and should be used in preference to it.  The mechanism is
72
 * implemented as a set of macros.
73
 *
74
 * This file requires that two external functions are provided:
75
 *
76
 *	extern void			E_exception_unhandled
6 7u83 77
 *			(ExceptionP, CStringP, unsigned);
2 7u83 78
 *	extern void			E_exception_corrupt_handler
6 7u83 79
 *			(CStringP, unsigned);
2 7u83 80
 *
81
 * The first of these functions will be called if there is an unhandled
82
 * exception.  The exception will be given as an argument, along with the name
83
 * of the file, and the line within that file that the exception was thrown
84
 * from.  The second function will be called if a corrupt exception handler
85
 * stack is detected.  It will be called with the file name, and line number
86
 * where the corrupt handler was established.  Neither of these functions
87
 * should return.  If either function raises an exception, the program will
88
 * abort.
89
 *
90
 * If the ``PO_EXCEPTION_STACK_DIRECTION'' macro is defined, then an attempt
91
 * is made to detect corrupt exception handler stacks (almost certainly due to
92
 * missing or excessive calls to the ``UNHANDLE'' macro).  If the macro is
93
 * defined to be less than zero, it is assumed that the (system) stack grows
94
 * downwards; if it defined to be greater than zero, then it is assumed that
95
 * the (system) stack grows upwards; if it is defined to be zero, then a
96
 * weaker check that doesn't use the stack direction is used.
97
 *
98
 ***=== TYPES ================================================================
99
 *
100
 ** Type:	ExceptionP
101
 ** Repr:	<private>
102
 *
103
 * This is the type of an exception.  Exceptions are initialised using the
104
 * ``EXCEPTION'' macro (see later).  Once initialised, the exception should
105
 * not be changed.
106
 *
107
 ** Type:	ThrowDataT
108
 ** Type:	ThrowDataP
109
 ** Repr:	<private>
110
 *
111
 * This type is used internally to store data about the exception being
112
 * thrown.
113
 *
114
 ** Type:	HandlerT
115
 ** Type:	HandlerP
116
 ** Repr:	<private>
117
 *
118
 * This type is used internally to store data about the exception handler
119
 * stack.
120
 *
121
 ***=== FUNCTIONS ============================================================
122
 *
123
 ** Function:	CStringP		exception_name
6 7u83 124
 *			(ExceptionP exception)
2 7u83 125
 *
126
 * This function returns the name of the specified exception.  The return
127
 * value should not be modified or deallocated.
128
 *
129
 ***=== MACROS ===============================================================
130
 *
131
 ** Macro:	EXCEPTION (name)
132
 *
133
 * This macro is used to initialise an exception, e.g.:
134
 *
135
 *	ExceptionP XX_exception = EXCEPTION ("an exception");
136
 *
137
 * This creates an exception object called ``XX_exception''.  The string used
138
 * as an argument to the ``EXCEPTION'' macro is a description of the
139
 * exception.  This string is used as a message to be printed when an
140
 * exception is thrown but not handled.  It can also be accessed through the
141
 * ``exception_name'' function.  The string should be different for each
142
 * exception (the string content should be different as well, as some
143
 * compilers put strings with the same content into the same memory location,
144
 * and the address of the string is used to make the exception unique).
145
 *
146
 * Exceptions should only be defined in global scope. Exceptions with
147
 * automatic scope may cause problems if they are not handled within their
148
 * scope.
149
 *
150
 ** Macro:	THROW (exception)
151
 *
152
 * This macro raises an exception.  The specified exception is thrown, and
153
 * control passes to the innermost exception handler.  If there are no
154
 * exception handlers, a message is printed and the program is aborted.
155
 *
156
 ** Macro:	THROW_VALUE (exception, value)
157
 *
158
 * This macro raises an exception.  The specified exception is thrown, and
159
 * control passes to the innermost exception handler.  If there are no
160
 * exception handlers, a message is printed and the program is aborted.
161
 * Unlike the ``THROW'' macro, this macro also passes a value to the exception
162
 * handler.  The value should be a pointer to a non-function object.  The
163
 * object pointed to should not be automatically allocated (unless it is
164
 * guaranteed to be caught within its scope).
165
 *
166
 ** Macro:	HANDLE
167
 ** Macro:	WITH
168
 ** Macro:	END_HANDLE
169
 *
170
 * These macros are used to handle an exception. They should be used as in the
171
 * following example:
172
 *
173
 *	HANDLE
174
 *		normal code - possible variable corruption here
175
 *	WITH
176
 *		exception handler code
177
 *	END_HANDLE
178
 *
179
 * The ``HANDLE'' macro begins an exception handler construct.  This should be
180
 * followed by the normal code to be executed.  The ``WITH'' macro begins the
181
 * exception handler region.  This macro is followed by the code to handle the
182
 * exception.  The ``END_HANDLE'' macro terminates the exception handler
183
 * construct.
184
 *
185
 * If any part of the construct is omitted, the code will not compile, or the
186
 * exception handler stack will become corrupted at run time.
187
 *
188
 * The exception handler is removed by the ``WITH'' macro, so throwing another
189
 * exception in the exception handler region (between the ``WITH'' macro and
190
 * the ``END_HANDLE'' macro) will cause the next error handler to be invoked.
191
 *
192
 * When an exception is caught, it is possible that some of the variables in
193
 * scope will not contain the correct value.  It is best to declare any
194
 * variables you wish to use inside an exception handler as ``volatile''.
195
 * This program assumes that what the ANSI C library specifiaction says about
196
 * ``setjmp'' and ``longjmp'' holds, so only non-volatile automatic variables
197
 * in the indicated region should become corrupted.
198
 *
199
 ** Macro:	EXCEPTION_EXCEPTION ()
200
 *
201
 * This macro returns the current exception.  It should only be used within
202
 * the exception handler region (between the ``WITH'' and ``END_HANDLE''
203
 * macros).
204
 *
205
 ** Macro:	EXCEPTION_VALUE ()
206
 *
207
 * This macro returns the data that was thrown with the current exception.  It
208
 * should only be used within the exception handler region (between the
209
 * ``WITH'' and ``END_HANDLE'' macros).
210
 *
211
 ** Macro:	EXCEPTION_LINE ()
212
 *
213
 * This macro returns the line from which the current exception was thrown.
214
 * It should only be used within the exception handler region (between the
215
 * ``WITH'' and ``END_HANDLE'' macros).
216
 *
217
 ** Macro:	EXCEPTION_FILE ()
218
 *
219
 * This macro returns the file from which the current exception was thrown.
220
 * It should only be used within the exception handler region (between the
221
 * ``WITH'' and ``END_HANDLE'' macros).
222
 *
223
 ** Macro:	RETHROW ()
224
 *
225
 * This macro should only be used in the exception handler region (between the
226
 * ``WITH'' and ``END_HANDLE'' macros), and causes the current exception to be
227
 * rethrown (to be caught by the next outermost exception handler).
228
 *
229
 ** Macro:	UNHANDLE
230
 *
231
 * This macro MUST be used before using a ``goto'' or ``return'' that would
232
 * cause the normal code region (between the ``HANDLE'' and ``WITH'' macros)
233
 * to be exited (otherwise the exception handler stack will become corrupt at
234
 * run time).
235
 *
236
 **** Change Log:
237
 * $Log: exception.h,v $
238
 * Revision 1.1.1.1  1998/01/17  15:57:45  release
239
 * First version to be checked into rolling release.
240
 *
241
 * Revision 1.2  1994/12/12  11:45:34  smf
242
 * Performing changes for 'CR94_178.sid+tld-update' - bringing in line with
243
 * OSSG C Coding Standards.
244
 *
245
 * Revision 1.1.1.1  1994/07/25  16:06:10  smf
246
 * Initial import of os-interface shared files.
247
 *
248
**/
249
 
250
/****************************************************************************/
251
 
252
#ifndef H_EXCEPTION
253
#define H_EXCEPTION
254
 
255
#include "os-interface.h"
256
 
257
/*--------------------------------------------------------------------------*/
258
 
259
typedef CStringP		ExceptionP;
260
 
261
typedef struct {
262
    CStringP			exception;
263
    GenericP			data;
264
    unsigned			line;
265
    CStringP			file;
266
} ThrowDataT, *ThrowDataP;
267
 
268
typedef struct HandlerT {
269
#ifdef PO_EXCEPTION_STACK_DIRECTION
270
    unsigned			magic_start;
271
    CStringP			file;
272
    unsigned			line;
273
#endif /* defined (PO_EXCEPTION_STACK_DIRECTION) */
274
    struct HandlerT	       *next;
275
    jmp_buf			buffer;
276
#ifdef PO_EXCEPTION_STACK_DIRECTION
277
    unsigned			magic_end;
278
#endif /* defined (PO_EXCEPTION_STACK_DIRECTION) */
279
} HandlerT, *HandlerP;
280
 
281
/*--------------------------------------------------------------------------*/
282
 
6 7u83 283
extern	CStringP		exception_name(ExceptionP);
2 7u83 284
 
285
/*--------------------------------------------------------------------------*/
286
 
287
extern HandlerP			X__exception_handler_stack;
288
extern ThrowDataT		X__exception_throw_data;
6 7u83 289
extern NoReturnT		X__exception_throw(void);
2 7u83 290
 
291
/*--------------------------------------------------------------------------*/
292
 
6 7u83 293
#define EXCEPTION(name)name
2 7u83 294
 
6 7u83 295
#define THROW(exc)\
2 7u83 296
{X__exception_throw_data.exception = (exc); \
6 7u83 297
 X__exception_throw_data.data      = NIL(GenericP); \
2 7u83 298
 X__exception_throw_data.line      = __LINE__; \
299
 X__exception_throw_data.file      = __FILE__; \
6 7u83 300
 X__exception_throw();}
2 7u83 301
 
6 7u83 302
#define THROW_VALUE(exc,val)\
2 7u83 303
{X__exception_throw_data.exception = (exc); \
6 7u83 304
 X__exception_throw_data.data      = ((GenericP)(val)); \
2 7u83 305
 X__exception_throw_data.line      = __LINE__; \
306
 X__exception_throw_data.file      = __FILE__; \
6 7u83 307
 X__exception_throw();}
2 7u83 308
 
309
#ifdef PO_EXCEPTION_STACK_DIRECTION
6 7u83 310
#define X__EXCEPTION_MAGIC(0x1234)
2 7u83 311
 
312
#define HANDLE \
313
{HandlerT X___exception_handler; \
314
 X___exception_handler.magic_start = X__EXCEPTION_MAGIC; \
315
 X___exception_handler.file        = __FILE__; \
316
 X___exception_handler.line        = __LINE__; \
317
 X___exception_handler.next        = X__exception_handler_stack; \
318
 X___exception_handler.magic_end   = X__EXCEPTION_MAGIC; \
319
 X__exception_handler_stack        = &X___exception_handler; \
6 7u83 320
 if (!setjmp(X___exception_handler.buffer)) {
2 7u83 321
#else
322
#define HANDLE \
323
{HandlerT X___exception_handler; \
324
 X___exception_handler.next = X__exception_handler_stack; \
325
 X__exception_handler_stack = &X___exception_handler; \
6 7u83 326
 if (!setjmp(X___exception_handler.buffer)) {
2 7u83 327
#endif /* defined (PO_EXCEPTION_STACK_DIRECTION) */
328
 
329
#define WITH \
330
     X__exception_handler_stack = X___exception_handler.next; \
331
 } else { \
332
     X__exception_handler_stack = X___exception_handler.next; {
333
 
334
#define END_HANDLE }}}
335
 
6 7u83 336
#define EXCEPTION_EXCEPTION()\
2 7u83 337
X__exception_throw_data.exception
338
 
6 7u83 339
#define EXCEPTION_VALUE()\
2 7u83 340
X__exception_throw_data.data
341
 
6 7u83 342
#define EXCEPTION_LINE()\
2 7u83 343
X__exception_throw_data.line
344
 
6 7u83 345
#define EXCEPTION_FILE()\
2 7u83 346
X__exception_throw_data.file
347
 
6 7u83 348
#define RETHROW()\
349
X__exception_throw();
2 7u83 350
 
351
#define UNHANDLE X__exception_handler_stack = X___exception_handler.next;
352
 
353
#endif /* !defined (H_EXCEPTION) */