xref: /csrg-svn/sys/deprecated/kdb/kdb_expr.c (revision 30296)
1*30296Ssam /*
2*30296Ssam  * Copyright (c) 1986 Regents of the University of California.
3*30296Ssam  * All rights reserved.  The Berkeley software License Agreement
4*30296Ssam  * specifies the terms and conditions for redistribution.
5*30296Ssam  *
6*30296Ssam  *	@(#)kdb_expr.c	7.4 (Berkeley) 12/15/86
7*30296Ssam  */
830107Ssam 
930107Ssam #include "../kdb/defs.h"
1030107Ssam 
1130107Ssam char	*BADSYM;
1230107Ssam char	*BADVAR;
1330107Ssam char	*BADKET;
1430107Ssam char	*BADSYN;
1530107Ssam char	*NOCFN;
1630107Ssam char	*NOADR;
1730107Ssam char	*BADLOC;
1830107Ssam 
1930107Ssam ADDR	lastframe;
2030107Ssam ADDR	savlastf;
2130107Ssam ADDR	savframe;
2230107Ssam ADDR	savpc;
2330107Ssam ADDR	callpc;
2430107Ssam 
2530107Ssam char	*lp;
2630107Ssam int	radix;
2730107Ssam char	isymbol[1024];
2830107Ssam 
2930107Ssam char	lastc, peekc;
3030107Ssam 
3130107Ssam long	ditto;
3230107Ssam long	expv;
3330107Ssam 
34*30296Ssam static long
35*30296Ssam round(a,b)
36*30296Ssam 	register long a, b;
37*30296Ssam {
38*30296Ssam 	register long w;
39*30296Ssam 
40*30296Ssam 	w = (a/b)*b;
41*30296Ssam 	if (a!=w)
42*30296Ssam 		w += b;
43*30296Ssam 	return (w);
44*30296Ssam }
45*30296Ssam 
4630107Ssam /* term | term dyadic expr |  */
4730107Ssam expr(a)
4830107Ssam {
4930107Ssam 	register rc;
5030107Ssam 	register long lhs;
5130107Ssam 
52*30296Ssam 	(void) rdc(); lp--; rc=term(a);
5330107Ssam 
5430107Ssam 	while (rc) {
5530107Ssam 		lhs = expv;
5630107Ssam 		switch ((int)readchar()) {
5730107Ssam 		case '+':
58*30296Ssam 			(void) term(a|1); expv += lhs; break;
5930107Ssam 		case '-':
60*30296Ssam 			(void) term(a|1); expv = lhs - expv; break;
6130107Ssam 		case '#':
62*30296Ssam 			(void) term(a|1); expv = round(lhs,expv); break;
6330107Ssam 		case '*':
64*30296Ssam 			(void) term(a|1); expv *= lhs; break;
6530107Ssam 		case '%':
66*30296Ssam 			(void) term(a|1); expv = lhs/expv; break;
6730107Ssam 		case '&':
68*30296Ssam 			(void) term(a|1); expv &= lhs; break;
6930107Ssam 		case '|':
70*30296Ssam 			(void) term(a|1); expv |= lhs; break;
7130107Ssam 		case ')':
7230107Ssam 			if ((a&2)==0)
7330107Ssam 				error(BADKET);
7430107Ssam 		default:
7530107Ssam 			lp--;
7630107Ssam 			return (rc);
7730107Ssam 		}
7830107Ssam 	}
7930107Ssam 	return (rc);
8030107Ssam }
8130107Ssam 
8230107Ssam /* item | monadic item | (expr) | */
8330107Ssam static
8430107Ssam term(a)
8530107Ssam {
8630107Ssam 
8730107Ssam 	switch ((int)readchar()) {
8830107Ssam 	case '*':
89*30296Ssam 		(void) term(a|1); expv=chkget(expv,DSP);
9030107Ssam 		return(1);
9130107Ssam 	case '@':
92*30296Ssam 		(void) term(a|1); expv=chkget(expv,ISP);
9330107Ssam 		return(1);
9430107Ssam 	case '-':
95*30296Ssam 		(void) term(a|1); expv = -expv;
9630107Ssam 		return(1);
9730107Ssam 	case '~':
98*30296Ssam 		(void) term(a|1); expv = ~expv;
9930107Ssam 		return(1);
10030107Ssam 	case '#':
101*30296Ssam 		(void) term(a|1); expv = !expv;
10230107Ssam 		return(1);
10330107Ssam 	case '(':
104*30296Ssam 		(void) expr(2);
10530107Ssam 		if (*lp!=')')
10630107Ssam 			error(BADSYN);
10730107Ssam 		lp++;
10830107Ssam 		return(1);
10930107Ssam 	}
11030107Ssam 	lp--;
11130107Ssam 	return (item(a));
11230107Ssam }
11330107Ssam 
11430107Ssam /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
11530107Ssam static
11630107Ssam item(a)
11730107Ssam {
11830107Ssam 	register base, d, regptr;
11930107Ssam 	char savc;
12030107Ssam 	register long frame;
12130107Ssam 	register struct nlist *symp;
12230107Ssam 
123*30296Ssam 	(void) readchar();
12430107Ssam 	if (symchar(0)) {
12530107Ssam 		readsym();
12630107Ssam 		if (lastc=='.') {
12730107Ssam 			frame = pcb.pcb_fp; lastframe = 0;
12830136Ssam 			callpc = pcb.pcb_pc;
12930136Ssam 			while (!errflg) {
13030136Ssam 				savpc = callpc;
131*30296Ssam 				(void) findsym((long)callpc,ISYM);
13230136Ssam 				if (eqsym(cursym->n_un.n_name,isymbol,'~'))
13330136Ssam 					break;
13430136Ssam 				callpc = getprevpc(frame);
13530136Ssam 				lastframe = frame;
13630136Ssam 				frame = getprevframe(frame);
13730136Ssam 				if (frame == NOFRAME)
13830136Ssam 					error(NOCFN);
13930107Ssam 			}
14030136Ssam 			savlastf = lastframe; savframe = frame;
141*30296Ssam 			(void) readchar();
14230107Ssam 			if (symchar(0))
14330107Ssam 				chkloc(expv=frame);
14430107Ssam 		} else if ((symp=lookup(isymbol))==0)
14530107Ssam 			error(BADSYM);
14630107Ssam 		else
14730107Ssam 			expv = symp->n_value;
14830107Ssam 		lp--;
14930136Ssam 		return (1);
15030136Ssam 	}
15130136Ssam 	if (getnum())
15230136Ssam 		return (1);
15330136Ssam 	switch (lastc) {
15430136Ssam 	case '.':
155*30296Ssam 		(void) readchar();
15630107Ssam 		if (symchar(0)) {
15730107Ssam 			lastframe=savlastf; callpc=savpc;
158*30296Ssam 			chkloc((long)savframe);
15930107Ssam 		} else
16030107Ssam 			expv=dot;
16130107Ssam 		lp--;
16230136Ssam 		break;
16330136Ssam 	case '"':
16430107Ssam 		expv=ditto;
16530136Ssam 		break;
16630136Ssam 	case '+':
16730107Ssam 		expv=inkdot(dotinc);
16830136Ssam 		break;
16930136Ssam 	case '^':
17030107Ssam 		expv=inkdot(-dotinc);
17130136Ssam 		break;
17230136Ssam 	case '<':
17330107Ssam 		savc=rdc();
17430107Ssam 		if ((regptr=getreg(savc)) != -1)
17530107Ssam 			expv = *(int *)regptr;
17630107Ssam 		else if ((base=varchk(savc)) != -1)
17730107Ssam 			expv=var[base];
17830107Ssam 		else
17930107Ssam 			error(BADVAR);
18030136Ssam 		break;
18130136Ssam 	case '\'':
18230107Ssam 		d=4; expv=0;
18330107Ssam 		while (quotchar()) {
18430107Ssam 		    if (d--) {
18530107Ssam 		         expv <<= 8;
18630107Ssam 			 expv |= lastc;
18730107Ssam 		    } else
18830107Ssam 			error(BADSYN);
18930107Ssam 		}
19030136Ssam 		break;
19130136Ssam 	default:
19230136Ssam 		if (a)
19330136Ssam 			error(NOADR);
19430107Ssam 		lp--;
19530107Ssam 		return(0);
19630107Ssam 	}
19730107Ssam 	return (1);
19830107Ssam }
19930107Ssam 
20030107Ssam /* service routines for expression reading */
20130107Ssam static
20230107Ssam getnum()
20330107Ssam {
20430107Ssam 	register base,d,frpt;
20530107Ssam 	union { float r; long i;} real;
20630107Ssam 
20730107Ssam 	if (!isdigit(lastc))
20830107Ssam 		return (0);
20930107Ssam 	if ((base = radix) < 0)
21030107Ssam 		base = -base;
21130107Ssam 	expv = 0;
21230107Ssam 	while (base>10 ? isxdigit(lastc) : isdigit(lastc)) {
21330107Ssam 		register m = MAXINT/base;
21430107Ssam 
21530107Ssam 		if (expv>m)		/* avoid overflow */
21630107Ssam 			expv = (expv-m)*base+m*base;
21730107Ssam 		else
21830107Ssam 			expv *= base;
21930107Ssam 		if ((d=convdig(lastc))>=base || d<0)
22030107Ssam 			error(BADSYN);
221*30296Ssam 		expv += d; (void) readchar();
22230107Ssam 		if (expv==0) {
22330107Ssam 			if (lastc=='x' || lastc=='X') {
224*30296Ssam 				 base=16; (void) readchar();
22530107Ssam 			} else if (lastc=='t' || lastc=='T') {
226*30296Ssam 				 base=10; (void) readchar();
22730107Ssam 			} else if (lastc=='o' || lastc=='O') {
228*30296Ssam 				 base=8; (void) readchar();
22930107Ssam 			}
23030107Ssam 		}
23130107Ssam 	}
23230107Ssam 	if (lastc=='.' && (base==10 || expv==0)) {
23330107Ssam 		real.r=expv; frpt=0; base=10;
23430107Ssam 		while (isdigit(readchar())) {
23530107Ssam 			real.r *= base; frpt++;
23630107Ssam 			real.r += lastc-'0';
23730107Ssam 		}
23830107Ssam 		while (frpt--)
23930107Ssam 			real.r /= base;
24030107Ssam 		expv = real.i;
24130107Ssam 	}
24230107Ssam 	peekc=lastc;
24330107Ssam 	return (1);
24430107Ssam }
24530107Ssam 
24630107Ssam static
24730107Ssam readsym()
24830107Ssam {
24930107Ssam 	register char *p;
25030107Ssam 
25130107Ssam 	p = isymbol;
25230107Ssam 	do {
253*30296Ssam 		if (p < &isymbol[sizeof(isymbol)-1])
254*30296Ssam 			*p++ = lastc;
255*30296Ssam 		(void) readchar();
25630107Ssam 	} while (symchar(1));
25730107Ssam 	*p++ = 0;
25830107Ssam }
25930107Ssam 
26030107Ssam static
26130107Ssam convdig(c)
26230107Ssam 	char c;
26330107Ssam {
26430107Ssam 	if (isdigit(c))
26530107Ssam 		return (c-'0');
26630107Ssam 	if (isxdigit(c))
26730107Ssam 		return (c-'a'+10);
26830107Ssam 	return (-1);
26930107Ssam }
27030107Ssam 
27130107Ssam static
27230107Ssam symchar(dig)
27330107Ssam {
27430107Ssam 
27530107Ssam 	if (lastc=='\\') {
276*30296Ssam 		(void) readchar();
27730118Ssam 		return (1);
27830107Ssam 	}
27930107Ssam 	return (isalpha(lastc) || lastc=='_' || dig && isdigit(lastc));
28030107Ssam }
28130107Ssam 
28230107Ssam varchk(name)
28330107Ssam 	register name;
28430107Ssam {
28530107Ssam 	if (isdigit(name))
28630107Ssam 		return (name-'0');
28730107Ssam 	if (isalpha(name))
28830107Ssam 		return ((name&037)-1+10);
28930107Ssam 	return (-1);
29030107Ssam }
29130107Ssam 
29230107Ssam static
29330107Ssam chkloc(frame)
29430107Ssam 	long frame;
29530107Ssam {
29630107Ssam 
29730107Ssam 	readsym();
29830107Ssam 	do {
29930107Ssam 		if (localsym(frame)==0)
30030107Ssam 			error(BADLOC);
30130107Ssam 		expv=localval;
30230107Ssam 	} while (!eqsym(cursym->n_un.n_name,isymbol,'~'));
30330107Ssam }
30430107Ssam 
30530107Ssam eqsym(s1, s2, c)
30630107Ssam 	register char *s1, *s2;
30730107Ssam {
30830107Ssam 
30930107Ssam 	if (streq(s1,s2))
31030107Ssam 		return (1);
31130107Ssam 	if (*s1 == c && streq(s1+1, s2))
31230107Ssam 		return (1);
31330107Ssam 	return (0);
31430107Ssam }
31530107Ssam 
31630107Ssam static
31730107Ssam streq(s1, s2)
31830107Ssam 	char *s1, *s2;
31930107Ssam {
32030107Ssam 
32130107Ssam 	while (*s1 == *s2++)
32230107Ssam 		if (*s1++ == '\0')
32330107Ssam 			return (1);
32430107Ssam 	return (0);
32530107Ssam }
326