~ubuntu-branches/ubuntu/wily/gargoyle-free/wily-proposed

« back to all changes in this revision

Viewing changes to tads/tads2/ler.h

  • Committer: Bazaar Package Importer
  • Author(s): Sylvain Beucler
  • Date: 2009-09-11 20:09:43 UTC
  • Revision ID: james.westby@ubuntu.com-20090911200943-idgzoyupq6650zpn
Tags: upstream-2009-08-25
ImportĀ upstreamĀ versionĀ 2009-08-25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
$Header: d:/cvsroot/tads/TADS2/LER.H,v 1.2 1999/05/17 02:52:12 MJRoberts Exp $
 
3
*/
 
4
 
 
5
/* 
 
6
 *   Copyright (c) 1991, 2002 Michael J. Roberts.  All Rights Reserved.
 
7
 *   
 
8
 *   Please see the accompanying license file, LICENSE.TXT, for information
 
9
 *   on using and copying this software.  
 
10
 */
 
11
/*
 
12
Name
 
13
  ler.h - library error handling definitions
 
14
Function
 
15
  Defines error handling mechanism
 
16
Notes
 
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.
 
20
 
 
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.
 
25
  
 
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
 
32
  the ERREND.
 
33
  
 
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.
 
41
  
 
42
  To signal an error, use errsig().
 
43
  
 
44
  To use a string argument in a signalled error, cover the string
 
45
  with errstr(ctx, str, len); for example:
 
46
  
 
47
     errsig1(ctx, ERR_XYZ, ERRTSTR, errstr(ctx, buf, strlen(buf)));
 
48
 
 
49
  This copies the string into a buffer that is unaffected by
 
50
  stack resetting during error signalling.
 
51
Modified
 
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
 
56
*/
 
57
 
 
58
#ifndef LER_INCLUDED
 
59
#define LER_INCLUDED
 
60
 
 
61
#include "os.h"
 
62
#ifndef LIB_INCLUDED
 
63
#include "lib.h"
 
64
#endif
 
65
#include <setjmp.h>
 
66
#include <assert.h>
 
67
 
 
68
#ifdef __cplusplus
 
69
extern "C" {
 
70
#endif
 
71
 
 
72
/* maximum length of a facility identifier */
 
73
#define ERRFACMAX    6
 
74
 
 
75
union erradef
 
76
{
 
77
    int   erraint;                                      /* integer argument */
 
78
    char *errastr;                                  /* text string argument */
 
79
};
 
80
typedef union erradef erradef;
 
81
 
 
82
struct errdef
 
83
{
 
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 */
 
90
};
 
91
typedef struct errdef errdef;
 
92
 
 
93
#define ERRBUFSIZ 512
 
94
 
 
95
/* seek location record for an error message by number */
 
96
struct errmfdef
 
97
{
 
98
    uint  errmfnum;                                         /* error number */
 
99
    ulong errmfseek;                       /* seek location of this message */
 
100
};
 
101
typedef struct errmfdef errmfdef;
 
102
 
 
103
struct errcxdef
 
104
{
 
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 */
 
116
};
 
117
typedef struct errcxdef errcxdef;
 
118
 
 
119
/* begin protected code */
 
120
#define ERRBEGIN(ctx) \
 
121
  { \
 
122
    errdef fr_; \
 
123
    if ((fr_.errcode = setjmp(fr_.errbuf)) == 0) \
 
124
    { \
 
125
      fr_.errprv = (ctx)->errcxptr; \
 
126
      (ctx)->errcxptr = &fr_;
 
127
 
 
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; \
 
132
    } \
 
133
    else \
 
134
    { \
 
135
      assert(2==2 && (ctx)->errcxptr != fr_.errprv); \
 
136
      (e) = fr_.errcode; \
 
137
      (ctx)->errcxptr = fr_.errprv;
 
138
        
 
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)
 
142
 
 
143
    
 
144
#define ERREND(ctx) \
 
145
    } \
 
146
  }
 
147
 
 
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; \
 
152
    } \
 
153
    else \
 
154
    { \
 
155
      assert((ctx)->errcxptr != fr_.errprv); \
 
156
      (ctx)->errcxptr = fr_.errprv;
 
157
 
 
158
#define ERRENDCLN(ctx) \
 
159
      errrse(ctx); \
 
160
    } \
 
161
  }
 
162
 
 
163
 
 
164
 
 
165
/* argument types for errors with arguments */
 
166
#define ERRTINT  erraint
 
