2
$Header: d:/cvsroot/tads/TADS2/LER.H,v 1.2 1999/05/17 02:52:12 MJRoberts Exp $
6
* Copyright (c) 1991, 2002 Michael J. Roberts. All Rights Reserved.
8
* Please see the accompanying license file, LICENSE.TXT, for information
9
* on using and copying this software.
13
ler.h - library error handling definitions
15
Defines error handling mechanism
17
All of the functions and macros in here are named ERRxxx because
18
this file was based on the TADS err.h, which used the ERRxxx naming
19
convention, and it would be a lot of trouble to change.
21
This package defines a set of macros that allows code to raise and
22
handle exceptions. A macro is provided which signals an error, which
23
does a non-local goto to the innermost enclosing exception handler.
24
A set of macros sets up exception handling code.
26
To catch exceptions that occur inside a block of code (i.e., in the
27
code or in any subroutines called by the code), begin the block with
28
ERRBEGIN. At the end of the protected code, place the exception
29
handler, which starts with ERRCATCH. At the end of the exception
30
handler, place ERREND. If no exception occurs, execution goes
31
through the protected code, then resumes at the code following
34
The exception handler can signal another error, which will cause
35
the next enclosing frame to catch the error. Alternatively, if
36
the exception handler doesn't signal an error or return, execution
37
continues at the code following the ERREND. Exceptions that are
38
signalled during exception handling will be caught by the next
39
enclosing frame, unless the exception handler code is itself
40
protected by another ERRBEGIN-ERREND block.
42
To signal an error, use errsig().
44
To use a string argument in a signalled error, cover the string
45
with errstr(ctx, str, len); for example:
47
errsig1(ctx, ERR_XYZ, ERRTSTR, errstr(ctx, buf, strlen(buf)));
49
This copies the string into a buffer that is unaffected by
50
stack resetting during error signalling.
52
10/23/97 CNebel - fixed warnings from Metrowerks C compiler.
53
12/30/92 MJRoberts - created from TADS err.h
54
09/14/92 MJRoberts - add errlog2
55
08/15/91 MJRoberts - creation
72
/* maximum length of a facility identifier */
77
int erraint; /* integer argument */
78
char *errastr; /* text string argument */
80
typedef union erradef erradef;
84
struct errdef *errprv; /* previous error frame */
85
int errcode; /* error code of exception being handled */
86
char errfac[ERRFACMAX+1]; /* facility of current error */
87
erradef erraav[10]; /* parameters for error */
88
int erraac; /* count of parameters in argc */
89
jmp_buf errbuf; /* jump buffer for current error frame */
91
typedef struct errdef errdef;
95
/* seek location record for an error message by number */
98
uint errmfnum; /* error number */
99
ulong errmfseek; /* seek location of this message */
101
typedef struct errmfdef errmfdef;
105
errdef *errcxptr; /* current error frame */
106
void (*errcxlog)(void *, char *fac, int err, int argc, erradef *);
107
/* error logging callback function */
108
void *errcxlgc; /* context for error logging callback */
109
int errcxofs; /* offset in argument buffer */
110
char errcxbuf[ERRBUFSIZ]; /* space for argument strings */
111
osfildef *errcxfp; /* message file, if one is being used */
112
errmfdef *errcxseek; /* seek locations of messages in file */
113
uint errcxsksz; /* size of errcxseek array */
114
ulong errcxbase; /* offset in physical file of logical error file */
115
struct appctxdef *errcxappctx; /* host application context */
117
typedef struct errcxdef errcxdef;
119
/* begin protected code */
120
#define ERRBEGIN(ctx) \
123
if ((fr_.errcode = setjmp(fr_.errbuf)) == 0) \
125
fr_.errprv = (ctx)->errcxptr; \
126
(ctx)->errcxptr = &fr_;
128
/* end protected code, begin error handler */
129
#define ERRCATCH(ctx, e) \
130
assert(1==1 && (ctx)->errcxptr != fr_.errprv); \
131
(ctx)->errcxptr = fr_.errprv; \
135
assert(2==2 && (ctx)->errcxptr != fr_.errprv); \
137
(ctx)->errcxptr = fr_.errprv;
139
/* retrieve argument (int, string) in current error frame */
140
#define errargint(argnum) (fr_.erraav[argnum].erraint)
141
#define errargstr(argnum) (fr_.erraav[argnum].errastr)
144
#define ERREND(ctx) \
148
/* end protected code, begin cleanup (no handling; just cleaning up) */
149
#define ERRCLEAN(ctx) \
150
assert((ctx)->errcxptr != fr_.errprv); \
151
(ctx)->errcxptr = fr_.errprv; \
155
assert((ctx)->errcxptr != fr_.errprv); \
156
(ctx)->errcxptr = fr_.errprv;
158
#define ERRENDCLN(ctx) \
165
/* argument types for errors with arguments */
166
#define ERRTINT erraint
167
#define ERRTSTR errastr
169
/* set argument count in error frame */
170
#define errargc(ctx,cnt) ((ctx)->errcxptr->erraac=(cnt))
172
/* enter string argument; returns pointer to argument used in errargv */
174
char *errstr(errcxdef *ctx, const char *str, int len);
175
#else /* ERR_NO_MACRO */
177
#define errstr(ctx,str,len) \
178
((memcpy(&(ctx)->errcxbuf[(ctx)->errcxofs],str,(size_t)len), \
179
(ctx)->errcxofs += (len), \
180
(ctx)->errcxbuf[(ctx)->errcxofs++] = '\0'), \
181
&(ctx)->errcxbuf[(ctx)->errcxofs-(len)-1])
183
#endif /* ERR_NO_MACRO */
185
/* set argument in error frame argument vector */
186
#define errargv(ctx,index,typ,arg) \
187
((ctx)->errcxptr->erraav[index].typ=(arg))
189
/* signal an error with argument count already set */
191
void errsign(errcxdef *ctx, int e, char *facility);
192
#else /* ERR_NO_MACRO */
194
void errjmp(jmp_buf buf, int e);
195
# define errsign(ctx, e, fac) \
196
(strncpy((ctx)->errcxptr->errfac, fac, ERRFACMAX),\
197
(ctx)->errcxptr->errfac[ERRFACMAX]='\0',\
198
(ctx)->errcxofs=0, errjmp((ctx)->errcxptr->errbuf, e))
200
# define errsign(ctx, e, fac) \
201
(strncpy((ctx)->errcxptr->errfac, fac, ERRFACMAX),\
202
(ctx)->errcxptr->errfac[ERRFACMAX]='\0',\
203
(ctx)->errcxofs=0, longjmp((ctx)->errcxptr->errbuf, e))
205
#endif /* ERR_NO_MACRO */
208
/* signal an error with no arguments */
210
void errsigf(errcxdef *ctx, char *facility, int err);
211
#else /* ERR_NO_MACRO */
212
#define errsigf(ctx, fac, e) (errargc(ctx,0),errsign(ctx,e,fac))
213
#endif /* ERR_NO_MACRO */
215
/* signal an error with one argument */
216
#define errsigf1(ctx, fac, e, typ1, arg1) \
217
(errargv(ctx,0,typ1,arg1),errargc(ctx,1),errsign(ctx,e,fac))
219
/* signal an error with two arguments */
220
#define errsigf2(ctx, fac, e, typ1, arg1, typ2, arg2) \
221
(errargv(ctx,0,typ1,arg1), errargv(ctx,1,typ2,arg2), \
222
errargc(ctx,2), errsign(ctx,e,fac))
224
/* resignal the current error - only usable within exception handlers */
226
void errrse1(errcxdef *ctx, errdef *fr);
227
# define errrse(ctx) errrse1(ctx, &fr_)
228
#else /* ERR_NO_MACRO */
230
/* void errrse(errcxdef *ctx); */
231
# define errrse(ctx) \
232
(errargc(ctx, fr_.erraac),\
233
memcpy((ctx)->errcxptr->erraav, fr_.erraav, \
234
(size_t)(fr_.erraac*sizeof(erradef))),\
235
errsign(ctx, fr_.errcode, fr_.errfac))
237
#endif /* ERR_NO_MACRO */
240
* For use in an error handler (ERRCATCH..ERREND) only: Copy the
241
* parameters from the error currently being handled to the enclosing
242
* frame. This is useful when "keeping" an error being handled - i.e.,
243
* the arguments will continue to be used outside of the
244
* ERRCATCH..ERREND code.
246
/* void errkeepargs(errcxdef *ctx); */
247
#define errkeepargs(ctx) errcopyargs(ctx, &fr_)
250
* copy the parameters for an error from another frame into the current
251
* frame - this can be used when we want to be able to display an error
252
* that occurred in an inner frame within code that is protected by a
253
* new enclosing error frame
255
/* void errcopyargs(errcxdef *ctx, errdef *fr); */
256
#define errcopyargs(ctx, fr) \
257
(errargc((ctx), (fr)->erraac), \
258
memcpy((ctx)->errcxptr->erraav, (fr)->erraav, \
259
(size_t)((fr)->erraac*sizeof(erradef))))
261
/* log error that's been caught, using arguments already caught */
262
#define errclog(ctx) \
263
((*(ctx)->errcxlog)((ctx)->errcxlgc,fr_.errfac,fr_.errcode,\
264
fr_.erraac,fr_.erraav))
266
/* log an error that's been set up but not signalled yet */
267
#define errprelog(ctx, err) \
268
((*(ctx)->errcxlog)((ctx)->errcxlgc,(ctx)->errcxptr->errfac,\
269
err,(ctx)->errcxptr->erraac,\
270
(ctx)->errcxptr->erraav))
272
/* log an error (no signalling, just reporting) */
274
void errlogn(errcxdef *ctx, int err, char *facility);
275
#else /* ERR_NO_MACRO */
277
#define errlogn(ctx,err,fac) \
279
(*(ctx)->errcxlog)((ctx)->errcxlgc,fac,err,(ctx)->errcxptr->erraac,\
280
(ctx)->errcxptr->erraav))
282
#endif /* ERR_NO_MACRO */
284
/* log an error with no arguments */
286
void errlogf(errcxdef *ctx, char *facility, int err);
287
#else /* ERR_NO_MACRO */
289
/* void errlogf(errcxdef *ctx, char *facility, int err); */
290
#define errlogf(ctx,fac,err) (errargc(ctx,0),errlogn(ctx,err,fac))
292
#endif /* ERR_NO_MACRO */
294
/* log an error with one argument */
295
#define errlogf1(ctx, fac, e, typ1, arg1) \
296
(errargv(ctx,0,typ1,arg1),errargc(ctx,1),errlogn(ctx,e,fac))
298
/* log an error with two arguments */
299
#define errlogf2(ctx, fac, e, typ1, arg1, typ2, arg2) \
300
(errargv(ctx,0,typ1,arg1),errargv(ctx,1,typ2,arg2),\
301
errargc(ctx,2),errlogn(ctx,e,fac))
305
* Format an error message, sprintf-style, using arguments in an
306
* erradef array (which is passed to the error-logging callback).
307
* Returns the length of the output string, even if the actual
308
* output string was truncated because the outbuf was too short.
309
* (If called with outbufl == 0, nothing will be written out, but
310
* the size of the buffer needed, minus the terminating null byte,
311
* will be computed and returned.)
313
int errfmt(char *outbuf, int outbufl, char *fmt, int argc,
316
/* get the text of an error */
317
void errmsg(errcxdef *ctx, char *outbuf, uint outbufl, uint err);
319
/* initialize error subsystem, opening error message file if necessary */
320
void errini(errcxdef *ctx, osfildef *fp);
322
/* allocate and initialize error context, free error context */
324
void lerfre(errcxdef *ctx);
326
/* error message structure - number + text */
327
typedef struct errmdef errmdef;
330
uint errmerr; /* error number */
331
char *errmtxt; /* text of error message */
338
#endif /* ERR_INCLUDED */