xref: /original-bsd/sys/deprecated/kdb/kdb_expr.c (revision e59fb703)
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.6 (Berkeley) 05/03/90
7  */
8 
9 #include "../kdb/defs.h"
10 
11 char	*kdbBADSYM;
12 char	*kdbBADVAR;
13 char	*kdbBADKET;
14 char	*kdbBADSYN;
15 char	*kdbNOCFN;
16 char	*kdbNOADR;
17 char	*kdbBADLOC;
18 
19 ADDR	kdblastframe;
20 ADDR	kdbsavlastf;
21 ADDR	kdbsavframe;
22 ADDR	kdbsavpc;
23 ADDR	kdbcallpc;
24 
25 char	*kdblp;
26 int	kdbradix;
27 char	kdbisymbol[1024];
28 
29 char	kdblastc, kdbpeekc;
30 
31 long	kdbditto;
32 long	kdbexpv;
33 
34 static long
35 kdbround(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 kdbexpr(a)
48 {
49 	register rc;
50 	register long lhs;
51 
52 	(void) kdbrdc(); kdblp--; rc=kdbterm(a);
53 
54 	while (rc) {
55 		lhs = kdbexpv;
56 		switch ((int)kdbreadchar()) {
57 		case '+':
58 			(void) kdbterm(a|1); kdbexpv += lhs; break;
59 		case '-':
60 			(void) kdbterm(a|1); kdbexpv = lhs - kdbexpv; break;
61 		case '#':
62 			(void) kdbterm(a|1); kdbexpv = kdbround(lhs,kdbexpv); break;
63 		case '*':
64 			(void) kdbterm(a|1); kdbexpv *= lhs; break;
65 		case '%':
66 			(void) kdbterm(a|1); kdbexpv = lhs/kdbexpv; break;
67 		case '&':
68 			(void) kdbterm(a|1); kdbexpv &= lhs; break;
69 		case '|':
70 			(void) kdbterm(a|1); kdbexpv |= lhs; break;
71 		case ')':
72 			if ((a&2)==0)
73 				kdberror(kdbBADKET);
74 		default:
75 			kdblp--;
76 			return (rc);
77 		}
78 	}
79 	return (rc);
80 }
81 
82 /* item | monadic item | (expr) | */
83 static
84 kdbterm(a)
85 {
86 
87 	switch ((int)kdbreadchar()) {
88 	case '*':
89 		(void) kdbterm(a|1); kdbexpv=kdbchkget(kdbexpv,DSP);
90 		return(1);
91 	case '@':
92 		(void) kdbterm(a|1); kdbexpv=kdbchkget(kdbexpv,ISP);
93 		return(1);
94 	case '-':
95 		(void) kdbterm(a|1); kdbexpv = -kdbexpv;
96 		return(1);
97 	case '~':
98 		(void) kdbterm(a|1); kdbexpv = ~kdbexpv;
99 		return(1);
100 	case '#':
101 		(void) kdbterm(a|1); kdbexpv = !kdbexpv;
102 		return(1);
103 	case '(':
104 		(void) kdbexpr(2);
105 		if (*kdblp!=')')
106 			kdberror(kdbBADSYN);
107 		kdblp++;
108 		return(1);
109 	}
110 	kdblp--;
111 	return (kdbitem(a));
112 }
113 
114 /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
115 static
116 kdbitem(a)
117 {
118 	register base, d, regptr;
119 	char savc;
120 	register long frame;
121 	register struct nlist *symp;
122 
123 	(void) kdbreadchar();
124 	if (kdbsymchar(0)) {
125 		kdbreadsym();
126 		if (kdblastc=='.') {
127 			frame = kdbpcb.pcb_fp; kdblastframe = 0;
128 			kdbcallpc = kdbpcb.pcb_pc;
129 			while (!kdberrflg) {
130 				kdbsavpc = kdbcallpc;
131 				(void) kdbfindsym((long)kdbcallpc,ISYM);
132 				if (kdbeqsym(kdbcursym->n_un.n_name,kdbisymbol,'~'))
133 					break;
134 				kdbcallpc = getprevpc(frame);
135 				kdblastframe = frame;
136 				frame = getprevframe(frame);
137 				if (frame == NOFRAME)
138 					kdberror(kdbNOCFN);
139 			}
140 			kdbsavlastf = kdblastframe; kdbsavframe = frame;
141 			(void) kdbreadchar();
142 			if (kdbsymchar(0))
143 				kdbchkloc(kdbexpv=frame);
144 		} else if ((symp=kdblookup(kdbisymbol))==0)
145 			kdberror(kdbBADSYM);
146 		else
147 			kdbexpv = symp->n_value;
148 		kdblp--;
149 		return (1);
150 	}
151 	if (kdbgetnum())
152 		return (1);
153 	switch (kdblastc) {
154 	case '.':
155 		(void) kdbreadchar();
156 		if (kdbsymchar(0)) {
157 			kdblastframe=kdbsavlastf; kdbcallpc=kdbsavpc;
158 			kdbchkloc((long)kdbsavframe);
159 		} else
160 			kdbexpv=kdbdot;
161 		kdblp--;
162 		break;
163 	case '"':
164 		kdbexpv=kdbditto;
165 		break;
166 	case '+':
167 		kdbexpv=kdbinkdot(kdbdotinc);
168 		break;
169 	case '^':
170 		kdbexpv=kdbinkdot(-kdbdotinc);
171 		break;
172 	case '<':
173 		savc=kdbrdc();
174 		if ((regptr=kdbgetreg(savc)) != -1)
175 			kdbexpv = *(int *)regptr;
176 		else if ((base=kdbvarchk(savc)) != -1)
177 			kdbexpv=kdbvar[base];
178 		else
179 			kdberror(kdbBADVAR);
180 		break;
181 	case '\'':
182 		d=4; kdbexpv=0;
183 		while (kdbquotchar()) {
184 		    if (d--) {
185 		         kdbexpv <<= 8;
186 			 kdbexpv |= kdblastc;
187 		    } else
188 			kdberror(kdbBADSYN);
189 		}
190 		break;
191 	default:
192 		if (a)
193 			kdberror(kdbNOADR);
194 		kdblp--;
195 		return(0);
196 	}
197 	return (1);
198 }
199 
200 /* service routines for expression reading */
201 static
202 kdbgetnum()
203 {
204 	register base,d,frpt;
205 
206 	if (!isdigit(kdblastc))
207 		return (0);
208 	if ((base = kdbradix) < 0)
209 		base = -base;
210 	kdbexpv = 0;
211 	while (base>10 ? isxdigit(kdblastc) : isdigit(kdblastc)) {
212 		register m = MAXINT/base;
213 
214 		if (kdbexpv>m)		/* avoid overflow */
215 			kdbexpv = (kdbexpv-m)*base+m*base;
216 		else
217 			kdbexpv *= base;
218 		if ((d=kdbconvdig(kdblastc))>=base || d<0)
219 			kdberror(kdbBADSYN);
220 		kdbexpv += d; (void) kdbreadchar();
221 		if (kdbexpv==0) {
222 			if (kdblastc=='x' || kdblastc=='X') {
223 				 base=16; (void) kdbreadchar();
224 			} else if (kdblastc=='t' || kdblastc=='T') {
225 				 base=10; (void) kdbreadchar();
226 			} else if (kdblastc=='o' || kdblastc=='O') {
227 				 base=8; (void) kdbreadchar();
228 			}
229 		}
230 	}
231 	if (kdblastc=='.' && (base==10 || kdbexpv==0)) {
232 		frpt=0; base=10;
233 		while (isdigit(kdbreadchar())) {
234 			if (frpt)
235 				continue;
236 			frpt++;
237 			if (kdblastc - '0' >= 5)
238 				kdbexpv++;
239 		}
240 	}
241 	kdbpeekc=kdblastc;
242 	return (1);
243 }
244 
245 static
246 kdbreadsym()
247 {
248 	register char *p;
249 
250 	p = kdbisymbol;
251 	do {
252 		if (p < &kdbisymbol[sizeof(kdbisymbol)-1])
253 			*p++ = kdblastc;
254 		(void) kdbreadchar();
255 	} while (kdbsymchar(1));
256 	*p++ = 0;
257 }
258 
259 static
260 kdbconvdig(c)
261 	char c;
262 {
263 	if (isdigit(c))
264 		return (c-'0');
265 	if (isxdigit(c))
266 		return (c-'a'+10);
267 	return (-1);
268 }
269 
270 static
271 kdbsymchar(dig)
272 {
273 
274 	if (kdblastc=='\\') {
275 		(void) kdbreadchar();
276 		return (1);
277 	}
278 	return (isalpha(kdblastc) || kdblastc=='_' || dig && isdigit(kdblastc));
279 }
280 
281 kdbvarchk(name)
282 	register name;
283 {
284 	if (isdigit(name))
285 		return (name-'0');
286 	if (isalpha(name))
287 		return ((name&037)-1+10);
288 	return (-1);
289 }
290 
291 static
292 kdbchkloc(frame)
293 	long frame;
294 {
295 
296 	kdbreadsym();
297 	do {
298 		if (kdblocalsym(frame)==0)
299 			kdberror(kdbBADLOC);
300 		kdbexpv=kdblocalval;
301 	} while (!kdbeqsym(kdbcursym->n_un.n_name,kdbisymbol,'~'));
302 }
303 
304 kdbeqsym(s1, s2, c)
305 	register char *s1, *s2;
306 {
307 
308 	if (kdbstreq(s1,s2))
309 		return (1);
310 	if (*s1 == c && kdbstreq(s1+1, s2))
311 		return (1);
312 	return (0);
313 }
314 
315 static
316 kdbstreq(s1, s2)
317 	char *s1, *s2;
318 {
319 
320 	while (*s1 == *s2++)
321 		if (*s1++ == '\0')
322 			return (1);
323 	return (0);
324 }
325