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