1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "../port/error.h" 7 #include "interp.h" 8 #include "isa.h" 9 #include "runt.h" 10 #include "kernel.h" 11 #include "raise.h" 12 13 static int 14 ematch(char *pat, char *exp) 15 { 16 int l; 17 18 if(strcmp(pat, exp) == 0) 19 return 1; 20 21 l = strlen(pat); 22 if(l == 0) 23 return 0; 24 if(pat[l-1] == '*') { 25 if(l == 1) 26 return 1; 27 if(strncmp(pat, exp, l-1) == 0) 28 return 1; 29 } 30 return 0; 31 } 32 33 static void 34 setstr(String *s, char *p) 35 { 36 if(s == H) 37 return; 38 if(s->len < 0 || s->max < 4) 39 return; 40 kstrcpy(s->Sascii, p, s->max); /* TO DO: we are assuming they aren't runes */ 41 s->len = strlen(s->Sascii); 42 } 43 44 static String *exstr; 45 46 void 47 excinit(void) 48 { 49 exstr = newstring(ERRMAX); 50 poolimmutable(D2H(exstr)); 51 } 52 53 static String* 54 newestring(char *estr) 55 { 56 String *s; 57 58 if(waserror()){ 59 setstr(exstr, estr); 60 D2H(exstr)->ref++; 61 return exstr; 62 } 63 s = c2string(estr, strlen(estr)); 64 poperror(); 65 return s; 66 } 67 68 #define NOPC 0xffffffff 69 70 #define FRTYPE(f) ((f)->t == nil ? SEXTYPE(f)->reg.TR : (f)->t) 71 72 /* 73 * clear up an uncalled frame 74 */ 75 static void 76 freeframe(uchar *fp, int setsp) 77 { 78 Frame *f; 79 80 f = (Frame*)fp; 81 if(f->t == nil) 82 unextend(f); 83 else if(f->t->np) 84 freeptrs(f, f->t); 85 if(setsp) 86 R.SP = fp; 87 } 88 89 int 90 handler(char *estr) 91 { 92 Prog *p; 93 Modlink *m, *mr; 94 int str, ne; 95 ulong pc, newpc; 96 long eoff; 97 uchar *fp, **eadr; 98 Frame *f; 99 Type *t, *zt; 100 Handler *h; 101 Except *e; 102 void *v; 103 104 p = currun(); 105 if(*estr == 0 || p == nil) 106 return 0; 107 str = p->exval == H || D2H(p->exval)->t == &Tstring; 108 m = R.M; 109 if(m->compiled) 110 pc = (ulong)R.PC-(ulong)m->prog; 111 else 112 pc = R.PC-m->prog; 113 pc--; 114 fp = R.FP; 115 while(fp != nil){ /* look for a handler */ 116 if((h = m->m->htab) != nil){ 117 for( ; h->etab != nil; h++){ 118 if(pc < h->pc1 || pc >= h->pc2) 119 continue; 120 eoff = h->eoff; 121 zt = h->t; 122 for(e = h->etab, ne = h->ne; e->s != nil; e++, ne--){ 123 if(ematch(e->s, estr) && (str && ne <= 0 || !str && ne > 0)){ 124 newpc = e->pc; 125 goto found; 126 } 127 } 128 newpc = e->pc; 129 if(newpc != NOPC) 130 goto found; 131 } 132 } 133 if(!str && fp != R.FP){ /* becomes a string exception in immediate caller */ 134 v = p->exval; 135 p->exval = *(String**)v; 136 D2H(p->exval)->ref++; 137 destroy(v); 138 str = 1; 139 continue; 140 } 141 f = (Frame*)fp; 142 if(f->mr != nil) 143 m = f->mr; 144 if(m->compiled) 145 pc = (ulong)f->lr-(ulong)m->prog; 146 else 147 pc = f->lr-m->prog; 148 pc--; 149 fp = f->fp; 150 } 151 destroy(p->exval); 152 p->exval = H; 153 return 0; 154 found: 155 { 156 int n; 157 char name[3*KNAMELEN]; 158 159 pc = modstatus(&R, name, sizeof(name)); 160 n = 10+1+strlen(name)+1+strlen(estr)+1; 161 p->exstr = realloc(p->exstr, n); 162 if(p->exstr != nil) 163 snprint(p->exstr, n, "%lud %s %s", pc, name, estr); 164 } 165 166 /* 167 * there may be an uncalled frame at the top of the stack 168 */ 169 f = (Frame*)R.FP; 170 t = FRTYPE(f); 171 if(R.FP < R.EX || R.FP >= R.TS) 172 freeframe(R.EX+OA(Stkext, reg.tos.fr), 0); 173 else if(R.FP+t->size < R.SP) 174 freeframe(R.FP+t->size, 1); 175 176 m = R.M; 177 while(R.FP != fp){ 178 f = (Frame*)R.FP; 179 R.PC = f->lr; 180 R.FP = f->fp; 181 R.SP = (uchar*)f; 182 mr = f->mr; 183 if(f->t == nil) 184 unextend(f); 185 else if(f->t->np) 186 freeptrs(f, f->t); 187 if(mr != nil){ 188 m = mr; 189 destroy(R.M); 190 R.M = m; 191 R.MP = m->MP; 192 } 193 } 194 if(zt != nil){ 195 freeptrs(fp, zt); 196 initmem(zt, fp); 197 } 198 eadr = (uchar**)(fp+eoff); 199 destroy(*eadr); 200 *eadr = H; 201 if(p->exval == H) 202 *eadr = (uchar*)newestring(estr); /* might fail */ 203 else{ 204 D2H(p->exval)->ref++; 205 *eadr = p->exval; 206 } 207 if(m->compiled) 208 R.PC = (Inst*)((ulong)m->prog+newpc); 209 else 210 R.PC = m->prog+newpc; 211 memmove(&p->R, &R, sizeof(R)); 212 p->kill = nil; 213 destroy(p->exval); 214 p->exval = H; 215 return 1; 216 } 217