#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 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 setstr(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; void excinit(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 void freeframe(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; } int handler(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; }