Subversion Repositories tendra.SVN

Rev

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

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