# define INCLUDE_FILE_IO # include "dgd.h" # include "str.h" # include "array.h" # include "object.h" # include "interpret.h" # include "comm.net.h" typedef struct { jmp_buf env; /* error context */ frame *f; /* frame context */ int offset; /* sp offset */ ec_ftn handler; /* error handler */ } context; static context stack[ERRSTACKSZ]; /* error context stack */ static context *esp = stack; /* error context stack pointer */ static char errbuf[4 * STRINGSZ]; /* current error message */ /* * NAME: errcontext->_push_() * DESCRIPTION: push and return the current errorcontext */ jmp_buf *_ec_push_(handler) ec_ftn handler; { if (esp == stack + ERRSTACKSZ) { error("Too many nested error contexts"); } esp->f = cframe; esp->offset = cframe->fp - cframe->sp; esp->handler = handler; return &(esp++)->env; } /* * NAME: errcontext->pop() * DESCRIPTION: pop the current errorcontext */ void ec_pop() { # ifdef DEBUG if (--esp < stack) { fatal("pop empty error stack"); } # else --esp; # endif } /* * NAME: errorcontext->handler() * DESCRIPTION: dummy handler for previously handled error */ static void ec_handler(f, depth) frame *f; Int depth; { } /* * NAME: errormesg() * DESCRIPTION: return the current error message */ char *errormesg() { return errbuf; } /* * NAME: error() * DESCRIPTION: cause an error */ void error(format, arg1, arg2, arg3, arg4, arg5, arg6) char *format, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6; { jmp_buf env; register context *e; frame *f; int offset; ec_ftn handler; if (format != (char *) NULL) { sprintf(errbuf, format, arg1, arg2, arg3, arg4, arg5, arg6); } ec_pop(); e = esp; f = e->f; offset = e->offset; memcpy(&env, &e->env, sizeof(jmp_buf)); do { if (e->handler != (ec_ftn) NULL) { handler = e->handler; e->handler = (ec_ftn) ec_handler; (*handler)(cframe, e->f->depth); break; } } while (--e >= stack); cframe = i_set_sp(cframe, f->fp - offset); longjmp(env, 1); } /* * NAME: fatal() * DESCRIPTION: a fatal error has been encountered; terminate the program and * dump a core if possible */ void fatal(format, arg1, arg2, arg3, arg4, arg5, arg6) char *format, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6; { static short count; char ebuf1[STRINGSZ], ebuf2[STRINGSZ]; if (count++ == 0) { sprintf(ebuf1, format, arg1, arg2, arg3, arg4, arg5, arg6); sprintf(ebuf2, "Fatal error: %s\012", ebuf1); /* LF */ P_message(ebuf2); /* show message */ comm_finish(); } abort(); } /* * NAME: message() * DESCRIPTION: issue a message on stderr */ void message(format, arg1, arg2, arg3, arg4, arg5, arg6) char *format, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6; { char ebuf[4 * STRINGSZ]; if (format == (char *) NULL) { sprintf(ebuf, "%s\012", errbuf); } else { sprintf(ebuf, format, arg1, arg2, arg3, arg4, arg5, arg6); } P_message(ebuf); /* show message */ }