#include "lib9.h"#include "dat.h"#include "fns.h"#include "error.h"#include "interp.h"#include "isa.h"#include "runt.h"#include "kernel.h" Inst ieclr = { IECLR, SRC(AXXX)|DST(AXXX) }; static voidrestorepc(Exception *e, Exception *l){ while(l != nil) { if(l->R.FP == e->R.FP) return; l = l->link; } *e->lrp = e->lr;} voidSys_raise(void *a){ char *e; F_Sys_raise *f; char buf[ERRLEN]; f = a; e = string2c(f->s); if(strlen(e) >= ERRLEN){ buf[0] = 0; strncat(buf, e, ERRLEN-1); e = buf; } error(e);} voidSys_rescue(void *a){ Prog *p; Modlink *m; Frame *cf, *bf, *fr; Stkext *sx; F_Sys_rescue *f; Exception *e, *l; Sys_Exception *le; f = a; p = currun(); cf = a; *f->ret = Sys_HANDLER; e = malloc(sizeof(Exception)); if(e == nil) error("no memory"); e->pattern = strdup(string2c(f->s)); e->rptr = f->ret; memmove(&e->R, &R, sizeof(e->R)); e->eptr = f->e; if(e->eptr != H) { le = f->e; D2H(le)->ref++; /* Populate these now because we could be * reporting no memory */ destroy(le->mod); le->mod = newstring(sizeof(m->m->name)); destroy(le->name); le->name = newstring(ERRLEN); } fr = (Frame*)R.FP; if(fr->t != nil) e->R.SP = R.FP; else { sx = SEXTYPE(fr); e->R.SP = sx->reg.SP; e->R.TS = sx->reg.TS; e->R.EX = sx->reg.EX; } e->R.PC = cf->lr; e->R.FP = cf->fp; if(cf->mr != nil) e->R.M = cf->mr; for(l = p->exsp; l != nil; l = l->link) if(l->R.FP == e->R.FP) break; bf = (Frame*)cf->fp; if(l == nil) { e->lrp = &bf->lr; e->lr = bf->lr; m = bf->mr; if(m == nil) m = cf->mr; if(m == nil) m = R.M; bf->lr = m->m->eclr; } else { e->lrp = l->lrp; e->lr = l->lr; } e->link = p->exsp; p->exsp = e;} voidSys_rescued(void *a){ Prog *p; F_Sys_rescued *f; char ebuf[ERRLEN]; Exception *eh, *e, **l; f = a; p = currun(); if(p->exhdlr == nil) return; switch(f->flag) { case Sys_ACTIVE: p->exhdlr = nil; return; case Sys_EXIT: error(up->env->error); case Sys_ONCE: case Sys_RAISE: eh = p->exhdlr; p->exhdlr = nil; l = &p->exsp; for(e = *l; e != nil; e = e->link) { if(e == eh) { *l = e->link; restorepc(e, p->exsp); expfree(e); break; /* was return; */ } l = &e->link; } if(f->flag == Sys_ONCE) return; if(f->s != H) strncpy(ebuf, string2c(f->s), ERRLEN-1); else memmove(ebuf, up->env->error, ERRLEN); error(ebuf); }} voidSys_unrescue(void *a){ Prog *p; Exception *e, *n; Frame *cf; cf = a; p = currun(); p->exhdlr = nil; e = p->exsp; if(e == nil || e->R.FP != cf->fp) return; n = e->link; if(n == nil || n->R.FP != e->R.FP) *e->lrp = e->lr; p->exsp = n; expfree(e);} static intematch(char *pat, char *exp){ int l; if(strcmp(pat, exp) == 0) return 1; l = strlen(pat); if(l == 0) return 0; if(pat[l-1] == '*') { if(l == 1) return 1; if(strncmp(pat, exp, l-1) == 0) return 1; } return 0;} static voidpopex(uchar *f){ Prog *p; Exception *e; p = currun(); while(p->exsp != nil) { e = p->exsp; if(e->R.FP != f) break; p->exsp = e->link; *e->lrp = e->lr; expfree(e); }} static voidunwind(REG *RF, REG *RT){ Frame *f; Modlink *m; while(RF->FP != RT->FP) { popex(RF->FP); f = (Frame*)RF->FP; RF->FP = f->fp; RF->SP = (uchar*)f; RF->PC = f->lr; m = f->mr; if(f->t == nil) unextend(f); else if (f->t->np) freeptrs(f, f->t); if(m != nil) { destroy(RF->M); RF->M = m; RF->MP = m->MP; } }} intactivated(void *exfp, REG *reg){ Type *t; Frame *f; Stkext *sx; uchar *fp, *sp, *ex; sp = reg->SP; ex = reg->EX; while(ex != nil) { sx = (Stkext*)ex; fp = sx->reg.tos.fu; while(fp != sp) { if(fp == exfp) return 1; f = (Frame*)fp; t = f->t; if(t == nil) t = sx->reg.TR; fp += t->size; } ex = sx->reg.EX; sp = sx->reg.SP; } return 0;} Inst*unlinkex(void){ Prog *p; Inst *i; Exception *e; p = currun(); i = nil; while(p->exsp != nil) { e = p->exsp; if(activated(e->R.FP, &R)) break; p->exsp = e->link; if(e->lr != nil) i = e->lr; expfree(e); } if(i == nil) error("bad unlinkex"); return i;} static voidsetstr(String *s, char *p, int len){ if(s == H) return; if(s->len < 0 || s->max < len) return; strncpy(s->Sascii, p, len-1); s->len = strlen(p);} inthandler(char *estr){ Prog *p; Exception *e; Sys_Exception *l; char name[NAMELEN]; p = currun(); if(p == nil || p->exhdlr != nil) return 0; for(e = p->exsp; e != nil; e = e->link) if(ematch(e->pattern, estr) && activated(e->R.FP, &R)) break; if(e == nil) return 0; l = e->eptr; if(l != H) { l->pc = modstatus(&R, name, sizeof(name)); setstr(l->mod, name, sizeof(name)); setstr(l->name, estr, ERRLEN); } unwind(&R, &e->R); memmove(&p->R, &e->R, sizeof(R)); *e->rptr = Sys_EXCEPTION; p->exhdlr = e; p->kill = nil; return 1;} voidcloseexp(Prog *p){ Exception *e; while(p->exsp != nil) { e = p->exsp; p->exsp = e->link; expfree(e); }} voidexpfree(Exception *e){ Sys_Exception *l; free(e->pattern); l = e->eptr; if(l != H) destroy(l); free(e);}
#include "lib9.h"
#include "dat.h"
#include "fns.h"
#include "error.h"
#include "interp.h"
#include "isa.h"
#include "runt.h"
#include "kernel.h"
Inst ieclr = { IECLR, SRC(AXXX)|DST(AXXX) };
static void
restorepc(Exception *e, Exception *l)
{
while(l != nil) {
if(l->R.FP == e->R.FP)
return;
l = l->link;
}
*e->lrp = e->lr;
}
void
Sys_raise(void *a)
{
char *e;
F_Sys_raise *f;
char buf[ERRLEN];
f = a;
e = string2c(f->s);
if(strlen(e) >= ERRLEN){
buf[0] = 0;
strncat(buf, e, ERRLEN-1);
e = buf;
}
error(e);
}
void
Sys_rescue(void *a)
{
Prog *p;
Modlink *m;
Frame *cf, *bf, *fr;
Stkext *sx;
F_Sys_rescue *f;
Exception *e, *l;
Sys_Exception *le;
f = a;
p = currun();
cf = a;
*f->ret = Sys_HANDLER;
e = malloc(sizeof(Exception));
if(e == nil)
error("no memory");
e->pattern = strdup(string2c(f->s));
e->rptr = f->ret;
memmove(&e->R, &R, sizeof(e->R));
e->eptr = f->e;
if(e->eptr != H) {
le = f->e;
D2H(le)->ref++;
/* Populate these now because we could be
* reporting no memory
*/
destroy(le->mod);
le->mod = newstring(sizeof(m->m->name));
destroy(le->name);
le->name = newstring(ERRLEN);
}
fr = (Frame*)R.FP;
if(fr->t != nil)
e->R.SP = R.FP;
else {
sx = SEXTYPE(fr);
e->R.SP = sx->reg.SP;
e->R.TS = sx->reg.TS;
e->R.EX = sx->reg.EX;
}
e->R.PC = cf->lr;
e->R.FP = cf->fp;
if(cf->mr != nil)
e->R.M = cf->mr;
for(l = p->exsp; l != nil; l = l->link)
if(l->R.FP == e->R.FP)
break;
bf = (Frame*)cf->fp;
if(l == nil) {
e->lrp = &bf->lr;
e->lr = bf->lr;
m = bf->mr;
if(m == nil)
m = cf->mr;
if(m == nil)
m = R.M;
bf->lr = m->m->eclr;
}
else {
e->lrp = l->lrp;
e->lr = l->lr;
}
e->link = p->exsp;
p->exsp = e;
}
void
Sys_rescued(void *a)
{
Prog *p;
F_Sys_rescued *f;
char ebuf[ERRLEN];
Exception *eh, *e, **l;
f = a;
p = currun();
if(p->exhdlr == nil)
return;
switch(f->flag) {
case Sys_ACTIVE:
p->exhdlr = nil;
return;
case Sys_EXIT:
error(up->env->error);
case Sys_ONCE:
case Sys_RAISE:
eh = p->exhdlr;
p->exhdlr = nil;
l = &p->exsp;
for(e = *l; e != nil; e = e->link) {
if(e == eh) {
*l = e->link;
restorepc(e, p->exsp);
expfree(e);
break; /* was return; */
}
l = &e->link;
}
if(f->flag == Sys_ONCE)
return;
if(f->s != H)
strncpy(ebuf, string2c(f->s), ERRLEN-1);
else
memmove(ebuf, up->env->error, ERRLEN);
error(ebuf);
}
}
void
Sys_unrescue(void *a)
{
Prog *p;
Exception *e, *n;
Frame *cf;
cf = a;
p = currun();
p->exhdlr = nil;
e = p->exsp;
if(e == nil || e->R.FP != cf->fp)
return;
n = e->link;
if(n == nil || n->R.FP != e->R.FP)
*e->lrp = e->lr;
p->exsp = n;
expfree(e);
}
static int
ematch(char *pat, char *exp)
{
int l;
if(strcmp(pat, exp) == 0)
return 1;
l = strlen(pat);
if(l == 0)
return 0;
if(pat[l-1] == '*') {
if(l == 1)
return 1;
if(strncmp(pat, exp, l-1) == 0)
return 1;
}
return 0;
}
static void
popex(uchar *f)
{
Prog *p;
Exception *e;
p = currun();
while(p->exsp != nil) {
e = p->exsp;
if(e->R.FP != f)
break;
p->exsp = e->link;
*e->lrp = e->lr;
expfree(e);
}
}
static void
unwind(REG *RF, REG *RT)
{
Frame *f;
Modlink *m;
while(RF->FP != RT->FP) {
popex(RF->FP);
f = (Frame*)RF->FP;
RF->FP = f->fp;
RF->SP = (uchar*)f;
RF->PC = f->lr;
m = f->mr;
if(f->t == nil)
unextend(f);
else if (f->t->np)
freeptrs(f, f->t);
if(m != nil) {
destroy(RF->M);
RF->M = m;
RF->MP = m->MP;
}
}
}
int
activated(void *exfp, REG *reg)
{
Type *t;
Frame *f;
Stkext *sx;
uchar *fp, *sp, *ex;
sp = reg->SP;
ex = reg->EX;
while(ex != nil) {
sx = (Stkext*)ex;
fp = sx->reg.tos.fu;
while(fp != sp) {
if(fp == exfp)
return 1;
f = (Frame*)fp;
t = f->t;
if(t == nil)
t = sx->reg.TR;
fp += t->size;
}
ex = sx->reg.EX;
sp = sx->reg.SP;
}
return 0;
}
Inst*
unlinkex(void)
{
Prog *p;
Inst *i;
Exception *e;
p = currun();
i = nil;
while(p->exsp != nil) {
e = p->exsp;
if(activated(e->R.FP, &R))
break;
p->exsp = e->link;
if(e->lr != nil)
i = e->lr;
expfree(e);
}
if(i == nil)
error("bad unlinkex");
return i;
}
static void
setstr(String *s, char *p, int len)
{
if(s == H)
return;
if(s->len < 0 || s->max < len)
return;
strncpy(s->Sascii, p, len-1);
s->len = strlen(p);
}
int
handler(char *estr)
{
Prog *p;
Exception *e;
Sys_Exception *l;
char name[NAMELEN];
p = currun();
if(p == nil || p->exhdlr != nil)
return 0;
for(e = p->exsp; e != nil; e = e->link)
if(ematch(e->pattern, estr) && activated(e->R.FP, &R))
break;
if(e == nil)
return 0;
l = e->eptr;
if(l != H) {
l->pc = modstatus(&R, name, sizeof(name));
setstr(l->mod, name, sizeof(name));
setstr(l->name, estr, ERRLEN);
}
unwind(&R, &e->R);
memmove(&p->R, &e->R, sizeof(R));
*e->rptr = Sys_EXCEPTION;
p->exhdlr = e;
p->kill = nil;
return 1;
}
void
closeexp(Prog *p)
{
Exception *e;
while(p->exsp != nil) {
e = p->exsp;
p->exsp = e->link;
expfree(e);
}
}
void
expfree(Exception *e)
{
Sys_Exception *l;
free(e->pattern);
l = e->eptr;
if(l != H)
destroy(l);
free(e);
}