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