xref: /csrg-svn/sys/deprecated/kdb/kdb_expr.c (revision 30136)
1*30136Ssam /*	kdb_expr.c	7.3	86/11/23	*/
230107Ssam 
330107Ssam #include "../kdb/defs.h"
430107Ssam 
530107Ssam char	*BADSYM;
630107Ssam char	*BADVAR;
730107Ssam char	*BADKET;
830107Ssam char	*BADSYN;
930107Ssam char	*NOCFN;
1030107Ssam char	*NOADR;
1130107Ssam char	*BADLOC;
1230107Ssam 
1330107Ssam ADDR	lastframe;
1430107Ssam ADDR	savlastf;
1530107Ssam ADDR	savframe;
1630107Ssam ADDR	savpc;
1730107Ssam ADDR	callpc;
1830107Ssam 
1930107Ssam char	*lp;
2030107Ssam int	radix;
2130107Ssam char	isymbol[1024];
2230107Ssam 
2330107Ssam char	lastc, peekc;
2430107Ssam 
2530107Ssam long	ditto;
2630107Ssam long	expv;
2730107Ssam 
2830107Ssam /* term | term dyadic expr |  */
2930107Ssam expr(a)
3030107Ssam {
3130107Ssam 	register rc;
3230107Ssam 	register long lhs;
3330107Ssam 
3430107Ssam 	rdc(); lp--; rc=term(a);
3530107Ssam 
3630107Ssam 	while (rc) {
3730107Ssam 		lhs = expv;
3830107Ssam 		switch ((int)readchar()) {
3930107Ssam 		case '+':
4030107Ssam 			term(a|1); expv += lhs; break;
4130107Ssam 		case '-':
4230107Ssam 			term(a|1); expv = lhs - expv; break;
4330107Ssam 		case '#':
4430107Ssam 			term(a|1); expv = round(lhs,expv); break;
4530107Ssam 		case '*':
4630107Ssam 			term(a|1); expv *= lhs; break;
4730107Ssam 		case '%':
4830107Ssam 			term(a|1); expv = lhs/expv; break;
4930107Ssam 		case '&':
5030107Ssam 			term(a|1); expv &= lhs; break;
5130107Ssam 		case '|':
5230107Ssam 			term(a|1); expv |= lhs; break;
5330107Ssam 		case ')':
5430107Ssam 			if ((a&2)==0)
5530107Ssam 				error(BADKET);
5630107Ssam 		default:
5730107Ssam 			lp--;
5830107Ssam 			return (rc);
5930107Ssam 		}
6030107Ssam 	}
6130107Ssam 	return (rc);
6230107Ssam }
6330107Ssam 
6430107Ssam /* item | monadic item | (expr) | */
6530107Ssam static
6630107Ssam term(a)
6730107Ssam {
6830107Ssam 
6930107Ssam 	switch ((int)readchar()) {
7030107Ssam 	case '*':
7130107Ssam 		term(a|1); expv=chkget(expv,DSP);
7230107Ssam 		return(1);
7330107Ssam 	case '@':
7430107Ssam 		term(a|1); expv=chkget(expv,ISP);
7530107Ssam 		return(1);
7630107Ssam 	case '-':
7730107Ssam 		term(a|1); expv = -expv;
7830107Ssam 		return(1);
7930107Ssam 	case '~':
8030107Ssam 		term(a|1); expv = ~expv;
8130107Ssam 		return(1);
8230107Ssam 	case '#':
8330107Ssam 		term(a|1); expv = !expv;
8430107Ssam 		return(1);
8530107Ssam 	case '(':
8630107Ssam 		expr(2);
8730107Ssam 		if (*lp!=')')
8830107Ssam 			error(BADSYN);
8930107Ssam 		lp++;
9030107Ssam 		return(1);
9130107Ssam 	}
9230107Ssam 	lp--;
9330107Ssam 	return (item(a));
9430107Ssam }
9530107Ssam 
9630107Ssam /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
9730107Ssam static
9830107Ssam item(a)
9930107Ssam {
10030107Ssam 	register base, d, regptr;
10130107Ssam 	char savc;
10230107Ssam 	register long frame;
10330107Ssam 	register struct nlist *symp;
10430107Ssam 
10530107Ssam 	readchar();
10630107Ssam 	if (symchar(0)) {
10730107Ssam 		readsym();
10830107Ssam 		if (lastc=='.') {
10930107Ssam 			frame = pcb.pcb_fp; lastframe = 0;
110*30136Ssam 			callpc = pcb.pcb_pc;
111*30136Ssam 			while (!errflg) {
112*30136Ssam 				savpc = callpc;
113*30136Ssam 				findsym(callpc,ISYM);
114*30136Ssam 				if (eqsym(cursym->n_un.n_name,isymbol,'~'))
115*30136Ssam 					break;
116*30136Ssam 				callpc = getprevpc(frame);
117*30136Ssam 				lastframe = frame;
118*30136Ssam 				frame = getprevframe(frame);
119*30136Ssam 				if (frame == NOFRAME)
120*30136Ssam 					error(NOCFN);
12130107Ssam 			}
122*30136Ssam 			savlastf = lastframe; savframe = frame;
12330107Ssam 			readchar();
12430107Ssam 			if (symchar(0))
12530107Ssam 				chkloc(expv=frame);
12630107Ssam 		} else if ((symp=lookup(isymbol))==0)
12730107Ssam 			error(BADSYM);
12830107Ssam 		else
12930107Ssam 			expv = symp->n_value;
13030107Ssam 		lp--;
131*30136Ssam 		return (1);
132*30136Ssam 	}
133*30136Ssam 	if (getnum())
134*30136Ssam 		return (1);
135*30136Ssam 	switch (lastc) {
136*30136Ssam 	case '.':
13730107Ssam 		readchar();
13830107Ssam 		if (symchar(0)) {
13930107Ssam 			lastframe=savlastf; callpc=savpc;
14030107Ssam 			chkloc(savframe);
14130107Ssam 		} else
14230107Ssam 			expv=dot;
14330107Ssam 		lp--;
144*30136Ssam 		break;
145*30136Ssam 	case '"':
14630107Ssam 		expv=ditto;
147*30136Ssam 		break;
148*30136Ssam 	case '+':
14930107Ssam 		expv=inkdot(dotinc);
150*30136Ssam 		break;
151*30136Ssam 	case '^':
15230107Ssam 		expv=inkdot(-dotinc);
153*30136Ssam 		break;
154*30136Ssam 	case '<':
15530107Ssam 		savc=rdc();
15630107Ssam 		if ((regptr=getreg(savc)) != -1)
15730107Ssam 			expv = *(int *)regptr;
15830107Ssam 		else if ((base=varchk(savc)) != -1)
15930107Ssam 			expv=var[base];
16030107Ssam 		else
16130107Ssam 			error(BADVAR);
162*30136Ssam 		break;
163*30136Ssam 	case '\'':
16430107Ssam 		d=4; expv=0;
16530107Ssam 		while (quotchar()) {
16630107Ssam 		    if (d--) {
16730107Ssam 		         expv <<= 8;
16830107Ssam 			 expv |= lastc;
16930107Ssam 		    } else
17030107Ssam 			error(BADSYN);
17130107Ssam 		}
172*30136Ssam 		break;
173*30136Ssam 	default:
174*30136Ssam 		if (a)
175*30136Ssam 			error(NOADR);
17630107Ssam 		lp--;
17730107Ssam 		return(0);
17830107Ssam 	}
17930107Ssam 	return (1);
18030107Ssam }
18130107Ssam 
18230107Ssam /* service routines for expression reading */
18330107Ssam static
18430107Ssam getnum()
18530107Ssam {
18630107Ssam 	register base,d,frpt;
18730107Ssam 	union { float r; long i;} real;
18830107Ssam 
18930107Ssam 	if (!isdigit(lastc))
19030107Ssam 		return (0);
19130107Ssam 	if ((base = radix) < 0)
19230107Ssam 		base = -base;
19330107Ssam 	expv = 0;
19430107Ssam 	while (base>10 ? isxdigit(lastc) : isdigit(lastc)) {
19530107Ssam 		register m = MAXINT/base;
19630107Ssam 
19730107Ssam 		if (expv>m)		/* avoid overflow */
19830107Ssam 			expv = (expv-m)*base+m*base;
19930107Ssam 		else
20030107Ssam 			expv *= base;
20130107Ssam 		if ((d=convdig(lastc))>=base || d<0)
20230107Ssam 			error(BADSYN);
20330107Ssam 		expv += d; readchar();
20430107Ssam 		if (expv==0) {
20530107Ssam 			if (lastc=='x' || lastc=='X') {
20630107Ssam 				 base=16; readchar();
20730107Ssam 			} else if (lastc=='t' || lastc=='T') {
20830107Ssam 				 base=10; readchar();
20930107Ssam 			} else if (lastc=='o' || lastc=='O') {
21030107Ssam 				 base=8; readchar();
21130107Ssam 			}
21230107Ssam 		}
21330107Ssam 	}
21430107Ssam 	if (lastc=='.' && (base==10 || expv==0)) {
21530107Ssam 		real.r=expv; frpt=0; base=10;
21630107Ssam 		while (isdigit(readchar())) {
21730107Ssam 			real.r *= base; frpt++;
21830107Ssam 			real.r += lastc-'0';
21930107Ssam 		}
22030107Ssam 		while (frpt--)
22130107Ssam 			real.r /= base;
22230107Ssam 		expv = real.i;
22330107Ssam 	}
22430107Ssam 	peekc=lastc;
22530107Ssam 	return (1);
22630107Ssam }
22730107Ssam 
22830107Ssam static
22930107Ssam readsym()
23030107Ssam {
23130107Ssam 	register char *p;
23230107Ssam 
23330107Ssam 	p = isymbol;
23430107Ssam 	do {
23530107Ssam 	    if (p < &isymbol[sizeof(isymbol)-1])
23630107Ssam 		    *p++ = lastc;
23730107Ssam 	    readchar();
23830107Ssam 	} while (symchar(1));
23930107Ssam 	*p++ = 0;
24030107Ssam }
24130107Ssam 
24230107Ssam static
24330107Ssam convdig(c)
24430107Ssam 	char c;
24530107Ssam {
24630107Ssam 	if (isdigit(c))
24730107Ssam 		return (c-'0');
24830107Ssam 	if (isxdigit(c))
24930107Ssam 		return (c-'a'+10);
25030107Ssam 	return (-1);
25130107Ssam }
25230107Ssam 
25330107Ssam static
25430107Ssam symchar(dig)
25530107Ssam {
25630107Ssam 
25730107Ssam 	if (lastc=='\\') {
25830107Ssam 		readchar();
25930118Ssam 		return (1);
26030107Ssam 	}
26130107Ssam 	return (isalpha(lastc) || lastc=='_' || dig && isdigit(lastc));
26230107Ssam }
26330107Ssam 
26430107Ssam varchk(name)
26530107Ssam 	register name;
26630107Ssam {
26730107Ssam 	if (isdigit(name))
26830107Ssam 		return (name-'0');
26930107Ssam 	if (isalpha(name))
27030107Ssam 		return ((name&037)-1+10);
27130107Ssam 	return (-1);
27230107Ssam }
27330107Ssam 
27430107Ssam static
27530107Ssam chkloc(frame)
27630107Ssam 	long frame;
27730107Ssam {
27830107Ssam 
27930107Ssam 	readsym();
28030107Ssam 	do {
28130107Ssam 		if (localsym(frame)==0)
28230107Ssam 			error(BADLOC);
28330107Ssam 		expv=localval;
28430107Ssam 	} while (!eqsym(cursym->n_un.n_name,isymbol,'~'));
28530107Ssam }
28630107Ssam 
28730107Ssam eqsym(s1, s2, c)
28830107Ssam 	register char *s1, *s2;
28930107Ssam {
29030107Ssam 
29130107Ssam 	if (streq(s1,s2))
29230107Ssam 		return (1);
29330107Ssam 	if (*s1 == c && streq(s1+1, s2))
29430107Ssam 		return (1);
29530107Ssam 	return (0);
29630107Ssam }
29730107Ssam 
29830107Ssam static
29930107Ssam streq(s1, s2)
30030107Ssam 	char *s1, *s2;
30130107Ssam {
30230107Ssam 
30330107Ssam 	while (*s1 == *s2++)
30430107Ssam 		if (*s1++ == '\0')
30530107Ssam 			return (1);
30630107Ssam 	return (0);
30730107Ssam }
30830107Ssam 
30930107Ssam static
31030107Ssam round(a,b)
31130107Ssam 	register long a, b;
31230107Ssam {
31330107Ssam 	register long w;
31430107Ssam 
31530107Ssam 	w = (a/b)*b;
31630107Ssam 	if (a!=w)
31730107Ssam 		w += b;
31830107Ssam 	return (w);
31930107Ssam }
320