Charles.Forsyth20060303644188019 years agoHistory
216 lines · 3.6 KB · C
RawDownload
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"#include "interp.h"#include "isa.h"#include "runt.h"#include "kernel.h"#include "raise.h" 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 voidsetstr(String *s, char *p){	if(s == H)		return;	if(s->len < 0 || s->max < 4)		return;	kstrcpy(s->Sascii, p, s->max);	/* TO DO: we are assuming they aren't runes */	s->len = strlen(s->Sascii);} static String *exstr; voidexcinit(void){	exstr = newstring(ERRMAX);	poolimmutable(D2H(exstr));} static String*newestring(char *estr){	String *s; 	if(waserror()){		setstr(exstr, estr);		D2H(exstr)->ref++;		return exstr;	}	s = c2string(estr, strlen(estr));	poperror();	return s;} #define NOPC	0xffffffff #define FRTYPE(f)	((f)->t == nil ? SEXTYPE(f)->reg.TR : (f)->t) /* * clear up an uncalled frame */static voidfreeframe(uchar *fp, int setsp){	Frame *f; 	f = (Frame*)fp;	if(f->t == nil)		unextend(f);	else if(f->t->np)		freeptrs(f, f->t);	if(setsp)		R.SP = fp;} inthandler(char *estr){	Prog *p;	Modlink *m, *mr;	int str, ne;	ulong pc, newpc;	long eoff;	uchar *fp, **eadr;	Frame *f;	Type *t, *zt;	Handler *h;	Except *e;	void *v; 	p = currun();	if(*estr == 0 || p == nil)		return 0;	str = p->exval == H || D2H(p->exval)->t == &Tstring;	m = R.M;	if(m->compiled)		pc = (ulong)R.PC-(ulong)m->prog;	else		pc = R.PC-m->prog;	pc--;	fp = R.FP;	while(fp != nil){		/* look for a handler */		if((h = m->m->htab) != nil){			for( ; h->etab != nil; h++){				if(pc < h->pc1 || pc >= h->pc2)					continue;				eoff = h->eoff;				zt = h->t;				for(e = h->etab, ne = h->ne; e->s != nil; e++, ne--){					if(ematch(e->s, estr) && (str && ne <= 0 || !str && ne > 0)){						newpc = e->pc;						goto found;					}				}				newpc = e->pc;				if(newpc != NOPC)					goto found;			}		}		if(!str && fp != R.FP){		/* becomes a string exception in immediate caller */			v = p->exval;			p->exval = *(String**)v;			D2H(p->exval)->ref++;			destroy(v);			str = 1;			continue;		}		f = (Frame*)fp;		if(f->mr != nil)			m = f->mr;		if(m->compiled)			pc = (ulong)f->lr-(ulong)m->prog;		else			pc = f->lr-m->prog;		pc--;		fp = f->fp;	}	destroy(p->exval);	p->exval = H;	return 0;found:	{		int n;		char name[3*KNAMELEN]; 		pc = modstatus(&R, name, sizeof(name));		n = 10+1+strlen(name)+1+strlen(estr)+1;		p->exstr = realloc(p->exstr, n);		if(p->exstr != nil)			snprint(p->exstr, n, "%lud %s %s", pc, name, estr);	} 	/*	 * there may be an uncalled frame at the top of the stack	 */	f = (Frame*)R.FP;	t = FRTYPE(f);	if(R.FP < R.EX || R.FP >= R.TS)		freeframe(R.EX+OA(Stkext, reg.tos.fr), 0);	else if(R.FP+t->size < R.SP)		freeframe(R.FP+t->size, 1); 	m = R.M;	while(R.FP != fp){		f = (Frame*)R.FP;		R.PC = f->lr;		R.FP = f->fp;		R.SP = (uchar*)f;		mr = f->mr;		if(f->t == nil)			unextend(f);		else if(f->t->np)			freeptrs(f, f->t);		if(mr != nil){			m = mr;			destroy(R.M);			R.M = m;			R.MP = m->MP;		}	}	if(zt != nil){		freeptrs(fp, zt);		initmem(zt, fp);	}	eadr = (uchar**)(fp+eoff);	destroy(*eadr);	*eadr = H;	if(p->exval == H)		*eadr = (uchar*)newestring(estr);	/* might fail */	else{		D2H(p->exval)->ref++;		*eadr = p->exval;	}	if(m->compiled)		R.PC = (Inst*)((ulong)m->prog+newpc);	else		R.PC = m->prog+newpc;	memmove(&p->R, &R, sizeof(R));	p->kill = nil;	destroy(p->exval);	p->exval = H;	return 1;}