167
#define ERRTSTR  errastr
 
168
 
 
169
/* set argument count in error frame */
 
170
#define errargc(ctx,cnt) ((ctx)->errcxptr->erraac=(cnt))
 
171
 
 
172
/* enter string argument; returns pointer to argument used in errargv */
 
173
#ifdef ERR_NO_MACRO
 
174
char *errstr(errcxdef *ctx, const char *str, int len);
 
175
#else /* ERR_NO_MACRO */
 
176
  
 
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])
 
182
 
 
183
#endif /* ERR_NO_MACRO */
 
184
 
 
185
/* set argument in error frame argument vector */
 
186
#define errargv(ctx,index,typ,arg) \
 
187
  ((ctx)->errcxptr->erraav[index].typ=(arg))
 
188
 
 
189
/* signal an error with argument count already set */
 
190
#ifdef ERR_NO_MACRO
 
191
void errsign(errcxdef *ctx, int e, char *facility);
 
192
#else /* ERR_NO_MACRO */
 
193
# ifdef DEBUG
 
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))
 
199
# else /* DEBUG */
 
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))
 
204
# endif /* DEBUG */
 
205
#endif /* ERR_NO_MACRO */
 
206
 
 
207
 
 
208
/* signal an error with no arguments */
 
209
#ifdef ERR_NO_MACRO
 
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 */
 
214
  
 
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))
 
218
 
 
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))
 
223
 
 
224
/* resignal the current error - only usable within exception handlers */
 
225
#ifdef ERR_NO_MACRO
 
226
void errrse1(errcxdef *ctx, errdef *fr);
 
227
# define errrse(ctx) errrse1(ctx, &fr_)
 
228
#else /* ERR_NO_MACRO */
 
229
 
 
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))
 
236
 
 
237
#endif /* ERR_NO_MACRO */
 
238
 
 
239
/*
 
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. 
 
245
 */
 
246
/* void errkeepargs(errcxdef *ctx); */
 
247
#define errkeepargs(ctx) errcopyargs(ctx, &fr_)
 
248
 
 
249
/* 
 
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 
 
254
 */
 
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))))
 
260
 
 
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))
 
265
 
 
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))
 
271
 
 
272
/* log an error (no signalling, just reporting) */
 
273
#ifdef ERR_NO_MACRO
 
274
void errlogn(errcxdef *ctx, int err, char *facility);
 
275
#else /* ERR_NO_MACRO */
 
276
 
 
277
#define errlogn(ctx,err,fac) \
 
278
 ((ctx)->errcxofs=0,\
 
279
  (*(ctx)->errcxlog)((ctx)->errcxlgc,fac,err,(ctx)->errcxptr->erraac,\
 
280
  (ctx)->errcxptr->erraav))
 
281
 
 
282
#endif /* ERR_NO_MACRO */
 
283
 
 
284
/* log an error with no arguments */
 
285
#ifdef ERR_NO_MACRO
 
286
void errlogf(errcxdef *ctx, char *facility, int err);
 
287
#else /* ERR_NO_MACRO */
 
288
 
 
289
/* void errlogf(errcxdef *ctx, char *facility, int err); */
 
290
#define errlogf(ctx,fac,err) (errargc(ctx,0),errlogn(ctx,err,fac))
 
291
 
 
292
#endif /* ERR_NO_MACRO */
 
293
 
 
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))
 
297
  
 
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))
 
302
 
 
303
 
 
304
/*
 
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.)
 
312
 */
 
313
int errfmt(char *outbuf, int outbufl, char *fmt, int argc,
 
314
           erradef *argv);
 
315
  
 
316
/* get the text of an error */
 
317
void errmsg(errcxdef *ctx, char *outbuf, uint outbufl, uint err);
 
318
  
 
319
/* initialize error subsystem, opening error message file if necessary */
 
320
void errini(errcxdef *ctx, osfildef *fp);
 
321
 
 
322
/* allocate and initialize error context, free error context */
 
323
errcxdef *lerini();
 
324
void      lerfre(errcxdef *ctx);
 
325
 
 
326
/* error message structure - number + text */
 
327
typedef struct errmdef errmdef;
 
328
struct errmdef
 
329
{
 
330
    uint   errmerr;                                         /* error number */
 
331
    char  *errmtxt;                                /* text of error message */
 
332
};
 
333
 
 
334
#ifdef __cplusplus
 
335
}
 
336
#endif
 
337
 
 
338
#endif /* ERR_INCLUDED */