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
ematch(char * pat,char * exp)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
setstr(String * s,char * p)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
excinit(void)44 excinit(void)
45 {
46 exstr = newstring(ERRMAX);
47 poolimmutable(D2H(exstr));
48 }
49
50 static String*
newestring(char * estr)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
freeframe(uchar * fp,int setsp)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
handler(char * estr)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