aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/tads/tads2/error_handling.h
diff options
context:
space:
mode:
authorPaul Gilbert2019-05-17 10:04:03 -1000
committerPaul Gilbert2019-05-24 18:21:06 -0700
commit0279143a62c2cdab635894103da03b43eba7cf9c (patch)
treefbc77cd007a4104204287825902601b6fb50bad1 /engines/glk/tads/tads2/error_handling.h
parent54d240d81f8858f7ad694c690fcf738b3ec8b89d (diff)
downloadscummvm-rg350-0279143a62c2cdab635894103da03b43eba7cf9c.tar.gz
scummvm-rg350-0279143a62c2cdab635894103da03b43eba7cf9c.tar.bz2
scummvm-rg350-0279143a62c2cdab635894103da03b43eba7cf9c.zip
GLK: TADS2: Adding headers
Diffstat (limited to 'engines/glk/tads/tads2/error_handling.h')
-rw-r--r--engines/glk/tads/tads2/error_handling.h338
1 files changed, 338 insertions, 0 deletions
diff --git a/engines/glk/tads/tads2/error_handling.h b/engines/glk/tads/tads2/error_handling.h
new file mode 100644
index 0000000000..a225bbea74
--- /dev/null
+++ b/engines/glk/tads/tads2/error_handling.h
@@ -0,0 +1,338 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Library error handling definitions
+ * All of the functions and macros in here are named ERRxxx because
+ * this file was based on the TADS err.h, which used the ERRxxx naming
+ * convention, and it would be a lot of trouble to change.
+ *
+ * This package defines a set of macros that allows code to raise and
+ * handle exceptions. A macro is provided which signals an error, which
+ * does a non-local goto to the innermost enclosing exception handler.
+ * A set of macros sets up exception handling code.
+ *
+ * To catch exceptions that occur inside a block of code (i.e., in the
+ * code or in any subroutines called by the code), begin the block with
+ * ERRBEGIN. At the end of the protected code, place the exception
+ * handler, which starts with ERRCATCH. At the end of the exception
+ * handler, place ERREND. If no exception occurs, execution goes
+ * through the protected code, then resumes at the code following
+ * the ERREND.
+ *
+ * The exception handler can signal another error, which will cause
+ * the next enclosing frame to catch the error. Alternatively, if
+ * the exception handler doesn't signal an error or return, execution
+ * continues at the code following the ERREND. Exceptions that are
+ * signalled during exception handling will be caught by the next
+ * enclosing frame, unless the exception handler code is itself
+ * protected by another ERRBEGIN-ERREND block.
+ *
+ * To signal an error, use errsig().
+ *
+ * To use a string argument in a signalled error, cover the string
+ * with errstr(ctx, str, len); for example:
+ *
+ * errsig1(ctx, ERR_XYZ, ERRTSTR, errstr(ctx, buf, strlen(buf)));
+ *
+ * This copies the string into a buffer that is unaffected by
+ * stack resetting during error signalling.
+ */
+
+#ifndef GLK_TADS_TADS2_ERROR_HANDLING
+#define GLK_TADS_TADS2_ERROR_HANDLING
+
+#include "glk/tads/tads2/lib.h"
+#include "glk/tads/osfrobtads.h"
+
+namespace Glk {
+namespace TADS {
+namespace TADS2 {
+
+// TODO: Clean away use of jmp_buf, since ScummVM doesn't allow it
+struct jmp_buf {};
+
+/**
+ * Maximum length of a facility identifier
+ */
+#define ERRFACMAX 6
+
+union erradef {
+ int erraint; /* integer argument */
+ char *errastr; /* text string argument */
+};
+
+struct errdef {
+ struct errdef *errprv; /* previous error frame */
+ int errcode; /* error code of exception being handled */
+ char errfac[ERRFACMAX+1]; /* facility of current error */
+ erradef erraav[10]; /* parameters for error */
+ int erraac; /* count of parameters in argc */
+ jmp_buf errbuf; /* jump buffer for current error frame */
+};
+
+#define ERRBUFSIZ 512
+
+/**
+ * Seek location record for an error message by number
+ */
+struct errmfdef {
+ uint errmfnum; /* error number */
+ ulong errmfseek; /* seek location of this message */
+};
+typedef struct errmfdef errmfdef;
+
+struct errcxdef {
+ errdef *errcxptr; /* current error frame */
+ void (*errcxlog)(void *, char *fac, int err, int argc, erradef *);
+ /* error logging callback function */
+ void *errcxlgc; /* context for error logging callback */
+ int errcxofs; /* offset in argument buffer */
+ char errcxbuf[ERRBUFSIZ]; /* space for argument strings */
+ osfildef *errcxfp; /* message file, if one is being used */
+ errmfdef *errcxseek; /* seek locations of messages in file */
+ uint errcxsksz; /* size of errcxseek array */
+ ulong errcxbase; /* offset in physical file of logical error file */
+ struct appctxdef *errcxappctx; /* host application context */
+};
+
+/**
+ * Begin protected code
+ */
+#define ERRBEGIN(ctx) \
+ { \
+ errdef fr_; \
+ if ((fr_.errcode = setjmp(fr_.errbuf)) == 0) \
+ { \
+ fr_.errprv = (ctx)->errcxptr; \
+ (ctx)->errcxptr = &fr_;
+
+/**
+ * End protected code, begin error handler
+ */
+#define ERRCATCH(ctx, e) \
+ assert(1==1 && (ctx)->errcxptr != fr_.errprv); \
+ (ctx)->errcxptr = fr_.errprv; \
+ } \
+ else \
+ { \
+ assert(2==2 && (ctx)->errcxptr != fr_.errprv); \
+ (e) = fr_.errcode; \
+ (ctx)->errcxptr = fr_.errprv;
+
+/* retrieve argument (int, string) in current error frame */
+#define errargint(argnum) (fr_.erraav[argnum].erraint)
+#define errargstr(argnum) (fr_.erraav[argnum].errastr)
+
+
+#define ERREND(ctx) \
+ } \
+ }
+
+/* end protected code, begin cleanup (no handling; just cleaning up) */
+#define ERRCLEAN(ctx) \
+ assert((ctx)->errcxptr != fr_.errprv); \
+ (ctx)->errcxptr = fr_.errprv; \
+ } \
+ else \
+ { \
+ assert((ctx)->errcxptr != fr_.errprv); \
+ (ctx)->errcxptr = fr_.errprv;
+
+#define ERRENDCLN(ctx) \
+ errrse(ctx); \
+ } \
+ }
+
+
+
+/* argument types for errors with arguments */
+#define ERRTINT erraint
+#define ERRTSTR errastr
+
+/* set argument count in error frame */
+#define errargc(ctx,cnt) ((ctx)->errcxptr->erraac=(cnt))
+
+/* enter string argument; returns pointer to argument used in errargv */
+#ifdef ERR_NO_MACRO
+char *errstr(errcxdef *ctx, const char *str, int len);
+#else /* ERR_NO_MACRO */
+
+#define errstr(ctx,str,len) \
+ ((memcpy(&(ctx)->errcxbuf[(ctx)->errcxofs],str,(size_t)len), \
+ (ctx)->errcxofs += (len), \
+ (ctx)->errcxbuf[(ctx)->errcxofs++] = '\0'), \
+ &(ctx)->errcxbuf[(ctx)->errcxofs-(len)-1])
+
+#endif /* ERR_NO_MACRO */
+
+/* set argument in error frame argument vector */
+#define errargv(ctx,index,typ,arg) \
+ ((ctx)->errcxptr->erraav[index].typ=(arg))
+
+/* signal an error with argument count already set */
+#ifdef ERR_NO_MACRO
+void errsign(errcxdef *ctx, int e, char *facility);
+#else /* ERR_NO_MACRO */
+# ifdef DEBUG
+void errjmp(jmp_buf buf, int e);
+# define errsign(ctx, e, fac) \
+ (strncpy((ctx)->errcxptr->errfac, fac, ERRFACMAX),\
+ (ctx)->errcxptr->errfac[ERRFACMAX]='\0',\
+ (ctx)->errcxofs=0, errjmp((ctx)->errcxptr->errbuf, e))
+# else /* DEBUG */
+# define errsign(ctx, e, fac) \
+ (strncpy((ctx)->errcxptr->errfac, fac, ERRFACMAX),\
+ (ctx)->errcxptr->errfac[ERRFACMAX]='\0',\
+ (ctx)->errcxofs=0, longjmp((ctx)->errcxptr->errbuf, e))
+# endif /* DEBUG */
+#endif /* ERR_NO_MACRO */
+
+
+/* signal an error with no arguments */
+#ifdef ERR_NO_MACRO
+void errsigf(errcxdef *ctx, char *facility, int err);
+#else /* ERR_NO_MACRO */
+#define errsigf(ctx, fac, e) (errargc(ctx,0),errsign(ctx,e,fac))
+#endif /* ERR_NO_MACRO */
+
+/* signal an error with one argument */
+#define errsigf1(ctx, fac, e, typ1, arg1) \
+ (errargv(ctx,0,typ1,arg1),errargc(ctx,1),errsign(ctx,e,fac))
+
+/* signal an error with two arguments */
+#define errsigf2(ctx, fac, e, typ1, arg1, typ2, arg2) \
+ (errargv(ctx,0,typ1,arg1), errargv(ctx,1,typ2,arg2), \
+ errargc(ctx,2), errsign(ctx,e,fac))
+
+/* resignal the current error - only usable within exception handlers */
+#ifdef ERR_NO_MACRO
+void errrse1(errcxdef *ctx, errdef *fr);
+# define errrse(ctx) errrse1(ctx, &fr_)
+#else /* ERR_NO_MACRO */
+
+/* void errrse(errcxdef *ctx); */
+# define errrse(ctx) \
+ (errargc(ctx, fr_.erraac),\
+ memcpy((ctx)->errcxptr->erraav, fr_.erraav, \
+ (size_t)(fr_.erraac*sizeof(erradef))),\
+ errsign(ctx, fr_.errcode, fr_.errfac))
+
+#endif /* ERR_NO_MACRO */
+
+/*
+ * For use in an error handler (ERRCATCH..ERREND) only: Copy the
+ * parameters from the error currently being handled to the enclosing
+ * frame. This is useful when "keeping" an error being handled - i.e.,
+ * the arguments will continue to be used outside of the
+ * ERRCATCH..ERREND code.
+ */
+/* void errkeepargs(errcxdef *ctx); */
+#define errkeepargs(ctx) errcopyargs(ctx, &fr_)
+
+/*
+ * copy the parameters for an error from another frame into the current
+ * frame - this can be used when we want to be able to display an error
+ * that occurred in an inner frame within code that is protected by a
+ * new enclosing error frame
+ */
+/* void errcopyargs(errcxdef *ctx, errdef *fr); */
+#define errcopyargs(ctx, fr) \
+ (errargc((ctx), (fr)->erraac), \
+ memcpy((ctx)->errcxptr->erraav, (fr)->erraav, \
+ (size_t)((fr)->erraac*sizeof(erradef))))
+
+/* log error that's been caught, using arguments already caught */
+#define errclog(ctx) \
+ ((*(ctx)->errcxlog)((ctx)->errcxlgc,fr_.errfac,fr_.errcode,\
+ fr_.erraac,fr_.erraav))
+
+/* log an error that's been set up but not signalled yet */
+#define errprelog(ctx, err) \
+ ((*(ctx)->errcxlog)((ctx)->errcxlgc,(ctx)->errcxptr->errfac,\
+ err,(ctx)->errcxptr->erraac,\
+ (ctx)->errcxptr->erraav))
+
+/* log an error (no signalling, just reporting) */
+#ifdef ERR_NO_MACRO
+void errlogn(errcxdef *ctx, int err, char *facility);
+#else /* ERR_NO_MACRO */
+
+#define errlogn(ctx,err,fac) \
+ ((ctx)->errcxofs=0,\
+ (*(ctx)->errcxlog)((ctx)->errcxlgc,fac,err,(ctx)->errcxptr->erraac,\
+ (ctx)->errcxptr->erraav))
+
+#endif /* ERR_NO_MACRO */
+
+/* log an error with no arguments */
+#ifdef ERR_NO_MACRO
+void errlogf(errcxdef *ctx, char *facility, int err);
+#else /* ERR_NO_MACRO */
+
+/* void errlogf(errcxdef *ctx, char *facility, int err); */
+#define errlogf(ctx,fac,err) (errargc(ctx,0),errlogn(ctx,err,fac))
+
+#endif /* ERR_NO_MACRO */
+
+/* log an error with one argument */
+#define errlogf1(ctx, fac, e, typ1, arg1) \
+ (errargv(ctx,0,typ1,arg1),errargc(ctx,1),errlogn(ctx,e,fac))
+
+/* log an error with two arguments */
+#define errlogf2(ctx, fac, e, typ1, arg1, typ2, arg2) \
+ (errargv(ctx,0,typ1,arg1),errargv(ctx,1,typ2,arg2),\
+ errargc(ctx,2),errlogn(ctx,e,fac))
+
+
+/*
+ * Format an error message, sprintf-style, using arguments in an
+ * erradef array (which is passed to the error-logging callback).
+ * Returns the length of the output string, even if the actual
+ * output string was truncated because the outbuf was too short.
+ * (If called with outbufl == 0, nothing will be written out, but
+ * the size of the buffer needed, minus the terminating null byte,
+ * will be computed and returned.)
+ */
+int errfmt(char *outbuf, int outbufl, char *fmt, int argc,
+ erradef *argv);
+
+/* get the text of an error */
+void errmsg(errcxdef *ctx, char *outbuf, uint outbufl, uint err);
+
+/* initialize error subsystem, opening error message file if necessary */
+void errini(errcxdef *ctx, osfildef *fp);
+
+/* allocate and initialize error context, free error context */
+errcxdef *lerini();
+void lerfre(errcxdef *ctx);
+
+/* error message structure - number + text */
+struct errmdef {
+ uint errmerr; /* error number */
+ char *errmtxt; /* text of error message */
+};
+
+} // End of namespace TADS2
+} // End of namespace TADS
+} // End of namespace Glk
+
+#endif