/* xljump - execution context routines */ /* Copyright (c) 1985, by David Michael Betz All Rights Reserved Permission is granted for unrestricted non-commercial use */ #include "xlisp.h" /* external variables */ extern XLCONTEXT *xlcontext,*xltarget; extern LVAL xlvalue,xlenv,xlfenv,xldenv; extern int xlmask; LOCAL void findandjump(int mask, char *error); /* xlbegin - beginning of an execution context */ void xlbegin(XLCONTEXT *cptr, int flags, LVAL expr) { cptr->c_flags = flags; cptr->c_expr = expr; cptr->c_xlstack = xlstack; cptr->c_xlenv = xlenv; cptr->c_xlfenv = xlfenv; cptr->c_xldenv = xldenv; cptr->c_xlcontext = xlcontext; cptr->c_xlargv = xlargv; cptr->c_xlargc = xlargc; cptr->c_xlfp = xlfp; cptr->c_xlsp = xlsp; xlcontext = cptr; } /* xlend - end of an execution context */ void xlend(XLCONTEXT *cptr) { xlcontext = cptr->c_xlcontext; } /* xlgo - go to a label */ void xlgo(LVAL label) { XLCONTEXT *cptr; LVAL *argv; int argc; /* find a tagbody context */ for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext) if (cptr->c_flags & CF_GO) { argc = cptr->c_xlargc; argv = cptr->c_xlargv; while (--argc >= 0) if (*argv++ == label) { cptr->c_xlargc = argc; cptr->c_xlargv = argv; xljump(cptr,CF_GO,NIL); } } xlfail("no target for GO"); } /* xlreturn - return from a block */ void xlreturn(LVAL name, LVAL val) { XLCONTEXT *cptr; /* find a block context */ for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext) if (cptr->c_flags & CF_RETURN && cptr->c_expr == name) xljump(cptr,CF_RETURN,val); xlfail("no target for RETURN"); } /* xlthrow - throw to a catch */ void xlthrow(LVAL tag, LVAL val) { XLCONTEXT *cptr; /* find a catch context */ for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext) if ((cptr->c_flags & CF_THROW) && cptr->c_expr == tag) xljump(cptr,CF_THROW,val); xlfail("no target for THROW"); } /* xlsignal - signal an error */ void xlsignal(char *emsg, LVAL arg) { XLCONTEXT *cptr; /* find an error catcher */ for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext) if (cptr->c_flags & CF_ERROR) { if (cptr->c_expr && emsg) xlerrprint("error",NULL,emsg,arg); xljump(cptr,CF_ERROR,NIL); } } /* xltoplevel - go back to the top level */ void xltoplevel(void) { close_loadingfiles(); stdputstr("[ back to top level ]\n"); findandjump(CF_TOPLEVEL,"no top level"); } /* xlbrklevel - go back to the previous break level */ void xlbrklevel(void) { findandjump(CF_BRKLEVEL,"no previous break level"); } /* xlcleanup - clean-up after an error */ void xlcleanup(void) { stdputstr("[ back to previous break level ]\n"); findandjump(CF_CLEANUP,"not in a break loop"); } /* xlcontinue - continue from an error */ void xlcontinue(void) { findandjump(CF_CONTINUE,"not in a break loop"); } /* xljump - jump to a saved execution context */ void xljump(XLCONTEXT *target, int mask, LVAL val) { /* unwind the execution stack */ for (; xlcontext != target; xlcontext = xlcontext->c_xlcontext) /* check for an UNWIND-PROTECT */ if ((xlcontext->c_flags & CF_UNWIND)) { xltarget = target; xlmask = mask; break; } /* restore the state */ xlstack = xlcontext->c_xlstack; xlenv = xlcontext->c_xlenv; xlfenv = xlcontext->c_xlfenv; xlunbind(xlcontext->c_xldenv); xlargv = xlcontext->c_xlargv; xlargc = xlcontext->c_xlargc; xlfp = xlcontext->c_xlfp; xlsp = xlcontext->c_xlsp; xlvalue = val; /* call the handler */ longjmp(xlcontext->c_jmpbuf,mask); } /* findandjump - find a target context frame and jump to it */ LOCAL void findandjump(int mask, char *error) { XLCONTEXT *cptr; /* find a block context */ for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext) if (cptr->c_flags & mask) xljump(cptr,mask,NIL); xlabort(error); }