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