xref: /csrg-svn/sys/deprecated/kdb/kdb_expr.c (revision 41345)
130296Ssam /*
230296Ssam  * Copyright (c) 1986 Regents of the University of California.
330296Ssam  * All rights reserved.  The Berkeley software License Agreement
430296Ssam  * specifies the terms and conditions for redistribution.
530296Ssam  *
6*41345Ssklower  *	@(#)kdb_expr.c	7.6 (Berkeley) 05/03/90
730296Ssam  */
830107Ssam 
930107Ssam #include "../kdb/defs.h"
1030107Ssam 
11*41345Ssklower char	*kdbBADSYM;
12*41345Ssklower char	*kdbBADVAR;
13*41345Ssklower char	*kdbBADKET;
14*41345Ssklower char	*kdbBADSYN;
15*41345Ssklower char	*kdbNOCFN;
16*41345Ssklower char	*kdbNOADR;
17*41345Ssklower char	*kdbBADLOC;
1830107Ssam 
19*41345Ssklower ADDR	kdblastframe;
20*41345Ssklower ADDR	kdbsavlastf;
21*41345Ssklower ADDR	kdbsavframe;
22*41345Ssklower ADDR	kdbsavpc;
23*41345Ssklower ADDR	kdbcallpc;
2430107Ssam 
25*41345Ssklower char	*kdblp;
26*41345Ssklower int	kdbradix;
27*41345Ssklower char	kdbisymbol[1024];
2830107Ssam 
29*41345Ssklower char	kdblastc, kdbpeekc;
3030107Ssam 
31*41345Ssklower long	kdbditto;
32*41345Ssklower long	kdbexpv;
3330107Ssam 
3430296Ssam static long
kdbround(a,b)35*41345Ssklower kdbround(a,b)
3630296Ssam 	register long a, b;
3730296Ssam {
3830296Ssam 	register long w;
3930296Ssam 
4030296Ssam 	w = (a/b)*b;
4130296Ssam 	if (a!=w)
4230296Ssam 		w += b;
4330296Ssam 	return (w);
4430296Ssam }
4530296Ssam 
4630107Ssam /* term | term dyadic expr |  */
kdbexpr(a)47*41345Ssklower kdbexpr(a)
4830107Ssam {
4930107Ssam 	register rc;
5030107Ssam 	register long lhs;
5130107Ssam 
52*41345Ssklower 	(void) kdbrdc(); kdblp--; rc=kdbterm(a);
5330107Ssam 
5430107Ssam 	while (rc) {
55*41345Ssklower 		lhs = kdbexpv;
56*41345Ssklower 		switch ((int)kdbreadchar()) {
5730107Ssam 		case '+':
58*41345Ssklower 			(void) kdbterm(a|1); kdbexpv += lhs; break;
5930107Ssam 		case '-':
60*41345Ssklower 			(void) kdbterm(a|1); kdbexpv = lhs - kdbexpv; break;
6130107Ssam 		case '#':
62*41345Ssklower 			(void) kdbterm(a|1); kdbexpv = kdbround(lhs,kdbexpv); break;
6330107Ssam 		case '*':
64*41345Ssklower 			(void) kdbterm(a|1); kdbexpv *= lhs; break;
6530107Ssam 		case '%':
66*41345Ssklower 			(void) kdbterm(a|1); kdbexpv = lhs/kdbexpv; break;
6730107Ssam 		case '&':
68*41345Ssklower 			(void) kdbterm(a|1); kdbexpv &= lhs; break;
6930107Ssam 		case '|':
70*41345Ssklower 			(void) kdbterm(a|1); kdbexpv |= lhs; break;
7130107Ssam 		case ')':
7230107Ssam 			if ((a&2)==0)
73*41345Ssklower 				kdberror(kdbBADKET);
7430107Ssam 		default:
75*41345Ssklower 			kdblp--;
7630107Ssam 			return (rc);
7730107Ssam 		}
7830107Ssam 	}
7930107Ssam 	return (rc);
8030107Ssam }
8130107Ssam 
8230107Ssam /* item | monadic item | (expr) | */
8330107Ssam static
kdbterm(a)84*41345Ssklower kdbterm(a)
8530107Ssam {
8630107Ssam 
87*41345Ssklower 	switch ((int)kdbreadchar()) {
8830107Ssam 	case '*':
89*41345Ssklower 		(void) kdbterm(a|1); kdbexpv=kdbchkget(kdbexpv,DSP);
9030107Ssam 		return(1);
9130107Ssam 	case '@':
92*41345Ssklower 		(void) kdbterm(a|1); kdbexpv=kdbchkget(kdbexpv,ISP);
9330107Ssam 		return(1);
9430107Ssam 	case '-':
95*41345Ssklower 		(void) kdbterm(a|1); kdbexpv = -kdbexpv;
9630107Ssam 		return(1);
9730107Ssam 	case '~':
98*41345Ssklower 		(void) kdbterm(a|1); kdbexpv = ~kdbexpv;
9930107Ssam 		return(1);
10030107Ssam 	case '#':
101*41345Ssklower 		(void) kdbterm(a|1); kdbexpv = !kdbexpv;
10230107Ssam 		return(1);
10330107Ssam 	case '(':
104*41345Ssklower 		(void) kdbexpr(2);
105*41345Ssklower 		if (*kdblp!=')')
106*41345Ssklower 			kdberror(kdbBADSYN);
107*41345Ssklower 		kdblp++;
10830107Ssam 		return(1);
10930107Ssam 	}
110*41345Ssklower 	kdblp--;
111*41345Ssklower 	return (kdbitem(a));
11230107Ssam }
11330107Ssam 
11430107Ssam /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
11530107Ssam static
kdbitem(a)116*41345Ssklower kdbitem(a)
11730107Ssam {
11830107Ssam 	register base, d, regptr;
11930107Ssam 	char savc;
12030107Ssam 	register long frame;
12130107Ssam 	register struct nlist *symp;
12230107Ssam 
123*41345Ssklower 	(void) kdbreadchar();
124*41345Ssklower 	if (kdbsymchar(0)) {
125*41345Ssklower 		kdbreadsym();
126*41345Ssklower 		if (kdblastc=='.') {
127*41345Ssklower 			frame = kdbpcb.pcb_fp; kdblastframe = 0;
128*41345Ssklower 			kdbcallpc = kdbpcb.pcb_pc;
129*41345Ssklower 			while (!kdberrflg) {
130*41345Ssklower 				kdbsavpc = kdbcallpc;
131*41345Ssklower 				(void) kdbfindsym((long)kdbcallpc,ISYM);
132*41345Ssklower 				if (kdbeqsym(kdbcursym->n_un.n_name,kdbisymbol,'~'))
13330136Ssam 					break;
134*41345Ssklower 				kdbcallpc = getprevpc(frame);
135*41345Ssklower 				kdblastframe = frame;
13630136Ssam 				frame = getprevframe(frame);
13730136Ssam 				if (frame == NOFRAME)
138*41345Ssklower 					kdberror(kdbNOCFN);
13930107Ssam 			}
140*41345Ssklower 			kdbsavlastf = kdblastframe; kdbsavframe = frame;
141*41345Ssklower 			(void) kdbreadchar();
142*41345Ssklower 			if (kdbsymchar(0))
143*41345Ssklower 				kdbchkloc(kdbexpv=frame);
144*41345Ssklower 		} else if ((symp=kdblookup(kdbisymbol))==0)
145*41345Ssklower 			kdberror(kdbBADSYM);
14630107Ssam 		else
147*41345Ssklower 			kdbexpv = symp->n_value;
148*41345Ssklower 		kdblp--;
14930136Ssam 		return (1);
15030136Ssam 	}
151*41345Ssklower 	if (kdbgetnum())
15230136Ssam 		return (1);
153*41345Ssklower 	switch (kdblastc) {
15430136Ssam 	case '.':
155*41345Ssklower 		(void) kdbreadchar();
156*41345Ssklower 		if (kdbsymchar(0)) {
157*41345Ssklower 			kdblastframe=kdbsavlastf; kdbcallpc=kdbsavpc;
158*41345Ssklower 			kdbchkloc((long)kdbsavframe);
15930107Ssam 		} else
160*41345Ssklower 			kdbexpv=kdbdot;
161*41345Ssklower 		kdblp--;
16230136Ssam 		break;
16330136Ssam 	case '"':
164*41345Ssklower 		kdbexpv=kdbditto;
16530136Ssam 		break;
16630136Ssam 	case '+':
167*41345Ssklower 		kdbexpv=kdbinkdot(kdbdotinc);
16830136Ssam 		break;
16930136Ssam 	case '^':
170*41345Ssklower 		kdbexpv=kdbinkdot(-kdbdotinc);
17130136Ssam 		break;
17230136Ssam 	case '<':
173*41345Ssklower 		savc=kdbrdc();
174*41345Ssklower 		if ((regptr=kdbgetreg(savc)) != -1)
175*41345Ssklower 			kdbexpv = *(int *)regptr;
176*41345Ssklower 		else if ((base=kdbvarchk(savc)) != -1)
177*41345Ssklower 			kdbexpv=kdbvar[base];
17830107Ssam 		else
179*41345Ssklower 			kdberror(kdbBADVAR);
18030136Ssam 		break;
18130136Ssam 	case '\'':
182*41345Ssklower 		d=4; kdbexpv=0;
183*41345Ssklower 		while (kdbquotchar()) {
18430107Ssam 		    if (d--) {
185*41345Ssklower 		         kdbexpv <<= 8;
186*41345Ssklower 			 kdbexpv |= kdblastc;
18730107Ssam 		    } else
188*41345Ssklower 			kdberror(kdbBADSYN);
18930107Ssam 		}
19030136Ssam 		break;
19130136Ssam 	default:
19230136Ssam 		if (a)
193*41345Ssklower 			kdberror(kdbNOADR);
194*41345Ssklower 		kdblp--;
19530107Ssam 		return(0);
19630107Ssam 	}
19730107Ssam 	return (1);
19830107Ssam }
19930107Ssam 
20030107Ssam /* service routines for expression reading */
20130107Ssam static
kdbgetnum()202*41345Ssklower kdbgetnum()
20330107Ssam {
20430107Ssam 	register base,d,frpt;
20530107Ssam 
206*41345Ssklower 	if (!isdigit(kdblastc))
20730107Ssam 		return (0);
208*41345Ssklower 	if ((base = kdbradix) < 0)
20930107Ssam 		base = -base;
210*41345Ssklower 	kdbexpv = 0;
211*41345Ssklower 	while (base>10 ? isxdigit(kdblastc) : isdigit(kdblastc)) {
21230107Ssam 		register m = MAXINT/base;
21330107Ssam 
214*41345Ssklower 		if (kdbexpv>m)		/* avoid overflow */
215*41345Ssklower 			kdbexpv = (kdbexpv-m)*base+m*base;
21630107Ssam 		else
217*41345Ssklower 			kdbexpv *= base;
218*41345Ssklower 		if ((d=kdbconvdig(kdblastc))>=base || d<0)
219*41345Ssklower 			kdberror(kdbBADSYN);
220*41345Ssklower 		kdbexpv += d; (void) kdbreadchar();
221*41345Ssklower 		if (kdbexpv==0) {
222*41345Ssklower 			if (kdblastc=='x' || kdblastc=='X') {
223*41345Ssklower 				 base=16; (void) kdbreadchar();
224*41345Ssklower 			} else if (kdblastc=='t' || kdblastc=='T') {
225*41345Ssklower 				 base=10; (void) kdbreadchar();
226*41345Ssklower 			} else if (kdblastc=='o' || kdblastc=='O') {
227*41345Ssklower 				 base=8; (void) kdbreadchar();
22830107Ssam 			}
22930107Ssam 		}
23030107Ssam 	}
231*41345Ssklower 	if (kdblastc=='.' && (base==10 || kdbexpv==0)) {
23238199Smckusick 		frpt=0; base=10;
233*41345Ssklower 		while (isdigit(kdbreadchar())) {
23438199Smckusick 			if (frpt)
23538199Smckusick 				continue;
23638199Smckusick 			frpt++;
237*41345Ssklower 			if (kdblastc - '0' >= 5)
238*41345Ssklower 				kdbexpv++;
23930107Ssam 		}
24030107Ssam 	}
241*41345Ssklower 	kdbpeekc=kdblastc;
24230107Ssam 	return (1);
24330107Ssam }
24430107Ssam 
24530107Ssam static
kdbreadsym()246*41345Ssklower kdbreadsym()
24730107Ssam {
24830107Ssam 	register char *p;
24930107Ssam 
250*41345Ssklower 	p = kdbisymbol;
25130107Ssam 	do {
252*41345Ssklower 		if (p < &kdbisymbol[sizeof(kdbisymbol)-1])
253*41345Ssklower 			*p++ = kdblastc;
254*41345Ssklower 		(void) kdbreadchar();
255*41345Ssklower 	} while (kdbsymchar(1));
25630107Ssam 	*p++ = 0;
25730107Ssam }
25830107Ssam 
25930107Ssam static
kdbconvdig(c)260*41345Ssklower kdbconvdig(c)
26130107Ssam 	char c;
26230107Ssam {
26330107Ssam 	if (isdigit(c))
26430107Ssam 		return (c-'0');
26530107Ssam 	if (isxdigit(c))
26630107Ssam 		return (c-'a'+10);
26730107Ssam 	return (-1);
26830107Ssam }
26930107Ssam 
27030107Ssam static
kdbsymchar(dig)271*41345Ssklower kdbsymchar(dig)
27230107Ssam {
27330107Ssam 
274*41345Ssklower 	if (kdblastc=='\\') {
275*41345Ssklower 		(void) kdbreadchar();
27630118Ssam 		return (1);
27730107Ssam 	}
278*41345Ssklower 	return (isalpha(kdblastc) || kdblastc=='_' || dig && isdigit(kdblastc));
27930107Ssam }
28030107Ssam 
kdbvarchk(name)281*41345Ssklower kdbvarchk(name)
28230107Ssam 	register name;
28330107Ssam {
28430107Ssam 	if (isdigit(name))
28530107Ssam 		return (name-'0');
28630107Ssam 	if (isalpha(name))
28730107Ssam 		return ((name&037)-1+10);
28830107Ssam 	return (-1);
28930107Ssam }
29030107Ssam 
29130107Ssam static
kdbchkloc(frame)292*41345Ssklower kdbchkloc(frame)
29330107Ssam 	long frame;
29430107Ssam {
29530107Ssam 
296*41345Ssklower 	kdbreadsym();
29730107Ssam 	do {
298*41345Ssklower 		if (kdblocalsym(frame)==0)
299*41345Ssklower 			kdberror(kdbBADLOC);
300*41345Ssklower 		kdbexpv=kdblocalval;
301*41345Ssklower 	} while (!kdbeqsym(kdbcursym->n_un.n_name,kdbisymbol,'~'));
30230107Ssam }
30330107Ssam 
kdbeqsym(s1,s2,c)304*41345Ssklower kdbeqsym(s1, s2, c)
30530107Ssam 	register char *s1, *s2;
30630107Ssam {
30730107Ssam 
308*41345Ssklower 	if (kdbstreq(s1,s2))
30930107Ssam 		return (1);
310*41345Ssklower 	if (*s1 == c && kdbstreq(s1+1, s2))
31130107Ssam 		return (1);
31230107Ssam 	return (0);
31330107Ssam }
31430107Ssam 
31530107Ssam static
kdbstreq(s1,s2)316*41345Ssklower kdbstreq(s1, s2)
31730107Ssam 	char *s1, *s2;
31830107Ssam {
31930107Ssam 
32030107Ssam 	while (*s1 == *s2++)
32130107Ssam 		if (*s1++ == '\0')
32230107Ssam 			return (1);
32330107Ssam 	return (0);
32430107Ssam }
325