358 lines · 5.0 KB · C
RawDownload
#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);}