xref: /csrg-svn/sys/deprecated/kdb/kdb_expr.c (revision 30296)
1 /*
2  * Copyright (c) 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)kdb_expr.c	7.4 (Berkeley) 12/15/86
7  */
8 
9 #include "../kdb/defs.h"
10 
11 char	*BADSYM;
12 char	*BADVAR;
13 char	*BADKET;
14 char	*BADSYN;
15 char	*NOCFN;
16 char	*NOADR;
17 char	*BADLOC;
18 
19 ADDR	lastframe;
20 ADDR	savlastf;
21 ADDR	savframe;
22 ADDR	savpc;
23 ADDR	callpc;
24 
25 char	*lp;
26 int	radix;
27 char	isymbol[1024];
28 
29 char	lastc, peekc;
30 
31 long	ditto;
32 long	expv;
33 
34 static long
35 round(a,b)
36 	register long a, b;
37 {
38 	register long w;
39 
40 	w = (a/b)*b;
41 	if (a!=w)
42 		w += b;
43 	return (w);
44 }
45 
46 /* term | term dyadic expr |  */
47 expr(a)
48 {
49 	register rc;
50 	register long lhs;
51 
52 	(void) rdc(); lp--; rc=term(a);
53 
54 	while (rc) {
55 		lhs = expv;
56 		switch ((int)readchar()) {
57 		case '+':
58 			(void) term(a|1); expv += lhs; break;
59 		case '-':
60 			(void) term(a|1); expv = lhs - expv; break;
61 		case '#':
62 			(void) term(a|1); expv = round(lhs,expv); break;
63 		case '*':
64 			(void) term(a|1); expv *= lhs; break;
65 		case '%':
66 			(void) term(a|1); expv = lhs/expv; break;
67 		case '&':
68 			(void) term(a|1); expv &= lhs; break;
69 		case '|':
70 			(void) term(a|1); expv |= lhs; break;
71 		case ')':
72 			if ((a&2)==0)
73 				error(BADKET);
74 		default:
75 			lp--;
76 			return (rc);
77 		}
78 	}
79 	return (rc);
80 }
81 
82 /* item | monadic item | (expr) | */
83 static
84 term(a)
85 {
86 
87 	switch ((int)readchar()) {
88 	case '*':
89 		(void) term(a|1); expv=chkget(expv,DSP);
90 		return(1);
91 	case '@':
92 		(void) term(a|1); expv=chkget(expv,ISP);
93 		return(1);
94 	case '-':
95 		(void) term(a|1); expv = -expv;
96 		return(1);
97 	case '~':
98 		(void) term(a|1); expv = ~expv;
99 		return(1);
100 	case '#':
101 		(void) term(a|1); expv = !expv;
102 		return(1);
103 	case '(':
104 		(void) expr(2);
105 		if (*lp!=')')
106 			error(BADSYN);
107 		lp++;
108 		return(1);
109 	}
110 	lp--;
111 	return (item(a));
112 }
113 
114 /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
115 static
116 item(a)
117 {
118 	register base, d, regptr;
119 	char savc;
120 	register long frame;
121 	register struct nlist *symp;
122 
123 	(void) readchar();
124 	if (symchar(0)) {
125 		readsym();
126 		if (lastc=='.') {
127 			frame = pcb.pcb_fp; lastframe = 0;
128 			callpc = pcb.pcb_pc;
129 			while (!errflg) {
130 				savpc = callpc;
131 				(void) findsym((long)callpc,ISYM);
132 				if (eqsym(cursym->n_un.n_name,isymbol,'~'))
133 					break;
134 				callpc = getprevpc(frame);
135 				lastframe = frame;
136 				frame = getprevframe(frame);
137 				if (frame == NOFRAME)
138 					error(NOCFN);
139 			}
140 			savlastf = lastframe; savframe = frame;
141 			(void) readchar();
142 			if (symchar(0))
143 				chkloc(expv=frame);
144 		} else if ((symp=lookup(isymbol))==0)
145 			error(BADSYM);
146 		else
147 			expv = symp->n_value;
148 		lp--;
149 		return (1);
150 	}
151 	if (getnum())
152 		return (1);
153 	switch (lastc) {
154 	case '.':
155 		(void) readchar();
156 		if (symchar(0)) {
157 			lastframe=savlastf; callpc=savpc;
158 			chkloc((long)savframe);
159 		} else
160 			expv=dot;
161 		lp--;
162 		break;
163 	case '"':
164 		expv=ditto;
165 		break;
166 	case '+':
167 		expv=inkdot(dotinc);
168 		break;
169 	case '^':
170 		expv=inkdot(-dotinc);
171 		break;
172 	case '<':
173 		savc=rdc();
174 		if ((regptr=getreg(savc)) != -1)
175 			expv = *(int *)regptr;
176 		else if ((base=varchk(savc)) != -1)
177 			expv=var[base];
178 		else
179 			error(BADVAR);
180 		break;
181 	case '\'':
182 		d=4; expv=0;
183 		while (quotchar()) {
184 		    if (d--) {
185 		         expv <<= 8;
186 			 expv |= lastc;
187 		    } else
188 			error(BADSYN);
189 		}
190 		break;
191 	default:
192 		if (a)
193 			error(NOADR);
194 		lp--;
195 		return(0);
196 	}
197 	return (1);
198 }
199 
200 /* service routines for expression reading */
201 static
202 getnum()
203 {
204 	register base,d,frpt;
205 	union { float r; long i;} real;
206 
207 	if (!isdigit(lastc))
208 		return (0);
209 	if ((base = radix) < 0)
210 		base = -base;
211 	expv = 0;
212 	while (base>10 ? isxdigit(lastc) : isdigit(lastc)) {
213 		register m = MAXINT/base;
214 
215 		if (expv>m)		/* avoid overflow */
216 			expv = (expv-m)*base+m*base;
217 		else
218 			expv *= base;
219 		if ((d=convdig(lastc))>=base || d<0)
220 			error(BADSYN);
221 		expv += d; (void) readchar();
222 		if (expv==0) {
223 			if (lastc=='x' || lastc=='X') {
224 				 base=16; (void) readchar();
225 			} else if (lastc=='t' || lastc=='T') {
226 				 base=10; (void) readchar();
227 			} else if (lastc=='o' || lastc=='O') {
228 				 base=8; (void) readchar();
229 			}
230 		}
231 	}
232 	if (lastc=='.' && (base==10 || expv==0)) {
233 		real.r=expv; frpt=0; base=10;
234 		while (isdigit(readchar())) {
235 			real.r *= base; frpt++;
236 			real.r += lastc-'0';
237 		}
238 		while (frpt--)
239 			real.r /= base;
240 		expv = real.i;
241 	}
242 	peekc=lastc;
243 	return (1);
244 }
245 
246 static
247 readsym()
248 {
249 	register char *p;
250 
251 	p = isymbol;
252 	do {
253 		if (p < &isymbol[sizeof(isymbol)-1])
254 			*p++ = lastc;
255 		(void) readchar();
256 	} while (symchar(1));
257 	*p++ = 0;
258 }
259 
260 static
261 convdig(c)
262 	char c;
263 {
264 	if (isdigit(c))
265 		return (c-'0');
266 	if (isxdigit(c))
267 		return (c-'a'+10);
268 	return (-1);
269 }
270 
271 static
272 symchar(dig)
273 {
274 
275 	if (lastc=='\\') {
276 		(void) readchar();
277 		return (1);
278 	}
279 	return (isalpha(lastc) || lastc=='_' || dig && isdigit(lastc));
280 }
281 
282 varchk(name)
283 	register name;
284 {
285 	if (isdigit(name))
286 		return (name-'0');
287 	if (isalpha(name))
288 		return ((name&037)-1+10);
289 	return (-1);
290 }
291 
292 static
293 chkloc(frame)
294 	long frame;
295 {
296 
297 	readsym();
298 	do {
299 		if (localsym(frame)==0)
300 			error(BADLOC);
301 		expv=localval;
302 	} while (!eqsym(cursym->n_un.n_name,isymbol,'~'));
303 }
304 
305 eqsym(s1, s2, c)
306 	register char *s1, *s2;
307 {
308 
309 	if (streq(s1,s2))
310 		return (1);
311 	if (*s1 == c && streq(s1+1, s2))
312 		return (1);
313 	return (0);
314 }
315 
316 static
317 streq(s1, s2)
318 	char *s1, *s2;
319 {
320 
321 	while (*s1 == *s2++)
322 		if (*s1++ == '\0')
323 			return (1);
324 	return (0);
325 }
326