xref: /csrg-svn/sys/deprecated/kdb/kdb_expr.c (revision 30118)
1*30118Ssam /*	kdb_expr.c	7.2	86/11/20	*/
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;
11030107Ssam 			callpc= pcb.pcb_pc;
11130107Ssam 			while (errflg==0) {
11230107Ssam 			    savpc=callpc;
11330107Ssam 			    findsym(callpc,ISYM);
11430107Ssam 			    if (eqsym(cursym->n_un.n_name,isymbol,'~'))
11530107Ssam 				    break;
11630107Ssam 			    callpc=get(frame-8, DSP);
11730107Ssam 			    lastframe=frame;
11830107Ssam 			    frame=get(frame, DSP)&ALIGN;
11930107Ssam 			    if (frame==0)
12030107Ssam 				    error(NOCFN);
12130107Ssam 			}
12230107Ssam 			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--;
13130107Ssam 	} else if (getnum())
13230107Ssam 		;
13330107Ssam 	else if (lastc=='.') {
13430107Ssam 		readchar();
13530107Ssam 		if (symchar(0)) {
13630107Ssam 			lastframe=savlastf; callpc=savpc;
13730107Ssam 			chkloc(savframe);
13830107Ssam 		} else
13930107Ssam 			expv=dot;
14030107Ssam 		lp--;
14130107Ssam 	} else if (lastc=='"')
14230107Ssam 		expv=ditto;
14330107Ssam 	else if (lastc=='+')
14430107Ssam 		expv=inkdot(dotinc);
14530107Ssam 	else if (lastc=='^')
14630107Ssam 		expv=inkdot(-dotinc);
14730107Ssam 	else if (lastc=='<') {
14830107Ssam 		savc=rdc();
14930107Ssam 		if ((regptr=getreg(savc)) != -1)
15030107Ssam 			expv = *(int *)regptr;
15130107Ssam 		else if ((base=varchk(savc)) != -1)
15230107Ssam 			expv=var[base];
15330107Ssam 		else
15430107Ssam 			error(BADVAR);
15530107Ssam 	} else if (lastc=='\'') {
15630107Ssam 		d=4; expv=0;
15730107Ssam 		while (quotchar()) {
15830107Ssam 		    if (d--) {
15930107Ssam 		         expv <<= 8;
16030107Ssam 			 expv |= lastc;
16130107Ssam 		    } else
16230107Ssam 			error(BADSYN);
16330107Ssam 		}
16430107Ssam 	} else if (a)
16530107Ssam 		error(NOADR);
16630107Ssam 	else {
16730107Ssam 		lp--;
16830107Ssam 		return(0);
16930107Ssam 	}
17030107Ssam 	return (1);
17130107Ssam }
17230107Ssam 
17330107Ssam /* service routines for expression reading */
17430107Ssam static
17530107Ssam getnum()
17630107Ssam {
17730107Ssam 	register base,d,frpt;
17830107Ssam 	union { float r; long i;} real;
17930107Ssam 
18030107Ssam 	if (!isdigit(lastc))
18130107Ssam 		return (0);
18230107Ssam 	if ((base = radix) < 0)
18330107Ssam 		base = -base;
18430107Ssam 	expv = 0;
18530107Ssam 	while (base>10 ? isxdigit(lastc) : isdigit(lastc)) {
18630107Ssam 		register m = MAXINT/base;
18730107Ssam 
18830107Ssam 		if (expv>m)		/* avoid overflow */
18930107Ssam 			expv = (expv-m)*base+m*base;
19030107Ssam 		else
19130107Ssam 			expv *= base;
19230107Ssam 		if ((d=convdig(lastc))>=base || d<0)
19330107Ssam 			error(BADSYN);
19430107Ssam 		expv += d; readchar();
19530107Ssam 		if (expv==0) {
19630107Ssam 			if (lastc=='x' || lastc=='X') {
19730107Ssam 				 base=16; readchar();
19830107Ssam 			} else if (lastc=='t' || lastc=='T') {
19930107Ssam 				 base=10; readchar();
20030107Ssam 			} else if (lastc=='o' || lastc=='O') {
20130107Ssam 				 base=8; readchar();
20230107Ssam 			}
20330107Ssam 		}
20430107Ssam 	}
20530107Ssam 	if (lastc=='.' && (base==10 || expv==0)) {
20630107Ssam 		real.r=expv; frpt=0; base=10;
20730107Ssam 		while (isdigit(readchar())) {
20830107Ssam 			real.r *= base; frpt++;
20930107Ssam 			real.r += lastc-'0';
21030107Ssam 		}
21130107Ssam 		while (frpt--)
21230107Ssam 			real.r /= base;
21330107Ssam 		expv = real.i;
21430107Ssam 	}
21530107Ssam 	peekc=lastc;
21630107Ssam 	return (1);
21730107Ssam }
21830107Ssam 
21930107Ssam static
22030107Ssam readsym()
22130107Ssam {
22230107Ssam 	register char *p;
22330107Ssam 
22430107Ssam 	p = isymbol;
22530107Ssam 	do {
22630107Ssam 	    if (p < &isymbol[sizeof(isymbol)-1])
22730107Ssam 		    *p++ = lastc;
22830107Ssam 	    readchar();
22930107Ssam 	} while (symchar(1));
23030107Ssam 	*p++ = 0;
23130107Ssam }
23230107Ssam 
23330107Ssam static
23430107Ssam convdig(c)
23530107Ssam 	char c;
23630107Ssam {
23730107Ssam 	if (isdigit(c))
23830107Ssam 		return (c-'0');
23930107Ssam 	if (isxdigit(c))
24030107Ssam 		return (c-'a'+10);
24130107Ssam 	return (-1);
24230107Ssam }
24330107Ssam 
24430107Ssam static
24530107Ssam symchar(dig)
24630107Ssam {
24730107Ssam 
24830107Ssam 	if (lastc=='\\') {
24930107Ssam 		readchar();
250*30118Ssam 		return (1);
25130107Ssam 	}
25230107Ssam 	return (isalpha(lastc) || lastc=='_' || dig && isdigit(lastc));
25330107Ssam }
25430107Ssam 
25530107Ssam varchk(name)
25630107Ssam 	register name;
25730107Ssam {
25830107Ssam 	if (isdigit(name))
25930107Ssam 		return (name-'0');
26030107Ssam 	if (isalpha(name))
26130107Ssam 		return ((name&037)-1+10);
26230107Ssam 	return (-1);
26330107Ssam }
26430107Ssam 
26530107Ssam static
26630107Ssam chkloc(frame)
26730107Ssam 	long frame;
26830107Ssam {
26930107Ssam 
27030107Ssam 	readsym();
27130107Ssam 	do {
27230107Ssam 		if (localsym(frame)==0)
27330107Ssam 			error(BADLOC);
27430107Ssam 		expv=localval;
27530107Ssam 	} while (!eqsym(cursym->n_un.n_name,isymbol,'~'));
27630107Ssam }
27730107Ssam 
27830107Ssam eqsym(s1, s2, c)
27930107Ssam 	register char *s1, *s2;
28030107Ssam {
28130107Ssam 
28230107Ssam 	if (streq(s1,s2))
28330107Ssam 		return (1);
28430107Ssam 	if (*s1 == c && streq(s1+1, s2))
28530107Ssam 		return (1);
28630107Ssam 	return (0);
28730107Ssam }
28830107Ssam 
28930107Ssam static
29030107Ssam streq(s1, s2)
29130107Ssam 	char *s1, *s2;
29230107Ssam {
29330107Ssam 
29430107Ssam 	while (*s1 == *s2++)
29530107Ssam 		if (*s1++ == '\0')
29630107Ssam 			return (1);
29730107Ssam 	return (0);
29830107Ssam }
29930107Ssam 
30030107Ssam static
30130107Ssam round(a,b)
30230107Ssam 	register long a, b;
30330107Ssam {
30430107Ssam 	register long w;
30530107Ssam 
30630107Ssam 	w = (a/b)*b;
30730107Ssam 	if (a!=w)
30830107Ssam 		w += b;
30930107Ssam 	return (w);
31030107Ssam }
311